Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Change the behavior of the sqlite3_wal_hook() callback. It should now return SQLITE_OK or an error code and the error code is propagated back up the stack. If a checkpoint is desired, the callback should invoke sqlite3_wal_callback() itself. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
1b14195e05fe5551992a39246ec3bcf6 |
User & Date: | drh 2010-05-05 20:00:26.000 |
Context
2010-05-06
| ||
07:43 | Add tests for handling errors returned by xShm VFS methods. (check-in: fbbcacb137 user: dan tags: trunk) | |
2010-05-05
| ||
20:00 | Change the behavior of the sqlite3_wal_hook() callback. It should now return SQLITE_OK or an error code and the error code is propagated back up the stack. If a checkpoint is desired, the callback should invoke sqlite3_wal_callback() itself. (check-in: 1b14195e05 user: drh tags: trunk) | |
19:09 | Further simplifications to the SHM locking logic. Remove the SQLITE_SHM_QUERY option. Unify the WRITE to READ and RECOVER to READ transitions. (check-in: e9bfa6e4ce user: drh tags: trunk) | |
Changes
Changes to src/main.c.
︙ | ︙ | |||
1185 1186 1187 1188 1189 1190 1191 | sqlite3_mutex_leave(db->mutex); return pRet; } #ifndef SQLITE_OMIT_WAL /* ** The sqlite3_wal_hook() callback registered by sqlite3_wal_autocheckpoint(). | < | | | | < | > > > < < | 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 | sqlite3_mutex_leave(db->mutex); return pRet; } #ifndef SQLITE_OMIT_WAL /* ** The sqlite3_wal_hook() callback registered by sqlite3_wal_autocheckpoint(). ** Invoke sqlite3_wal_checkpoint if the number of frames in the log file ** is greater than sqlite3.pWalArg cast to an integer (the value configured by ** wal_autocheckpoint()). */ int sqlite3WalDefaultHook( void *pClientData, /* Argument */ sqlite3 *db, /* Connection */ const char *zDb, /* Database */ int nFrame /* Size of WAL */ ){ if( nFrame>=SQLITE_PTR_TO_INT(pClientData) ){ sqlite3_wal_checkpoint(db, zDb); } return SQLITE_OK; } #endif /* SQLITE_OMIT_WAL */ /* ** Configure an sqlite3_wal_hook() callback to automatically checkpoint ** a database after committing a transaction if there are nFrame or ** more frames in the log file. Passing zero or a negative value as the ** nFrame parameter disables automatic checkpoints entirely. ** ** The callback registered by this function replaces any existing callback ** registered using sqlite3_wal_hook(). Likewise, registering a callback ** using sqlite3_wal_hook() disables the automatic checkpoint mechanism ** configured by this function. */ int sqlite3_wal_autocheckpoint(sqlite3 *db, int nFrame){ #ifndef SQLITE_OMIT_WAL if( nFrame>0 ){ sqlite3_wal_hook(db, sqlite3WalDefaultHook, SQLITE_INT_TO_PTR(nFrame)); }else{ sqlite3_wal_hook(db, 0, 0); } #endif return SQLITE_OK; } /* ** Register a callback to be invoked each time a transaction is written ** into the write-ahead-log by this database connection. |
︙ | ︙ |
Changes to src/sqlite.h.in.
︙ | ︙ | |||
5776 5777 5778 5779 5780 5781 5782 | ** is a copy of the third parameter passed to sqlite3_wal_hook() when ** registering the callback. The second is a copy of the database handle. ** The third parameter is the name of the database that was written to - ** either "main" or the name of an ATTACHed database. The fourth parameter ** is the number of pages currently in the log file, including those that ** were just committed. ** | | | > | | 5776 5777 5778 5779 5780 5781 5782 5783 5784 5785 5786 5787 5788 5789 5790 5791 5792 5793 | ** is a copy of the third parameter passed to sqlite3_wal_hook() when ** registering the callback. The second is a copy of the database handle. ** The third parameter is the name of the database that was written to - ** either "main" or the name of an ATTACHed database. The fourth parameter ** is the number of pages currently in the log file, including those that ** were just committed. ** ** The callback function should normally return SQLITE_OK. If an error ** code is returned, that error will propagate back up through the ** SQLite code base to cause the statement that provoked the callback ** to fail. ** ** A single database handle may have at most a single log callback ** registered at one time. Calling [sqlite3_wal_hook()] replaces any ** previously registered log callback. */ void *sqlite3_wal_hook( sqlite3*, |
︙ | ︙ |
Changes to src/tclsqlite.c.
︙ | ︙ | |||
119 120 121 122 123 124 125 | char *zProgress; /* The progress callback routine */ char *zAuth; /* The authorization callback routine */ int disableAuth; /* Disable the authorizer if it exists */ char *zNull; /* Text to substitute for an SQL NULL value */ SqlFunc *pFunc; /* List of SQL functions */ Tcl_Obj *pUpdateHook; /* Update hook script (if any) */ Tcl_Obj *pRollbackHook; /* Rollback hook script (if any) */ | | | 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 | char *zProgress; /* The progress callback routine */ char *zAuth; /* The authorization callback routine */ int disableAuth; /* Disable the authorizer if it exists */ char *zNull; /* Text to substitute for an SQL NULL value */ SqlFunc *pFunc; /* List of SQL functions */ Tcl_Obj *pUpdateHook; /* Update hook script (if any) */ Tcl_Obj *pRollbackHook; /* Rollback hook script (if any) */ Tcl_Obj *pWalHook; /* WAL hook script (if any) */ Tcl_Obj *pUnlockNotify; /* Unlock notify script (if any) */ SqlCollate *pCollate; /* List of SQL collation functions */ int rc; /* Return code of most recent sqlite3_exec() */ Tcl_Obj *pCollateNeeded; /* Collation needed script */ SqlPreparedStmt *stmtList; /* List of prepared statements*/ SqlPreparedStmt *stmtLast; /* Last statement in the list */ int maxStmt; /* The next maximum number of stmtList */ |
︙ | ︙ | |||
482 483 484 485 486 487 488 | } if( pDb->pUpdateHook ){ Tcl_DecrRefCount(pDb->pUpdateHook); } if( pDb->pRollbackHook ){ Tcl_DecrRefCount(pDb->pRollbackHook); } | | | | 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 | } if( pDb->pUpdateHook ){ Tcl_DecrRefCount(pDb->pUpdateHook); } if( pDb->pRollbackHook ){ Tcl_DecrRefCount(pDb->pRollbackHook); } if( pDb->pWalHook ){ Tcl_DecrRefCount(pDb->pWalHook); } if( pDb->pCollateNeeded ){ Tcl_DecrRefCount(pDb->pCollateNeeded); } Tcl_Free((char*)pDb); } |
︙ | ︙ | |||
589 590 591 592 593 594 595 | SqliteDb *pDb = (SqliteDb*)clientData; assert(pDb->pRollbackHook); if( TCL_OK!=Tcl_EvalObjEx(pDb->interp, pDb->pRollbackHook, 0) ){ Tcl_BackgroundError(pDb->interp); } } | > > > | | | | | 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 | SqliteDb *pDb = (SqliteDb*)clientData; assert(pDb->pRollbackHook); if( TCL_OK!=Tcl_EvalObjEx(pDb->interp, pDb->pRollbackHook, 0) ){ Tcl_BackgroundError(pDb->interp); } } /* ** This procedure handles wal_hook callbacks. */ static int DbWalHandler( void *clientData, sqlite3 *db, const char *zDb, int nEntry ){ int ret = SQLITE_OK; Tcl_Obj *p; SqliteDb *pDb = (SqliteDb*)clientData; Tcl_Interp *interp = pDb->interp; assert(pDb->pWalHook); p = Tcl_DuplicateObj(pDb->pWalHook); Tcl_IncrRefCount(p); Tcl_ListObjAppendElement(interp, p, Tcl_NewStringObj(zDb, -1)); Tcl_ListObjAppendElement(interp, p, Tcl_NewIntObj(nEntry)); if( TCL_OK!=Tcl_EvalObjEx(interp, p, 0) || TCL_OK!=Tcl_GetIntFromObj(interp, Tcl_GetObjResult(interp), &ret) ){ Tcl_BackgroundError(interp); |
︙ | ︙ | |||
2771 2772 2773 2774 2775 2776 2777 | /* set ppHook to point at pUpdateHook or pRollbackHook, depending on ** whether [$db update_hook] or [$db rollback_hook] was invoked. */ Tcl_Obj **ppHook; if( choice==DB_UPDATE_HOOK ){ ppHook = &pDb->pUpdateHook; }else if( choice==DB_WAL_HOOK ){ | | | 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 | /* set ppHook to point at pUpdateHook or pRollbackHook, depending on ** whether [$db update_hook] or [$db rollback_hook] was invoked. */ Tcl_Obj **ppHook; if( choice==DB_UPDATE_HOOK ){ ppHook = &pDb->pUpdateHook; }else if( choice==DB_WAL_HOOK ){ ppHook = &pDb->pWalHook; }else{ ppHook = &pDb->pRollbackHook; } if( objc!=2 && objc!=3 ){ Tcl_WrongNumArgs(interp, 2, objv, "?SCRIPT?"); return TCL_ERROR; |
︙ | ︙ | |||
2797 2798 2799 2800 2801 2802 2803 | *ppHook = objv[2]; Tcl_IncrRefCount(*ppHook); } } sqlite3_update_hook(pDb->db, (pDb->pUpdateHook?DbUpdateHandler:0), pDb); sqlite3_rollback_hook(pDb->db,(pDb->pRollbackHook?DbRollbackHandler:0),pDb); | | | 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 | *ppHook = objv[2]; Tcl_IncrRefCount(*ppHook); } } sqlite3_update_hook(pDb->db, (pDb->pUpdateHook?DbUpdateHandler:0), pDb); sqlite3_rollback_hook(pDb->db,(pDb->pRollbackHook?DbRollbackHandler:0),pDb); sqlite3_wal_hook(pDb->db,(pDb->pWalHook?DbWalHandler:0),pDb); break; } /* $db version ** ** Return the version string for this database. |
︙ | ︙ |
Changes to src/vdbeapi.c.
︙ | ︙ | |||
314 315 316 317 318 319 320 | int rc = SQLITE_OK; #ifndef SQLITE_OMIT_WAL int i; for(i=0; i<db->nDb; i++){ Btree *pBt = db->aDb[i].pBt; if( pBt ){ int nEntry = sqlite3PagerWalCallback(sqlite3BtreePager(pBt)); | | | < < | 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 | int rc = SQLITE_OK; #ifndef SQLITE_OMIT_WAL int i; for(i=0; i<db->nDb; i++){ Btree *pBt = db->aDb[i].pBt; if( pBt ){ int nEntry = sqlite3PagerWalCallback(sqlite3BtreePager(pBt)); if( db->xWalCallback && nEntry>0 && rc==SQLITE_OK ){ rc = db->xWalCallback(db->pWalArg, db, db->aDb[i].zName, nEntry); } } } #endif return rc; } |
︙ | ︙ |
Changes to test/walhook.test.
︙ | ︙ | |||
45 46 47 48 49 50 51 | do_test walhook-1.2 { set ::wal_hook [list] execsql { INSERT INTO t1 VALUES(1, 'one') } set ::wal_hook } {main 5} do_test walhook-1.3 { | | | 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | do_test walhook-1.2 { set ::wal_hook [list] execsql { INSERT INTO t1 VALUES(1, 'one') } set ::wal_hook } {main 5} do_test walhook-1.3 { proc wal_hook {args} { db eval {PRAGMA wal_checkpoint}; return 0 } execsql { INSERT INTO t1 VALUES(2, 'two') } file size test.db } [expr 3*1024] do_test walhook-1.4 { proc wal_hook {zDb nEntry} { execsql { PRAGMA wal_checkpoint } return 0 |
︙ | ︙ |
Changes to test/walthread.test.
︙ | ︙ | |||
386 387 388 389 390 391 392 | INSERT INTO t1 VALUES(0, 0, 0); } } -thread t 10 { set nextwrite $E(pid) proc wal_hook {zDb nEntry} { | | | 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 | INSERT INTO t1 VALUES(0, 0, 0); } } -thread t 10 { set nextwrite $E(pid) proc wal_hook {zDb nEntry} { if {$nEntry>10} {db eval {PRAGMA wal_checkpoint}} return 0 } db wal_hook wal_hook while {[tt_continue]} { set max 0 while { $max != ($nextwrite-1) && [tt_continue] } { |
︙ | ︙ | |||
439 440 441 442 443 444 445 | # busy-handler is not required. Disable it to check that this is true. db busy {} while {[tt_continue]} integrity_check set {} ok } -thread w 1 { proc wal_hook {zDb nEntry} { | | | 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 | # busy-handler is not required. Disable it to check that this is true. db busy {} while {[tt_continue]} integrity_check set {} ok } -thread w 1 { proc wal_hook {zDb nEntry} { if {$nEntry>15} {db eval {PRAGMA wal_checkpoint}} return 0 } db wal_hook wal_hook set row 1 while {[tt_continue]} { db eval { REPLACE INTO t1 VALUES($row, randomblob(300)) } incr row |
︙ | ︙ |