36.17. Внутреннее устройство #

В этом разделе рассказывается, как препроцессор ECPG устроен внутри. Эта информация может оказаться полезной для пользователей, желающих понять, как использовать ECPG.

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

Встречая команду EXEC SQL, он вмешивается и изменяет её. Данная команда начинается со слов EXEC SQL и заканчивается знаком ;. Всё между ними воспринимается как оператор SQL и разбирается для подстановки переменных.

Подстановка переменных имеет место, когда символ начинается с двоеточия (:). ECPG будет искать переменную с таким именем среди переменных, ранее объявленных в секции EXEC SQL DECLARE.

Самая важная функция в библиотеке — ECPGdo, которая осуществляет выполнение большинства команд. Она принимает переменное число аргументов (это число легко может достигать 50, и мы надеемся, что это не приведёт к проблемам ни на какой платформе).

Ей передаются следующие аргументы:

Номер строки #

Номер исходной строки; используется только в сообщениях об ошибках.

Строка #

Команда SQL, которая должна быть выполнена. На её содержимое влияют входные переменные, то есть переменные, добавленные в команду, но неизвестные во время компиляции. Места, в которые должны вставляться переменные, обозначаются знаками ?.

Входные переменные #

Для каждой входной переменной формируются десять аргументов. (См. ниже.)

ECPGt_EOIT #

Перечисление (enum), показывающее, что больше входных переменных нет.

Выходные переменные #

Для каждой входной переменной формируются десять аргументов. (См. ниже.) Эти переменные заполняются данной функцией.

ECPGt_EORT #

Перечисление (enum), показывающее, что больше выходных переменных нет.

Для каждой переменной, включённой в команду SQL, эта функция принимает десять аргументов:

  1. Тип в виде специального символа.

  2. Указатель на значение или указатель на указатель.

  3. Размер переменной, если она имеет тип char или varchar.

  4. Число элементов в массиве (при выборке данных в массив).

  5. Смещение следующего элемента в массиве (при выборке данных в массив).

  6. Тип переменной-индикатора в виде специального символа.

  7. Указатель на переменную-индикатор.

  8. 0

  9. Число элементов в массиве индикаторов (при выборке данных в массив).

  10. Смещение следующего элемента в массиве индикаторов (при выборке данных в массив).

Заметьте, что не все команды SQL обрабатываются таким образом. Например, команда открытия курсора вида:

EXEC SQL OPEN курсор;

не копируется в вывод. Вместо этого в позиции команды OPEN применяется команда DECLARE этого курсора, так как на самом деле курсор открывает она.

Ниже показан полный пример, демонстрирующий результат обработки препроцессором файла foo.pgc (детали могут меняться от версии к версии препроцессора):

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;

преобразуется в:

/* Processed by ecpg (2.6.0) */
/* These two include files are added by the preprocessor */
#include <ecpgtype.h>;
#include <ecpglib.h>;

/* exec sql begin declare section */

#line 1 "foo.pgc"

 int index;
 int result;
/* exec sql end declare section */
...
ECPGdo(__LINE__, NULL, "SELECT res FROM mytable WHERE index = ?     ",
        ECPGt_int,&(index),1L,1L,sizeof(int),
        ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EOIT,
        ECPGt_int,&(result),1L,1L,sizeof(int),
        ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT);
#line 147 "foo.pgc"

(Отступы здесь добавлены для читаемости, препроцессор их не вставляет.)