Модераторы: Akella
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Interbase API Ошибка при получении данных 
:(
    Опции темы
TeX
Дата 13.10.2009, 16:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 16
Регистрация: 23.12.2007

Репутация: нет
Всего: нет



Доброго дня !
Разрабатываю приложение, которое работает с Firebird через api.
Начальный функционал, подключение/отключение, работа с транзакциями, уже оттестировал все работает.
Столкнулся с проблемой при получении данных из таблицы. 
Запрос такой:
Код

SELECT * FROM LIC_ASSORT

Вот код процедуры, она прост тупо считает число полученных записей из таблицы:
Код

function GetRecordsCount(dbHandle:isc_db_handle; trHandle:isc_tr_handle; sql:AnsiString):integer;
var
 status : status_vector;
 count,i,j : integer;
 out_da : PXSQLDA;
 out_var : XSQLVAR;
 stmtHandle : isc_stmt_handle;
 fetch_stat : integer;
begin
 StmtHandle := nil;
 getmem(out_da,SQLDA_LENGTH(4));
 out_da^.version := SQLDA_VERSION1;
 out_da^.sqln := 4;
 if isc_dsql_allocate_statement(@STATUS,@dbHandle,@stmtHandle) <> 0 then
   HandleIBErrors( @status);
 if isc_dsql_prepare(@STATUS,@trHandle,@stmtHandle,0,pchar(sql),3,nil) <> 0 then
   HandleIBErrors( @status);
 if  isc_dsql_describe(@STATUS,@stmtHandle,1,out_da) <> 0 then
   HandleIBErrors( @status);

 if out_da^.sqld > out_da^.sqln then
  begin
    i := out_da^.sqld;
    freemem(out_da,SQLDA_LENGTH(4));
    out_da^.version := SQLDA_VERSION1;
    out_da^.sqln := i;
    if isc_dsql_describe(@STATUS,@stmtHandle,1,out_da) <> 0 then
      HandleIBErrors( @status);
  end;

 for i := 0 to out_da^.sqld-1 do
  begin
   out_var := out_da^.sqlvar[i];
   case out_var.sqltype of
      SQL_VARYING : begin
                     out_var.sqltype := SQL_TEXT;
                     out_var.sqldata:= AllocMem(sizeof(char)*(out_var.sqllen + 2));
                    end;
      449         : begin
                     out_var.sqltype := SQL_TEXT;
                     out_var.sqldata:= AllocMem(sizeof(char)*(out_var.sqllen + 2));
                    end;
      SQL_TEXT    : out_var.sqldata:= AllocMem(sizeof(char)*(out_var.sqllen));
      SQL_LONG    : out_var.sqldata:= AllocMem(sizeof(longint));
      SQL_DATE    : out_var.sqldata:= AllocMem(SizeOf(ISC_QUAD));
   end;

   if out_var.sqltype = 1  then
      getmem(out_var.sqlind,sizeof(short));
  end;

 if isc_dsql_execute(@status,@trHandle,@stmtHandle,1,nil) <> 0 then
   HandleIBErrors(@status);
 //isc_dsql_set_cursor_name(@status,@stmtHandle,'dyn_cursor', null);
 try
   count:=0;
   fetch_stat:=0;
   while fetch_stat = 0 do
    begin
      fetch_stat:= isc_dsql_fetch(@Status,@StmtHandle,1,out_da);
      inc(count);
    end;
    if fetch_stat <> 100 then
     HandleIBErrors(@STATUS);
 finally;
  isc_dsql_free_statement(@Status,@stmtHandle,DSQL_Close);
  Result:=count;
 end;
end;

Таблица состоит из 2-х полей. Первое типа Integer, второе varchar.
после того как пытаюсь получить данные с помощью fetch_stat:= isc_dsql_fetch(@Status,@StmtHandle,1,out_da);
в fetch_stat возвращается результат не равный 0 или 100 и обработчик ошибок выдает сообщение
-804 Incorrect values within SQLDA structure.
На форуме находил ссылки на материалы по api, все сделано по ним и по interbase api guide.
Вчем может быть проблема ?

PM MAIL   Вверх
Akina
Дата 13.10.2009, 16:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Советчик
****


Профиль
Группа: Модератор
Сообщений: 20581
Регистрация: 8.4.2004
Где: Зеленоград

Репутация: 3
Всего: 454



Цитата(TeX @  13.10.2009,  17:07 Найти цитируемый пост)
Запрос такой:
Код

SELECT * FROM LIC_ASSORT

Вот код процедуры, она прост тупо считает число полученных записей из таблицы:

А почему не сразу 
Код

SELECT Count(*) FROM LIC_ASSORT

?


--------------------
 О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума.

PM MAIL WWW ICQ Jabber   Вверх
TeX
Дата 16.10.2009, 07:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 16
Регистрация: 23.12.2007

Репутация: нет
Всего: нет



Цитата(Akina @ 13.10.2009,  16:46)
А почему не сразу 
Код

SELECT Count(*) FROM LIC_ASSORT

?

Это не столь важно,можно будет и так делать - это просто процедура для отработки алгоритма.
PM MAIL   Вверх
TeX
Дата 16.10.2009, 10:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 16
Регистрация: 23.12.2007

Репутация: нет
Всего: нет



А ошибка была банальной, совсем банальной, даже немного стыдно.  smile 

Просто необходимо было сделать так:
Код

for i := 0 to out_da^.sqld-1 do
  begin
   out_var := out_da^.sqlvar[i];
   case out_var.sqltype of
      SQL_VARYING : begin
                     out_var.sqltype := SQL_TEXT;
                     out_var.sqldata:= AllocMem(sizeof(char)*(out_var.sqllen + 2));
                    end;
      449         : begin
                     out_var.sqltype := SQL_TEXT;
                     out_var.sqldata:= AllocMem(sizeof(char)*(out_var.sqllen + 2));
                    end;
      SQL_TEXT    : out_var.sqldata:= AllocMem(sizeof(char)*(out_var.sqllen));
      SQL_LONG    : out_var.sqldata:= AllocMem(sizeof(longint));
      SQL_DATE    : out_var.sqldata:= AllocMem(SizeOf(ISC_QUAD));
   end;

   if out_var.sqltype = 1  then
      getmem(out_var.sqlind,sizeof(short));
   out_da^.sqlvar[i]:=out_var;     <--------- Добавить эту строчку
  end;




Это сообщение отредактировал(а) TeX - 16.10.2009, 10:41
PM MAIL   Вверх
TeX
Дата 8.1.2010, 15:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 16
Регистрация: 23.12.2007

Репутация: нет
Всего: нет



При дальнейшей разработке столкнулся с проблемой другого рода.
Отработал код, привел его более-менее в порядок, работает почти отлично.
Вот основная функция.
Код

function GetFirstRecord(Field:ShortString;dbHandle:isc_db_handle;SQL:ShortString; out Count:integer):ShortString;
var
  transact : isc_tr_handle;
  fetch_stat,i : integer;
  xsd : PXSQLDA;
  status : status_vector;
  stmtHandle : isc_stmt_handle;
begin
 if dbHandle <> nil then
   begin
    xsd:=nil;
    transact:=nil;
    StmtHandle := nil;
    xsd:=AllocMem(SQLDA_LENGTH(1));
    xsd^.version := SQLDA_VERSION1;
    xsd^.sqln := 1;
    Field:=UpperCase(Field);
   try
     StartTransaction(dbHandle,transact);
     dsqlAllocateStatement(dbHandle,stmtHandle);
     dsqlPrepare(transact,stmtHandle,sql,SQLdialect);
     dsqlDescribe(dbHandle,stmtHandle,xsd);
     GetDataBuffers(xsd);
     dsqlExecute(transact,stmtHandle,xsd);
     fetch_stat:= isc_dsql_fetch(@Status,@stmtHandle,1,xsd);
     GetRecordCount(stmtHandle,Count);
     if fetch_stat = 0 then
      begin
       for i:=0 to xsd.sqld-1 do
        begin
         if AnsiUpperCase(string(xsd.sqlvar[i].aliasname)) = Field then
          begin
           Result:=asString(xsd,i);
           fetch_stat:=100;
          end
         else
          begin
           fetch_stat:=100;
           Result:='';
          end;
        end;
      end;
     if fetch_stat <> 100 then
      HandleIBErrors(@STATUS);
   finally;
     isc_dsql_free_statement(@Status,@stmtHandle,DSQL_Close);
     CommitTransaction(transact);
     FreeMem(xsd);
     xsd:=nil;
    end;
   end;
end;


Некоторые дополнительные процедуры.
Код

rocedure dsqlPrepare(var trHandle:isc_tr_handle; var stmtHandle:isc_stmt_handle;
                      const SQL:AnsiString; dialect:byte);
var
  status:status_vector;
begin
 if isc_dsql_prepare(@STATUS,@trHandle,@stmtHandle,0,pchar(SQL),dialect,nil) <> 0 then
   HandleIBErrors( @status);
end;

procedure dsqlDescribe(var dbHandle:isc_db_handle; var stmtHandle:isc_stmt_handle; var SQLDA:PXSQLDA);
var
  status:status_vector;
  i:integer;
begin
 if isc_dsql_describe(@STATUS,@stmtHandle,1,SQLDA) <> 0 then
   HandleIBErrors( @status);
 if SQLDA^.sqld > SQLDA^.sqln then
  begin
    i := SQLDA^.sqld;
  //  freemem(out_da,SQLDA_LENGTH(1));  // old variant
    FreeMem(SQLDA);
    GetMem(SQLDA,SQLDA_LENGTH(i));
    SQLDA^.version := SQLDA_VERSION1;
    SQLDA^.sqln := i;
    if isc_dsql_describe(@STATUS,@stmtHandle,1,SQLDA) <> 0 then
      HandleIBErrors( @status);
  end;
end;

procedure dsqlExecute(var trHandle:isc_tr_handle; var stmtHandle:isc_stmt_handle; var SQLDA:PXSQLDA);
var
  status:status_vector;
begin
 if isc_dsql_execute(@status,@trHandle,@stmtHandle,1,nil) <> 0 then
   HandleIBErrors(@status);
end;

procedure GetDataBuffers(var SQLDA:PXSQLDA);
var
 i:integer;
 tmp_var:XSQLVAR;
begin
 for i := 0 to SQLDA^.sqld-1 do
  begin
    tmp_var := SQLDA^.sqlvar[i];
    case tmp_var.sqltype of
      SQL_VARYING,449 : begin
                           GetMem(tmp_var.sqldata,sizeof(char)*(tmp_var.sqllen + 3));
                           FillChar(tmp_var.sqldata,sizeof(char)*(tmp_var.sqllen + 3),' ');
                        end;
      SQL_TEXT        :  tmp_var.sqldata:= AllocMem(sizeof(char)*(tmp_var.sqllen));
      SQL_LONG,497    :  tmp_var.sqldata:= AllocMem(sizeof(Integer));
      SQL_TIMESTAMP   :  tmp_var.sqldata:= AllocMem(SizeOf(ISC_QUAD));
    end;
    if tmp_var.sqltype = 1  then
     getmem(tmp_var.sqlind,sizeof(short));
    SQLDA^.sqlvar[i]:=tmp_var;
  end;
end;


Суть проблемы такова при вызове функции с такими патаметрами
Код

GetFirstRecord('NACL_ID',db_global_handle,'SELECT NACL_ID FROM NACLADN',cnt)

Все проходит нормально, получаю первую запись из выборки и количество записей в выборке, НО... когда вызываю функцию так
Код

GetFirstRecord('maxid',db_global_handle,'SELECT max(NACL_ID) as maxid FROM NACLADN',cnt)

при fetch-е возвращается ошибка 335544569 и выдается ошибка 
Dynamic SQL Error SQL error code = -804 Incorrect values within SQLDA structure.
Проверил код полностью, поиск в Интеренете не принес положительных ответов. 
При анализе заметил, что в структуре SQLVAR не заполняются поля
Код
    sqlname_length
    sqlname
    relname_length
    relname
    ownname_length
    ownname

А заполняются только поля
Код
    aliasname_length
    aliasname

Может кто подскажет в чем дело и как исправить это ?
З.Ы. Использую GDS32.dll версии 2.1

Это сообщение отредактировал(а) TeX - 8.1.2010, 15:42
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Interbase"
Alex

Обязательно указание:

1. Версию InterBase (Firebird, Yaffil)

2. Способа доступа (ADO, BDE, IBX и т.д.)

  • КАК ПРАВИЛЬНО ОФОРМИТЬ КОД - ЗДЕСЬ
  • КАК ПРАВИЛЬНО УКАЗАТЬ ТЕКСТ ОШИБКИ - ЗДЕСЬ
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • FAQ раздела лежит здесь!

Если Вам понравилась атмосфера форума, заходите к нам чаще! С Уважением, Akella.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Firebird, Interbase | Следующая тема »


 




[ Время генерации скрипта: 0.0905 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.