]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Added experimental APIs: sqlite_begin_hook() and sqlite_commit_hook(). (CVS 896)
authordrh <drh@noemail.net>
Thu, 3 Apr 2003 15:46:04 +0000 (15:46 +0000)
committerdrh <drh@noemail.net>
Thu, 3 Apr 2003 15:46:04 +0000 (15:46 +0000)
FossilOrigin-Name: 5efbf62313519d0a6e8b8f5dbb29d3ef428d73e8

manifest
manifest.uuid
src/main.c
src/sqlite.h.in
src/sqliteInt.h
src/tclsqlite.c
src/vdbe.c
test/hook.test [new file with mode: 0644]
test/tclsqlite.test

index 30dd63c5fe70e501fd21c36cd6f36bdcb9c1d1fe..1ebff78c20f0c3ae578a93a8a256cefccd491ee2 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Use\sa\sintermediate\stable\swhen\sinserting\sa\sTEMP\stable\sfrom\sa\sSELECT\sthat\nreads\sfrom\sthat\ssame\sTEMP\stable.\s\sTicket\s#275.\s(CVS\s895)
-D 2003-04-03T01:50:44
+C Added\sexperimental\sAPIs:\ssqlite_begin_hook()\sand\ssqlite_commit_hook().\s(CVS\s896)
+D 2003-04-03T15:46:04
 F Makefile.in 3c4ba24253e61c954d67adbbb4245e7117c5357e
 F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
 F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
@@ -30,7 +30,7 @@ F src/func.c 882c3ed5a02be18cd904715c7ec62947a34a3605
 F src/hash.c 4fc39feb7b7711f6495ee9f2159559bedb043e1f
 F src/hash.h cd0433998bc1a3759d244e1637fe5a3c13b53bf8
 F src/insert.c e2f5e7feecb507d904a7da48874595f440b715aa
-F src/main.c 6d9a38491fdc40c041df64a7399244c364481a09
+F src/main.c 60a64f792a9bcd2e270ef143d8cc75cd74bde8e9
 F src/md5.c fe4f9c9c6f71dfc26af8da63e4d04489b1430565
 F src/os.c dfed46091f69cd2d1e601f8a214d41344f2b00b6
 F src/os.h aa52f0c9da321ff6134d19f2ca959e18e33615d0
@@ -42,10 +42,10 @@ F src/random.c 19e8e00fe0df32a742f115773f57651be327cabe
 F src/select.c 14e2e2a512f4edfc75fb310ebcb502ff3ee87402
 F src/shell.c c13ff46e905a59eb1c7dbea7c1850f8f115e6395
 F src/shell.tcl 27ecbd63dd88396ad16d81ab44f73e6c0ea9d20e
-F src/sqlite.h.in be3e56214fecc73d72195ca62d8a3d6663602ff4
-F src/sqliteInt.h 18eb5a7f2ba010ad7d7ba81625f4b35fe3438239
+F src/sqlite.h.in f49c2cdec7d24cb03e496a1ca519e16306495ee1
+F src/sqliteInt.h 5c2371b20f69f2607ee988ba0aee85cdf9367370
 F src/table.c eed2098c9b577aa17f8abe89313a9c4413f57d63
-F src/tclsqlite.c 4cb0ffa863123ae037db359849a231ff5cebfed4
+F src/tclsqlite.c 7a072c3c8ba9796edc25e5ffa62b68558134e192
 F src/test1.c 7ad4e6308dde0bf5a0f0775ce20cb2ec37a328f8
 F src/test2.c 5014337d8576b731cce5b5a14bec4f0daf432700
 F src/test3.c c12ea7f1c3fbbd58904e81e6cb10ad424e6fc728
@@ -54,7 +54,7 @@ F src/tokenize.c 675b4718d17c69fe7609dc8e85e426ef002be811
 F src/trigger.c bd5a5b234b47f28f9f21a46243dcaf1c5b2383a3
 F src/update.c b368369f1fbe6d7f56a53e5ffad3b75dae9e3e1a
 F src/util.c 8953c612a036e30f24c1c1f5a1498176173daa37
-F src/vdbe.c b3b840b555b5238926b7ebb01cd47526a29bb853
+F src/vdbe.c 540c480912e11e23f5c08a31b8b3594df016f4d1
 F src/vdbe.h 985c24f312d10f9ef8f9a8b8ea62fcdf68e82f21
 F src/where.c e5733f7d5e9cc4ed3590dc3401f779e7b7bb8127
 F test/all.test 569a92a8ee88f5300c057cc4a8f50fbbc69a3242
@@ -73,6 +73,7 @@ F test/expr.test 290e2617b89b5c5e3bf71f19367d285102128be4
 F test/fkey1.test d65c824459916249bee501532d6154ddab0b5db7
 F test/format3.test 64ab6c4db132b28a645996d413530f7b2a462cc2
 F test/func.test 000515779001ac6899eec4b54e65c6e2501279d4
+F test/hook.test 7a4c97b886801d265c981dc4ec123c77af642a9d
 F test/in.test 3171a2b3170a8223665c1a4f26be5f3eda36cc4b
 F test/index.test faeb1bcf776e3ff9ba1b4be1eadd1fece708aa7b
 F test/insert.test 5697ba098e4d8a6f0151f281b7e39dec9c439e05
@@ -106,7 +107,7 @@ F test/sort.test 61a729023ae4ac3be9b225dc0be026fb43fec4e6
 F test/subselect.test f0fea8cf9f386d416d64d152e3c65f9116d0f50f
 F test/table.test 371a1fc1c470982b2f68f9732f903a5d96f949c4
 F test/tableapi.test 3c80421a889e1d106df16e5800fa787f0d2914a6
-F test/tclsqlite.test 4a69bd223eb18f8cdc58a9ca193881121fa7a8d2
+F test/tclsqlite.test 62773bcb94f7d7b69f1ab05c0ae07a22c737440f
 F test/temptable.test 6feff1960c707e924d5462356c5303943dac4a8e
 F test/tester.tcl d7a5835edaf118539241145d8188f0822b673488
 F test/trans.test 75e7a171b5d2d94ee56766459113e2ad0e5f809d
@@ -155,7 +156,7 @@ F www/speed.tcl cb4c10a722614aea76d2c51f32ee43400d5951be
 F www/sqlite.tcl ae3dcfb077e53833b59d4fcc94d8a12c50a44098
 F www/tclsqlite.tcl 1db15abeb446aad0caf0b95b8b9579720e4ea331
 F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218
-P 79b3aed2a74a67cbad631c4e2e4a43469d80c162
-R 6e7a48442426732645524eccf6cea407
+P 087d1e83af12b3a9aedd4945f02774a1043b1eb4
+R 367f6fd088c73003bdf4587260d5c5b6
 U drh
-Z b83fa935d7c88982a4c85635851f4582
+Z 9020be80da9a15f4bf8643579ba2aa56
index 534960f4e9abac9763c4746ab75121bc0b6227da..12b051336ef61975c8e6592b4122e475cf272f6e 100644 (file)
@@ -1 +1 @@
-087d1e83af12b3a9aedd4945f02774a1043b1eb4
\ No newline at end of file
+5efbf62313519d0a6e8b8f5dbb29d3ef428d73e8
\ No newline at end of file
index aa4e4b3cf186fdf1b115b769bd1ecdc4a48e12f7..dacf11235fbfbfe332ae750a3badb390807f2c74 100644 (file)
@@ -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.119 2003/03/31 00:30:48 drh Exp $
+** $Id: main.c,v 1.120 2003/04/03 15:46:04 drh Exp $
 */
 #include "sqliteInt.h"
 #include "os.h"
@@ -1023,3 +1023,29 @@ void *sqlite_trace(sqlite *db, void (*xTrace)(void*,const char*), void *pArg){
   return 0;
 #endif
 }
+
+/*
+** Register functions to be invoked when a transaction is started or when
+** a transaction commits.  If either function returns non-zero, then the
+** corresponding operation aborts with a constraint error.
+*/
+void *sqlite_begin_hook(
+  sqlite *db,
+  int (*xCallback)(void*),
+  void *pArg
+){
+  void *pOld = db->pBeginArg;
+  db->xBeginCallback = xCallback;
+  db->pBeginArg = pArg;
+  return pOld;
+}
+void *sqlite_commit_hook(
+  sqlite *db,
+  int (*xCallback)(void*),
+  void *pArg
+){
+  void *pOld = db->pCommitArg;
+  db->xCommitCallback = xCallback;
+  db->pCommitArg = pArg;
+  return pOld;
+}
index 7b224ea526aa32297717c087246607be14817fab..7d9e12b8c640091cc8af838f0b8dcc5da984d6e8 100644 (file)
@@ -12,7 +12,7 @@
 ** This header file defines the interface that the SQLite library
 ** presents to client programs.
 **
-** @(#) $Id: sqlite.h.in,v 1.43 2003/03/31 00:30:49 drh Exp $
+** @(#) $Id: sqlite.h.in,v 1.44 2003/04/03 15:46:04 drh Exp $
 */
 #ifndef _SQLITE_H_
 #define _SQLITE_H_
@@ -676,6 +676,21 @@ int sqlite_step(
 */
 int sqlite_finalize(sqlite_vm*, char **pzErrMsg);
 
+/*** EXPERIMENTAL ***
+** 
+** Register a callback function to be invoked whenever a new transaction
+** is started or committed.  The pArg argument is passed through to the
+** callback.  If the callback function returns non-zero, then the operation
+** is aborted with a constraint error.
+**
+** If another function was previously registered, its pArg value is returned.
+** Otherwise NULL is returned.
+**
+** Registering a NULL function disables the callback.
+*/
+void *sqlite_begin_hook(sqlite*, int(*)(void*), void*);
+void *sqlite_commit_hook(sqlite*, int(*)(void*), void*);
+
 #ifdef __cplusplus
 }  /* End of the 'extern "C"' block */
 #endif
index 93bf922621f4af02332212d0bf551b67b725c445..fa1d4fd30f0f36fcef32794dddaaf65e6054cead 100644 (file)
@@ -11,7 +11,7 @@
 *************************************************************************
 ** Internal interface definitions for SQLite.
 **
-** @(#) $Id: sqliteInt.h,v 1.169 2003/03/31 13:36:09 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.170 2003/04/03 15:46:04 drh Exp $
 */
 #include "config.h"
 #include "sqlite.h"
@@ -244,6 +244,10 @@ struct sqlite {
   int nTable;                   /* Number of tables in the database */
   void *pBusyArg;               /* 1st Argument to the busy callback */
   int (*xBusyCallback)(void *,const char*,int);  /* The busy callback */
+  void *pBeginArg;              /* Argument to the xBeginCallback() */
+  int (*xBeginCallback)(void*); /* Invoked at every transaction start */
+  void *pCommitArg;             /* Argument to xCommitCallback() */   
+  int (*xCommitCallback)(void*);/* Invoked at every commit. */
   Hash aFunc;                   /* All functions that can be in SQL exprs */
   int lastRowid;                /* ROWID of most recent insert */
   int priorNewRowid;            /* Last randomly generated ROWID */
index 69f70bd416039966e0d178377142e579c3755a4c..dd21cad4e30328fdc317ed1008c434a0395efd86 100644 (file)
@@ -11,7 +11,7 @@
 *************************************************************************
 ** A TCL Interface to SQLite
 **
-** $Id: tclsqlite.c,v 1.45 2003/03/30 19:17:03 drh Exp $
+** $Id: tclsqlite.c,v 1.46 2003/04/03 15:46:04 drh Exp $
 */
 #ifndef NO_TCL     /* Omit this whole file if TCL is unavailable */
 
@@ -51,6 +51,8 @@ struct SqliteDb {
   sqlite *db;           /* The "real" database structure */
   Tcl_Interp *interp;   /* The interpreter used for this database */
   char *zBusy;          /* The busy callback routine */
+  char *zBegin;         /* The begin-transaction callback routine */
+  char *zCommit;        /* The commit-transaction callback routine */
   SqlFunc *pFunc;       /* List of SQL functions */
   int rc;               /* Return code of most recent sqlite_exec() */
 };
@@ -260,6 +262,12 @@ static void DbDeleteCmd(void *db){
   if( pDb->zBusy ){
     Tcl_Free(pDb->zBusy);
   }
+  if( pDb->zBegin ){
+    Tcl_Free(pDb->zBegin);
+  }
+  if( pDb->zCommit ){
+    Tcl_Free(pDb->zCommit);
+  }
   Tcl_Free((char*)pDb);
 }
 
@@ -288,6 +296,39 @@ static int DbBusyHandler(void *cd, const char *zTable, int nTries){
   return 1;
 }
 
+/*
+** This routine is called when a new transaction is started.  The
+** TCL script in pDb->zBegin is executed.  If it returns non-zero or
+** if it throws an exception, the transaction is aborted.
+*/
+static int DbBeginHandler(void *cd){
+  SqliteDb *pDb = (SqliteDb*)cd;
+  int rc;
+
+  rc = Tcl_Eval(pDb->interp, pDb->zBegin);
+  if( rc!=TCL_OK || atoi(Tcl_GetStringResult(pDb->interp)) ){
+    return 1;
+  }
+  return 0;
+}
+
+/*
+** This routine is called when a transaction is committed.  The
+** TCL script in pDb->zCommit is executed.  If it returns non-zero or
+** if it throws an exception, the transaction is rolled back instead
+** of being committed.
+*/
+static int DbCommitHandler(void *cd){
+  SqliteDb *pDb = (SqliteDb*)cd;
+  int rc;
+
+  rc = Tcl_Eval(pDb->interp, pDb->zCommit);
+  if( rc!=TCL_OK || atoi(Tcl_GetStringResult(pDb->interp)) ){
+    return 1;
+  }
+  return 0;
+}
+
 /*
 ** This routine is called to evaluate an SQL function implemented
 ** using TCL script.
@@ -328,15 +369,16 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
   SqliteDb *pDb = (SqliteDb*)cd;
   int choice;
   static const char *DB_strs[] = {
-    "busy",               "changes",           "close",
-    "complete",           "errorcode",         "eval",
-    "function",           "last_insert_rowid", "timeout",
-    0                    
+    "begin_hook",         "busy",              "changes",
+    "close",              "commit_hook",       "complete",
+    "errorcode",          "eval",              "function",
+    "last_insert_rowid",  "timeout",           0
   };
   enum DB_enum {
-    DB_BUSY,              DB_CHANGES,          DB_CLOSE,
-    DB_COMPLETE,          DB_ERRORCODE,        DB_EVAL,
-    DB_FUNCTION,          DB_LAST_INSERT_ROWID,DB_TIMEOUT,          
+    DB_BEGIN_HOOK,        DB_BUSY,             DB_CHANGES,
+    DB_CLOSE,             DB_COMMIT_HOOK,      DB_COMPLETE,
+    DB_ERRORCODE,         DB_EVAL,             DB_FUNCTION,
+    DB_LAST_INSERT_ROWID, DB_TIMEOUT,          
   };
 
   if( objc<2 ){
@@ -349,6 +391,43 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
 
   switch( (enum DB_enum)choice ){
 
+  /*    $db begin_callback ?CALLBACK?
+  **
+  ** Invoke the given callback at the beginning of every SQL transaction.
+  ** If the callback throws an exception or returns non-zero, then the
+  ** transaction is aborted.  If CALLBACK is an empty string, the callback
+  ** is disabled.
+  */
+  case DB_BEGIN_HOOK: {
+    if( objc>3 ){
+      Tcl_WrongNumArgs(interp, 2, objv, "?CALLBACK?");
+    }else if( objc==2 ){
+      if( pDb->zBegin ){
+        Tcl_AppendResult(interp, pDb->zBegin, 0);
+      }
+    }else{
+      char *zBegin;
+      int len;
+      if( pDb->zBegin ){
+        Tcl_Free(pDb->zBegin);
+      }
+      zBegin = Tcl_GetStringFromObj(objv[2], &len);
+      if( zBegin && len>0 ){
+        pDb->zBegin = Tcl_Alloc( len + 1 );
+        strcpy(pDb->zBegin, zBegin);
+      }else{
+        pDb->zBegin = 0;
+      }
+      if( pDb->zBegin ){
+        pDb->interp = interp;
+        sqlite_begin_hook(pDb->db, DbBeginHandler, pDb);
+      }else{
+        sqlite_begin_hook(pDb->db, 0, 0);
+      }
+    }
+    break;
+  }
+
   /*    $db busy ?CALLBACK?
   **
   ** Invoke the given callback if an SQL statement attempts to open
@@ -413,6 +492,43 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
     break;
   }
 
+  /*    $db commit_hook ?CALLBACK?
+  **
+  ** Invoke the given callback just before committing every SQL transaction.
+  ** If the callback throws an exception or returns non-zero, then the
+  ** transaction is aborted.  If CALLBACK is an empty string, the callback
+  ** is disabled.
+  */
+  case DB_COMMIT_HOOK: {
+    if( objc>3 ){
+      Tcl_WrongNumArgs(interp, 2, objv, "?CALLBACK?");
+    }else if( objc==2 ){
+      if( pDb->zCommit ){
+        Tcl_AppendResult(interp, pDb->zCommit, 0);
+      }
+    }else{
+      char *zCommit;
+      int len;
+      if( pDb->zCommit ){
+        Tcl_Free(pDb->zCommit);
+      }
+      zCommit = Tcl_GetStringFromObj(objv[2], &len);
+      if( zCommit && len>0 ){
+        pDb->zCommit = Tcl_Alloc( len + 1 );
+        strcpy(pDb->zCommit, zCommit);
+      }else{
+        pDb->zCommit = 0;
+      }
+      if( pDb->zCommit ){
+        pDb->interp = interp;
+        sqlite_commit_hook(pDb->db, DbCommitHandler, pDb);
+      }else{
+        sqlite_commit_hook(pDb->db, 0, 0);
+      }
+    }
+    break;
+  }
+
   /*    $db complete SQL
   **
   ** Return TRUE if SQL is a complete SQL statement.  Return FALSE if
index f1c0aa6f8e11e72bd72e93a402f9d3dfcb06b733..5c59d8b7913a43742376ca3dcc852e4ef5ab3479 100644 (file)
@@ -36,7 +36,7 @@
 ** in this file for details.  If in doubt, do not deviate from existing
 ** commenting and indentation practices when changing or adding code.
 **
-** $Id: vdbe.c,v 1.210 2003/04/03 01:50:45 drh Exp $
+** $Id: vdbe.c,v 1.211 2003/04/03 15:46:04 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -3233,6 +3233,13 @@ case OP_Transaction: {
   }
   db->aDb[i].inTrans = 1;
   p->undoTransOnError = 1;
+  if( db->xBeginCallback!=0 && i==1 && rc==SQLITE_OK ){
+    if( sqliteSafetyOff(db) ) goto abort_due_to_misuse; 
+    if( db->xBeginCallback(db->pBeginArg)!=0 ){
+      rc = SQLITE_CONSTRAINT;
+    }
+    if( sqliteSafetyOn(db) ) goto abort_due_to_misuse;
+  }
   break;
 }
 
@@ -3246,6 +3253,14 @@ case OP_Transaction: {
 */
 case OP_Commit: {
   int i;
+  if( db->xCommitCallback!=0 ){
+    if( sqliteSafetyOff(db) ) goto abort_due_to_misuse; 
+    if( db->xCommitCallback(db->pCommitArg)!=0 ){
+      rc = SQLITE_CONSTRAINT;
+    }
+    if( sqliteSafetyOn(db) ) goto abort_due_to_misuse;
+    if( rc ) break;
+  }
   assert( rc==SQLITE_OK );
   for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
     if( db->aDb[i].inTrans ){
diff --git a/test/hook.test b/test/hook.test
new file mode 100644 (file)
index 0000000..78682b7
--- /dev/null
@@ -0,0 +1,148 @@
+# 2003 April 3
+#
+# The author disclaims copyright to this source code.  In place of
+# a legal notice, here is a blessing:
+#
+#    May you do good and not evil.
+#    May you find forgiveness for yourself and forgive others.
+#    May you share freely, never taking more than you give.
+#
+#***********************************************************************
+# This file implements regression tests for TCL interface to the
+# SQLite library. 
+#
+# The focus of the tests in this file is the  following interface:
+#
+#      sqlite_begin_hook
+#      sqlite_commit_hook
+#
+# $Id: hook.test,v 1.1 2003/04/03 15:46:05 drh Exp $
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+do_test hook-1.1 {
+  db begin_hook
+} {}
+do_test hook-1.2 {
+  db commit_hook
+} {}
+
+do_test hook-2.1 {
+  set begin_cnt 0
+  proc begin_hook {} {
+    incr ::begin_cnt
+    return 0
+  }
+  db begin_hook begin_hook
+  db begin_hook
+} {begin_hook}
+do_test hook-2.2 {
+  set begin_cnt
+} {0}
+do_test hook-2.3 {
+  execsql {
+    CREATE TABLE t1(a,b);
+  }
+  set begin_cnt
+} {1}
+do_test hook-2.4 {
+  execsql {
+    INSERT INTO t1 VALUES(1,2);
+    INSERT INTO t1 SELECT a+1, b+1 FROM t1;
+    INSERT INTO t1 SELECT a+2, b+2 FROM t1;
+  }
+  set begin_cnt
+} {4}
+do_test hook-2.5 {
+  execsql {
+    SELECT * FROM t1
+  }
+} {1 2 2 3 3 4 4 5}
+do_test hook-2.6 {
+  set begin_cnt
+} {4}
+do_test hook-2.7 {
+  proc begin_hook {} {
+    incr ::begin_cnt
+    return 1
+  }
+  catchsql {
+    INSERT INTO t1 VALUES(9,10);
+  }
+} {1 {constraint failed}}
+do_test hook-2.8 {
+  set begin_cnt
+} {5}
+do_test hook-2.9 {
+  execsql {
+    SELECT * FROM t1;
+  }
+} {1 2 2 3 3 4 4 5}
+do_test hook-2.10 {
+  db begin_hook {}
+  db begin_hook
+} {}
+do_test hook-2.11 {
+  execsql {
+    INSERT INTO t1 VALUES(9,10);
+    SELECT * FROM t1
+  }
+} {1 2 2 3 3 4 4 5 9 10}
+
+do_test hook-3.1 {
+  set commit_cnt 0
+  proc commit_hook {} {
+    incr ::commit_cnt
+    return 0
+  }
+  db commit_hook ::commit_hook
+  db commit_hook
+} {::commit_hook}
+do_test hook-3.2 {
+  set commit_cnt
+} {0}
+do_test hook-3.3 {
+  execsql {
+    CREATE TABLE t2(a,b);
+  }
+  set commit_cnt
+} {1}
+do_test hook-3.4 {
+  execsql {
+    INSERT INTO t2 VALUES(1,2);
+    INSERT INTO t2 SELECT a+1, b+1 FROM t2;
+    INSERT INTO t2 SELECT a+2, b+2 FROM t2;
+  }
+  set commit_cnt
+} {4}
+do_test hook-3.5 {
+  set commit_cnt {}
+  proc commit_hook {} {
+    set ::commit_cnt [execsql {SELECT * FROM t2}]
+    return 0
+  }
+  execsql {
+    INSERT INTO t2 VALUES(5,6);
+  }
+  set commit_cnt
+} {1 2 2 3 3 4 4 5 5 6}
+do_test hook-3.6 {
+  set commit_cnt {}
+  proc commit_hook {} {
+    set ::commit_cnt [execsql {SELECT * FROM t2}]
+    return 1
+  }
+  catchsql {
+    INSERT INTO t2 VALUES(6,7);
+  }
+} {1 {constraint failed}}
+do_test hook-3.7 {
+  set commit_cnt
+} {1 2 2 3 3 4 4 5 5 6 6 7}
+do_test hook-3.8 {
+  execsql {SELECT * FROM t2}
+} {1 2 2 3 3 4 4 5 5 6}
+
+
+finish_test
index cca0abb15c1eda6a469eb936dd70e780de76b266..14bf1f347ac568de24befe335d1b09a92ab56df4 100644 (file)
@@ -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.10 2003/03/30 19:17:03 drh Exp $
+# $Id: tclsqlite.test,v 1.11 2003/04/03 15:46:05 drh Exp $
 
 set testdir [file dirname $argv0]
 source $testdir/tester.tcl
@@ -29,7 +29,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 busy, changes, close, complete, errorcode, eval, function, last_insert_rowid, or timeout}}
+} {1 {bad option "bogus": must be begin_hook, busy, changes, close, commit_hook, complete, errorcode, eval, function, last_insert_rowid, or timeout}}
 do_test tcl-1.3 {
   execsql {CREATE TABLE t1(a int, b int)}
   execsql {INSERT INTO t1 VALUES(10,20)}