PostgreSQL 中文参考文档
🌐 英文原版 官方 ↗

34.9. 预处理器指令 #

34.9.1. Including Files
34.9.2. define 与 undef 指令
34.9.3. ifdef、ifndef、elif、else 与 endif 指令

有多个预处理器指令可用于修改 ecpg 预处理器解析和处理 文件的方式。

34.9.1. Including Files #

要把一个外部文件包含到你的嵌入式 SQL 程序中,使用:

EXEC SQL INCLUDE filename;
EXEC SQL INCLUDE <filename>;
EXEC SQL INCLUDE "filename";

嵌入式 SQL 预处理器会查找名为 filename.h 的文件,对它进行预处理,并将它包含到生成的 C 输出中。这样, 被包含文件中的嵌入式 SQL 语句就能得到正确的处理。

ecpg 预处理器会按以下顺序在多个目录中搜索文件:

  • 当前目录
  • /usr/local/include
  • PostgreSQL include 目录,在构建时定义(例如 /usr/local/pgsql/include)
  • /usr/include

但当使用 EXEC SQL INCLUDE "filename" 时,只会搜索 当前目录。

在每个目录中,预处理器首先按给定的文件名查找,如果未找到, 则会在文件名后追加 .h 再试一次(除非指定的 文件名已经带有该后缀)。

注意,EXEC SQL INCLUDE 不等同于:

#include <filename.h>

因为这样的文件不会经过 SQL 命令预处理。当然,你仍然可以继续使用 C 的 #include 指令来包含其他头文件。

Note

包含文件名是区分大小写的,即便 EXEC SQL INCLUDE 命令的其余部分遵循普通的 SQL 大小写规则。

34.9.2. define 与 undef 指令 #

与 C 语言中熟知的 #define 指令类似, 嵌入式 SQL 也有一个类似的概念:

EXEC SQL DEFINE name;
EXEC SQL DEFINE name value;

这样你就可以定义一个名字:

EXEC SQL DEFINE HAVE_FEATURE;

你也可以定义常量:

EXEC SQL DEFINE MYNUMBER 12;
EXEC SQL DEFINE MYSTRING 'abc';

使用 undef 移除先前的定义:

EXEC SQL UNDEF MYNUMBER;

当然,你可以在嵌入式 SQL 程序中继续使用 C 版本的 #define 和 #undef。区别在于 你定义的值在哪里被求值。如果你使用 EXEC SQL DEFINE,那么 ecpg 预处理器会对这些 定义进行求值并替换相应的值。例如,如果你写:

EXEC SQL DEFINE MYNUMBER 12;
...
EXEC SQL UPDATE Tbl SET col = MYNUMBER;

那么 ecpg 会预先完成替换,你的 C 编译器将永远 看不到任何名为 MYNUMBER 的名字或标识符。注意, 对于将要在嵌入式 SQL 查询中使用的常量,你不能使用 #define 来定义,因为在这种情况下,嵌入式 SQL 预编译器无法看到这个声明。

如果在 ecpg 预处理器的命令行上指定了多个输入 文件,EXEC SQL DEFINE 和 EXEC SQL UNDEF 的效果不会跨文件传递:每个文件 开头只有由命令行上 -D 开关定义的符号。

34.9.3. ifdef、ifndef、elif、else 与 endif 指令 #

你可以使用以下指令有条件地编译代码段:

EXEC SQL ifdef name; #

检查一个 name,如果该 name 已通过 EXEC SQL define name 定义,则处理后续的行。

EXEC SQL ifndef name; #

检查一个 name,如果该 name 尚未通过 EXEC SQL define name 定义,则处理后续的行。

EXEC SQL elif name; #

在 EXEC SQL ifdef name 或 EXEC SQL ifndef name 指令之后开始一个可选的备选段。elif 段可以出现任意多次。如果 name 已被定义并且同一个 ifdef/ifndef...endif 构造中此前的段都没有被处理过,则 elif 之后的行会被处理。

EXEC SQL else; #

在 EXEC SQL ifdef name 或 EXEC SQL ifndef name 指令之后开始一个可选的、最后的备选段。如果同一个 ifdef/ifndef...endif 构造中此前的段都没有被处理过,则后续的行会被处理。

EXEC SQL endif; #

结束一个 ifdef/ifndef...endif 构造。后续的行将被正常处理。

ifdef/ifndef...endif 构造可以嵌套,最深可达 127 层。

这个示例将恰好编译三条 SET TIMEZONE 命令中的一条:

EXEC SQL ifdef TZVAR;
EXEC SQL SET TIMEZONE TO TZVAR;
EXEC SQL elif TZNAME;
EXEC SQL SET TIMEZONE TO TZNAME;
EXEC SQL else;
EXEC SQL SET TIMEZONE TO 'GMT';
EXEC SQL endif;