37.9. Директивы препроцессора

Препроцессор ecpg поддерживает ряд директив, которые позволяют управлять разбором и обработкой исходных файлов.

37.9.1. Включение файлов

Для включения внешнего файла в программу со встраиваемым SQL, используется конструкция:

EXEC SQL INCLUDE имя_файла;
EXEC SQL INCLUDE <имя_файла>;
EXEC SQL INCLUDE "имя_файла";

Встретив такую директиву, препроцессор встраиваемого SQL будет искать файл имя_файла.h, обрабатывать его и включать в выходной код C. В результате встраиваемые SQL-операторы во включённом таким образом файле будут обработаны корректно.

Препроцессор ecpg будет искать указанный файл в нескольких каталогах в следующем порядке:

  • текущий каталог
  • /usr/local/include
  • каталог включаемых файлов Postgres Pro, определённый во время сборки (например, /usr/local/pgsql/include)
  • /usr/include

Но когда используется форма EXEC SQL INCLUDE "имя_файла", просматривается только текущий каталог.

В каждом каталоге препроцессор будет сначала искать файл с заданным именем, а если не обнаружит его, попытается найти файл с добавленным расширением .h (если только заданное имя файла уже не содержит это расширение).

Заметьте, что команда EXEC SQL INCLUDE не равнозначна включению:

#include <имя_файла.h>

так как во втором случае включаемый файл не проходит через препроцессор SQL-команд. Естественно, директиву C #include можно по-прежнему применять для включения других заголовочных файлов.

Примечание

Имя включаемого файла чувствительно к регистру, несмотря на то, что остальная команда EXEC SQL INCLUDE подчиняется обычным правилам чувствительности к регистру SQL.

37.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 не сможет увидеть это определение.

37.9.3. Директивы ifdef, ifndef, elif, else и endif

Для условной компиляции блоков кода можно использовать следующие указания:

EXEC SQL ifdef имя;

Проверяет имя и обрабатывает последующие строки, если имя было определено командой EXEC SQL define имя.

EXEC SQL ifndef имя;

Проверяет имя и обрабатывает последующие строки, если имя не было определено командой EXEC SQL define имя.

EXEC SQL elif имя;

Начинает необязательный альтернативный блок после указания EXEC SQL ifdef имя или EXEC SQL ifndef имя. Количество блоков elif может быть любым. Строки, следующие за elif, будут обрабатываться, если имя определено и при этом не был обработан ни один из блоков той же конструкции ifdef/ifndef...endif.

EXEC SQL else;

Начинает необязательный заключительный блок после указания EXEC SQL ifdef имя или EXEC SQL ifndef имя. Последующие строки будут обрабатываться, если не был обработан ни один из блоков той же конструкции 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;