pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。
本节面向想要开发 ecpg 接口的人。它 描述各部分如何工作。这里的定位是让本节 包含给想深入了解的人的内容,而 如何使用一节应该足以回答所有 常规问题。 所以,在研究 ecpg 的内部 之前先读这一节。如果你 对它究竟如何工作不感兴趣,请跳过本节。
这个版本的预处理器有一些缺陷:
ecpg 所使用的 PQ 接口(尤其是 PQexec 函数)依赖 请求是以字符串形式构建的。在某些 情况下,比如数据中包含空字符时,这会是 一个严重的问题。
不同的错误应当有不同的错误编号, 而不是全都用 -1。
to_date et al.
记录或结构必须在 declare 区中定义。
下列语句迄今尚未实现:
exec sql insert select from 语句中"no data"的 错误消息应该是 100。
如果 SET DESCRIPTOR 语句中指定的 PRECISION 或 SCALE 值将被忽略,sqlwarn[6] 应为 'W'。
建立数据库需要一些包含表定义和 其他配置参数的脚本。如果你有一套旧 数据库的这些脚本,你会希望直接应用它们得到一个以 相同方式工作的 Postgres 数据库。
这种功能可以用一些转换脚本来实现, 但速度永远无法以这种方式达成。要做到这一点,你需要 对数据库的构造和使用有比 脚本所能实现的更深入的 理解。
写入输出的前四行是:两行注释和两行与库接口 所必需的 包含行。
随后预处理器只单遍工作,边读输入文件 边写输出。通常它只是 把所有内容原样回显到输出而不再细看。
当遇到 EXEC SQL 语句时,它会介入并 根据其类型 进行改写。EXEC SQL 语句 可以是下列之一:
声明节以
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;
在输出中被翻译为
ECPGrollback(__LINE__);
其他 SQL 语句是其他以 exec sql 开始、以 ; 结束的 语句。中间的一切 都被当作 SQL 语句并解析变量替换。
当符号以冒号 (:)开头时发生变量替换。此时会在先前 于声明节中声明的变量里找到具有该名字的变量,并且根据 SQL 语句是否把它当作输入或 输出变量,把指向 变量的指针写入输出以允许函数 访问。
对于 SQL 请求中的每个变量, 函数都会得到另外五个参数:
| 以特殊符号表示的类型 |
| 指向值的指针 |
| 变量的大小(如果是 varchar) |
| 数组中的元素个数(用于数组抓取) |
| 到数组中下一个元素的偏移量(用于数组抓取) |
由于数组抓取尚未实现,最后两个参数 其实并不重要。它们或许本可以省略。
下面是一个完整的例子,描述预处理器的输出:
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 );
(本手册中的缩进是为了可读性而加的,并不是 预处理器能做的。)
库中最重要的函数是 ECPGdo 函数。它接受数量可变的参数。但愿我们不会碰到 对 varchar 函数可接受的变量数量有 限制的机器。这很容易累积到 50 个左右的 参数。
参数有:
这是原语句的行号,只用于错误消息。
这是要发出的 SQL 请求。该请求被输入 变量修改,即那些编译时未知但要输入 请求的变量。在变量应出现的 位置,字符串中包含 “;”。
如关于预处理器的 一节所述,每个输入变量 得到五个参数。
一个枚举,表示不再有输入变量。
如关于预处理器的 一节所述,每个输出变量 得到五个参数。这些变量由函数填充。
一个枚举,表示不再有变量。
所有 SQL 语句都在一个事务中执行, 除非你发出 提交事务。其机制是第一条事务或 提交/回滚之后的第一条语句总是会开始一个事务。
待完成:描述其他条目的条目。
译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。