您的位置:寻梦网首页编程乐园数据库PostgreSQL 7.2 Documentation

6.6. 寄语开发者

本节解释 ecpg 内部是如何工作的. 这里描述了这些接口是怎样工作的. 它包含帮助用户理解如何使用 ecpg 的宝贵信息.

6.6.1. 预编译器

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

  • userid / password

  • userid identified by password

  • userid using password

最后的 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 请求里的每个变量,函数都得到其它一些参数:

  • 作为特殊符号的类型。

  • 指向数值的指针或指针的指针。

  • 如果变量是 varchar 或者 char 变量的尺寸。

  • 数组里的元素个数(对数组抓取)。

  • 数组里下一个元素的偏移量(对数组抓取)

  • 做为特殊符号的标识器变量的类型。

  • 一个指向标识器变量值或者标识器变量指针的指针。

  • 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;

被解释成:

/* 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"

(本手册里的缩进是为可读性追加的,可不是预编译器干的.)

6.6.3. 库

在库里面最重要的函数是 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 明确地关闭.