SQLDescribeCol () возвращает SQL_VARCHAR для BINARY, BLOB, WCHAR, DECIMAL - PullRequest
0 голосов
/ 17 октября 2019

Используя драйвер ODBC для SQLite в unixodbc, я часто получаю бесполезные результаты из SQLDescribeCol.

Например, в таблице, созданной с помощью:

CREATE TABLE `test_table` (
    id INTEGER PRIMARY KEY NOT NULL,
    `value` BINARY(3) NOT NULL
)

Я делаю простой ODBC-запрос без параметров:

SELECT value FROM `test_table`

, который возвращает набор результатов с одним столбцом, где мой код на C говорит что-то вроде:

SQLWCHAR title[COLUMN_TITLE_SIZE];
SQLSMALLINT title_length;
SQLSMALLINT sql_type;  
SQLULEN column_size;
SQLSMALLINT precision;  
SQLSMALLINT nullable;

SQLRETURN rc = SQLDescribeColW(
    hstmt,
    column_index,  // 1 in this case
    &title[0],
    COLUMN_TITLE_SIZE,
    &title_length,
    &sql_type,
    &column_size,
    &precision,
    &nullable
);

Несмотря на двоичный код в определении таблицы, он возвращается с sql_type == SQL_VARCHAR. Эта проблема не существует для некоторых типов ... таких как целые числа или времена / даты, SQL_BIT или большинство чисел с плавающей запятой. Но то же самое происходит со столбцами BLOB, столбцами NCHAR и, в частности, DECIMAL.

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

1 Ответ

0 голосов
/ 17 октября 2019

Это может показаться ошибкой (или неосуществленной функцией) в драйвере SQLite unixodbc. Кажется, что проблема заключается в том, что для любого типа, который имеет malloc() произвольный буфер, его внутренняя типизация одинакова.

Вот предлагаемый обходной путь: драйвер на самом деле знает строковое имятип столбца ... и вы можете получить его с помощью SQLColAttribute , передав его SQL_DESC_TYPE_NAME.

char type_name[100];  // Note: `typename` is a C++ keyword
SQLSMALLINT type_name_len;
rc = SQLColAttribute(  // or SQLColAttributeW--see NOTE below
    hstmt,  // StatementHandle
    column_index,  // ColumnNumber
    SQL_DESC_TYPE_NAME,  // FieldIdentifier, see SQL_DESC_XXX list
    &type_name,  // CharacterAttributePtr
    100,  // BufferLength
    &type_name_len,  // StringLengthPtr
    nullptr  // NumericAttributePtr, not needed w/string attribute
);

ПРИМЕЧАНИЕ. Вышеописанное работало на unixodbc. Но пришли сообщения, что драйвер Windows SQLite возвращал строку широких символов в качестве type_name, хотя вызывался SQLColAttribute, а не SQLColAttributeW. Если кому-то есть что сказать по этому поводу, пожалуйста, включите.

Этот type_name вернется и даст вам такое различие, как BINARY, и поэтому, если вы ищете шаблоны тех типов, которые вам нужнытем, что вы можете генерировать требуемые типы SQL_BINARY и т. д.

Примечание: в драйвере есть код для сопоставления строк с SQL_TYPEs . Но, похоже, он не используется в SELECT, а только во INSERT.

...