Обработка запроса [API/FireBird/C++]

IBX, FIBPlus, UIB, ADO, .Net и прочее-прочее-прочее, в общем все, что относится к созданию приложений, работающих с InterBase, Firebird и Yaffil - клиент-серверных, трехзвенных, консольных и т.п.

Модератор: kdv

Ответить
NeedForSleep
Сообщения: 2
Зарегистрирован: 25 дек 2009, 10:29

Обработка запроса [API/FireBird/C++]

Сообщение NeedForSleep » 25 дек 2009, 10:38

Значит, я пытаюсь писать клиентское приложение на С++ с испольхованием АПИ. В данный момент столкнулся с проблемой обработки запроса.
Получается только обработать текстовые запросы, другие, например, вещественные данные не выводятся.. Что мне надо делать ?
Вот, что у меня получилось написать...

Код: Выделить всё

void __fastcall TForm1::Button2Click(TObject *Sender)
{
char *sel_str =
     "SELECT radius FROM planets;";
isc_tr_handle    trans = 0;
int                num_cols, i;
isc_stmt_handle    stmt = NULL;
XSQLDA             *sqlda;
XSQLVAR            *var;
char               empdb[128];
long                    fetch_stat;

sqlda = (XSQLDA *) malloc(XSQLDA_LENGTH(3));
sqlda->sqln = 3;
sqlda->version = 1;

isc_start_transaction(status_vector, &trans, 1, &db1, 0, NULL);

isc_dsql_allocate_statement(status_vector, &db1, &stmt);

isc_dsql_prepare(status_vector, &trans, &stmt, 0, sel_str, 1, sqlda);

isc_dsql_describe(status_vector, &stmt, 1, sqlda);

num_cols = sqlda->sqld;

for (i=0, var = sqlda->sqlvar; i < num_cols; i++, var++)
{

ISC_SHORT dtype = (var->sqltype & ~1);
switch(dtype)
{
case SQL_VARYING:
var->sqltype = SQL_TEXT;
var->sqldata = (char *)malloc(sizeof(char)*var->sqllen);
break;
case SQL_TEXT: 
var->sqldata = (char *)malloc(sizeof(char)*var->sqllen);
break;
case SQL_LONG: 
var->sqldata = (char *)malloc(sizeof(long)*var->sqllen);
break;
case SQL_SHORT:
var->sqldata = (char *)malloc(sizeof(short)*var->sqllen);
break;
case SQL_DOUBLE:
var->sqldata = (char *)malloc(sizeof(double)*var->sqllen);
break;
}

if (var->sqltype & 1)
{
var->sqlind = (short *)malloc(sizeof(short));
}
}
isc_dsql_execute(status_vector, &trans, &stmt, SQL_DIALECT_V6, NULL);
while ((fetch_stat = isc_dsql_fetch(status_vector, &stmt, SQL_DIALECT_V6, sqlda)) == 0)
{
for (i = 0; i < num_cols; i++)
{
Form1->Memo1->Lines->Add(sqlda->sqlvar[i].sqldata);
}
}
}
За код прошу не ругать, а указать на возможные ошибки = )

Dimitry Sibiryakov
Заслуженный разработчик
Сообщения: 1436
Зарегистрирован: 15 сен 2005, 09:05

Re: Обработка запроса [API/FireBird/C++]

Сообщение Dimitry Sibiryakov » 25 дек 2009, 13:36

NeedForSleep писал(а):Получается только обработать текстовые запросы, другие, например, вещественные данные не выводятся..

Код: Выделить всё

isc_dsql_prepare(status_vector, &trans, &stmt, 0, sel_str, 1, sqlda);

isc_dsql_describe(status_vector, &stmt, 1, sqlda);
....
case SQL_VARYING:
var->sqltype = SQL_TEXT;
var->sqldata = (char *)malloc(sizeof(char)*var->sqllen);
break;
....
case SQL_LONG: 
var->sqldata = (char *)malloc(sizeof(long)*var->sqllen);
break;
....
Form1->Memo1->Lines->Add(sqlda->sqlvar[i].sqldata);
За код прошу не ругать, а указать на возможные ошибки = )
1) describe тут не нужен, prepare уже всё описал. Но и безопасен.
2) Преобразование VARCHAR в TEXT довольно плохая идея: результат всё равно не будет null-terminated, а значение реального размера строки ты теряешь.
3) Выделение памяти под нетекстовые данные забавно, но тоже безопасно.
4) (и главное) несмотря на то, что sqldata объявлен как char*, в случае любого типа кроме SQL_TEXT он ссылается отнюдь не на строку. Смотри в API Guide таблицу соответствия типов данных FB и типов C. Раздел "SQL datatype macro constants".

hvlad
Разработчик Firebird
Сообщения: 1244
Зарегистрирован: 21 мар 2005, 10:48

Re: Обработка запроса [API/FireBird/C++]

Сообщение hvlad » 25 дек 2009, 13:57

Ошибки кто проверять будет ?

Зачем для "SELECT radius FROM planets" создавать 3 дескриптора (XSQLDA_LENGTH(3)) ?

Добавлять в TStrings указатель на double - это более чем оригинально :
Form1->Memo1->Lines->Add(sqlda->sqlvar.sqldata);

Dimitry Sibiryakov
Заслуженный разработчик
Сообщения: 1436
Зарегистрирован: 15 сен 2005, 09:05

Re: Обработка запроса [API/FireBird/C++]

Сообщение Dimitry Sibiryakov » 26 дек 2009, 13:41

hvlad писал(а):Зачем для "SELECT radius FROM planets" создавать 3 дескриптора (XSQLDA_LENGTH(3)) ?
Нафсякей. Практически наверняка первоначально запрос был шире, но сократился в процессе отладки.
Да и запас карман не тянет. Например, у меня при загрузке конфигурации на все запросы одна SQLDA максимальной ширины.

NeedForSleep
Сообщения: 2
Зарегистрирован: 25 дек 2009, 10:29

Re: Обработка запроса [API/FireBird/C++]

Сообщение NeedForSleep » 28 дек 2009, 17:13

4) (и главное) несмотря на то, что sqldata объявлен как char*, в случае любого типа кроме SQL_TEXT он ссылается отнюдь не на строку. Смотри в API Guide таблицу соответствия типов данных FB и типов C. Раздел "SQL datatype macro constants".
Я так и не разобрался.. Вот если я получу переменную типа SQL_DOUBLE, то как мне получить её значение?..

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Re: Обработка запроса [API/FireBird/C++]

Сообщение kdv » 29 дек 2009, 00:35

не мучайтесь, возьмите какую-нибудь объектную обертку типа ibpp, IBX и так далее, и смотрите как там сделано.

Dimitry Sibiryakov
Заслуженный разработчик
Сообщения: 1436
Зарегистрирован: 15 сен 2005, 09:05

Re: Обработка запроса [API/FireBird/C++]

Сообщение Dimitry Sibiryakov » 29 дек 2009, 14:11

NeedForSleep писал(а):Я так и не разобрался.. Вот если я получу переменную типа SQL_DOUBLE, то как мне получить её значение?..
Привести char* к double* а потом делай с этим double что хочешь.

Ответить