From: danielk1977 Date: Fri, 16 Dec 2005 06:54:01 +0000 (+0000) Subject: Add the sqlite3_rollback_hook() API. Still requires further testing. (CVS 2823) X-Git-Tag: version-3.6.10~3337 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=71fd80bf5ca3027464eb233c36bd928f2249edc4;p=thirdparty%2Fsqlite.git Add the sqlite3_rollback_hook() API. Still requires further testing. (CVS 2823) FossilOrigin-Name: 3baa3ff32435b64e7ae7646b17a98fef9296aaa0 --- diff --git a/main.mk b/main.mk index 32ccb77ca2..ff6b843b25 100644 --- a/main.mk +++ b/main.mk @@ -133,13 +133,14 @@ TESTSRC = \ $(TOP)/src/test4.c \ $(TOP)/src/test5.c \ $(TOP)/src/test6.c \ - $(TOP)/src/test_async.c \ $(TOP)/src/utf.c \ $(TOP)/src/util.c \ $(TOP)/src/vdbe.c \ $(TOP)/src/md5.c \ $(TOP)/src/where.c +# $(TOP)/src/test_async.c + # Header files used by all library source files. # HDR = \ diff --git a/manifest b/manifest index fa524f5373..01a4d601e6 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Initial\sinfrastructure\sfor\srecognizing\sDESC\sindices\sand\sbeing\sable\sto\sread\r\nand\swrite\solder\sdatabases\sthat\sspecify\sDESC\sindices\sbut\sdo\snot\sreally\suse\r\nthem.\s\sNothing\sis\sclose\sto\sworking\syet.\s(CVS\s2822) -D 2005-12-16T01:06:17 +C Add\sthe\ssqlite3_rollback_hook()\sAPI.\sStill\srequires\sfurther\stesting.\s(CVS\s2823) +D 2005-12-16T06:54:02 F Makefile.in e3c6b3a38d734d41574c04f2fc90d18de2b87102 F Makefile.linux-gcc aee18d8a05546dcf1888bd4547e442008a49a092 F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028 @@ -19,7 +19,7 @@ F doc/lemon.html f0f682f50210928c07e562621c3b7e8ab912a538 F doc/report1.txt a031aaf37b185e4fa540223cb516d3bccec7eeac F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 F ltmain.sh f6b283068efa69f06eb8aa1fe4bddfdbdeb35826 -F main.mk 1376cec5c19b087d00d679527cfab9fa6598c2c3 +F main.mk c5c5087f957210233fd6ecb5e7c161c2c90038b9 F mkdll.sh 5ec23622515d5bf8969404e80cfb5e220ddf0512 F mkopcodec.awk bd46ad001c98dfbab07b1713cb8e692fa0e5415d F mkopcodeh.awk 071dbba4eaf56c8d643baf4604a043af35683316 @@ -34,7 +34,7 @@ F src/alter.c 7bc737c689044fa00ff2f445139c61f5c9ee0ad8 F src/analyze.c ea42005eed52c382fcc7ef66969e7f1858597633 F src/attach.c ee70131f128d31a9c6dcb8824e8471c91b18601a F src/auth.c 31e2304bef67f44d635655f44234387ea7d21454 -F src/btree.c de0fc1a0f6a4631001ffb6070d1b7588cdebcbc5 +F src/btree.c f880db4dc6339e279e982a342cbd1ff7c1f0d388 F src/btree.h 1ed561263ca0e335bc3e81d761c9d5ff8c22f61e F src/build.c 178a5c36365b5ec89a4a29a74186583f503c10fa F src/callback.c 62066afd516f220575e81b1a1239ab92a2eae252 @@ -48,7 +48,7 @@ F src/hash.c 8747cf51d12de46512880dfcf1b68b4e24072863 F src/hash.h 1b0c445e1c89ff2aaad9b4605ba61375af001e84 F src/insert.c a5629e462560d6aa9be7e0dafb6ed1518bb623bb F src/legacy.c 59757d857ab95fcbb0ac27692d3201e35f093dd7 -F src/main.c 066356cdc7f7fbef389c1849b1ccbeec96a5b348 +F src/main.c cbab4a1b056eddf03f671f0e9d76f69f48e6bff2 F src/md5.c c5fdfa5c2593eaee2e32a5ce6c6927c986eaf217 F src/os.c 7b4a002d9c9421580276db55d2329636a604e8ef F src/os.h e941992043b127fdb1bd114f0b4319ae1c4562a7 @@ -68,10 +68,10 @@ F src/printf.c f47a2f4b5387cd2ebb12e9117a1a5d6bd9a2b812 F src/random.c ff5e9a8cad790e2a51cd4d2e7737dc8540e09d1d F src/select.c 2292b065bc6be61e01aad39a2e1b93e332fb7e57 F src/shell.c 4872acee1d2a826c73c914961e469e563204b7f9 -F src/sqlite.h.in 31ab5ef5268c7f1ee909151a0fc45c659290ec15 -F src/sqliteInt.h 853a868ee69e841b9eba078f359932cddd3cf264 +F src/sqlite.h.in 6b9ec2fee44d5a2da19e72f2890f802a9efe8e7c +F src/sqliteInt.h e6063bc65e02682ee923f795b74afa85d9823f9a F src/table.c 486dcfce532685b53b5a2b5da8bba0ded6fb2316 -F src/tclsqlite.c c2303e1b1e6602b8cfef4dad00e4d76a47868c5e +F src/tclsqlite.c b21dd96ffab1625c986513e003a1945a6ae112ae F src/test1.c d6924b182773b2ad3b22e435e4d3bfd5a846da9e F src/test2.c 36390cdfc70c08e5ee0b466d0654a117f398bbff F src/test3.c 7c97833e33496c2b69f4fe6b9882ac60a481da97 @@ -88,7 +88,7 @@ F src/vdbe.c a9acffc91d3e06af24dc1dcf5bf7d5e77460b1c5 F src/vdbe.h 8729a4ee16ff9aeab2af9667df3cf300ff978e13 F src/vdbeInt.h 7b8b8c5dcb203243e4a9a4414c9e488473f67741 F src/vdbeapi.c b270b680cbc5d20b5a1abfdb08339667985df94e -F src/vdbeaux.c 722736cd433f06942bc5c7b7915e6561be0b400c +F src/vdbeaux.c c878807fd0f5829c9a02fa069db2ec69692b0ff6 F src/vdbefifo.c 9efb94c8c3f4c979ebd0028219483f88e57584f5 F src/vdbemem.c deba8d6e3727643924b210a8c531a496c2b8d386 F src/where.c 269569f380ddc018518f67765fe2f0d3c8760e28 @@ -153,7 +153,7 @@ F test/enc3.test f6a5f0b7b7f3a88f030d3143729b87cd5c86d837 F test/expr.test 06381174d8c25fbbfd9ed335fe0cde835d39123d F test/fkey1.test 153004438d51e6769fb1ce165f6313972d6263ce F test/func.test e891bebf5a939fd45c9453ad35e2280f41a30687 -F test/hook.test 4a5e598af0dd2436f757706e1650be3e4bbe30a6 +F test/hook.test 2b771652ae4f27e95fc3e6992c618af7954ce785 F test/in.test cead6165aebbe0d451bb2263a307173acfeb6240 F test/index.test 3871c47ec475f779f0b99dc36a3d177951995712 F test/index2.test 9ad98243fd7fe833795a9cc662f371f0eed4ff4f @@ -221,7 +221,7 @@ F test/subselect.test 2d13fb7f450db3595adcdd24079a0dd1d2d6abc2 F test/sync.test 6e8b885cec5ccba2090e92c90f747a7142f53c88 F test/table.test ec0e6c2186bb8f6824f470caa118524dfd8fe057 F test/tableapi.test 6a66d58b37d46dc0f2b3c7d4bd2617d209399bd1 -F test/tclsqlite.test 9890d58c6c2a72b6a57daf88e2e7aa9c4a141213 +F test/tclsqlite.test 26ee144ca70738ee0f3d8b5c1113b2f13652658b F test/temptable.test 7927261befdbc7b0a7ffebb85ecc70a74fa7b15b F test/tester.tcl a06c798a653daefb5bce2c85fc3a7d06450a1875 F test/thread1.test 776c9e459b75ba905193b351926ac4019b049f35 @@ -327,7 +327,7 @@ F www/tclsqlite.tcl ddcf912ea48695603c8ed7efb29f0812ef8d1b49 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0 F www/version3.tcl a99cf5f6d8bd4d5537584a2b342f0fb9fa601d8b F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513 -P 4fba2db38e0693be52ca7251e4958bd836607f05 -R cf0e0e36b0268dddfac27efc891f1d3b -U drh -Z e31baf15a60fd5885441bd2ca28e4cd9 +P cd110aa225b09591064405dd8952b3df37278c52 +R 3161ff073c4e4c2688e57ee8d03a85ab +U danielk1977 +Z 7173f459f67aead630a0b046899d180b diff --git a/manifest.uuid b/manifest.uuid index cc851b73f4..d22ff49843 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -cd110aa225b09591064405dd8952b3df37278c52 \ No newline at end of file +3baa3ff32435b64e7ae7646b17a98fef9296aaa0 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index ba5e6c4926..65b5594dd6 100644 --- a/src/btree.c +++ b/src/btree.c @@ -9,7 +9,7 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* -** $Id: btree.c,v 1.273 2005/12/09 20:02:05 drh Exp $ +** $Id: btree.c,v 1.274 2005/12/16 06:54:02 danielk1977 Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** For a detailed discussion of BTrees, refer to @@ -4906,9 +4906,11 @@ int sqlite3BtreeClearTable(Btree *pBt, int iTable){ } } rc = clearDatabasePage(pBt, (Pgno)iTable, 0, 0); +#if 0 if( rc ){ sqlite3BtreeRollback(pBt); } +#endif return rc; } diff --git a/src/main.c b/src/main.c index 8bc6bb885b..ba0bb5feb3 100644 --- a/src/main.c +++ b/src/main.c @@ -14,7 +14,7 @@ ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** -** $Id: main.c,v 1.310 2005/12/15 15:22:09 danielk1977 Exp $ +** $Id: main.c,v 1.311 2005/12/16 06:54:02 danielk1977 Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -210,7 +210,14 @@ void sqlite3RollbackAll(sqlite3 *db){ db->aDb[i].inTrans = 0; } } - sqlite3ResetInternalSchema(db, 0); + if( db->flags&SQLITE_InternChanges ){ + sqlite3ResetInternalSchema(db, 0); + } + + /* If one has been configured, invoke the rollback-hook callback */ + if( db->xRollbackCallback ){ + db->xRollbackCallback(db->pRollbackArg); + } } /* @@ -534,7 +541,7 @@ void *sqlite3_profile( /*** EXPERIMENTAL *** ** ** Register a function to be invoked when a transaction comments. -** If either function returns non-zero, then the commit becomes a +** If the invoked function returns non-zero, then the commit becomes a ** rollback. */ void *sqlite3_commit_hook( @@ -552,15 +559,31 @@ void *sqlite3_commit_hook( ** Register a callback to be invoked each time a row is updated, ** inserted or deleted using this database connection. */ -void sqlite3_update_hook( +void *sqlite3_update_hook( sqlite3 *db, /* Attach the hook to this database */ void (*xCallback)(void*,int,char const *,char const *,sqlite_int64), void *pArg /* Argument to the function */ ){ + void *pRet = db->pUpdateArg; db->xUpdateCallback = xCallback; db->pUpdateArg = pArg; + return pRet; } +/* +** Register a callback to be invoked each time a transaction is rolled +** back by this database connection. +*/ +void *sqlite3_rollback_hook( + sqlite3 *db, /* Attach the hook to this database */ + void (*xCallback)(void*), /* Callback function */ + void *pArg /* Argument to the function */ +){ + void *pRet = db->pRollbackArg; + db->xRollbackCallback = xCallback; + db->pRollbackArg = pArg; + return pRet; +} /* ** This routine is called to create a connection to a database BTree diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 86d75d26d0..966b38a206 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -12,7 +12,7 @@ ** This header file defines the interface that the SQLite library ** presents to client programs. ** -** @(#) $Id: sqlite.h.in,v 1.146 2005/12/15 15:22:09 danielk1977 Exp $ +** @(#) $Id: sqlite.h.in,v 1.147 2005/12/16 06:54:02 danielk1977 Exp $ */ #ifndef _SQLITE3_H_ #define _SQLITE3_H_ @@ -1309,13 +1309,18 @@ void sqlite3_soft_heap_limit(int); ** ** The update hook is not invoked when internal system tables are ** modified (i.e. sqlite_master and sqlite_sequence). +** +** If another function was previously registered, its pArg value is returned. +** Otherwise NULL is returned. */ -void sqlite3_update_hook( +void *sqlite3_update_hook( sqlite3*, void(*)(void *,int ,char const *,char const *,sqlite_int64), void* ); +void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*); + /* ** Undo the hack that converts floating point types to integer for ** builds on processors without floating point support. diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 0285677f87..11624cab9d 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -11,7 +11,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.438 2005/12/16 01:06:17 drh Exp $ +** @(#) $Id: sqliteInt.h,v 1.439 2005/12/16 06:54:02 danielk1977 Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ @@ -440,8 +440,10 @@ struct sqlite3 { void *pTraceArg; /* Argument to the trace function */ void (*xProfile)(void*,const char*,u64); /* Profiling function */ void *pProfileArg; /* Argument to profile function */ - void *pCommitArg; /* Argument to xCommitCallback() */ - int (*xCommitCallback)(void*);/* Invoked at every commit. */ + void *pCommitArg; /* Argument to xCommitCallback() */ + int (*xCommitCallback)(void*); /* Invoked at every commit. */ + void *pRollbackArg; /* Argument to xRollbackCallback() */ + void (*xRollbackCallback)(void*); /* Invoked at every commit. */ void *pUpdateArg; void (*xUpdateCallback)(void*,int, const char*,const char*,sqlite_int64); void(*xCollNeeded)(void*,sqlite3*,int eTextRep,const char*); diff --git a/src/tclsqlite.c b/src/tclsqlite.c index b862df3f0a..337cdefb47 100644 --- a/src/tclsqlite.c +++ b/src/tclsqlite.c @@ -11,7 +11,7 @@ ************************************************************************* ** A TCL Interface to SQLite ** -** $Id: tclsqlite.c,v 1.139 2005/12/15 15:22:10 danielk1977 Exp $ +** $Id: tclsqlite.c,v 1.140 2005/12/16 06:54:03 danielk1977 Exp $ */ #ifndef NO_TCL /* Omit this whole file if TCL is unavailable */ @@ -100,6 +100,7 @@ struct SqliteDb { 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) */ SqlCollate *pCollate; /* List of SQL collation functions */ int rc; /* Return code of most recent sqlite3_exec() */ Tcl_Obj *pCollateNeeded; /* Collation needed script */ @@ -214,6 +215,9 @@ static void DbDeleteCmd(void *db){ if( pDb->pUpdateHook ){ Tcl_DecrRefCount(pDb->pUpdateHook); } + if( pDb->pRollbackHook ){ + Tcl_DecrRefCount(pDb->pRollbackHook); + } if( pDb->pCollateNeeded ){ Tcl_DecrRefCount(pDb->pCollateNeeded); } @@ -304,6 +308,14 @@ static int DbCommitHandler(void *cd){ return 0; } +static void DbRollbackHandler(void *clientData){ + SqliteDb *pDb = (SqliteDb*)clientData; + assert(pDb->pRollbackHook); + if( TCL_OK!=Tcl_EvalObjEx(pDb->interp, pDb->pRollbackHook, 0) ){ + Tcl_BackgroundError(pDb->interp); + } +} + static void DbUpdateHandler( void *p, int op, @@ -653,10 +665,10 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ "copy", "errorcode", "eval", "exists", "function", "last_insert_rowid", "nullvalue", "onecolumn", "profile", - "progress", "rekey", "soft_heap_limit", - "timeout", "total_changes", "trace", - "transaction", "update_hook", "version", - 0 + "progress", "rekey", "rollback_hook", + "soft_heap_limit", "timeout", "total_changes", + "trace", "transaction", "update_hook", + "version", 0 }; enum DB_enum { DB_AUTHORIZER, DB_BUSY, DB_CACHE, @@ -665,9 +677,10 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ DB_COPY, DB_ERRORCODE, DB_EVAL, DB_EXISTS, DB_FUNCTION, DB_LAST_INSERT_ROWID, DB_NULLVALUE, DB_ONECOLUMN, DB_PROFILE, - DB_PROGRESS, DB_REKEY, DB_SOFT_HEAP_LIMIT, - DB_TIMEOUT, DB_TOTAL_CHANGES, DB_TRACE, - DB_TRANSACTION, DB_UPDATE_HOOK, DB_VERSION + DB_PROGRESS, DB_REKEY, DB_ROLLBACK_HOOK, + DB_SOFT_HEAP_LIMIT, DB_TIMEOUT, DB_TOTAL_CHANGES, + DB_TRACE, DB_TRANSACTION, DB_UPDATE_HOOK, + DB_VERSION }; /* don't leave trailing commas on DB_enum, it confuses the AIX xlc compiler */ @@ -1872,28 +1885,43 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ /* ** $db update_hook ?script? + ** $db rollback_hook ?script? */ - case DB_UPDATE_HOOK: { + case DB_UPDATE_HOOK: + case DB_ROLLBACK_HOOK: { + + /* 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{ + ppHook = &pDb->pRollbackHook; + } + if( objc!=2 && objc!=3 ){ Tcl_WrongNumArgs(interp, 2, objv, "?SCRIPT?"); return TCL_ERROR; } - if( pDb->pUpdateHook ){ - Tcl_SetObjResult(interp, pDb->pUpdateHook); + if( *ppHook ){ + Tcl_SetObjResult(interp, *ppHook); if( objc==3 ){ - Tcl_DecrRefCount(pDb->pUpdateHook); - pDb->pUpdateHook = 0; + Tcl_DecrRefCount(*ppHook); + *ppHook = 0; } } if( objc==3 ){ + assert( !(*ppHook) ); if( Tcl_GetCharLength(objv[2])>0 ){ - pDb->pUpdateHook = objv[2]; - Tcl_IncrRefCount(pDb->pUpdateHook); - sqlite3_update_hook(pDb->db, DbUpdateHandler, pDb); - }else{ - sqlite3_update_hook(pDb->db, 0, 0); + *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); + break; } @@ -2160,7 +2188,7 @@ int TCLSH_MAIN(int argc, char **argv){ Sqlitetest4_Init(interp); Sqlitetest5_Init(interp); Sqlitetest6_Init(interp); - Sqlitetestasync_Init(interp); + /* Sqlitetestasync_Init(interp); */ Md5_Init(interp); #ifdef SQLITE_SSE Sqlitetestsse_Init(interp); diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 6949f8c35c..a99dc46434 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -1233,17 +1233,27 @@ int sqlite3VdbeHalt(Vdbe *p){ } } - /* If xFunc is not NULL, then it is one of sqlite3BtreeRollback, + /* If xFunc is not NULL, then it is one of ** sqlite3BtreeRollbackStmt or sqlite3BtreeCommitStmt. Call it once on ** each backend. If an error occurs and the return code is still ** SQLITE_OK, set the return code to the new error value. */ - for(i=0; xFunc && inDb; i++){ - int rc; - Btree *pBt = db->aDb[i].pBt; - if( pBt ){ - rc = xFunc(pBt); - if( p->rc==SQLITE_OK ) p->rc = rc; + assert(!xFunc || + xFunc==sqlite3BtreeCommitStmt || + xFunc==sqlite3BtreeRollbackStmt || + xFunc==sqlite3BtreeRollback + ); + if( xFunc==sqlite3BtreeRollback ){ + assert( p->rc!=SQLITE_OK ); + sqlite3RollbackAll(db); + }else{ + for(i=0; xFunc && inDb; i++){ + int rc; + Btree *pBt = db->aDb[i].pBt; + if( pBt ){ + rc = xFunc(pBt); + if( p->rc==SQLITE_OK ) p->rc = rc; + } } } diff --git a/test/hook.test b/test/hook.test index 7060366bde..dcffd7053c 100644 --- a/test/hook.test +++ b/test/hook.test @@ -13,10 +13,11 @@ # # The focus of the tests in this file is the following interface: # -# sqlite_commit_hook -# sqlite_update_hook (tests hook-4 onwards) +# sqlite_commit_hook (tests hook-1..hook-3 inclusive) +# sqlite_update_hook (tests hook-4-*) +# sqlite_rollback_hook (tests hook-5.*) # -# $Id: hook.test,v 1.6 2005/12/15 15:22:10 danielk1977 Exp $ +# $Id: hook.test,v 1.7 2005/12/16 06:54:03 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -91,11 +92,22 @@ do_test hook-3.9 { set ::commit_cnt } {} -# Very simple tests. Test that the update hook is invoked correctly for INSERT, -# DELETE and UPDATE statements, including DELETE statements with no WHERE -# clause. +#---------------------------------------------------------------------------- +# Tests for the update-hook. # -do_test hook-4.1 { +# 4.1.* - Very simple tests. Test that the update hook is invoked correctly +# for INSERT, DELETE and UPDATE statements, including DELETE +# statements with no WHERE clause. +# 4.2.* - Check that the update-hook is invoked for rows modified by trigger +# bodies. Also that the database name is correctly reported when +# an attached database is modified. +# 4.3.* - Do some sorting, grouping, compound queries, population and +# depopulation of indices, to make sure the update-hook is not +# invoked incorrectly. +# + +# Simple tests +do_test hook-4.1.1 { catchsql { DROP TABLE t1; } @@ -107,7 +119,7 @@ do_test hook-4.1 { } db update_hook [list lappend ::update_hook] } {} -do_test hook-4.2 { +do_test hook-4.1.2 { execsql { INSERT INTO t1 VALUES(4, 'four'); DELETE FROM t1 WHERE b = 'two'; @@ -125,11 +137,8 @@ do_test hook-4.2 { DELETE main t1 4 \ ] -# Check that the update-hook is invoked for rows modified by trigger -# bodies. -# set ::update_hook {} -do_test hook-5.1 { +do_test hook-4.2.1 { catchsql { DROP TABLE t2; } @@ -142,7 +151,7 @@ do_test hook-5.1 { END; } } {} -do_test hook-5.2 { +do_test hook-4.2.2 { execsql { INSERT INTO t1 VALUES(1, 'one'); INSERT INTO t1 VALUES(2, 'two'); @@ -159,8 +168,9 @@ do_test hook-5.2 { DELETE main t2 2 \ ] +# Triggers + ATTACH set ::update_hook {} -do_test hook-6.1 { +do_test hook-4.2.3 { file delete -force test2.db execsql { ATTACH 'test2.db' AS aux; @@ -178,11 +188,10 @@ do_test hook-6.1 { DELETE aux t3 2 \ ] -# Do some sorting, grouping, compound queries, population and depopulation -# of indices, to make sure the update-hook is not invoked incorrectly. -# +# Test that other vdbe operations involving btree structures do not +# incorrectly invoke the update-hook. set ::update_hook {} -do_test hook-7.1 { +do_test hook-4.3.1 { execsql { DROP TRIGGER t1_trigger; CREATE INDEX t1_i ON t1(b); @@ -200,7 +209,7 @@ do_test hook-7.1 { DELETE main t1 3 \ ] set ::update_hook {} -do_test hook-7.2 { +do_test hook-4.3.2 { execsql { SELECT * FROM t1 UNION SELECT * FROM t3; SELECT * FROM t1 UNION ALL SELECT * FROM t3; @@ -211,6 +220,58 @@ do_test hook-7.2 { } set ::update_hook } [list] +db update_hook {} +# +#---------------------------------------------------------------------------- + +#---------------------------------------------------------------------------- +# Test the rollback-hook. The rollback-hook is a bit more complicated than +# either the commit or update hooks because a rollback can happen +# explicitly (an sql ROLLBACK statement) or implicitly (a constraint or +# error condition). +# +# hook-5.1.* - Test explicit rollbacks. +# hook-5.2.* - Test implicit rollbacks. +# hook-5.3.* - Test hot-journal rollbacks. +# + +do_test hook-5.0 { + # Configure the rollback hook to increment global variable + # $::rollback_hook each time it is invoked. + set ::rollback_hook 0 + db rollback_hook [list incr ::rollback_hook] +} {} + +# Test explicit rollbacks. Not much can really go wrong here. +do_test hook-5.1.1 { + set ::rollback_hook 0 + execsql { + BEGIN; + ROLLBACK; + } + set ::rollback_hook +} {1} + +# Test implicit rollbacks caused by constraints. +do_test hook-5.2.1 { + set ::rollback_hook 0 + catchsql { + DROP TABLE t1; + CREATE TABLE t1(a PRIMARY KEY, b); + INSERT INTO t1 VALUES('one', 'I'); + INSERT INTO t1 VALUES('one', 'I'); + } + set ::rollback_hook +} {1} +do_test hook-5.2.2 { + # Check that the INSERT transaction above really was rolled back. + execsql { + SELECT count(*) FROM t1; + } +} {1} + +# +#---------------------------------------------------------------------------- finish_test diff --git a/test/tclsqlite.test b/test/tclsqlite.test index 083d42377f..239fcbbd59 100644 --- a/test/tclsqlite.test +++ b/test/tclsqlite.test @@ -15,7 +15,7 @@ # interface is pretty well tested. This file contains some addition # tests for fringe issues that the main test suite does not cover. # -# $Id: tclsqlite.test,v 1.46 2005/12/12 06:53:05 danielk1977 Exp $ +# $Id: tclsqlite.test,v 1.47 2005/12/16 06:54:03 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -34,7 +34,7 @@ do_test tcl-1.1 { do_test tcl-1.2 { set v [catch {db bogus} msg] lappend v $msg -} {1 {bad option "bogus": must be authorizer, busy, cache, changes, close, collate, collation_needed, commit_hook, complete, copy, errorcode, eval, exists, function, last_insert_rowid, nullvalue, onecolumn, profile, progress, rekey, soft_heap_limit, timeout, total_changes, trace, transaction, or version}} +} {1 {bad option "bogus": must be authorizer, busy, cache, changes, close, collate, collation_needed, commit_hook, complete, copy, errorcode, eval, exists, function, last_insert_rowid, nullvalue, onecolumn, profile, progress, rekey, rollback_hook, soft_heap_limit, timeout, total_changes, trace, transaction, update_hook, or version}} do_test tcl-1.3 { execsql {CREATE TABLE t1(a int, b int)} execsql {INSERT INTO t1 VALUES(10,20)}