36.9. Директивы препроцессора
Препроцессор ecpg поддерживает ряд директив, которые позволяют управлять разбором и обработкой исходных файлов.
36.9.1. Включение файлов
Для включения внешнего файла в программу со встраиваемым SQL, используется конструкция:
EXEC SQL INCLUDEимя_файла; EXEC SQL INCLUDE <имя_файла>; EXEC SQL INCLUDE "имя_файла";
Встретив такую директиву, препроцессор встраиваемого SQL будет искать файл , обрабатывать его и включать в выходной код C. В результате встраиваемые SQL-операторы во включённом таким образом файле будут обработаны корректно.имя_файла.h
Препроцессор ecpg будет искать указанный файл в нескольких каталогах в следующем порядке:
- текущий каталог
/usr/local/include- каталог включаемых файлов PostgreSQL, определённый во время сборки (например,
/usr/local/pgsql/include) /usr/include
Но когда используется форма EXEC SQL INCLUDE ", просматривается только текущий каталог.имя_файла"
В каждом каталоге препроцессор будет сначала искать файл с заданным именем, а если не обнаружит его, попытается найти файл с добавленным расширением .h (если только заданное имя файла уже не содержит это расширение).
Заметьте, что команда EXEC SQL INCLUDE не равнозначна включению:
#include <имя_файла.h> так как во втором случае включаемый файл не проходит через препроцессор SQL-команд. Естественно, директиву C #include можно по-прежнему применять для включения других заголовочных файлов.
Примечание
Имя включаемого файла чувствительно к регистру, несмотря на то, что остальная команда EXEC SQL INCLUDE подчиняется обычным правилам чувствительности к регистру SQL.
36.9.2. Директивы define и undef
Во встраиваемом SQL есть конструкция, подобная директиве #define, известной в C:
EXEC SQL DEFINEимя; EXEC SQL DEFINEимязначение;
Используя её, можно определить имя:
EXEC SQL DEFINE HAVE_FEATURE;
И также можно определить константы:
EXEC SQL DEFINE MYNUMBER 12; EXEC SQL DEFINE MYSTRING 'abc';
Удалить предыдущее определение позволяет команда undef:
EXEC SQL UNDEF MYNUMBER;
Разумеется, в программе со встраиваемым SQL можно продолжать использовать версии #define и #undef языка C. Отличие состоит в том, когда вычисляются определяемые значения. Когда применяется команда EXEC SQL DEFINE, вычислять определения и подставлять значения будет препроцессор ecpg. Например, если написать:
EXEC SQL DEFINE MYNUMBER 12; ... EXEC SQL UPDATE Tbl SET col = MYNUMBER;
подстановку выполнит ecpg и компилятор C никогда не увидит имени или идентификатора MYNUMBER. Заметьте, что с другой стороны #define не подходит для определения константы, которую вы хотите использовать во встраиваемом SQL, так как препроцессор встраиваемого SQL не сможет увидеть это определение.
36.9.3. Директивы ifdef, ifndef, else, elif и endif
Для условной компиляции блоков кода можно использовать следующие указания:
EXEC SQL ifdefимя;Проверяет
имяи обрабатывает последующие строки, еслиимябыло определено командойEXEC SQL define.имяEXEC SQL ifndefимя;Проверяет
имяи обрабатывает последующие строки, еслиимяне было определено командойEXEC SQL define.имяEXEC SQL else;Начинает альтернативную ветвь условия, открытого командой
EXEC SQL ifdefилиимяEXEC SQL ifndef.имяEXEC SQL elifимя;Проверяет
имяи начинает альтернативную ветвь условия, еслиимябыло определено командойEXEC SQL define.имяEXEC SQL endif;Завершает ветвь условия.
Пример:
EXEC SQL ifndef TZVAR; EXEC SQL SET TIMEZONE TO 'GMT'; EXEC SQL elif TZNAME; EXEC SQL SET TIMEZONE TO TZNAME; EXEC SQL else; EXEC SQL SET TIMEZONE TO TZVAR; EXEC SQL endif;
36.9. Preprocessor Directives
Several preprocessor directives are available that modify how the ecpg preprocessor parses and processes a file.
36.9.1. Including Files
To include an external file into your embedded SQL program, use:
EXEC SQL INCLUDEfilename; EXEC SQL INCLUDE <filename>; EXEC SQL INCLUDE "filename";
The embedded SQL preprocessor will look for a file named , preprocess it, and include it in the resulting C output. Thus, embedded SQL statements in the included file are handled correctly. filename.h
The ecpg preprocessor will search a file at several directories in following order:
- current directory
/usr/local/include- PostgreSQL include directory, defined at build time (e.g.,
/usr/local/pgsql/include) /usr/include
But when EXEC SQL INCLUDE " is used, only the current directory is searched. filename"
In each directory, the preprocessor will first look for the file name as given, and if not found will append .h to the file name and try again (unless the specified file name already has that suffix).
Note that EXEC SQL INCLUDE is not the same as:
#include <filename.h>
because this file would not be subject to SQL command preprocessing. Naturally, you can continue to use the C #include directive to include other header files.
Note
The include file name is case-sensitive, even though the rest of the EXEC SQL INCLUDE command follows the normal SQL case-sensitivity rules.
36.9.2. The define and undef Directives
Similar to the directive #define that is known from C, embedded SQL has a similar concept:
EXEC SQL DEFINEname; EXEC SQL DEFINEnamevalue;
So you can define a name:
EXEC SQL DEFINE HAVE_FEATURE;
And you can also define constants:
EXEC SQL DEFINE MYNUMBER 12; EXEC SQL DEFINE MYSTRING 'abc';
Use undef to remove a previous definition:
EXEC SQL UNDEF MYNUMBER;
Of course you can continue to use the C versions #define and #undef in your embedded SQL program. The difference is where your defined values get evaluated. If you use EXEC SQL DEFINE then the ecpg preprocessor evaluates the defines and substitutes the values. For example if you write:
EXEC SQL DEFINE MYNUMBER 12; ... EXEC SQL UPDATE Tbl SET col = MYNUMBER;
then ecpg will already do the substitution and your C compiler will never see any name or identifier MYNUMBER. Note that you cannot use #define for a constant that you are going to use in an embedded SQL query because in this case the embedded SQL precompiler is not able to see this declaration.
36.9.3. ifdef, ifndef, else, elif, and endif Directives
You can use the following directives to compile code sections conditionally:
EXEC SQL ifdefname;Checks a
nameand processes subsequent lines ifnamehas been created withEXEC SQL define.nameEXEC SQL ifndefname;Checks a
nameand processes subsequent lines ifnamehas not been created withEXEC SQL define.nameEXEC SQL else;Starts processing an alternative section to a section introduced by either
EXEC SQL ifdefornameEXEC SQL ifndef.nameEXEC SQL elifname;Checks
nameand starts an alternative section ifnamehas been created withEXEC SQL define.nameEXEC SQL endif;Ends an alternative section.
Example:
EXEC SQL ifndef TZVAR; EXEC SQL SET TIMEZONE TO 'GMT'; EXEC SQL elif TZNAME; EXEC SQL SET TIMEZONE TO TZNAME; EXEC SQL else; EXEC SQL SET TIMEZONE TO TZVAR; EXEC SQL endif;