Russian Qt Forum
Июнь 16, 2024, 05:03 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: QSqlQuery - почему не работает last/size?  (Прочитано 10015 раз)
Alex_C
Гость
« : Август 10, 2012, 09:08 »

Переделываю свой проект на Qt. До того, как не столкнулся с работой с БД Access все было отлично. Но такое впечатление, что с Access Qt принципиально не хочет работать.
Делаю запрос:
Код
C++ (Qt)
   QSqlQuery q(queryStr);
   if(q.isSelect())
   {
       q.last();
       qDebug() << q.value(2).toString();
   }
 
Выдает
QSqlQuery::value: not positioned on a valid record

Меняешь last на first - все ок!
И size выдает -1.
Проверял - q.last() выдает true.
Может что не так делаю?
Записан
LisandreL
Птица говорун
*****
Offline Offline

Сообщений: 984


Надо улыбаться


Просмотр профиля
« Ответ #1 : Август 10, 2012, 09:10 »

А exec где?
Записан
Alex_C
Гость
« Ответ #2 : Август 10, 2012, 09:44 »

Из документации:
If query is not an empty string, it will be executed.

queryStr - как раз строка "SELECT * ... "
Записан
Странник
Гость
« Ответ #3 : Август 10, 2012, 09:44 »

А exec где?
в генетическом кодЕ:
Цитировать
QSqlQuery::QSqlQuery ( const QString & query = QString(), QSqlDatabase db = QSqlDatabase() )
Constructs a QSqlQuery object using the SQL query and the database db. If db is not specified, or is invalid, the application's default database is used. If query is not an empty string, it will be executed.
что касается last() - если возвращает true, логично ожидать успешного выполнения. похоже на баг.
Записан
LisandreL
Птица говорун
*****
Offline Offline

Сообщений: 984


Надо улыбаться


Просмотр профиля
« Ответ #4 : Август 10, 2012, 10:10 »

в генетическом кодЕ
Всегда через prepare использую, поэтому забыл, что так сразу выполняться будет.
Код
C++ (Qt)
QVariant QSqlQuery::value(int index) const
{
   if (isActive() && isValid() && (index > QSql::BeforeFirstRow))
       return d->sqlResult->data(index);
   qWarning("QSqlQuery::value: not positioned on a valid record");
   return QVariant();
}
Проверяйте, какое из 3 условий у вас не срабатывает.
Записан
Alex_C
Гость
« Ответ #5 : Август 10, 2012, 15:14 »

Код
C++ (Qt)
   QSqlQuery q;
   q.exec(queryStr);
 
   qDebug() << q.isActive();
   qDebug() << q.isSelect();
   q.last();
   qDebug() << q.value(2).toString();
 

ответ

Код:
true 
true
QSqlQuery::value: not positioned on a valid record

Итог: все условия срабатывают.

... q.last() тоже true возвращает.
« Последнее редактирование: Август 10, 2012, 15:16 от Alex_C » Записан
LisandreL
Птица говорун
*****
Offline Offline

Сообщений: 984


Надо улыбаться


Просмотр профиля
« Ответ #6 : Август 10, 2012, 15:25 »

Итог: все условия срабатывают
Я имел в виду вот эти 3:
1) isActive()
2) isValid()
3) index > QSql::BeforeFirstRow

Первый проверен, третий очевиден, остался isValid().

Может запрос завершается с ошибкой? Что q.exec возвращает?
Записан
Alex_C
Гость
« Ответ #7 : Август 13, 2012, 14:40 »

Вот что получается.
Код:

Код
C++ (Qt)
   qDebug() << q.exec(queryStr);
   qDebug() << q.first();
   qDebug() << q.isActive();
   qDebug() << q.isSelect();
   qDebug() << q.isValid();
   qDebug() << q.last();
   qDebug() << q.isValid();
   qDebug() << q.value(2).toString();
 

вывод
Код
C++ (Qt)
true
true
true
true
true
true
false
QSqlQuery::value: not positioned on a valid record
 

Итог: last() не срабатывает. Почему?
Чтобы добраться до последней записи нужно while(q.next());
Но разве так правильно с БД работать?
Записан
LisandreL
Птица говорун
*****
Offline Offline

Сообщений: 984


Надо улыбаться


Просмотр профиля
« Ответ #8 : Август 13, 2012, 15:05 »

И size выдает -1.
Если это всегда так, то можно предположить, что
QSqlDriver::hasFeature( QSqlDriver::QuerySize ) == false
а это скорее всего означает, что данная БД позволяет осуществлять только последовательный доступ к записям и даже правильная реализация last() сводилось бы к while(q.next());
Но то что q.last(); возвращает true, но при этом устанавливает курсор на невалидную позицию - это безусловно баг. Было бы не плохо оформить багрепорт.

P.S. queryStr не покажете?
Записан
Alex_C
Гость
« Ответ #9 : Август 13, 2012, 16:19 »

Да тут похоже баг существенно больше: БД - Access, и методы last/first/RecordCount в том же Дельфи через ADO работают без проблем. 
А строка запроса самая простоя - SELECT * FROM table.
Мда, перечитал все что нашел по работе Qt с БД - по хоже у Qt это самое слабое место. Дельфи/Билдер куда как больше возможностей предоставляют.
Записан
Странник
Гость
« Ответ #10 : Август 13, 2012, 22:29 »

Да тут похоже баг существенно больше: БД - Access, и методы last/first/RecordCount в том же Дельфи через ADO работают без проблем. 
А строка запроса самая простоя - SELECT * FROM table.
Мда, перечитал все что нашел по работе Qt с БД - по хоже у Qt это самое слабое место. Дельфи/Билдер куда как больше возможностей предоставляют.
а то, что вы пользуетесь ODBC, не смущает?) напишите свой ADOвый драйвер, с маджонгом и гейшами - нация оценит.
Записан
Noel
Гость
« Ответ #11 : Август 14, 2012, 15:35 »

Цитировать
Мда, перечитал все что нашел по работе Qt с БД - по хоже у Qt это самое слабое место. Дельфи/Билдер куда как больше возможностей предоставляют.
Как писали классики : "Ну ты, батенька, да... Ну ты, батенька, тут сглупил, конечно! Сказал не подумавши!".
В своё время (года два-три назад) пилил курсачи за еду на Qt. И как раз с QODBC драйвером очень часто сталкивался. Всё работает нормально. Никаких багов я в нём не заметил, тем более, что он из коробки идёт.
Читать надо не "всё, что нашёл по работе.." а доку и екземплы. Тем более, что екземплов - тьма-тьмущая.

If не нужен. На самом деле мне кажется, что QSqlQuery просто не привязан к твоей БД. Т.е. он выполняется куда-то в холостую.
Код:
QSqlQuery q(queryStr);
if(q.isSelect())
{
    q.last();
    qDebug() << q.value(2).toString();
}

Попробуй, к примеру, этот код.

Код:
QSqlDataBase m_db = QSqlDataBase::addDatabase("QODBC", "newConnection");
m_db.setDatabaseName("mydb");
m_db.open();

QSqlQuery que(m_db);
if (que.exec("SELECT * FROM table"))
    que.last();
int someVal = que.value(0).toInt();

Записан
Странник
Гость
« Ответ #12 : Август 14, 2012, 15:50 »

Всё работает нормально. Никаких багов я в нём не заметил, тем более, что он из коробки идёт.
багов-то нет, но функционал уступает ADO. да и помедленнее он будет.
Записан
Noel
Гость
« Ответ #13 : Август 14, 2012, 16:45 »

Цитировать
функционал уступает ADO.
Пожалуйста, можно примеры?
Цитировать
да и помедленнее он будет.
Я пологаю, что не критично медленней.

Тем более, что у Qt есть контейнер ActiveX. При желании возни с ADO можно идти прямиком туда. Только особых преймуществ - не будет.
Записан
Странник
Гость
« Ответ #14 : Август 14, 2012, 17:31 »

Пожалуйста, можно примеры?
если идти по фичам драйвера: QSqlDriver::QuerySize, QSqlDriver::LastInsertId (пустячок, а неприятно), QSqlDriver::MultipleResultSets (намучался в свое время - ODBC вел себя крайне неадекватно).
Alex_C недавно напомнил, что ODBC не поддерживает хранение резалтсета не сервере. и в производительности разница заметна, работаю с MS SQL по ADO и ODBC. c ODBC, правда, еще и Qt-оверхед.
Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.295 секунд. Запросов: 22.