Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / C++ [игнор отключен] [закрыт для гостей] / Qt+firebird как правильно реализовать выборку >50 000 строк / 25 сообщений из 26, страница 1 из 2
13.10.2012, 16:24
    #37996995
magister_ludi
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Qt+firebird как правильно реализовать выборку >50 000 строк
Собственно сабж. Если делать в лоб, т.е. с помощью QSqlQuery, валится на строке 36 064 возвращаемого результата.
QSqlModel подойдет для этой цели?
Спасибо.
...
Рейтинг: 0 / 0
13.10.2012, 16:26
    #37996996
Qt+firebird как правильно реализовать выборку >50 000 строк
magister_ludiСобственно сабж. Если делать в лоб, т.е. с помощью QSqlQuery, валится на строке 36 064 возвращаемого результата.
QSqlModel подойдет для этой цели?
Спасибо.
Какие название и номер ошибки?
...
Рейтинг: 0 / 0
13.10.2012, 16:34
    #37997002
magister_ludi
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Qt+firebird как правильно реализовать выборку >50 000 строк
название и номер ошибкиmagister_ludiСобственно сабж. Если делать в лоб, т.е. с помощью QSqlQuery, валится на строке 36 064 возвращаемого результата.
QSqlModel подойдет для этой цели?
Спасибо.
Какие название и номер ошибки?

сигнал: sigsegv. назначение: segmentation fault.
...
Рейтинг: 0 / 0
13.10.2012, 19:24
    #37997094
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Qt+firebird как правильно реализовать выборку >50 000 строк
magister_ludiсигнал: sigsegv. назначение: segmentation fault.

Разреши core dump, грузи его в gdb, смотри где и на чём оно упало.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
13.10.2012, 19:52
    #37997114
magister_ludi
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Qt+firebird как правильно реализовать выборку >50 000 строк
Dimitry Sibiryakovmagister_ludiсигнал: sigsegv. назначение: segmentation fault.

Разреши core dump, грузи его в gdb, смотри где и на чём оно упало.


дамп мало о чем сказал. вылетел на while(query.next()). Судя по стеку вызовов проблема в qt'шном драйвере для firebird, присутствует вызов QSqlCachedResult::cacheNext().
Драйвер устанавливался как пакет из репозитория Debian 6, командой apt-get install.
Были у кого такие проблемы? Как решали?
...
Рейтинг: 0 / 0
13.10.2012, 20:00
    #37997124
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Qt+firebird как правильно реализовать выборку >50 000 строк
magister_ludiвылетел на while(query.next()).
А ты уверен, что для этого цикла тебе требуется именно кэшированный датасет?.. Может,
обойдёшься таким, который не складывает полученные данные за щёку?..
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
13.10.2012, 20:21
    #37997140
magister_ludi
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Qt+firebird как правильно реализовать выборку >50 000 строк
Dimitry Sibiryakovmagister_ludiвылетел на while(query.next()).
А ты уверен, что для этого цикла тебе требуется именно кэшированный датасет?.. Может,
обойдёшься таким, который не складывает полученные данные за щёку?..


query->setForwardOnly(true)?
...
Рейтинг: 0 / 0
15.10.2012, 16:59
    #37998969
kolobok0
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Qt+firebird как правильно реализовать выборку >50 000 строк
magister_ludi..на строке 36 064 возвращаемого результата. ...

вот мне дико интересно, а что потом Вы будете делать с результатом то???

представил бесконечную бумажную ленту ползущую из принтера(типа убить бумагу, принтер, тонер в раз)...
Или файл отчёта для весу так сказать (типа у меня отчётов на 20 гигов!)?
Может быть Вы захотели всё втянуть "для скорости", и у вас самое крутое локальное железо? :)

короче говоря - просвятите дурака нахрена это делать то???

(круглый)
...
Рейтинг: 0 / 0
15.10.2012, 17:36
    #37999059
vvm
vvm
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Qt+firebird как правильно реализовать выборку >50 000 строк
kolobok0,

Назови, пожалуйста, нижнюю границу обёма выборки, до которой ты бы не стал поднимать свой вопрос.
Спасибо. :)
...
Рейтинг: 0 / 0
15.10.2012, 17:59
    #37999099
mayton
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Qt+firebird как правильно реализовать выборку >50 000 строк
magister_ludiприсутствует вызов QSqlCachedResult::cacheNext().
Скорее всего ты упёрся в лимит объёма этого Кешированного ДатаСета.
Читай документацию. Да и вообще, знающие верно подметили
что прогружать всю базу на клиента это не cool. Соптимизируй
объём.
...
Рейтинг: 0 / 0
15.10.2012, 19:45
    #37999223
Anatoly Moskovsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Qt+firebird как правильно реализовать выборку >50 000 строк
vvmkolobok0,

Назови, пожалуйста, нижнюю границу обёма выборки, до которой ты бы не стал поднимать свой вопрос.
Спасибо. :)
2-3 экрана записей
...
Рейтинг: 0 / 0
16.10.2012, 13:20
    #38000280
magister_ludi
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Qt+firebird как правильно реализовать выборку >50 000 строк
kolobok0magister_ludi..на строке 36 064 возвращаемого результата. ...

короче говоря - просвятите дурака нахрена это делать то???

(круглый)

Специализированная программа для создания файлов конфигурации графа технического состояния промышленного комплекса. Не я это придумал, да.
...
Рейтинг: 0 / 0
16.10.2012, 13:35
    #38000324
magister_ludi
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Qt+firebird как правильно реализовать выборку >50 000 строк
maytonmagister_ludiприсутствует вызов QSqlCachedResult::cacheNext().
Да и вообще, знающие верно подметили
что прогружать всю базу на клиента это не cool. Соптимизируй
объём.

Все верно, это я понимаю. Ситуация стандартна: кто-то эту жесть придумал, другой написал и уволился, а третий со всем этим гумном разбирается. И вот в текущей ситуации, кроме как делать выборку по всем записям, ничего сделать нельзя. Благо база локальная.
...
Рейтинг: 0 / 0
16.10.2012, 15:08
    #38000578
rovan
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Qt+firebird как правильно реализовать выборку >50 000 строк
Сделай setForwardOnly(true), и, раз уж не обойтись без предварительного кэширования, начитывай данные в свои струтуры. И храни в своих структурах. Так, хотя бы, сможешь управлять процессом начитки и кеширования.
...
Рейтинг: 0 / 0
17.10.2012, 05:57
    #38001585
magister_ludi
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Qt+firebird как правильно реализовать выборку >50 000 строк
rovanСделай setForwardOnly(true), и, раз уж не обойтись без предварительного кэширования, начитывай данные в свои струтуры. И храни в своих структурах. Так, хотя бы, сможешь управлять процессом начитки и кеширования.

так и делаю. результат такой же: segmentation fault
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
               QSqlQuery* query = new QSqlQuery(this->dbss);              
               QString queryString = "SELECT FIRST %1 SKIP %2 * FROM SAVE_ADDRS";
               query->setForwardOnly(true);
              //формирование строки запроса не привожу
               if (query->exec(queryStringWithArgs))
               {
                   while(query->next())
                   {
                       //тут действия с данными
                       //где-то на записи 36 066 ломается
                   }
               }
...
Рейтинг: 0 / 0
17.10.2012, 06:09
    #38001589
Anatoly Moskovsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Qt+firebird как правильно реализовать выборку >50 000 строк
magister_ludi,

А есть segfault если закомментарить тело цикла?
...
Рейтинг: 0 / 0
17.10.2012, 06:15
    #38001593
Anatoly Moskovsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Qt+firebird как правильно реализовать выборку >50 000 строк
magister_ludiформирование строки запроса не привожу

И кстати зря не приводите, т.к. в коде форматирующем строки часто бывают ошибки переполнения буфера. А они в свою очередь прямо ведут к segfault в произвольных местах программы.
...
Рейтинг: 0 / 0
17.10.2012, 06:42
    #38001601
magister_ludi
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Qt+firebird как правильно реализовать выборку >50 000 строк
Anatoly Moskovskymagister_ludi,

А есть segfault если закомментарить тело цикла?

все работает
...
Рейтинг: 0 / 0
17.10.2012, 06:59
    #38001607
magister_ludi
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Qt+firebird как правильно реализовать выборку >50 000 строк
Anatoly Moskovskymagister_ludiформирование строки запроса не привожу

И кстати зря не приводите, т.к. в коде форматирующем строки часто бывают ошибки переполнения буфера. А они в свою очередь прямо ведут к segfault в произвольных местах программы.

Почему я не стал писать формироание строки запроса. Изначально запрос был таким:
Код: plsql
1.
SELECT * FROM SAVE_ADDRS



Это уже потом начал подгружать данные порциями в надежде победить ошибку и все равно результата нет.
...
Рейтинг: 0 / 0
17.10.2012, 08:15
    #38001632
rovan
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Qt+firebird как правильно реализовать выборку >50 000 строк
magister_ludiПочему я не стал писать формироание строки запроса. Изначально запрос был таким:

Так а сейчас он какой?
...
Рейтинг: 0 / 0
17.10.2012, 13:39
    #38002326
Anatoly Moskovsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Qt+firebird как правильно реализовать выборку >50 000 строк
magister_ludiAnatoly Moskovskymagister_ludi,

А есть segfault если закомментарить тело цикла?

все работает
Ну так как вы нам тогда предлагаете гадать из-за чего ошибка, если не приведен код вызывающий ее?
...
Рейтинг: 0 / 0
17.10.2012, 20:07
    #38003280
magister_ludi
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Qt+firebird как правильно реализовать выборку >50 000 строк
Извиняюсь. Вот код:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
unsigned long *buff/*буфер*/, i, n/*позиция в буфере*/, num /*число символов на запись*/;
    i = 0; n = 0; 
    QString s;
    buff = NULL;

       if (this->dbss.open())
       {
               QSqlQuery query;
               QString queryString = "SELECT * FROM SAVE_ADDRS";
               query.setForwardOnly(true);

               if (query.exec(queryString))
               {

                   while(query.next())
                   {
                       if (query.at() == 0)
                       {
                           //из первой строки берем кол-во записей
                           if (query.value(0).toInt() !=1)
                               return;
                           *cnt = query.value(1).toInt();//кол-во записей
                           i++;
                           continue;

                       }
                       if (query.at() == 1)
                       {
                            //из второй размер буфера
                            if (query.value(0).toInt() !=2)
                                return;
                            *size = *cnt + query.value(1).toInt();//размер буфера
                            buff = (long unsigned int*)malloc(*size);
                            _mem = (void*)buff;
                            n++;
                            if (buff == NULL)
                                return;
                            i++;
                            continue;

                       }
                       if ((query.at() > 1)&&(query.value(0).toInt() !=0))
                       {
                           return;
                       }
                       if (i ==(*cnt))
                       {
                           break;
                       }

                       if (query.value(2).isNull())
                       {
                           buff = 0;
                           n++;
                       }
                       else
                       {
                         s = query.value(2).toString().trimmed();
                         const char* sourceString = s.toAscii().constData();
                         num =s.size();
                          //если копирование в буфер убрать, то все работает.
                          memcpy(&buff[n], sourceString,num);
                          n+=num;
                          buff[n]=0;
                          n++;
                          i++;
                          qDebug()<< i << sourceString;
                       }


                   }
           int writeResult = fwrite((void *)buff, *size, 1, _ofile);
           free(buff); _mem = NULL;
           if(writeResult != 1)
           {
               qDebug() << "error write data to file";
           }
       }

}
...
Рейтинг: 0 / 0
17.10.2012, 20:35
    #38003303
Anatoly Moskovsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Qt+firebird как правильно реализовать выборку >50 000 строк
magister_ludi,

Обратите внимание на этот код
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
if (query.value(2).isNull())
                       {
                           buff = 0;
                           ...
                       }
                       else
                       {
                           ...
                          //если копирование в буфер убрать, то все работает.
                          memcpy(&buff[n], sourceString,num);
                           ...
                       }


Т.е. у вас, если в очередной записи встретился null в поле №2, то указатель на буфер обнуляется, и на следующей итерации цикла где не будет null, memcpy затрет память около нулевого адреса (а эта страница всегда защищена от записи - отсюда и сегфолт).

Ну и обнуление указателя на буфер делает бессмысленным free() в конце цикла.
...
Рейтинг: 0 / 0
17.10.2012, 20:44
    #38003309
Anatoly Moskovsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Qt+firebird как правильно реализовать выборку >50 000 строк
Ну и так тоже нельзя делать:
Код: plaintext
1.
const char* sourceString = s.toAscii().constData();


- т.к. здесь вы в указатель записываете адрес временной переменной, которая будет удалена до того как вы этим указателем воспольуетесь.

Правильно так:
Код: plaintext
1.
2.
XXXX tmp_s = s.toAscii(); // теперь время жизни tmp_s больше чем sourceString
const char* sourceString = tmp_s.constData();


Вместо XXX поставьте тип который возвращает toAscii() (я его не знаю, см. доку)

Это ошибка тоже может приводить к сегфолту. Но думаю что до нее не доходит, т.к. срабатывает гарантированный сегфолт описанный в моем предыдущем сообщении.
...
Рейтинг: 0 / 0
17.10.2012, 20:57
    #38003315
Anatoly Moskovsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Qt+firebird как правильно реализовать выборку >50 000 строк
И еще.

У вас объявлено
Код: plaintext
1.
unsigned long *buff

, т.е. указатель на массив элементов размера 4 или 8 байтов.
А в коде вы к нему обращаетесь как к указателю на байты (char *buff).
Код: plaintext
1.
2.
3.
memcpy(&buff[n], sourceString,num);  // num - размер строки в байтах
n+=num; // но n в следующецй строке индексирует элементы размером в несколько байтов, прибавлять к нему байты некорректно 
buff[n]=0;


Это неминуемое переполнение буфера.
...
Рейтинг: 0 / 0
Форумы / C++ [игнор отключен] [закрыт для гостей] / Qt+firebird как правильно реализовать выборку >50 000 строк / 25 сообщений из 26, страница 1 из 2
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]