Index: src/main.c ================================================================== --- src/main.c +++ src/main.c @@ -1114,10 +1114,11 @@ ){ sqlite3_mutex_enter(db->mutex); db->busyHandler.xFunc = xBusy; db->busyHandler.pArg = pArg; db->busyHandler.nBusy = 0; + db->busyTimeout = 0; sqlite3_mutex_leave(db->mutex); return SQLITE_OK; } #ifndef SQLITE_OMIT_PROGRESS_CALLBACK @@ -1151,12 +1152,12 @@ ** This routine installs a default busy handler that waits for the ** specified number of milliseconds before returning 0. */ int sqlite3_busy_timeout(sqlite3 *db, int ms){ if( ms>0 ){ - db->busyTimeout = ms; sqlite3_busy_handler(db, sqliteDefaultBusyCallback, (void*)db); + db->busyTimeout = ms; }else{ sqlite3_busy_handler(db, 0, 0); } return SQLITE_OK; } Index: src/pragma.c ================================================================== --- src/pragma.c +++ src/pragma.c @@ -1534,10 +1534,26 @@ */ if( sqlite3StrICmp(zLeft, "shrink_memory")==0 ){ sqlite3_db_release_memory(db); }else + /* + ** PRAGMA busy_timeout + ** PRAGMA busy_timeout = N + ** + ** Call sqlite3_busy_timeout(db, N). Return the current timeout value + ** if one is set. If no busy handler or a different busy handler is set + ** then 0 is returned. Setting the busy_timeout to 0 or negative + ** disables the timeout. + */ + if( sqlite3StrICmp(zLeft, "busy_timeout")==0 ){ + if( zRight ){ + sqlite3_busy_timeout(db, sqlite3Atoi(zRight)); + } + returnSingleInt(pParse, "timeout", db->busyTimeout); + }else + #if defined(SQLITE_DEBUG) || defined(SQLITE_TEST) /* ** Report the current state of file logs for all databases */ if( sqlite3StrICmp(zLeft, "lock_status")==0 ){ Index: test/lock.test ================================================================== --- test/lock.test +++ test/lock.test @@ -245,15 +245,38 @@ db2 timeout 400 execsql BEGIN execsql {UPDATE t1 SET a = 0 WHERE 0} catchsql {BEGIN EXCLUSIVE;} db2 } {1 {database is locked}} +do_test lock-2.8b { + db2 eval {PRAGMA busy_timeout} +} {400} do_test lock-2.9 { db2 timeout 0 execsql COMMIT } {} +do_test lock-2.9b { + db2 eval {PRAGMA busy_timeout} +} {0} integrity_check lock-2.10 +do_test lock-2.11 { + db2 eval {PRAGMA busy_timeout(400)} + execsql BEGIN + execsql {UPDATE t1 SET a = 0 WHERE 0} + catchsql {BEGIN EXCLUSIVE;} db2 +} {1 {database is locked}} +do_test lock-2.11b { + db2 eval {PRAGMA busy_timeout} +} {400} +do_test lock-2.12 { + db2 eval {PRAGMA busy_timeout(0)} + execsql COMMIT +} {} +do_test lock-2.12b { + db2 eval {PRAGMA busy_timeout} +} {0} +integrity_check lock-2.13 # Try to start two transactions in a row # do_test lock-3.1 { execsql {BEGIN TRANSACTION}