Название: Странное поведение QSqlQuery и ошибка Driver Not Loaded Отправлено: SadSido от Декабрь 08, 2008, 13:00 Добрый день!
Хочу поделится описанием неочевидной проблемы, с которой я столкнулся при программировании запросов к базе данных на SQLite (от типа базы данных проблема не зависит). В коде создаётся некий модуль, инкапсулирующий работу с БД. Создаётся сама база и несколько наиболее употребляемых запросов SQL: Код: class CDatabaseModule Этот код содержит фундаментальную ошибку, поведение которой выражается в том, что все SQL-запросы к этой БД будут провалены. То есть, для любого объекта QSqlQuery к этой БД метод exec() вернёт false. Будет получен объект QSqlError с текстом driverText() = "Driver not loaded" и databaseText() = "Driver not loaded". На отлов этой ошибки может уйти много времени, но всегда приятнее изучать чужие грабли, чем наступать на свои. Итак: Объекты mBeginQuery и mCommitQuery создаются на стеке, а не в динамической памяти, и, поскольку в коде конструктора нет никаких указаний по поводу их инициализации, компилятор вызывает для них конструкторы по умолчанию. Класс QSqlQuery имеет конструктор без параметров: QSqlQuery(const QString& iQuery = QString(), QSqlDatabase iDB = 0). Таким образом, объекты mBeginQuery и mCommitQuery инициализируются ссылкой на базу данных до того, как было установлено соединение с базой данных. Преодолевается ошибка следующим образом: Код: // ... Из всего этого мне осталось непонятным лишь только, почему ВСЕ запросы проваливались? Даже те, что были созданы после инициализации базы данных... Полагаю тут проявляется какой-нибудь побочный эффект работы с глобальными переменными QSqlDatabase... В-общем, надеюсь, что это кому-нибудь сэкономит время! Удачного программирования! Название: Re: Странное поведение QSqlQuery и ошибка Driver Not Loaded Отправлено: ритт от Декабрь 08, 2008, 13:13 Цитировать bool QSqlDatabase::transaction () Begins a transaction on the database if the driver supports transactions. Returns true if the operation succeeded. Otherwise it returns false. Цитировать bool QSqlDatabase::commit () Commits a transaction to the database if the driver supports transactions and a transaction() has been started. Returns true if the operation succeeded. Otherwise it returns false. Note: For some databases, the commit will fail and return false if there is an active query using the database for a SELECT. Make the query inactive before doing the commit. Call lastError() to get information about errors. Цитировать bool QSqlDatabase::rollback () Rolls back a transaction on the database, if the driver supports transactions and a transaction() has been started. Returns true if the operation succeeded. Otherwise it returns false. Note: For some databases, the rollback will fail and return false if there is an active query using the database for a SELECT. Make the query inactive before doing the rollback. Call lastError() to get information about errors. Название: Re: Странное поведение QSqlQuery и ошибка Driver Not Loaded Отправлено: Rcus от Декабрь 08, 2008, 13:37 Пока соединение с базой не установлено запросы нормально не инициализируются. Можно просто добавить после открытия соединения
Код
Название: Re: Странное поведение QSqlQuery и ошибка Driver Not Loaded Отправлено: SadSido от Декабрь 08, 2008, 15:26 > Константин
Спасибо! Database::transaction() и Database::commit()... Уже несколько раз убеждался, что пытаюсь изобрести то, что уже есть в Qt4. Но пользователь может захотеть кешировать произвольные запросы, например SELECT. >Rcus Вы уверены? По-моему, этот номер не пройдёт :) Обращаю внимание, что в исходном коде проваливались ВСЕ запросы к БД, а не только "BEGIN" и "COMMIT"... Как мне кажется, объявлять переменные QSqlQuery на стеке в рассматриваемом примере просто нельзя . Название: Re: Странное поведение QSqlQuery и ошибка Driver Not Loaded Отправлено: Rcus от Декабрь 08, 2008, 17:08 Уверен, потому что и на вашем примере проверил, и много раз до этого так делал.
Попробуйте после Код вставить Код
Название: Re: Странное поведение QSqlQuery и ошибка Driver Not Loaded Отправлено: ритт от Декабрь 08, 2008, 18:28 Спасибо! Database::transaction() и Database::commit()... Уже несколько раз убеждался, что пытаюсь изобрести то, что уже есть в Qt4. Но пользователь может захотеть кешировать произвольные запросы, например SELECT. пожалуйста. у тебя такой же точно ассистант и ты точно так же мог копнуть доки по интересующему вопросу.кешируй на здоровье. только не забудь перед закрытием и удалением базы отключить "кешируемый" запрос (queryVar = QSqlQuery() или queryVar.finish())... Обращаю внимание, что в исходном коде проваливались ВСЕ запросы к БД, а не только "BEGIN" и "COMMIT"... Как мне кажется, объявлять переменные QSqlQuery на стеке в рассматриваемом примере просто нельзя . можно. а запросы у тебя проваливались (если действительно _все_), скорее всего, из-за сбоя инициализации - попробовал бы клонироваь коннект и проверить запросы на клоне. |