Skip to content

Commit 65cf6ed

Browse files
committed
NLS adoc
1 parent d7e7e70 commit 65cf6ed

1 file changed

Lines changed: 94 additions & 0 deletions

File tree

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
2+
:sectnums:
3+
:sectnumlevels: 5
4+
5+
6+
= **功能概述**
7+
8+
IvorySQL提供了兼容Oracle的NLS参数功能,包含如下参数。
9+
10+
[cols="2,8"]
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+
对于pliSQL函数,在创建函数时,系统表pg_proc中存储函数参数为全部参数个数(包括OUT参数个数)及对应的参数数据类型。
28+
29+
在处理函数参数的interpret_function_parameter_list()函数中,根据参数模式,判断如果是IN OUT,则参数不能有默认值。
30+
31+
在make_return_stmt函数中,去掉如果发现有out参数报错的处理。
32+
33+
通过修改FuncnameGetCandidates函数,在函数查找时匹配包括out参数在内的所有参数。
34+
35+
函数编译时,构造一个row变量来容纳OUT参数变量和返回值变量。修改编译好的函数返回类型(function->fn_rettype)为RECORDOID。
36+
37+
函数执行时,在ExecInitFunc函数中调用新函数ExecInitFuncOutParams, 构造OUT参数计算节点,通过计算函数plisql_out_param将函数返回值和OUT参数值从tuple中分离,并且为OUT参数向外赋值。
38+
39+
=== 匿名块支持out参数
40+
41+
为了支持冒号占位符形式的绑定变量,修改ora_scan.l文件,添加语法,遇到冒号占位符返回ORAPARAM。在ora_gram.y文件中,在c_expr和赋值plassign_target的语法中,添加对ORAPARAM添加处理,构造一个OraParamRef节点。
42+
43+
新增 DO + USING 语法:
44+
```
45+
DO [ LANGUAGE lang_name ] code [USING IN | OUT | IN OUT, ...]
46+
```
47+
修改ora_gram.y文件,增加DO+USING语法支持。DoStmt结构体中增加 paramsmode 用于存储匿名块中的绑定变量模式等信息的列表。
48+
49+
对PBE过程的修改包括:exec_parse_message函数中,根据应用接口传过来的参数类型oid,识别出实参的模式;在exec_bind_message函数中,对于匿名块DO+USING,识别出USING后面参数的模式,向执行器传递参数信息。
50+
51+
含OUT参数匿名块的执行
52+
53+
1. 在PortalStart函数中对匿名块语句,调用CreateTupleDescFromParams函数,增加参数构造描述信息。
54+
55+
2. PLiSQL_function成员fn_prokind增加新值PROKIND_ANONYMOUS_BLOCK用来表示匿名块。
56+
57+
3. 在plisql_exec_function函数中,对有out参数的匿名块做判断,调用plisql_anonymous_return_out_parameter函数完成对OUT参数构造PLiSQL_row类型的变量,最后将row类型的变量求值当作匿名块函数的返回值。
58+
59+
=== libpq中调用含out参数的函数
60+
61+
修改Libpq以支持按位置和按参数名字绑定,涉及SQL端,PLiSQL端,libpq接口端。
62+
63+
1. SQL端:在服务器端实现系统函数 get_parameter_description,该函数根据SQL语句,返回变量名字与位置的关系。这个函数被用在libpq接口函数中。
64+
返回的第一行name显示SQL类型,后面行依次显示占位符名字、位置信息。
65+
66+
```
67+
ivorysql=# select * from get_parameter_description('insert into t values(:x, :y);');
68+
name | position
69+
-------+----------
70+
false | 0
71+
:x | 1
72+
:y | 2
73+
(3 rows)
74+
```
75+
对于匿名块语句,尚不支持。
76+
77+
2. PLiSQL端:主要是PL/iSQL块根据参数位置或参数名称调整参数内部标识。
78+
79+
执行函数需要从绑定句柄中获取参数的值与类型的信息;
80+
81+
对out参数的返回列名称做一个特殊处理。如果是out参数,那么其列名称为_column_xxx,其中xxx是out参数的位置,从而根据绑定位置与返回的位置从结果集中给out参数赋值;
82+
83+
在PLiSQL执行端,根据参数名字出现的位置,调整名字转换成内部标识的变量,如$number。在返回到客户端的时候,发送描述信息给libpq, 从而达到返回的列名是由参数名字构造,LIBPQ端根据列名来给out参数赋值。
84+
85+
3. libpq接口端:提供准备、绑定、执行函数,这些函数与OCI接口相应函数类似。
86+
87+
一般调用流程如下:
88+
使用IvyHandleAlloc分配语句句柄和错误句柄。
89+
调用IvyStmtPrepare准备语句。
90+
调用IvyBindByPos或IvyBindByName 绑定参数。
91+
调用IvyStmtExecute 执行,可重复执行。
92+
调用IvyFreeHandle 释放语句句柄和错误句柄。
93+
94+
另外还实现了Ivyconnectdb,Ivystatus,Ivyexec,IvyresultStatus,IvyCreatePreparedStatement,IvybindOutParameterByPos,IvyexecPreparedStatement,IvyexecPreparedStatement2,Ivynfields,Ivyntuples,Ivyclear等一系列接口函数。

0 commit comments

Comments
 (0)