[Qt+Firebird] Как установить начальное значение генератора/последовательности из клиента

В процессе работы столкнулся с необходимостью – дать возможность пользователю устанавливать начальное значение для генератора (точнее в стандарте – SEQUENCE).
Плохо это или хорошо, речь не о том.

Для этого в Interbase/Firebirde используется DDL-запрос:
[code]
SET GENERATOR name TO value
[/code]
и соответственно был написан код:
[code]
int dmModule::setGenGoods(const int gen){
dmBaseModule::db.transaction();
QString query_str = “SET GENERATOR GEN_SPRGOODS_ID TO ?”;
QSqlQuery *query = new QSqlQuery(dmBaseModule::db);
query->prepare(query_str);
query->addBindValue(gen);
query->setForwardOnly(true);
query->exec();
if(query->lastError().isValid()){
QMessageBox::about(0,”errror”,query->lastError().text()+query->lastQuery());
dmBaseModule::db.rollback();
delete query;
return 0;
}
dmBaseModule::db.commit();
delete query;
return 1;

}

[/code]
Все было бы хорошо, код выполнялся но ничего не изменялось. В результате обсуждения на prog.org.ru было упомянуто о том, что якобы стандартный QIBASE возможно работает криво, а лучше воспользоваться QFIREBIRD на основе ibpp(Qt SQL driver for Firebird with IBPP library). После этого дело сдвинулось – так как теперь в процессе выполнения кода начала появляться ошибка:
[code]
***IBPP::LogicException*** Context: Statement::Execute Message:No Statement has been prepared. Unable execute statement
[/code]
что конечно не могло не радовать, с учетом того, что до этого не появлялось вообще ничего. В процессе дальнейшего обсуждения выяснилось, что на самом деле, использовать параметры совместно с DDL-запросами нельзя. Это первое. И второе – использование транзакции в данном случае было абсолютно лишним.
Кроме этого (но это уже не существенно), в стандарте SQL нет такого понятия как GENERATOR, и конструкция вида SET GENERATOR поддерживается Firebird 2.0 только для совместимости со старыми приложениями. Для новых приложений рекомендуется использовать стандартные CREATE SEQUENCE/ALTER SEQUENCE
Таким образом, итоговый код выглядит вот так:
[code]
int dmModule::setGenGoods(const int gen){
QString query_str = “ALTER SEQUENCE GEN_SPRGOODS_ID RESTART WITH “+QString::number(gen);
QSqlQuery *query = new QSqlQuery(dmBaseModule::db);
if(!query->exec(query_str)){
QMessageBox::about(0,”errror”,query->lastError().text()+query->lastQuery());
delete query;
return 0;
}
delete query;
return 1;

}

[/code]
Это один вариант. Если же необходимо организовать работу приложения с серверами версии ниже чем 2.0, то для этих целей нужно использовать следующий запрос (который кстати может быть параметризован)
[code]
int dmModule::setGenGoods(const int gen){
QString query_str = “SELECT GEN_ID(MY_GENERATOR, ? – GEN_ID(MY_GENERATOR, 0)) FROM RDB$DATABASE”;
QSqlQuery *query = new QSqlQuery(dmBaseModule::db);
query->prepare(query_str);
query->addBindValue(gen);
if(!query->exec()){
QMessageBox::about(0,”errror”,query->lastError().text()+query->lastQuery());
delete query;
return 0;
}
delete query;
return 1;

}

[/code]
Данный вопрос обсуждался на sql.ru
Хорошая статья о использовании генераторов в Firebird – рекомендую к изучению.

Спасибо за внимание. Если есть вопросы пишите.

Если статья была полезна вам – не забывайте поделиться ею со своими друзьями в социальных сетях. Если есть вопросы – задавайте в комментариях либо в наших социальных группах.