ecpg
写到输出的头四行是固定的内容.
两行是注释以及两行与库进行接口所必须的包含行.
然后预编译器一边读输入文件,一边输出到输出文件.
通常它只是把不加分析的把所有东西输出到输出文件里去.
当处理到
EXEC SQL
语句时,预编译器对之进行处理并修改它.
EXEC SQL
语句可以是下列之一:
-
声明段
-
Declare
段以
exec sql begin declare section;
开头,以
exec sql end declare section;
结束.在这个段里只允许变量声明.这个段里定义的每个变量同时也
放到一个以变量名和对应类型为索引的变量列表里头.
尤其是结构(struct)或者联合(union)的定义同样必须在
declare
段里面列出。
否则
ecpg
就不能处理这些类型,
因为它不知道声明(是什么)。
声明同时也输出到文件里把这些变量作为通常的 C-变量.
特殊的类型
VARCHAR
和
VARCHAR2
的每个变量都被转换成一个命名结构.
一个下面这样的定义:
VARCHAR var[180];
被转换成∶
struct varchar_var { int len; char arr[180]; } var;
-
包含语句
-
一个包含语句看起来象:
exec sql include filename;
注意这个与下面这行∶
#include <filename.h>
是不一样的。被包含的文件由
ecpg
本身分析。因此声明的头文件被包括在生成的 C 代码里。
这样你也能够在一个头文件里声明 EXEC SQL 语句。
-
联接语句
-
一个联接语句看起来象:
exec sql connect to
connection target
;
它创建与指定数据库的联接。
connection target
(联接目标)可以用下面的方法声明:
-
dbname[@server][:port][as
connection
name
][user
user name
]
-
tcp:postgresql://server[:port][/dbname][as
connection name
][user
user name
]
-
unix:postgresql://server[:port][/dbname][as
connection name
][user
user name
]
-
character variable
[as
connection name
][user
user name
]
-
character string
[as
connection name
][
user
]
-
default
-
user
也有不同的方法声明用户名:
最后的
userid
和
password
可以是一个文本常量,一个字符变量或者一个字符串。
-
断开语句
-
一个断开语句看起来象:
exec sql disconnect [
connection target
];
它关闭与指定数据库的联接。
connection target
可以用下面方法声明:
-
connection name
-
default
-
current
-
all
-
打开游标语句
-
一个打开游标语句看起来象:
exec sql open
cursor
;
它不会被拷贝到输出文件.
而实际上使用了游标的
DECLARE
命令,因为它同时也打开了
游标.
-
提交语句
-
一个提交语句看起来象∶
exec sql commit;
-
回卷语句
-
一个回卷语句看起来象∶
exec sql rollback;
-
其他语句
-
其他
SQL
语句是通过以
exec sql
开头并且以
;
结尾来使用的.所有两者之间的东西都被认为是一个
SQL
语句并做变量替换分析.
当一个符号以冒号(
:
)开头时,就会发生变量替换.
分析器会到前面
declare
段里
声明的变量列表里找出该名称的变量,
然后根据该变量是用于输入还是输出,
把指向该变量的指针写到输出里供函数访问使用.
对
SQL
请求里的每个变量,函数都得到其它一些参数:
下面是一个完整的描述预编译器对文件
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;
被解释成:
/* 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"
(本手册里的缩进是为可读性追加的,可不是预编译器干的.)
在库里面最重要的函数是
ECPGdo
函数.它有可变的参数.
希望我们不会碰到那些对变参数个数的函数的参数个数有限制的机器.
这些参数个数很容易多达 50 个.
这些参数是:
-
一个行号
-
这是原始出错行的行号;只用于错误信息.
-
一个字符串
-
这是声明的
SQL
请求。它被输入变量修改,
也就是说用那些编译时未知但要输入到请求里的变量.
这时变量应该包含
?
放到字符串里.
-
输入变量
-
象预编译器节里描述的那样,每个输入变量换成十个参数.
-
ECPGt_EOIT
-
一个 enum (枚举)表明输入变量(列表)的结尾.
没有更多需要输入的变量了.
-
Output variables
-
象预编译器节里描述的那样,每个输出变量换成十个参数.
这些变量由函数填充.
-
ECPGt_EORT
-
一个 enum (枚举)表明变量(列表)的结尾.
在缺省模式下,查询只有在发出
exec sql commit
的时候才提交.
Ecpg
也支持通过
-t
命令行选项或者通过
exec sql set autocommit to on
语句实现的事务的
自动提交特性.在
autocommit
(自动提交)模式下,
每个查询都会被自动提交,除非它包含在一个明确的事务块内部.
这个模式可以用
exec sql set autocommit to off
明确地关闭.