Страница 1 из 1
isc_dsql_fetch + набор данных ~50тыс.=arithmetic exception?!
Добавлено: 05 июн 2006, 16:13
sunduk4
Стандартный код -
Код: Выделить всё
main_sqlda = (XSQLDA *)malloc(XSQLDA_LENGTH(3));
main_sqlda->sqln = 3;
main_sqlda->sqld = 3;
main_sqlda->version = 1;
if (isc_dsql_prepare(status, &trans, &main_stmt, 0, main_select, 1, NULL))
{
ERREXIT(status, 1)
}
isc_dsql_describe(status, &main_stmt, 1, main_sqlda);
for (i=0, main_var = main_sqlda->sqlvar; i < main_sqlda->sqld; i++, main_var++)
{
main_dtype = (main_var->sqltype & ~1);
switch(main_dtype)
{
case SQL_VARYING:
main_var->sqldata = (char *)malloc(sizeof(char)*main_var->sqllen + 1);
break;
case SQL_TEXT:
main_var->sqldata = (char *)malloc(sizeof(char)*main_var->sqllen);
break;
case SQL_LONG:
main_var->sqldata = (char *)malloc(sizeof(long));
break;
case SQL_SHORT:
main_var->sqldata = (char *)malloc(sizeof(short));
break;
}
if (main_var->sqltype & 1)
{
main_var->sqlind = (short *)malloc(sizeof(short));
}
}
if (isc_dsql_execute2(status, &trans, &main_stmt, 1, main_sqlda, NULL))
{
ERREXIT(status, 1)
}
isc_dsql_set_cursor_name(status, &main_stmt, "main_cursor", NULL);
while ((main_fetch_stat = isc_dsql_fetch(status, &main_stmt, 1, main_sqlda)) == 0)
{
.....обработка данных....
}
if (main_fetch_stat != 100L)
{
ERREXIT(status, 1)
}
if (isc_dsql_free_statement(status, &main_stmt, DSQL_close))
{
ERREXIT(status, 1)
}
на небольших наборах данных все ок. но на фетче 50тыс. записей вываливается с ошибкой. Что не так?
При этом сильно растет объем памяти, занимаемый приложением. Есть ли возможность фетча записей не вытягивая весь набор данных?
Добавлено: 05 июн 2006, 16:50
hvlad
isc_dsql_free_statement(.., DSQL_close) не достаточно, ещё нужен DSQL_drop
Добавлено: 05 июн 2006, 16:56
kdv
При этом сильно растет объем памяти, занимаемый приложением.
если ты считываемые записи буферизируешь - разумеется будет расти.
Есть ли возможность фетча записей не вытягивая весь набор данных?
эээ...что??? фетч - это выборка ОДНОЙ записи. Никуда ее не складываешь - откуда возьмется расход памяти?
насчет arithmetic exception - это ты или данные кривые занес, или колупал структуру таблиц руками....
Добавлено: 05 июн 2006, 17:10
sunduk4
isc_dsql_free_statement(.., DSQL_close) не достаточно, ещё нужен DSQL_drop
съедаемая память наполовину уменьшилась, но проблема осталась..
если ты считываемые записи буферизируешь - разумеется будет расти.
а как избавиться от буферизации записей? вся моя задача - данные из таблицы в файлик лить..
насчет arithmetic exception - это ты или данные кривые занес, или колупал структуру таблиц руками....
ни того ни другого не было. данные заливал скриптом, который ибэксперт сгенерил. после чего был сделан успешный бэкап-рестор базы.
Добавлено: 05 июн 2006, 17:19
kdv
а как избавиться от буферизации записей? вся моя задача - данные из таблицы в файлик лить..
так это ты в своем коде их буферизируешь. или нет?
кстати, malloc, вижу, а совобождается где?
потом, я смутно помню описание xsqlda, но что то не припомню, чтобы под sql_ind надо было память аллокировать...
Добавлено: 05 июн 2006, 17:30
sunduk4
так это ты в своем коде их буферизируешь. или нет?
в коде данные из получаемой записи собираются в строку и пишутся в файл. строка - массив символов.
кстати, malloc, вижу, а совобождается где?
потом, я смутно помню описание xsqlda, но что то не припомню, чтобы под sql_ind надо было память аллокировать...
прошу прощения, после free_statement естественно делаю
free(main_sqlda)
судя по api guide, под нулл-индикатор надо выделять память..
Добавлено: 06 июн 2006, 00:18
hvlad
sunduk4 писал(а):так это ты в своем коде их буферизируешь. или нет?
в коде данные из получаемой записи собираются в строку и пишутся в файл. строка - массив символов.
Строка растёт по мере необходимости ? Это грабли
sunduk4 писал(а):кстати, malloc, вижу, а совобождается где?
потом, я смутно помню описание xsqlda, но что то не припомню, чтобы под sql_ind надо было память аллокировать...
прошу прощения, после free_statement естественно делаю
free(main_sqlda)
А все sqldata\sqlind освобождаются ?
Добавлено: 06 июн 2006, 06:49
sunduk4
Строка растёт по мере необходимости ? Это грабли
строка - char result_str[64000];
после записи в файл каждой строчки - strcpy(result_str, "");
размер строчки нигде не изменяется в программе.
А все sqldata\sqlind освобождаются ?
хм.. вообще-то нет. а разве не достаточно после фетча освободить sqlda?
и sqlda\sqlind следует освобождать после каждой отфетченой строки либо после всего фетча?
Добавлено: 06 июн 2006, 08:10
Dimitry Sibiryakov
Во-первых, любые структуры надо освобождать когда они тебе больше не нужны. Кстати, DSQL_close достаточно если ты потом будешь хэндл использовать без повторного prepare.
Во-вторых, под SQL_VARYING надо выделять как минимум sqllen+sizeof(SHORT). Иначе - AV.
В-третьих, ты все же определись: в main_sqlda у тебя значения параметров или возвращаемых полей. Если первое - не суй ее в fetch. Если второе - в execute2. Кстати, нафига execute2? Простой execute надежнее.
Добавлено: 06 июн 2006, 08:31
sunduk4
Во-первых, любые структуры надо освобождать когда они тебе больше не нужны. Кстати, DSQL_close достаточно если ты потом будешь хэндл использовать без повторного prepare.
с памятью разобрался - действительно, структуры освобождаю - приложение от силы до 8мб памяти использует.
Во-вторых, под SQL_VARYING надо выделять как минимум sqllen+sizeof(SHORT). Иначе - AV.
В-третьих, ты все же определись: в main_sqlda у тебя значения параметров или возвращаемых полей. Если первое - не суй ее в fetch. Если второе - в execute2. Кстати, нафига execute2? Простой execute надежнее.
под SQL_VARYING память выделяю так -
main_sqlda->sqlvar->sqldata = (char *)malloc(sizeof(char)*main_sqlda->sqlvar->sqllen + 1)
в main_sqlda у меня значения возвращаемых полей. переделал на execute все, убрал структуру из execute. Проблема осталась.
Ошибку получаю вот тут -
Код: Выделить всё
if (main_fetch_stat != 100L)
{
ERREXIT(status, 1)
}
Добавлено: 06 июн 2006, 10:14
sunduk4
Всем спасибо! Разобрался.
Оказалось, что для одной из колонок память не совсем верно выделялась.
Добавлено: 06 июн 2006, 10:19
Ivan_Pisarevsky
sunduk4 писал(а):так это ты в своем коде их буферизируешь. или нет?
в коде данные из получаемой записи собираются в строку и пишутся в файл. строка - массив символов.
кстати, malloc, вижу, а совобождается где?
потом, я смутно помню описание xsqlda, но что то не припомню, чтобы под sql_ind надо было память аллокировать...
прошу прощения, после free_statement естественно делаю
free(main_sqlda)
судя по api guide, под нулл-индикатор надо выделять память..
Что мешает использовать экстернал тэйбл? инсерт ... селект тра-та-та, потом обычнам копированием забрал готовый файлик.
Добавлено: 06 июн 2006, 10:26
sunduk4
Что мешает использовать экстернал тэйбл? инсерт ... селект тра-та-та, потом обычнам копированием забрал готовый файлик.
задача немного сложнее стоит. пытаюсь написать свой репликатор.
Добавлено: 06 июн 2006, 10:55
Dimitry Sibiryakov
sunduk4 писал(а):под SQL_VARYING память выделяю так -
main_sqlda->sqlvar->sqldata = (char *)malloc(sizeof(char)*main_sqlda->sqlvar->sqllen + 1)
Читай по губам: sqllen+sizeof(SHORT). sizeof(SHORT) ==
2. Т.е. ты под буфер выделяешь на байт меньше чем требуется.
Добавлено: 06 июн 2006, 10:56
Dimitry Sibiryakov
sunduk4 писал(а):задача немного сложнее стоит. пытаюсь написать свой репликатор.
А чем готовые не устраивают? Я понимаю IBReplicator дорогой, но FBReplicator-то халява.
Добавлено: 06 июн 2006, 11:45
sunduk4
Читай по губам: sqllen+sizeof(SHORT). sizeof(SHORT) == 2. Т.е. ты под буфер выделяешь на байт меньше чем требуется.
упс, точно...
А чем готовые не устраивают? Я понимаю IBReplicator дорогой, но FBReplicator-то халява.
к требованиям он не совсем подходит. -
1. связь между серверами оставляет желать лучшего, по-этому о прямом коннекте речь идти не может.
2. нужна репликация блоб-полей.
3. ОС - линукс
это минимум требований.