IBX, FIBPlus, UIB, ADO, .Net и прочее-прочее-прочее, в общем все, что относится к созданию приложений, работающих с InterBase, Firebird и Yaffil - клиент-серверных, трехзвенных, консольных и т.п.
Модератор: kdv
-
sunduk4
- Сообщения: 18
- Зарегистрирован: 02 май 2006, 13:45
Сообщение
sunduk4 » 05 июн 2006, 16:13
Стандартный код -
Код: Выделить всё
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тыс. записей вываливается с ошибкой. Что не так?
При этом сильно растет объем памяти, занимаемый приложением. Есть ли возможность фетча записей не вытягивая весь набор данных?
-
hvlad
- Разработчик Firebird
- Сообщения: 1244
- Зарегистрирован: 21 мар 2005, 10:48
Сообщение
hvlad » 05 июн 2006, 16:50
isc_dsql_free_statement(.., DSQL_close) не достаточно, ещё нужен DSQL_drop
-
kdv
- Forum Admin
- Сообщения: 6595
- Зарегистрирован: 25 окт 2004, 18:07
Сообщение
kdv » 05 июн 2006, 16:56
При этом сильно растет объем памяти, занимаемый приложением.
если ты считываемые записи буферизируешь - разумеется будет расти.
Есть ли возможность фетча записей не вытягивая весь набор данных?
эээ...что??? фетч - это выборка ОДНОЙ записи. Никуда ее не складываешь - откуда возьмется расход памяти?
насчет arithmetic exception - это ты или данные кривые занес, или колупал структуру таблиц руками....
-
sunduk4
- Сообщения: 18
- Зарегистрирован: 02 май 2006, 13:45
Сообщение
sunduk4 » 05 июн 2006, 17:10
isc_dsql_free_statement(.., DSQL_close) не достаточно, ещё нужен DSQL_drop
съедаемая память наполовину уменьшилась, но проблема осталась..
если ты считываемые записи буферизируешь - разумеется будет расти.
а как избавиться от буферизации записей? вся моя задача - данные из таблицы в файлик лить..
насчет arithmetic exception - это ты или данные кривые занес, или колупал структуру таблиц руками....
ни того ни другого не было. данные заливал скриптом, который ибэксперт сгенерил. после чего был сделан успешный бэкап-рестор базы.
-
kdv
- Forum Admin
- Сообщения: 6595
- Зарегистрирован: 25 окт 2004, 18:07
Сообщение
kdv » 05 июн 2006, 17:19
а как избавиться от буферизации записей? вся моя задача - данные из таблицы в файлик лить..
так это ты в своем коде их буферизируешь. или нет?
кстати, malloc, вижу, а совобождается где?
потом, я смутно помню описание xsqlda, но что то не припомню, чтобы под sql_ind надо было память аллокировать...
-
sunduk4
- Сообщения: 18
- Зарегистрирован: 02 май 2006, 13:45
Сообщение
sunduk4 » 05 июн 2006, 17:30
так это ты в своем коде их буферизируешь. или нет?
в коде данные из получаемой записи собираются в строку и пишутся в файл. строка - массив символов.
кстати, malloc, вижу, а совобождается где?
потом, я смутно помню описание xsqlda, но что то не припомню, чтобы под sql_ind надо было память аллокировать...
прошу прощения, после free_statement естественно делаю
free(main_sqlda)
судя по api guide, под нулл-индикатор надо выделять память..
-
hvlad
- Разработчик Firebird
- Сообщения: 1244
- Зарегистрирован: 21 мар 2005, 10:48
Сообщение
hvlad » 06 июн 2006, 00:18
sunduk4 писал(а):так это ты в своем коде их буферизируешь. или нет?
в коде данные из получаемой записи собираются в строку и пишутся в файл. строка - массив символов.
Строка растёт по мере необходимости ? Это грабли
sunduk4 писал(а):кстати, malloc, вижу, а совобождается где?
потом, я смутно помню описание xsqlda, но что то не припомню, чтобы под sql_ind надо было память аллокировать...
прошу прощения, после free_statement естественно делаю
free(main_sqlda)
А все sqldata\sqlind освобождаются ?
-
sunduk4
- Сообщения: 18
- Зарегистрирован: 02 май 2006, 13:45
Сообщение
sunduk4 » 06 июн 2006, 06:49
Строка растёт по мере необходимости ? Это грабли
строка - char result_str[64000];
после записи в файл каждой строчки - strcpy(result_str, "");
размер строчки нигде не изменяется в программе.
А все sqldata\sqlind освобождаются ?
хм.. вообще-то нет. а разве не достаточно после фетча освободить sqlda?
и sqlda\sqlind следует освобождать после каждой отфетченой строки либо после всего фетча?
-
Dimitry Sibiryakov
- Заслуженный разработчик
- Сообщения: 1436
- Зарегистрирован: 15 сен 2005, 09:05
Сообщение
Dimitry Sibiryakov » 06 июн 2006, 08:10
Во-первых, любые структуры надо освобождать когда они тебе больше не нужны. Кстати, DSQL_close достаточно если ты потом будешь хэндл использовать без повторного prepare.
Во-вторых, под SQL_VARYING надо выделять как минимум sqllen+sizeof(SHORT). Иначе - AV.
В-третьих, ты все же определись: в main_sqlda у тебя значения параметров или возвращаемых полей. Если первое - не суй ее в fetch. Если второе - в execute2. Кстати, нафига execute2? Простой execute надежнее.
-
sunduk4
- Сообщения: 18
- Зарегистрирован: 02 май 2006, 13:45
Сообщение
sunduk4 » 06 июн 2006, 08:31
Во-первых, любые структуры надо освобождать когда они тебе больше не нужны. Кстати, 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)
}
-
sunduk4
- Сообщения: 18
- Зарегистрирован: 02 май 2006, 13:45
Сообщение
sunduk4 » 06 июн 2006, 10:14
Всем спасибо! Разобрался.
Оказалось, что для одной из колонок память не совсем верно выделялась.
-
Ivan_Pisarevsky
- Заслуженный разработчик
- Сообщения: 644
- Зарегистрирован: 15 фев 2005, 11:34
Сообщение
Ivan_Pisarevsky » 06 июн 2006, 10:19
sunduk4 писал(а):так это ты в своем коде их буферизируешь. или нет?
в коде данные из получаемой записи собираются в строку и пишутся в файл. строка - массив символов.
кстати, malloc, вижу, а совобождается где?
потом, я смутно помню описание xsqlda, но что то не припомню, чтобы под sql_ind надо было память аллокировать...
прошу прощения, после free_statement естественно делаю
free(main_sqlda)
судя по api guide, под нулл-индикатор надо выделять память..
Что мешает использовать экстернал тэйбл? инсерт ... селект тра-та-та, потом обычнам копированием забрал готовый файлик.
-
sunduk4
- Сообщения: 18
- Зарегистрирован: 02 май 2006, 13:45
Сообщение
sunduk4 » 06 июн 2006, 10:26
Что мешает использовать экстернал тэйбл? инсерт ... селект тра-та-та, потом обычнам копированием забрал готовый файлик.
задача немного сложнее стоит. пытаюсь написать свой репликатор.
-
Dimitry Sibiryakov
- Заслуженный разработчик
- Сообщения: 1436
- Зарегистрирован: 15 сен 2005, 09:05
Сообщение
Dimitry Sibiryakov » 06 июн 2006, 10:55
sunduk4 писал(а):под SQL_VARYING память выделяю так -
main_sqlda->sqlvar->sqldata = (char *)malloc(sizeof(char)*main_sqlda->sqlvar->sqllen + 1)
Читай по губам: sqllen+sizeof(SHORT). sizeof(SHORT) ==
2. Т.е. ты под буфер выделяешь на байт меньше чем требуется.
-
Dimitry Sibiryakov
- Заслуженный разработчик
- Сообщения: 1436
- Зарегистрирован: 15 сен 2005, 09:05
Сообщение
Dimitry Sibiryakov » 06 июн 2006, 10:56
sunduk4 писал(а):задача немного сложнее стоит. пытаюсь написать свой репликатор.
А чем готовые не устраивают? Я понимаю IBReplicator дорогой, но FBReplicator-то халява.
-
sunduk4
- Сообщения: 18
- Зарегистрирован: 02 май 2006, 13:45
Сообщение
sunduk4 » 06 июн 2006, 11:45
Читай по губам: sqllen+sizeof(SHORT). sizeof(SHORT) == 2. Т.е. ты под буфер выделяешь на байт меньше чем требуется.
упс, точно...
А чем готовые не устраивают? Я понимаю IBReplicator дорогой, но FBReplicator-то халява.
к требованиям он не совсем подходит. -
1. связь между серверами оставляет желать лучшего, по-этому о прямом коннекте речь идти не может.
2. нужна репликация блоб-полей.
3. ОС - линукс
это минимум требований.