Skip to content

Commit 9392763

Browse files
committed
add Chinese doc for NLS parmeters
1 parent b60867a commit 9392763

2 files changed

Lines changed: 140 additions & 0 deletions

File tree

CN/modules/ROOT/nav.adoc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
**** xref:master/6.3.3.adoc[RowID]
2626
**** xref:master/6.3.2.adoc[OUT 参数]
2727
**** xref:master/6.3.4.adoc[%TYPE、%ROWTYPE]
28+
**** xref:master/6.3.5.adoc[NLS 参数]
2829
*** xref:master/6.4.adoc[国标GB18030]
2930
** Oracle兼容功能列表
3031
*** xref:master/7.1.adoc[1、框架设计]
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
2+
:sectnums:
3+
:sectnumlevels: 5
4+
5+
6+
= **功能概述**
7+
8+
IvorySQL提供了兼容Oracle的NLS参数功能,包含如下参数。
9+
10+
[cols="3,7"]
11+
|====
12+
|*参数名称*|*功能描述*
13+
|ivorysql.datetime_ignore_nls_mask | 表示日期格式是否忽略NLS参数影响,默认为0。
14+
|nls_length_semantics | 兼容Oracle的同名参数,表示char/varchar/varchar2的类型修饰符的大小单位是字节还是字符。
15+
|nls_date_format | 表示默认的日期格式,可以通过show命令查看,默认为‘YYYY-MM-DD’。
16+
|nls_timestamp_format | 兼容Oracle的同名参数,控制带时间的日期格式。
17+
|nls_timestamp_tz_format | 兼容Oracle的同名参数,控制带时区的日期时间格式。
18+
|nls_territory | 兼容Oracle的同名参数,指定数据库的默认区域。
19+
|nls_iso_currency | 兼容Oracle的同名参数,指定的国家和区域制定唯一的货币符号。
20+
|nls_currency | 兼容Oracle的同名参数,指定显示本地货币的符号,对应数字字符串格式中占位符L。
21+
|====
22+
23+
== 实现原理
24+
25+
=== nls_length_semantics参数
26+
27+
IvorySQL中的数据类型存在一个属性修饰符typmod,是对类型的补充说明,比如在VARCHAR(n)类型中,n就是类型修饰符。在创建或修改表的列时可以指定长度类型,例如:
28+
```
29+
ivorysql=# create table t1(name varchar2(2 byte));
30+
```
31+
32+
对于列类型为CHAR、VARCHAR和VARCHAR2字符型的列,当没有显式指定列的长度类型时,IvorySQL使用nls_length_semantics参数的值来决定长度类型,有byte和char两种值,默认为byte。需要特别注意的是,nls_length_semantics参数的值仅影响新创建的列,对已经存在的列不会产生任何影响。
33+
34+
在语法解析文件 ora_gram.y中,存在如下代码来根据nls_length_semantics 把原本的char/varchar/varchar2类型改成oracharchar或者oracharbyte:
35+
```
36+
CharacterWithLength: character '(' Iconst ')'
37+
{
38+
if (ORA_PARSER == compatible_db)
39+
{
40+
if (strcmp($1, "bpchar"))
41+
{
42+
if (nls_length_semantics == NLS_LENGTH_CHAR)
43+
$1 = "oravarcharchar";
44+
else
45+
$1 = "oravarcharbyte";
46+
}
47+
else
48+
{
49+
if (nls_length_semantics == NLS_LENGTH_CHAR)
50+
$1 = "oracharchar";
51+
else
52+
$1 = "oracharbyte";
53+
}
54+
55+
$$ = OracleSystemTypeName($1);
56+
$$->typmods = list_make1(makeIntConst($3, @3));
57+
$$->location = @1;
58+
}
59+
else
60+
{
61+
...
62+
}
63+
}
64+
;
65+
66+
```
67+
68+
IvorySQL 中数据类型oracharchar和oracharbyte的修饰符输入输出函数包括:
69+
oravarcharchartypmodout() / oravarcharbytetypmodout() / oracharbytetypmodout() / oracharchartypmodout()
70+
71+
上面这些函数调用C语言实现的函数 anychar_typmodout() ,后者根据 nls_length_semantics 的值来调整输出的内容是否包含 byte/char 的说明。
72+
73+
nls_length_semantics 另一个作用是限制表中的列长度:
74+
根据上述代码在语法解析文件 ora_gram.y中,如果原本的varchar类型被转换成了oracharchar类型,则函数oravarcharchar()会被调用,而pg_mbcharcliplen()函数计算字符长度,而不是字节长度。
75+
```
76+
Datum
77+
oravarcharchar(PG_FUNCTION_ARGS)
78+
{
79+
VarChar *source = PG_GETARG_VARCHAR_PP(0);
80+
int32 typmod = PG_GETARG_INT32(1);
81+
bool isExplicit = PG_GETARG_BOOL(2);
82+
int32 len,
83+
maxlen;
84+
size_t maxmblen;
85+
char *s_data;
86+
87+
len = VARSIZE_ANY_EXHDR(source);
88+
s_data = VARDATA_ANY(source);
89+
maxlen = typmod - VARHDRSZ;
90+
91+
/* No work if typmod is invalid or supplied data fits it already */
92+
if (maxlen < 0 || len <= maxlen)
93+
PG_RETURN_VARCHAR_P(source);
94+
95+
maxmblen = pg_mbcharcliplen(s_data, len, maxlen);
96+
97+
...
98+
}
99+
```
100+
101+
=== GUC参数datetime_ignore_nls_mask
102+
103+
这个参数被定义为一个int值,低四位分别表示是否在相应的日期时间格式上忽略NLS参数的影响,掩码定义如下:
104+
```
105+
#define ORADATE_MASK 0x01
106+
#define ORATIMESTAMP_MASK 0x02
107+
#define ORATIMESTAMPTZ_MASK 0x04
108+
#define ORATIMESTAMPLTZ_MASK 0x08
109+
```
110+
111+
在源代码中,这个GUC参数被用于下面这些函数:
112+
oradate_in()、oratimestamp_in()、oratimestampltz_in()以及oratimestamptz_in()。
113+
114+
如果相应的掩码被设置,则调用原生PG的处理函数,否则调用兼容代码并忽略NLS格式。
115+
116+
=== GUC参数 nls_date_format/nls_timestamp_format/nls_timestamp_tz_format
117+
118+
这三个GUC参数,在函数 ora_do_to_timestamp() 中做为格式字符串,对输入的字符串进行格式检查与模式识别。
119+
下面是其默认值,可以通过设置其值为"pg"使其失效。"pg"表示禁用NLS特定行为,恢复为PostgreSQL的默认行为。
120+
```
121+
char *nls_date_format = "YYYY-MM-DD";
122+
char *nls_timestamp_format = "YYYY-MM-DD HH24:MI:SS.FF6";
123+
char *nls_timestamp_tz_format = "YYYY-MM-DD HH24:MI:SS.FF6 TZH:TZM";
124+
```
125+
126+
=== GUC参数 nls_currency/nls_iso_currency/nls_territory
127+
128+
目前nls_territory和nls_iso_currency支持CHINA与AMERICA两个值
129+
130+
```
131+
char *nls_territory = "AMERICA";
132+
char *nls_currency = "$";
133+
char *nls_iso_currency = "AMERICA";
134+
```
135+
这三个参数将在oracle兼容函数to_number()中被使用。
136+
[NOTE]
137+
====
138+
`to_number()`函数尚未实现。
139+
====

0 commit comments

Comments
 (0)