]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Fix for bug #15: Add the sqlite_changes() API function for retrieving the
authordrh <drh@noemail.net>
Fri, 12 Apr 2002 10:08:59 +0000 (10:08 +0000)
committerdrh <drh@noemail.net>
Fri, 12 Apr 2002 10:08:59 +0000 (10:08 +0000)
number of rows that changed in the previous operation. (CVS 526)

FossilOrigin-Name: 6e71493b9dc77d508c3ce90562766789e87e6d80

15 files changed:
manifest
manifest.uuid
src/delete.c
src/insert.c
src/main.c
src/sqlite.h.in
src/sqliteInt.h
src/tclsqlite.c
src/vdbe.c
test/conflict.test
test/insert2.test
test/tclsqlite.test
www/c_interface.tcl
www/lang.tcl
www/tclsqlite.tcl

index 74e4b8aad3fe1e3d51e0c2e3506768e14e5aacd2..4666b62ff1c9be6f12601fb5b42eb41ff0286c9f 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Fix\sfor\sbug\s#16:\sCheck\sfor\sinvalid\sfunctions\sin\sthe\sVALUES\sclause\sof\san\nINSERT\sstatement.\s(CVS\s525)
-D 2002-04-12T03:55:16
+C Fix\sfor\sbug\s#15:\sAdd\sthe\ssqlite_changes()\sAPI\sfunction\sfor\sretrieving\sthe\nnumber\sof\srows\sthat\schanged\sin\sthe\sprevious\soperation.\s(CVS\s526)
+D 2002-04-12T10:08:59
 F Makefile.in 50f1b3351df109b5774771350d8c1b8d3640130d
 F Makefile.template 89e373b2dad0321df00400fa968dc14b61a03296
 F README a4c0ba11354ef6ba0776b400d057c59da47a4cc0
@@ -23,13 +23,13 @@ F src/TODO af7f3cab0228e34149cf98e073aa83d45878e7e6
 F src/btree.c 7dd7ddc66459982dd0cb9800958c1f8d65a32d9f
 F src/btree.h 8abeabfe6e0b1a990b64fa457592a6482f6674f3
 F src/build.c d01b81f41481e733e27ab2fa8e1bfcc64f24257d
-F src/delete.c 577da499162291c1855f0b304b211bffcf9da945
+F src/delete.c 6a6b8192cdff5e4b083da3bc63de099f3790d01f
 F src/expr.c e7a1e22bc2ebcd789f0f8c0db544cf16ad664054
 F src/func.c dca9df811298cd0beb3724d40cee348e884352b2
 F src/hash.c cc259475e358baaf299b00a2c7370f2b03dda892
 F src/hash.h dca065dda89d4575f3176e75e9a3dc0f4b4fb8b9
-F src/insert.c 80105ff6a8bdabe8122948b0066fb1914f9b86c7
-F src/main.c b21019084b93fe685a8a25217d01f6958584ae9b
+F src/insert.c 31233f44fc79edbb43523a830e54736a8e222ff4
+F src/main.c df43fe585d2bfb925c837b6822783c0ee3dd6e1c
 F src/md5.c b2b1a34fce66ceca97f4e0dabc20be8be7933c92
 F src/os.c 5ab8b6b4590d0c1ab8e96c67996c170e4462e0fc
 F src/os.h 4a361fccfbc4e7609b3e1557f604f94c1e96ad10
@@ -41,10 +41,10 @@ F src/random.c 19e8e00fe0df32a742f115773f57651be327cabe
 F src/select.c 92aef3f69e90dc065d680d88b1f075409e9249bb
 F src/shell.c 994ca7c8c40c40a95011812013fbbf9828f5a0e7
 F src/shell.tcl 27ecbd63dd88396ad16d81ab44f73e6c0ea9d20e
-F src/sqlite.h.in 1dae50411aee9439860d7fbe315183c582d27197
-F src/sqliteInt.h 73e7d0f39a3c11d395fc422986959261bd193eba
+F src/sqlite.h.in ffcacf73b5ed1a4939205d29a704a185758fa6a6
+F src/sqliteInt.h e47ca9267a4c4a98e9f8d90c2df994a18f23d699
 F src/table.c eed2098c9b577aa17f8abe89313a9c4413f57d63
-F src/tclsqlite.c df847b71b28277f1cfa1ee1e3e51452ffe5a9a26
+F src/tclsqlite.c c9e9039762d9866eae70bf782237d0206a13f57e
 F src/test1.c d46ab7a82a9c16a3b1ee363cb4c0f98c5ff65743
 F src/test2.c d410dbd8a90faa466c3ab694fa0aa57f5a773aa6
 F src/test3.c 4e52fff8b01f08bd202f7633feda5639b7ba2b5e
@@ -52,7 +52,7 @@ F src/threadtest.c 81f0598e0f031c1bd506af337fdc1b7e8dff263f
 F src/tokenize.c 5624d342601f616157ba266abccc1368a5afee70
 F src/update.c 7dd714a6a7fa47f849ebb36b6d915974d6c6accb
 F src/util.c b34cd91387bbfdc79319ea451a7d120cef478120
-F src/vdbe.c ccc394cf72b5c43b71309fecc35cdf5cd252e154
+F src/vdbe.c 9213ff1ab136eabcf3e8a58157765a01274bf8e9
 F src/vdbe.h f9be1f6e9a336c3ff4d14ea7489ee976e07460cc
 F src/where.c 9d36f6c9fea4af71501770c13089f824cb9b033c
 F test/all.test 6aa106eee4d7127afa5cee97c51a783a79694ead
@@ -60,7 +60,7 @@ F test/bigrow.test 8ab252dba108f12ad64e337b0f2ff31a807ac578
 F test/btree.test bf326f546a666617367a7033fa2c07451bd4f8e1
 F test/btree2.test e3b81ec33dc2f89b3e6087436dfe605b870c9080
 F test/btree3.test 9caa9e22491dd8cd8aa36d7ac3b48b089817c895
-F test/conflict.test 3383ac08da14cdba11bb4c9495583cf87f67afb1
+F test/conflict.test 5149646703d3930c9111068b5cda7e2e938476e3
 F test/copy.test b3cefcb520c64d7e7dfedbab06b4d4c31fa5b99a
 F test/delete.test c904a62129fe102b314a96111a8417f10249e4d8
 F test/expr.test 846795016b5993a7411f772eebe82ab67bd7230a
@@ -68,7 +68,7 @@ F test/func.test d34e461f0acb0cf2978a4b3a3e098460f2ea8fbc
 F test/in.test c09312672e3f0709fa02c8e2e9cd8fb4bd6269aa
 F test/index.test c8a471243bbf878974b99baf5badd59407237cf3
 F test/insert.test c36d534a4ab58c2cd452a273e51b2b0dd1ede1f9
-F test/insert2.test 2f02b1e0dbfba3e8c76496209be5f4010b584181
+F test/insert2.test eb8481878a7f52ccb4e3346f87550f5afdd77f76
 F test/intpkey.test 31b5f28b2c44273e6695cf36ab2e4133aee7753c
 F test/ioerr.test 57d9bffaca18b34f9e976f786eadc2591d6efc6a
 F test/limit.test a930f3eba2a7691c8397ccab33710b931589566a
@@ -94,7 +94,7 @@ F test/sort.test 3b996ce7ca385f9cd559944ac0f4027a23aa546b
 F test/subselect.test 335d3dad8d585726c447dfee8d9c4f7383c76b78
 F test/table.test 17b0b6eafa3faaee5545b7a94e6c1ff73f0880f3
 F test/tableapi.test 3c80421a889e1d106df16e5800fa787f0d2914a6
-F test/tclsqlite.test ca8dd89b02ab68bd4540163c24551756a69f6783
+F test/tclsqlite.test 79deeffd7cd637ca0f06c5dbbf2f44d272079533
 F test/temptable.test 0e9934283259a5e637eec756a7eefd6964c0f79b
 F test/tester.tcl dc1b56bd628b487e4d75bfd1e7480b5ed8810ac6
 F test/trans.test ae0b9a82d5d34122c3a3108781eb8d078091ccee
@@ -115,7 +115,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
 F www/arch.fig d5f9752a4dbf242e9cfffffd3f5762b6c63b3bcf
 F www/arch.png 82ef36db1143828a7abc88b1e308a5f55d4336f4
 F www/arch.tcl 72a0c80e9054cc7025a50928d28d9c75c02c2b8b
-F www/c_interface.tcl 567cda531aac9d68a61ef02e26c6b202bd856db2
+F www/c_interface.tcl 79f63ffa8c6e7adb9e3449ff325d093cfb0ce3e3
 F www/changes.tcl 4083f03195f0ae36411e095a2d18e5fb4a3c40d9
 F www/conflict.tcl 81dd21f9a679e60aae049e9dd8ab53d59570cda2
 F www/crosscompile.tcl 3622ebbe518927a3854a12de51344673eb2dd060
@@ -124,14 +124,14 @@ F www/dynload.tcl 02eb8273aa78cfa9070dd4501dca937fb22b466c
 F www/faq.tcl fb1e92e2f604546694f83a36d969492f52fb685d
 F www/formatchng.tcl 2ce21ff30663fad6618198fe747ce675df577590
 F www/index.tcl 2a9653ebeeaba3aca3401f476ba0e0e4acb40929
-F www/lang.tcl 75615f1acd8a428d93546ad9edfbf8f78ee1e2df
+F www/lang.tcl 2d4654255ad1ec7f58d02dc41b59528c0ee6ea44
 F www/mingw.tcl f1c7c0a7f53387dd9bb4f8c7e8571b7561510ebc
 F www/opcode.tcl bdec8ef9f100dbd87bbef8976c54b88e43fd8ccc
 F www/speed.tcl da8afcc1d3ccc5696cfb388a68982bc3d9f7f00f
 F www/sqlite.tcl 8b5884354cb615049aed83039f8dfe1552a44279
-F www/tclsqlite.tcl 829b393d1ab187fd7a5e978631b3429318885c49
+F www/tclsqlite.tcl 1db15abeb446aad0caf0b95b8b9579720e4ea331
 F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218
-P bb83642e9a6c1c9ade861618496933c9f922a8f8
-R f474a54633adfc730f9670e6001e85d7
+P 43a77f019d34e1a6b3f502ad0ec31a00c8fdbe6e
+R f1c51fffab48448616c03a8f7db64a46
 U drh
-Z ee5b859e30a1d5d36bceb3c81154e192
+Z fa8a7c3395ff2734ddb7f18394f23f2a
index f9104e48d013e25abe1040960e68e96321b77edf..88dedaadec882ba23edf6bb331422929bb7de1d6 100644 (file)
@@ -1 +1 @@
-43a77f019d34e1a6b3f502ad0ec31a00c8fdbe6e
\ No newline at end of file
+6e71493b9dc77d508c3ce90562766789e87e6d80
\ No newline at end of file
index 03df82ea2e3d323e8d91a2cec6d27a4be9ddbfbe..3f7e0f7edf6f4ad60ca14e1cbb5d451acc1aed7e 100644 (file)
@@ -12,7 +12,7 @@
 ** This file contains C code routines that are called by the parser
 ** to handle DELETE FROM statements.
 **
-** $Id: delete.c,v 1.29 2002/03/03 18:59:40 drh Exp $
+** $Id: delete.c,v 1.30 2002/04/12 10:08:59 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -183,7 +183,7 @@ void sqliteDeleteFrom(
     }
     end = sqliteVdbeMakeLabel(v);
     addr = sqliteVdbeAddOp(v, OP_ListRead, 0, end);
-    sqliteGenerateRowDelete(v, pTab, base);
+    sqliteGenerateRowDelete(v, pTab, base, 1);
     sqliteVdbeAddOp(v, OP_Goto, 0, addr);
     sqliteVdbeResolveLabel(v, end);
     sqliteVdbeAddOp(v, OP_ListReset, 0, 0);
@@ -229,11 +229,12 @@ delete_from_cleanup:
 void sqliteGenerateRowDelete(
   Vdbe *v,           /* Generate code into this VDBE */
   Table *pTab,       /* Table containing the row to be deleted */
-  int base           /* Cursor number for the table */
+  int base,          /* Cursor number for the table */
+  int count          /* Increment the row change counter */
 ){
   sqliteVdbeAddOp(v, OP_MoveTo, base, 0);
   sqliteGenerateRowIndexDelete(v, pTab, base, 0);
-  sqliteVdbeAddOp(v, OP_Delete, base, 0);
+  sqliteVdbeAddOp(v, OP_Delete, base, count);
 }
 
 /*
index 94867c55bbc4f92d63d858d056c9768d2ae983a3..a848ee12bb456927ee4a6af1b2b1a34d8ae07f71 100644 (file)
@@ -12,7 +12,7 @@
 ** This file contains C code routines that are called by the parser
 ** to handle INSERT statements in SQLite.
 **
-** $Id: insert.c,v 1.51 2002/04/12 03:55:16 drh Exp $
+** $Id: insert.c,v 1.52 2002/04/12 10:08:59 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -526,7 +526,7 @@ void sqliteGenerateConstraintChecks(
         break;
       }
       case OE_Replace: {
-        sqliteGenerateRowDelete(v, pTab, base);
+        sqliteGenerateRowDelete(v, pTab, base, 0);
         if( isUpdate ){
           sqliteVdbeAddOp(v, OP_Dup, nCol+extra+1+hasTwoRecnos, 1);
           sqliteVdbeAddOp(v, OP_MoveTo, base, 0);
@@ -573,7 +573,7 @@ void sqliteCompleteInsertion(
     sqliteVdbeAddOp(v, OP_IdxPut, base+i+1, 0);
   }
   sqliteVdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);
-  sqliteVdbeAddOp(v, OP_PutIntKey, base, 0);
+  sqliteVdbeAddOp(v, OP_PutIntKey, base, 1);
   if( isUpdate && recnoChng ){
     sqliteVdbeAddOp(v, OP_Pop, 1, 0);
   }
index 389507903c58314441cb7655fe17217f36f434b8..c5aa1927c282883eb82911eb150929f3233fa963 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.68 2002/03/06 22:01:36 drh Exp $
+** $Id: main.c,v 1.69 2002/04/12 10:08:59 drh Exp $
 */
 #include "sqliteInt.h"
 #include "os.h"
@@ -421,6 +421,13 @@ int sqlite_last_insert_rowid(sqlite *db){
   return db->lastRowid;
 }
 
+/*
+** Return the number of changes in the most recent call to sqlite_exec().
+*/
+int sqlite_changes(sqlite *db){
+  return db->nChange;
+}
+
 /*
 ** Close an existing SQLite database
 */
@@ -526,6 +533,8 @@ int sqlite_exec(
       return rc;
     }
   }
+  if( db->recursionDepth==0 ){ db->nChange = 0; }
+  db->recursionDepth++;
   memset(&sParse, 0, sizeof(sParse));
   sParse.db = db;
   sParse.pBe = db->pBe;
@@ -544,6 +553,7 @@ int sqlite_exec(
   if( sParse.rc==SQLITE_SCHEMA ){
     clearHashTable(db, 1);
   }
+  db->recursionDepth--;
   return sParse.rc;
 }
 
index 097ce305bacaaf2b8fefb26a08f5f1494ca77b1d..1ba84badbe632a4bd1556e7f4e492f6e826bb544 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.29 2002/03/08 02:12:00 drh Exp $
+** @(#) $Id: sqlite.h.in,v 1.30 2002/04/12 10:08:59 drh Exp $
 */
 #ifndef _SQLITE_H_
 #define _SQLITE_H_
@@ -173,6 +173,28 @@ int sqlite_exec(
 */
 int sqlite_last_insert_rowid(sqlite*);
 
+/*
+** This function returns the number of database rows that were changed
+** (or inserted or deleted) by the most recent called sqlite_exec().
+**
+** All changes are counted, even if they were later undone by a
+** ROLLBACK or ABORT.  Except, changes associated with creating and
+** dropping tables are not counted.
+**
+** If a callback invokes sqlite_exec() recursively, then the changes
+** in the inner, recursive call are counted together with the changes
+** in the outer call.
+**
+** SQLite implements the command "DELETE FROM table" without a WHERE clause
+** by dropping and recreating the table.  (This is much faster than going
+** through and deleting individual elements form the table.)  Because of
+** this optimization, the change count for "DELETE FROM table" will be
+** zero regardless of the number of elements that were originally in the
+** table. To get an accurate count of the number of rows deleted, use
+** "DELETE FROM table WHERE 1" instead.
+*/
+int sqlite_changes(sqlite*);
+
 /* If the parameter to this routine is one of the return value constants
 ** defined above, then this routine returns a constant text string which
 ** descripts (in English) the meaning of the return value.
index 0cb7eaafdf0cbafca0ad5e1ddf858fc857c91069..5fcbd4a39222add38afd0178de20086ac04b4264 100644 (file)
@@ -11,7 +11,7 @@
 *************************************************************************
 ** Internal interface definitions for SQLite.
 **
-** @(#) $Id: sqliteInt.h,v 1.104 2002/03/12 23:10:05 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.105 2002/04/12 10:08:59 drh Exp $
 */
 #include "sqlite.h"
 #include "hash.h"
@@ -167,6 +167,8 @@ struct sqlite {
   int lastRowid;                /* ROWID of most recent insert */
   int priorNewRowid;            /* Last randomly generated ROWID */
   int onError;                  /* Default conflict algorithm */
+  int nChange;                  /* Number of rows changed */
+  int recursionDepth;           /* Number of nested calls to sqlite_exec() */
 };
 
 /*
@@ -630,7 +632,7 @@ void sqliteCommitTransaction(Parse*);
 void sqliteRollbackTransaction(Parse*);
 char *sqlite_mprintf(const char *, ...);
 int sqliteExprIsConstant(Expr*);
-void sqliteGenerateRowDelete(Vdbe*, Table*, int);
+void sqliteGenerateRowDelete(Vdbe*, Table*, int, int);
 void sqliteGenerateRowIndexDelete(Vdbe*, Table*, int, char*);
 void sqliteGenerateConstraintChecks(Parse*,Table*,int,char*,int,int,int,int);
 void sqliteCompleteInsertion(Parse*, Table*, int, char*, int, int);
index edf94765549fbd7cd08a4b995572a56ba5b45fed..045c18d78868e2622572cc968d0b0af098a20d45 100644 (file)
@@ -11,7 +11,7 @@
 *************************************************************************
 ** A TCL Interface to SQLite
 **
-** $Id: tclsqlite.c,v 1.30 2002/03/11 02:06:13 drh Exp $
+** $Id: tclsqlite.c,v 1.31 2002/04/12 10:08:59 drh Exp $
 */
 #ifndef NO_TCL     /* Omit this whole file if TCL is unavailable */
 
@@ -268,10 +268,12 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
   SqliteDb *pDb = (SqliteDb*)cd;
   int choice;
   static char *DB_optStrs[] = {
-     "busy",   "close",  "complete",  "eval",  "last_insert_rowid", "timeout", 0
+     "busy",  "changes",            "close",    "complete", 
+     "eval",  "last_insert_rowid",  "timeout",  0
   };
   enum DB_opts {
-     DB_BUSY,  DB_CLOSE, DB_COMPLETE, DB_EVAL, DB_LAST_INSERT_ROWID, DB_TIMEOUT
+     DB_BUSY, DB_CHANGES,           DB_CLOSE,   DB_COMPLETE,
+     DB_EVAL, DB_LAST_INSERT_ROWID, DB_TIMEOUT
   };
 
   if( objc<2 ){
@@ -320,6 +322,25 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
     break;
   }
 
+  /*
+  **     $db changes
+  **
+  ** Return the number of rows that were modified, inserted, or deleted by
+  ** the most recent "eval".
+  */
+  case DB_CHANGES: {
+    Tcl_Obj *pResult;
+    int nChange;
+    if( objc!=2 ){
+      Tcl_WrongNumArgs(interp, 2, objv, "");
+      return TCL_ERROR;
+    }
+    nChange = sqlite_changes(pDb->db);
+    pResult = Tcl_GetObjResult(interp);
+    Tcl_SetIntObj(pResult, nChange);
+    break;
+  }
+
   /*    $db close
   **
   ** Shutdown the database
index 467c6272865588025ae911c7a747bf8ee85275db..2c9a35b32ad1eae717666f5d628e6f4cdcc31638 100644 (file)
@@ -30,7 +30,7 @@
 ** But other routines are also provided to help in building up
 ** a program instruction by instruction.
 **
-** $Id: vdbe.c,v 1.137 2002/04/09 03:15:07 drh Exp $
+** $Id: vdbe.c,v 1.138 2002/04/12 10:09:00 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -3155,19 +3155,16 @@ case OP_NewRecno: {
 ** stack.  The key is the next value down on the stack.  The key must
 ** be an integer.  The stack is popped twice by this instruction.
 **
-** If P2==1 then overwriting is prohibited.  If a prior entry with
-** the same key exists, an SQLITE_CONSTRAINT exception is raised.
+** If P2==1 then the row change count is incremented.  If P2==0 the
+** row change count is unmodified.
 */
-/* Opcode: PutStrKey P1 P2 *
+/* Opcode: PutStrKey P1 * *
 **
 ** Write an entry into the database file P1.  A new entry is
 ** created if it doesn't already exist or the data for an existing
 ** entry is overwritten.  The data is the value on the top of the
 ** stack.  The key is the next value down on the stack.  The key must
 ** be a string.  The stack is popped twice by this instruction.
-**
-** If P2==1 then overwriting is prohibited.  If a prior entry with
-** the same key exists, an SQLITE_CONSTRAINT exception is raised.
 */
 case OP_PutIntKey:
 case OP_PutStrKey: {
@@ -3188,16 +3185,7 @@ case OP_PutStrKey: {
       iKey = intToKey(aStack[nos].i);
       zKey = (char*)&iKey;
       db->lastRowid = aStack[nos].i;
-    }
-    if( pOp->p2 ){
-      int res;
-      rc = sqliteBtreeMoveto(p->aCsr[i].pCursor, zKey, nKey, &res);
-      if( res==0 && rc==SQLITE_OK ){
-        rc = SQLITE_CONSTRAINT;
-      }
-      if( rc!=SQLITE_OK ){
-        goto abort_due_to_error;
-      }
+      if( pOp->p2 ) db->nChange++;
     }
     rc = sqliteBtreeInsert(p->aCsr[i].pCursor, zKey, nKey,
                         zStack[tos], aStack[tos].n);
@@ -3208,7 +3196,7 @@ case OP_PutStrKey: {
   break;
 }
 
-/* Opcode: Delete P1 * *
+/* Opcode: Delete P1 P2 *
 **
 ** Delete the record at which the P1 cursor is currently pointing.
 **
@@ -3216,12 +3204,16 @@ case OP_PutStrKey: {
 ** record in the table. If it is left pointing at the next record, then
 ** the next Next instruction will be a no-op.  Hence it is OK to delete
 ** a record from within an Next loop.
+**
+** The row change counter is incremented if P2==1 and is unmodified
+** if P2==0.
 */
 case OP_Delete: {
   int i = pOp->p1;
   if( VERIFY( i>=0 && i<p->nCursor && ) p->aCsr[i].pCursor!=0 ){
     rc = sqliteBtreeDelete(p->aCsr[i].pCursor);
   }
+  if( pOp->p2 ) db->nChange++;
   break;
 }
 
index a3f6bee74581ee604f8281a026f35f63f8091cd5..8db98e820578e6667f2d93da031f3b6908f14986 100644 (file)
@@ -13,7 +13,7 @@
 # This file implements tests for the conflict resolution extension
 # to SQLite.
 #
-# $Id: conflict.test,v 1.10 2002/04/09 03:28:01 drh Exp $
+# $Id: conflict.test,v 1.11 2002/04/12 10:09:00 drh Exp $
 
 set testdir [file dirname $argv0]
 source $testdir/tester.tcl
@@ -399,6 +399,9 @@ do_test conflict-7.2 {
     UPDATE OR IGNORE t1 SET a=1000;
   }
 } {1}
+do_test conflict-7.2.1 {
+  db changes
+} {1}
 do_test conflict-7.3 {
   execsql {
     SELECT b FROM t1 WHERE a=1000;
@@ -415,6 +418,9 @@ do_test conflict-7.5 {
     UPDATE OR REPLACE t1 SET a=1001;
   }
 } {50}
+do_test conflict-7.5.1 {
+  db changes
+} {50}
 do_test conflict-7.6 {
   execsql {
     SELECT b FROM t1 WHERE a=1001;
@@ -425,6 +431,9 @@ do_test conflict-7.7 {
     SELECT count(*) FROM t1;
   }
 } {1}
+do_test conflict-7.7.1 {
+  db changes
+} {0}
 
 # Make sure the row count is right for rows that are ignored on
 # an insert.
@@ -438,31 +447,49 @@ do_test conflict-8.1 {
     INSERT OR IGNORE INTO t1 VALUES(2,3);
   }
 } {1}
+do_test conflict-8.1.1 {
+  db changes
+} {1}
 do_test conflict-8.2 {
   execsql {
     INSERT OR IGNORE INTO t1 VALUES(2,4);
   }
 } {0}
+do_test conflict-8.2.1 {
+  db changes
+} {0}
 do_test conflict-8.3 {
   execsql {
     INSERT OR REPLACE INTO t1 VALUES(2,4);
   }
 } {1}
+do_test conflict-8.3.1 {
+  db changes
+} {1}
 do_test conflict-8.4 {
   execsql {
     INSERT OR IGNORE INTO t1 SELECT * FROM t1;
   }
 } {0}
+do_test conflict-8.4.1 {
+  db changes
+} {0}
 do_test conflict-8.5 {
   execsql {
     INSERT OR IGNORE INTO t1 SELECT a+2,b+2 FROM t1;
   }
 } {2}
+do_test conflict-8.5.1 {
+  db changes
+} {2}
 do_test conflict-8.6 {
   execsql {
     INSERT OR IGNORE INTO t1 SELECT a+3,b+3 FROM t1;
   }
 } {3}
+do_test conflict-8.6.1 {
+  db changes
+} {3}
 
 do_test insert-99.1 {
   set x [execsql {PRAGMA integrity_check}]
index fca4865edbfdd68a0bdc5cda0d6d32fd48294a18..f90c320304599108a8240e6cb641db70696125a5 100644 (file)
@@ -12,7 +12,7 @@
 # focus of this file is testing the INSERT statement that takes is
 # result from a SELECT.
 #
-# $Id: insert2.test,v 1.8 2002/03/03 02:49:52 drh Exp $
+# $Id: insert2.test,v 1.9 2002/04/12 10:09:00 drh Exp $
 
 set testdir [file dirname $argv0]
 source $testdir/tester.tcl
@@ -38,6 +38,9 @@ do_test insert2-1.1.1 {
   }
 } {6}
 do_test insert2-1.1.2 {
+  db changes
+} {6}
+do_test insert2-1.1.3 {
   execsql {SELECT * FROM t1 ORDER BY log}
 } {0 1 1 1 2 2 3 4 4 8 5 4}
 
@@ -138,6 +141,11 @@ do_test insert2-3.2 {
     INSERT INTO t4 VALUES(9,18);
     INSERT INTO t4 VALUES(10,20);
     COMMIT;
+  }
+  db changes
+} {9}
+do_test insert2-3.2.1 {
+  execsql {
     SELECT count(*) FROM t4;
   }
 } {10}
@@ -182,5 +190,8 @@ do_test insert2-3.7 {
     ROLLBACK;
   }
 } {1}
+do_test insert2-3.8 {
+  db changes
+} {159}
 
 finish_test
index 42ff8d19f0c908640b12f64e18ba856852204424..b8e99b2f32c016df60ce20af7673c3683a095246 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.5 2002/01/16 21:00:28 drh Exp $
+# $Id: tclsqlite.test,v 1.6 2002/04/12 10:09:00 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, close, complete, eval, last_insert_rowid, or timeout}}
+} {1 {bad option "bogus": must be busy, changes, close, complete, eval, 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)}
index 5f2f361745677d2ddf8761728534c34423db16bc..88afe38f4e91d146c3bd6fb2cc5d12a3250512d4 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Run this Tcl script to generate the sqlite.html file.
 #
-set rcsid {$Id: c_interface.tcl,v 1.25 2002/03/04 02:26:17 drh Exp $}
+set rcsid {$Id: c_interface.tcl,v 1.26 2002/04/12 10:09:00 drh Exp $}
 
 puts {<html>
 <head>
@@ -307,6 +307,8 @@ useful interfaces.  These extended routines are as follows:
 <blockquote><pre>
 int sqlite_last_insert_rowid(sqlite*);
 
+int sqlite_changes(sqlite*);
+
 int sqlite_get_table(
   sqlite*,
   char *sql,
@@ -389,6 +391,22 @@ the key is automatically generated.  You can find the value of the key
 for the most recent INSERT statement using the
 <b>sqlite_last_insert_rowid()</b> API function.</p>
 
+<h2>The number of rows that changed</h2>
+
+<p>The <b>sqlite_changes()</b> API function returns the number of rows
+that were inserted, deleted, or modified during the most recent
+<b>sqlite_exec()</b> call.  The number reported includes any changes
+that were later undo by a ROLLBACK or ABORT.  But rows that are
+deleted because of a DROP TABLE are <em>not</em> counted.</p>
+
+<p>SQLite implements the command "<b>DELETE FROM table</b>" (without
+a WHERE clause) by dropping the table then recreating it.  
+This is much faster than deleting the elements of the table individually.
+But it also means that the value returned from <b>sqlite_changes()</b>
+will be zero regardless of the number of elements that were originally
+in the table.  If an accurate count of the number of elements deleted
+is necessary, use "<b>DELETE FROM table WHERE 1</b>" instead.</p>
+
 <h2>Querying without using a callback function</h2>
 
 <p>The <b>sqlite_get_table()</b> function is a wrapper around
index be8a8200873422d524540300bdca090a866f4765..b959470cd31cd5811317dcbfd20ca5216339d6da 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Run this Tcl script to generate the sqlite.html file.
 #
-set rcsid {$Id: lang.tcl,v 1.31 2002/04/06 14:10:48 drh Exp $}
+set rcsid {$Id: lang.tcl,v 1.32 2002/04/12 10:09:00 drh Exp $}
 
 puts {<html>
 <head>
@@ -843,6 +843,8 @@ with caution.</p>
     <p>When on, the COUNT_CHANGES pragma causes the callback function to
     be invoked once for each DELETE, INSERT, or UPDATE operation.  The
     argument is the number of rows that were changed.</p>
+    <p>This pragma may be removed from future versions of SQLite.
+    Consider using the <b>sqlite_changes()</b> API function instead.</p></li>
 
 <li><p><b>PRAGMA default_cache_size;
        <br>PRAGMA default_cache_size = </b><i>Number-of-pages</i><b>;</b></p>
index f54069885d12bf7524944cfe3b247dcb874ea535..862966cd171a3d7bf7dd045b4865c5c732a2d3d2 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Run this Tcl script to generate the tclsqlite.html file.
 #
-set rcsid {$Id: tclsqlite.tcl,v 1.6 2002/01/16 21:00:28 drh Exp $}
+set rcsid {$Id: tclsqlite.tcl,v 1.7 2002/04/12 10:09:00 drh Exp $}
 
 puts {<html>
 <head>
@@ -50,12 +50,13 @@ the database is stored.
 
 <p>
 Once an SQLite database is open, it can be controlled using 
-methods of the <i>dbcmd</i>.  There are currently 6 methods
+methods of the <i>dbcmd</i>.  There are currently 7 methods
 defined:</p>
 
 <p>
 <ul>
 <li> busy
+<li> changes
 <li> close
 <li> complete
 <li> eval
@@ -248,6 +249,12 @@ should return "1" if it wants SQLite to abandon the current operation.
 <p>The "last_insert_rowid" method returns an integer which is the ROWID
 of the most recently inserted database row.</p>
 
+<h2>The "changes" method</h2>
+
+<p>The "changes" method returns an integer which is the number of rows
+in the database that were inserted, deleted, and/or modified by the most
+recent "eval" method.</p>
+
 }
 
 puts {