LINUX.ORG.RU

sqlite3 database is locked

 ,


0

2

Добрый день, всем!

Что делаю не так?

if(условие1){
   sqlite3 *db;
   sqlite3_open(mysqlitefile, &db);
   zRequest = "SELECT ... ? ...";
   sqlite3_stmt *stmt; 
   sqlite3_prepare_v2(db, zRequest,-1,&stmt,0);
   sqlite3_bind_...;
   sqlite3_step(stmt);
   val1 = sqlite3_column_double(stmt,0);
   ...
   sqlite3_reset(stmt);
   sqlite3_finalize(stmt);
   sqlite3_close(db);
}

// ...

if(условие2){
   sqlite3 *db;
   sqlite3_open(mysqlitefile, &db);
   zRequest = "UPDATE ... ? ...";
   sqlite3_stmt *stmt; 
   sqlite3_prepare_v2(db, zRequest,-1,&stmt,0);
   sqlite3_bind_...;
   sqlite3_step(stmt); // вот тут ошибка database is locked
   ...
   sqlite3_finalize(stmt);
   sqlite3_close(db);
}

P.S. ничего не меняется при от открытии базы во втором случае, с явным флагом о записи:

sqlite3_open_v2(mysqlitefile, &db, SQLITE_OPEN_READWRITE, NULL)



Последнее исправление: developer-cpp (всего исправлений: 2)

Ответ на: комментарий от ananas

не помогло:

chmod a=rw myfile.sqlite3

P.S.1 было rw у владельца, от имени которого запускается приложение

P.S.2 если запустить только пишущий код из условия2, без кода из условия 1 - все работает

developer-cpp
() автор топика
Ответ на: комментарий от ananas

Тут проблема с повторным открытием соединения с базой. Если в приложение выполняется только условие1 или только условие 2, то все ok.

А вот если выполняется условие1 а за ним условие2, то ошибка. Чего-то я не знаю о sqlite3.

developer-cpp
() автор топика
Ответ на: комментарий от developer-cpp

а ты в условие2 тоже select воткни. заодно и посмотришь, в повторном открытии дело, или в типе операции

ananas ★★★★★
()
Ответ на: комментарий от developer-cpp

если в условие2 воткнуть SELECT, то все нормально работает.

developer-cpp
() автор топика

НО ПРИ ЧЕМ ТУТ С++???

asaw ★★★★★
()

Скачай отладочные символы к sqlite3 и пройдись отладчиком пошагово по той функции.

i-rinat ★★★★★
()
Ответ на: комментарий от Sorcerer

Почему sqlite3_close() возвращает ошибку?

что не так в алгоритме ниже:

sqlite3 *db; 
sqlite3_stmt *stmt;  
char const* zReq;

// первая выборка
zReq = "SELECT ...;";
sqlite3_prepare_v2(db, zReq,-1,&stmt,0);
sqlite3_step(stmt);
Val1 = sqlite3_column_int(stmt,0);
sqlite3_reset(stmt);

// вторая выборка
zReq = "SELECT ...;";
sqlite3_prepare_v2(db, zReq,-1,&stmt,0);
sqlite3_step(stmt);
Val2 = sqlite3_column_int(stmt,0);
sqlite3_reset(stmt);

// третья выборка
zReq = "SELECT ... ? ? ? ? ?;";
sqlite3_prepare_v2(db, zReq,-1,&stmt,0);
sqlite3_bind_int(stmt,1,...);
sqlite3_bind_int(stmt,2,...);
// ...
while( sqlite3_step(stmt) == SQLITE_ROW ){
             x = sqlite3_column_int(stmt,0);
             y = sqlite3_column_int(stmt,1);
             // .....
}
sqlite3_reset(stmt);

// ...

sqlite3_finalize(stmt);
sqlite3_close(db); // ошибка SQLITE_BUSY 

P.S.

If the database connection is associated with unfinalized prepared statements or unfinished sqlite3_backup objects then sqlite3_close() will leave the database connection open and return SQLITE_BUSY.

developer-cpp
() автор топика
Ответ на: комментарий от developer-cpp

Почему-то вы считаете, что если вы переиспользуете переменную stmt, то вы работаете с «одним и тем же» объектом, и sqlite3_finalize нужно делать один раз (из последнего примера наконец стало очевидно, что именно так вы и считаете).

На самом деле prepare_v2, которому вы передаёте &stmt, присвоит stmt новый statement handle, а старый handle при этом потеряется: вы его не храните и не можете финализировать, а должны.

Вывод: просто добавьте sqlite3_finalize(stmt) в нескольких местах (там, где у вас сейчас reset, после которого ничего нет до следующего prepare_v2).

LeninGad
()
Ответ на: комментарий от developer-cpp

reset нужен, когда один и тот же statement перезапускаете (то есть с одним и тем же handle). Один раз prepare_v2, много раз bind/step/reset, bind/step/step/reset, один раз finalize.

Можно, например, подготовить много statement'ов и хранить все их handle, пользоваться по необходимости, а перед закрытием базы на каждый из них finalize сделать. А можно обмазать это какими-нибудь C++-классами, которые будут делать prepare_v2 перед первым использованием данного запроса, и finalize в деструкторе (если был сделан prepare_v2).

LeninGad
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.