6.6. 给开发者 #
本节解释 ecpg 的内部工作原理。它包含有助于用户理解如何使用 ecpg 的宝贵信息。
6.6.1. The Preprocessor
ecpg 写入输出的前四行是固定的:其中两行是注释,另外两行是与库接口所必需的包含行。
随后预处理器通读整个文件并写出输出。通常它只是把所有内容原样回显到输出。
当它遇到 EXEC SQL 语句时,会介入并改变它。EXEC SQL
语句可以是下列之一:
- 声明节
Declare节以:exec sql begin declare section;
开始,以:
exec sql end declare section;
结束。此节内只允许变量声明。此节内声明的每个变量都按名称索引连同其对应类型存储在一个变量列表中。
特别是结构或联合的定义也必须列在
declare区内。否则 ecpg 无法处理这些类型,因为它不知道定义。声明也会被回显到文件中,使其成为普通的 C 变量。
特殊类型
VARCHAR和VARCHAR2会为每个变量转换成一个命名的结构。像这样的声明:VARCHAR var[180];
会被转换为:
struct varchar_var { int len; char arr[180]; } var;- 包含语句
include 语句的形式是:
exec sql include filename;
注意这不同于:
#include <filename.h>
Instead the file specified is parsed by ecpg so the contents of the file are included in the resulting C code. This way you are able to specify EXEC SQL commands in an include file.
- 连接语句
connect 语句的形式是:
exec sql connect to
connection target;它创建到指定数据库的一个连接。
connection target可以用下列方式指定:-
dbname[@server][:port][asconnection name][useruser name] -
tcp:postgresql://server[:port][/dbname][asconnection name][useruser name] -
unix:postgresql://server[:port][/dbname][asconnection name][useruser name] -
character variable[asconnection name][useruser name] -
character string[asconnection name][user] -
default -
user
还有几种指定用户名的方式:
-
userid -
userid/password -
userididentified bypassword -
useridusingpassword
最后,
userid和password可以是常量文本、字符变量或字符串。-
- 断开语句
disconnect 语句的形式是:
exec sql disconnect [
connection target];它关闭到指定数据库的连接。
connection target可以用下列方式指定:-
connection name -
default -
current -
all
-
- 打开游标语句
open cursor 语句的形式是:
exec sql open
cursor;并且不被复制到输出中。相反,会使用游标的
DECLARE命令,因为它也会打开游标。- 提交语句
commit 语句的形式是:
exec sql commit;
- 回滚语句
rollback 语句的形式是:
exec sql rollback;
- 其他语句
其他 SQL 语句以
exec sql开始、以;结束的方式使用。中间的一切都被当作 SQL 语句并解析变量替换。当符号以冒号(
:)开头时发生变量替换。此时会在先前于declare节中声明的变量里查找具有该名字的变量。根据该变量用于输入还是输出,指向该变量的指针会被写到输出中以允许函数访问。对于作为 SQL 查询一部分的每个变量,函数会得到其他参数:
The type as a special symbol.
指向值的指针,或指向指针的指针。
如果变量是
char或varchar,则为变量的大小。数组中的元素个数(用于数组抓取)。
到数组中下一个元素的偏移(用于数组抓取)。
作为特殊符号的指示符变量的类型。
指向指示符变量值的指针,或指向指示符变量指针的指针。
0.
指示符数组中的元素个数(用于数组抓取)。
到指示符数组中下一个元素的偏移(用于数组抓取)。
6.6.2. 一个完整的例子
下面是一个完整的例子,描述预处理器对文件
foo.pgc 的输出:
exec sql begin declare section; int index; int result; exec sql end declare section; ... exec sql select res into :result from mytable where index = :index;
is translated into:
/* Processed by ecpg (2.6.0) */
/* These two include files are added by the preprocessor */
#include <ecpgtype.h>;
#include <ecpglib.h>;
/* exec sql begin declare section */
#line 1 "foo.pgc"
int index;
int result;
/* exec sql end declare section */
...
ECPGdo(__LINE__, NULL, "select res from mytable where index = ? ",
ECPGt_int,&(index),1L,1L,sizeof(int),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
ECPGt_int,&(result),1L,1L,sizeof(int),
ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
#line 147 "foo.pgc"(The indentation in this manual is added for readability and not something the preprocessor does.)
6.6.3. 库
库中最重要的函数是
ECPGdo。它接受数量可变的参数。但愿没有计算机会限制
varargs() 函数可接受的变量数。这很容易累积到
50 个左右的参数。
参数有:
- A line number
这是原语句的行号;只用于错误消息。
- A string
这是要发出的 SQL 查询。它被输入变量修改,即那些编译时未知但要输入查询的变量。在变量应出现的位置,字符串中包含
?。- 输入变量
如关于预处理器的一节所述,每个输入变量得到十个参数。
ECPGt_EOIT一个枚举,表示不再有输入变量。
- 输出变量
如关于预处理器的一节所述,每个输入变量得到十个参数。These variables are filled by the function.
- ECPGt_EORT
一个枚举,表示不再有变量。
在默认模式下,只有在发出 exec
sql commit 时查询才被提交。Ecpg
还通过
-t 命令行选项或 exec
sql set autocommit to on 语句支持事务的自动提交。在
autocommit 模式下,除非处于显式的事务块中,每条查询都会自动提交。这个模式可以用 exec sql set
autocommit to off 显式关闭。