↑↓ 选择 ↵ 打开 ⌫ 改范围 完整检索页

pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。

不受支持的版本: 6.3
历史版本PostgreSQL 6.3 已于 2003 年 3 月结束社区维护,本页译文保留供仍在使用旧版本的读者参考。新系统请看当前版本手册首页。

44.7. 给开发者

本节面向想要开发 ecpg 接口的人。它 描述各部分如何工作。这里的定位是让本节 包含给想深入了解的人的内容,而 如何使用一节应该足以回答所有 常规问题。 所以,在研究 ecpg 的内部之前先读这一节。如果你 对它究竟如何工作不感兴趣,请跳过本节。

44.7.1. 待办列表

这个版本的预处理器有一些缺陷:

预处理器输出

这些变量应该是 static 的。

预处理器无法对你的 SQL 语句做语法检查

你写的任何内容都会几乎原样复制给 Postgres,直到运行时你才能定位 错误。

并非只限于字符串

ecpg 所使用的 PQ 接口(尤其是 PQexec 函数)依赖 请求是以字符串形式构建的。在某些 情况下,比如数据中包含空字符时,这会是 一个严重的问题。

错误码

不同的错误应当有不同的错误编号, 而不是全都用 -1。

库函数

to_date et al.

records

希望能够在 declare 区中以某种方式定义记录或 结构,使该记录可以从数据库中的一行来填充。

这是一种每次处理整行的更简单方式。

数组操作

Oracle 有能提升速度的数组操作。 在 ecpg 中实现它只是出于 兼容性原因。要让它们提升 速度,需要对 Postgres 内部 机制比我更深入的理解。

指示符变量

Oracle 有指示符变量,用来说明一个值是 null 还是 空。这大大简化了数组操作,并提供了一种绕过 VARCHAR2 处理中某些设计缺陷的方法 (比如空字符串无法与 null 值区分)。我不确定这是 Oracle 的扩展还是 ANSI 标准的一部分。

typedefs

除了记录和数组这样的复杂类型外,typedef 也 值得处理。

脚本转换

建立数据库需要一些包含表定义和 其他配置参数的脚本。如果你有一套旧 数据库的这些脚本,你会希望直接应用它们得到一个以 相同方式工作的 Postgres 数据库。

这种功能可以用一些转换脚本来实现, 但速度永远无法以这种方式达成。要做到这一点,你需要 对数据库的构造和使用有比 脚本所能实现的更深入的 理解。

44.7.2. 预处理器

前四行被写入输出。两行注释和两行与库接口所必需的 include 行。

然后预处理器单遍工作,边读输入文件边 向输出写入。通常它只是把所有内容 原样回显到输出,不做进一步检查。

当遇到 EXEC SQL 语句时,它会介入并根据 其种类改变它们。EXEC SQL 语句可以是 下列之一:

Declare sections

声明节以

exec sql begin declare section;

开始,以

exec sql end declare section;

结束。此节内只允许变量声明。此节内 声明的每个变量也按名称索引连同其对应 类型登记到一个变量列表中。

声明也会被回显到文件中,使该变量同时成为 普通的 C 变量。

特殊类型 VARCHAR 和 VARCHAR2 会为每个变量 转换成一个命名的结构。像这样的声明:

VARCHAR var[180];

会被转换为

struct varchar_var { int len; char arr[180]; } var;
包含语句

include 语句的形式是:

exec sql include filename;

它被转换成

#include <filename.h>
连接语句

connect 语句的形式是:

exec sql connect 'database';

该语句被转换成

ECPGconnect("database");
打开游标语句

open cursor 语句的形式是:

exec sql open cursor;

它被忽略,不复制到输出中。

提交语句

commit 语句的形式是

exec sql commit;

在输出中被翻译为

ECPGcommit(__LINE__);
回滚语句

rollback 语句的形式是

exec sql rollback;

and is translated on the output to

ECPGrollback(__LINE__);
其他语句

其他 SQL 语句是其他以 exec sql 开始、以 ; 结束的 语句。中间的一切都被当作 SQL 语句并解析变量替换。

当符号以冒号(:)开头时发生 变量替换。此时会在先前在 declare 区中声明的变量里查找具有该名称的变量,并根据 SQL 语句是否知道它是用于输入还是 输出的变量,把指向这些变量的指针写到输出中, 供该函数访问。

对于作为 SQL 请求一部分的每个变量,函数还会 得到另外五个参数。

作为特殊符号的类型
指向值的指针
如果变量是 varchar 则为变量的大小
数组中的元素个数(用于数组抓取)
到数组中下一个元素的偏移(用于数组抓取)

由于数组抓取尚未实现,最后两个 参数其实并不重要。也许本可以把它们 省去。

44.7.3. 一个完整的例子

下面是一个完整的例子,描述预处理器的输出:

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;

被翻译成:

/* These two include files are added by the preprocessor */
#include <ecpgtype.h>
#include <ecpglib.h>
/* exec sql begin declare section */

 int index;
 int result;
/* exec sql end declare section */

...
    ECPGdo(__LINE__, "select res from mytable where index = ;;", 
           ECPGt_int,&index,0,0,sizeof(int), 
           ECPGt_EOIT, 
           ECPGt_int,&result,0,0,sizeof(int), 
           ECPGt_EORT );

(the indentation in this manual is added for readability and not something that the preprocessor can do.)

44.7.4. 库

库中最重要的函数是 ECPGdo 函数。它接受数量可变的参数。希望我们不会遇到 对 varchar 函数可接受的变量数量 有限制的机器。参数很容易累计到 50 个 左右。

参数有:

一个行号

这是原语句的行号,只用于错误消息。

A string

这是要发出的 SQL 请求。该请求被输入 变量修改,即那些编译时未知但要输入 请求的变量。在变量应出现的 位置,字符串中包含 “;”。

输入变量

如关于预处理器的 一节所述,每个输入变量 得到五个参数。

ECPGt_EOIT

一个枚举,表示不再有输入变量。

输出变量

如关于预处理器的 一节所述,每个输入变量 得到五个参数。 These variables are filled by the function.

ECPGt_EORT

一个枚举,表示不再有变量。

除非你发出提交事务命令,所有 SQL 语句都在一个事务中执行。 其工作方式是:第一个事务,或提交/回滚之后的 第一个事务,总是开始一个新事务。

待完成:描述其余条目的条目。

提交更正

译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。