XSQLVAR::sqltype и XSQLVAR::sqlind

Привет всем.

В ISC API, для представления описаний и значений колонок (параметров запроса), определена структура XSQLVAR.

typedef struct
{
 ISC_SHORT  sqltype;          /* datatype of field */
 ISC_SHORT  sqlscale;         /* scale factor */
 ISC_SHORT  sqlsubtype;       /* datatype subtype - currently BLOBs only */
 ISC_SHORT  sqllen;           /* length of data area */
 ISC_SCHAR* sqldata;          /* address of data */
 ISC_SHORT* sqlind;           /* address of indicator variable */
 ISC_SHORT  sqlname_length;   /* length of sqlname field */
 ISC_SCHAR  sqlname[32];      /* name of field, name length + space for NULL */
 ISC_SHORT  relname_length;   /* length of relation name */
 ISC_SCHAR  relname[32];      /* field's relation name + space for NULL */
 ISC_SHORT  ownname_length;   /* length of owner name */
 ISC_SCHAR  ownname[32];      /* relation's owner name + space for NULL */
 ISC_SHORT  aliasname_length; /* length of alias name */
 ISC_SCHAR  aliasname[32];    /* relation's alias name + space for NULL */
} XSQLVAR; 

Идентификатор типа указывается в поле XSQLVAR::sqltype и в случае NOT NULL колонки представляет собой четное число. Для Firebird 2.5 определен следующий набор идентификаторов типов данных:

#define SQL_TEXT         452
#define SQL_VARYING      448
#define SQL_SHORT        500
#define SQL_LONG         496
#define SQL_FLOAT        482
#define SQL_DOUBLE       480
#define SQL_D_FLOAT      530
#define SQL_TIMESTAMP    510
#define SQL_BLOB         520
#define SQL_ARRAY        540
#define SQL_QUAD         550
#define SQL_TYPE_TIME    560
#define SQL_TYPE_DATE    570
#define SQL_INT64        580
#define SQL_NULL       32766

В случае колонок, которые могут принимать значение NULL, к идентификатору типа данных добавляется единица.

Само значение индикатора NULL-состояние доступно по указателю XSQLVAR::sqlind. Минус один (-1) для NULL и ноль (0) для NOT NULL состояния.

Если идентификатор типа (XSQLVAR::sqltype) описывает обнуляемый тип, то XSQLVAR::sqlind должен содержать ненулевой указатель. Иначе возникнут проблемы.

Если идентификатор типа (XSQLVAR::sqltype) описывает NOT NULL колонку, то XSQLVAR::sqlind игнорируется.

Вот здесь мы подошли к вопросу, который регулярно появляется в моей голове, когда я вожусь с этим самым «XSQLVAR::sqlind»:

Какому гению пришло в голову увязывать наличие/отсутствие индикатора NULL-состояния (sqlind) значения с описанием типа (sqltype)?

Это же две несвязанные вещи!

1. Допустим, мы выполняем параметризованный INSERT-запрос с указанием NULL-значения для колонки с первичным ключом таблицы — «insert into TEST_TABLE (ID) values(?)».

Если мы запросим описание параметров, то сервер вернет нам NOT NULL описание для связанного параметра. XSQLVAR::sqltype будет содержать четное число.

Поскольку мы хотим передать NULL-значение (чтобы учитывался sqlind), нужно модифицировать XSQLVAR::sqltype — добавить единицу. Соответственно, гробим оригинальное описание параметра.

Необходимо сохранить оригинальное описание параметра? Сделайте копию!

2. Смотрим описание «Change Views» в IB12 (XE7). Информация о модификациях колонок передается через XSQLVAR::sqlind, который (сюрприз) опять будет учитываться только если XSQLVAR::sqltype описывает обнуляемые данные (содержит нечетное число).

Ага — получаем описание NOT NULL колонки и опять должны искорежить sqltype, чтобы получать данные через sqlind.

IB XE7. Data Defintion Guide.
It is required to use the «odd-numbered» SQL DATA TYPES (SQLVAR variable, sqltype) when working with change views. This allows the SQL indicator variable in the SQLVAR to receive status on the returned column data.

Хотели сохранить оригинальное описание колонки? Сделайте копию!


В общем, все интуитивно, понятно и, главное, очень удобно.

С другой стороны — это всего лишь капля, которой не повезло и она переполнила стакан.

Leave a Comment