/ Check-in [ae2f4a09]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Update sqlite3_changes() to match the documentation and add sqlite3_total_changes(). (CVS 1645)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: ae2f4a0943854fedbbb6fab1dc3aaf972722ed95
User & Date: danielk1977 2004-06-21 06:50:27
Context
2004-06-21
07:36
Update sqlite3_column_decltype() to return NULL as the declartion type for an expression that is not a column reference. (CVS 1646) check-in: ee9dffd9 user: danielk1977 tags: trunk
06:50
Update sqlite3_changes() to match the documentation and add sqlite3_total_changes(). (CVS 1645) check-in: ae2f4a09 user: danielk1977 tags: trunk
2004-06-20
03:06
fix fulltest error by restoring unset (CVS 1644) check-in: d2ccac9d user: dougcurrie tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/delete.c.

     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** This file contains C code routines that are called by the parser
    13     13   ** to handle DELETE FROM statements.
    14     14   **
    15         -** $Id: delete.c,v 1.75 2004/06/17 07:53:02 danielk1977 Exp $
           15  +** $Id: delete.c,v 1.76 2004/06/21 06:50:27 danielk1977 Exp $
    16     16   */
    17     17   #include "sqliteInt.h"
    18     18   
    19     19   /*
    20     20   ** Look up every table that is named in pSrc.  If any table is not found,
    21     21   ** add an error message to pParse->zErrMsg and return NULL.  If all tables
    22     22   ** are found, return a pointer to the last table.
................................................................................
   138    138   
   139    139     /* Begin generating code.
   140    140     */
   141    141     v = sqlite3GetVdbe(pParse);
   142    142     if( v==0 ){
   143    143       goto delete_from_cleanup;
   144    144     }
          145  +  sqlite3VdbeCountChanges(v);
   145    146     sqlite3BeginWriteOperation(pParse, row_triggers_exist, pTab->iDb);
   146    147   
   147    148     /* If we are trying to delete from a view, construct that view into
   148    149     ** a temporary table.
   149    150     */
   150    151     if( isView ){
   151    152       Select *pView = sqlite3SelectDup(pTab->pSelect);
................................................................................
   267    268         /* This is the beginning of the delete loop when there are no
   268    269         ** row triggers */
   269    270         if( !row_triggers_exist ){ 
   270    271           addr = sqlite3VdbeAddOp(v, OP_ListRead, 0, end);
   271    272         }
   272    273   
   273    274         /* Delete the row */
   274         -      sqlite3GenerateRowDelete(db, v, pTab, iCur, pParse->trigStack==0);
          275  +      sqlite3GenerateRowDelete(db, v, pTab, iCur, 1);
   275    276       }
   276    277   
   277    278       /* If there are row triggers, close all cursors then invoke
   278    279       ** the AFTER triggers
   279    280       */
   280    281       if( row_triggers_exist ){
   281    282         if( !isView ){
................................................................................
   299    300         for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
   300    301           sqlite3VdbeAddOp(v, OP_Close, iCur + i, pIdx->tnum);
   301    302         }
   302    303         sqlite3VdbeAddOp(v, OP_Close, iCur, 0);
   303    304         pParse->nTab = iCur;
   304    305       }
   305    306     }
   306         -  sqlite3VdbeAddOp(v, OP_SetCounts, 0, 0);
   307    307     sqlite3EndWriteOperation(pParse);
   308    308   
   309    309     /*
   310    310     ** Return the number of rows that were deleted.
   311    311     */
   312    312     if( db->flags & SQLITE_CountRows ){
   313    313       sqlite3VdbeAddOp(v, OP_Callback, 1, 0);
................................................................................
   348    348     Table *pTab,       /* Table containing the row to be deleted */
   349    349     int iCur,          /* Cursor number for the table */
   350    350     int count          /* Increment the row change counter */
   351    351   ){
   352    352     int addr;
   353    353     addr = sqlite3VdbeAddOp(v, OP_NotExists, iCur, 0);
   354    354     sqlite3GenerateRowIndexDelete(db, v, pTab, iCur, 0);
   355         -  sqlite3VdbeAddOp(v, OP_Delete, iCur,
   356         -    (count?OPFLAG_NCHANGE:0) | OPFLAG_CSCHANGE);
          355  +  sqlite3VdbeAddOp(v, OP_Delete, iCur, (count?OPFLAG_NCHANGE:0));
   357    356     sqlite3VdbeChangeP2(v, addr, sqlite3VdbeCurrentAddr(v));
   358    357   }
   359    358   
   360    359   /*
   361    360   ** This routine generates VDBE code that causes the deletion of all
   362    361   ** index entries associated with a single row of a single table.
   363    362   **

Changes to src/func.c.

    12     12   ** This file contains the C functions that implement various SQL
    13     13   ** functions of SQLite.  
    14     14   **
    15     15   ** There is only one exported symbol in this file - the function
    16     16   ** sqliteRegisterBuildinFunctions() found at the bottom of the file.
    17     17   ** All other code has file scope.
    18     18   **
    19         -** $Id: func.c,v 1.74 2004/06/19 17:33:07 drh Exp $
           19  +** $Id: func.c,v 1.75 2004/06/21 06:50:28 danielk1977 Exp $
    20     20   */
    21     21   #include <ctype.h>
    22     22   #include <math.h>
    23     23   #include <stdlib.h>
    24     24   #include <assert.h>
    25     25   #include "sqliteInt.h"
    26     26   #include "vdbeInt.h"
................................................................................
   269    269     sqlite3_value **argv
   270    270   ){
   271    271     sqlite *db = sqlite3_user_data(context);
   272    272     sqlite3_result_int64(context, sqlite3_last_insert_rowid(db));
   273    273   }
   274    274   
   275    275   /*
   276         -** Implementation of the change_count() SQL function.  The return
   277         -** value is the same as the sqlite3_changes() API function.
          276  +** Implementation of the changes() SQL function.  The return value is the
          277  +** same as the sqlite3_changes() API function.
   278    278   */
   279         -static void change_count(
          279  +static void changes(
   280    280     sqlite3_context *context,
   281    281     int arg,
   282    282     sqlite3_value **argv
   283    283   ){
   284    284     sqlite *db = sqlite3_user_data(context);
   285    285     sqlite3_result_int(context, sqlite3_changes(db));
   286    286   }
   287    287   
   288    288   /*
   289         -** Implementation of the last_statement_change_count() SQL function.  The
   290         -** return value is the same as the sqlite3_last_statement_changes() API
   291         -** function.
          289  +** Implementation of the total_changes() SQL function.  The return value is
          290  +** the same as the sqlite3_total_changes() API function.
   292    291   */
   293         -static void last_statement_change_count(
   294         -  sqlite3_context *context, 
          292  +static void total_changes(
          293  +  sqlite3_context *context,
   295    294     int arg,
   296    295     sqlite3_value **argv
   297    296   ){
   298    297     sqlite *db = sqlite3_user_data(context);
   299         -  sqlite3_result_int(context, sqlite3_last_statement_changes(db));
          298  +  sqlite3_result_int(context, sqlite3_total_changes(db));
   300    299   }
          300  +
          301  +#if 0
   301    302   
   302    303   /*
   303    304   ** A LIKE pattern compiles to an instance of the following structure. Refer
   304    305   ** to the comment for compileLike() function for details.
   305    306   */
   306    307   struct LikePattern {
   307    308     int nState;
................................................................................
   311    312     } aState[1];
   312    313   };
   313    314   typedef struct LikePattern LikePattern;
   314    315   
   315    316   void deleteLike(void *pLike){
   316    317     sqliteFree(pLike);
   317    318   }
   318         -
   319         -
   320         -#if 0
   321    319   /* #define TRACE_LIKE */
   322    320   #if defined(TRACE_LIKE) && !defined(NDEBUG)
   323    321   char *dumpLike(LikePattern *pLike){
   324    322     int i;
   325    323     int k = 0;
   326    324     char *zBuf = (char *)sqliteMalloc(pLike->nState*40);
   327    325     
................................................................................
  1037   1035       { "like",                        2, 0, SQLITE_UTF8, 0, likeFunc   },
  1038   1036   /* { "like",                        2, 2, SQLITE_UTF16,0, likeFunc   }, */
  1039   1037       { "glob",                        2, 0, SQLITE_UTF8, 0, globFunc   },
  1040   1038       { "nullif",                      2, 0, SQLITE_UTF8, 0, nullifFunc },
  1041   1039       { "sqlite_version",              0, 0, SQLITE_UTF8, 0, versionFunc},
  1042   1040       { "quote",                       1, 0, SQLITE_UTF8, 0, quoteFunc  },
  1043   1041       { "last_insert_rowid",           0, 1, SQLITE_UTF8, 0, last_insert_rowid },
  1044         -    { "change_count",                0, 1, SQLITE_UTF8, 0, change_count      },
  1045         -    { "last_statement_change_count", 0, 1, SQLITE_UTF8, 0, 
  1046         -       last_statement_change_count },
         1042  +    { "changes",                     0, 1, SQLITE_UTF8, 0, changes    },
         1043  +    { "total_changes",               0, 1, SQLITE_UTF8, 0, total_changes },
  1047   1044   #ifdef SQLITE_SOUNDEX
  1048   1045       { "soundex",                     1, 0, SQLITE_UTF8, 0, soundexFunc},
  1049   1046   #endif
  1050   1047   #ifdef SQLITE_TEST
  1051   1048       { "randstr",                     2, 0, SQLITE_UTF8, 0, randStr    },
  1052   1049       { "test_destructor",             1, 0, SQLITE_UTF8, 0, test_destructor},
  1053   1050       { "test_destructor_count", 0, 0, SQLITE_UTF8, 0, test_destructor_count},

Changes to src/insert.c.

     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** This file contains C code routines that are called by the parser
    13     13   ** to handle INSERT statements in SQLite.
    14     14   **
    15         -** $Id: insert.c,v 1.112 2004/06/17 07:53:03 danielk1977 Exp $
           15  +** $Id: insert.c,v 1.113 2004/06/21 06:50:28 danielk1977 Exp $
    16     16   */
    17     17   #include "sqliteInt.h"
    18     18   
    19     19   /*
    20     20   ** Set P3 of the most recently inserted opcode to a column affinity
    21     21   ** string for index pIdx. A column affinity string has one character
    22     22   ** for each column in the table, according to the affinity of the column:
................................................................................
   241    241       }
   242    242     }
   243    243   
   244    244     /* Allocate a VDBE
   245    245     */
   246    246     v = sqlite3GetVdbe(pParse);
   247    247     if( v==0 ) goto insert_cleanup;
          248  +  sqlite3VdbeCountChanges(v);
   248    249     sqlite3BeginWriteOperation(pParse, pSelect || row_triggers_exist, pTab->iDb);
   249    250   
   250    251     /* if there are row triggers, allocate a temp table for new.* references. */
   251    252     if( row_triggers_exist ){
   252    253       newIdx = pParse->nTab++;
   253    254     }
   254    255   
................................................................................
   613    614       /* Close all tables opened */
   614    615       sqlite3VdbeAddOp(v, OP_Close, base, 0);
   615    616       for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){
   616    617         sqlite3VdbeAddOp(v, OP_Close, idx+base, 0);
   617    618       }
   618    619     }
   619    620   
   620         -  sqlite3VdbeAddOp(v, OP_SetCounts, 0, 0);
   621    621     sqlite3EndWriteOperation(pParse);
   622    622   
   623    623     /*
   624    624     ** Return the number of rows inserted.
   625    625     */
   626    626     if( db->flags & SQLITE_CountRows ){
   627    627       sqlite3VdbeAddOp(v, OP_MemLoad, iCntMem, 0);
................................................................................
   963    963     int isUpdate,       /* True for UPDATE, False for INSERT */
   964    964     int newIdx          /* Index of NEW table for triggers.  -1 if none */
   965    965   ){
   966    966     int i;
   967    967     Vdbe *v;
   968    968     int nIdx;
   969    969     Index *pIdx;
          970  +  int pik_flags;
   970    971   
   971    972     v = sqlite3GetVdbe(pParse);
   972    973     assert( v!=0 );
   973    974     assert( pTab->pSelect==0 );  /* This table is not a VIEW */
   974    975     for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){}
   975    976     for(i=nIdx-1; i>=0; i--){
   976    977       if( aIdxUsed && aIdxUsed[i]==0 ) continue;
................................................................................
   979    980     sqlite3VdbeAddOp(v, OP_MakeRecord, pTab->nCol, 0);
   980    981     sqlite3TableAffinityStr(v, pTab);
   981    982     if( newIdx>=0 ){
   982    983       sqlite3VdbeAddOp(v, OP_Dup, 1, 0);
   983    984       sqlite3VdbeAddOp(v, OP_Dup, 1, 0);
   984    985       sqlite3VdbeAddOp(v, OP_PutIntKey, newIdx, 0);
   985    986     }
   986         -  sqlite3VdbeAddOp(v, OP_PutIntKey, base,
   987         -    (pParse->trigStack?0:OPFLAG_NCHANGE) |
   988         -    (isUpdate?0:OPFLAG_LASTROWID) | OPFLAG_CSCHANGE);
          987  +  pik_flags = (OPFLAG_NCHANGE|(isUpdate?0:OPFLAG_LASTROWID));
          988  +  sqlite3VdbeAddOp(v, OP_PutIntKey, base, pik_flags);
          989  +  
   989    990     if( isUpdate && recnoChng ){
   990    991       sqlite3VdbeAddOp(v, OP_Pop, 1, 0);
   991    992     }
   992    993   }
   993    994   
   994    995   /*
   995    996   ** Generate code that will open write cursors for a table and for all

Changes to src/main.c.

    10     10   **
    11     11   *************************************************************************
    12     12   ** Main file for the SQLite library.  The routines in this file
    13     13   ** implement the programmer interface to the library.  Routines in
    14     14   ** other files are for internal use by SQLite and should not be
    15     15   ** accessed by users of the library.
    16     16   **
    17         -** $Id: main.c,v 1.230 2004/06/19 09:35:37 danielk1977 Exp $
           17  +** $Id: main.c,v 1.231 2004/06/21 06:50:28 danielk1977 Exp $
    18     18   */
    19     19   #include "sqliteInt.h"
    20     20   #include "os.h"
    21     21   #include <ctype.h>
    22     22   
    23     23   /*
    24     24   ** A pointer to this structure is used to communicate information
................................................................................
   444    444   ** Return the number of changes in the most recent call to sqlite3_exec().
   445    445   */
   446    446   int sqlite3_changes(sqlite *db){
   447    447     return db->nChange;
   448    448   }
   449    449   
   450    450   /*
   451         -** Return the number of changes produced by the last INSERT, UPDATE, or
   452         -** DELETE statement to complete execution. The count does not include
   453         -** changes due to SQL statements executed in trigger programs that were
   454         -** triggered by that statement
          451  +** Return the number of changes since the database handle was opened.
   455    452   */
   456         -int sqlite3_last_statement_changes(sqlite *db){
   457         -  return db->lsChange;
          453  +int sqlite3_total_changes(sqlite3 *db){
          454  +  return db->nTotalChange;
   458    455   }
   459    456   
   460    457   /*
   461    458   ** Close an existing SQLite database
   462    459   */
   463    460   int sqlite3_close(sqlite *db){
   464    461     HashElem *i;
................................................................................
   948    945     assert( ppStmt );
   949    946     *ppStmt = 0;
   950    947     if( sqlite3SafetyOn(db) ){
   951    948       rc = SQLITE_MISUSE;
   952    949       goto prepare_out;
   953    950     }
   954    951   
   955         -  if( db->pVdbe==0 ){ db->nChange = 0; }
   956    952     memset(&sParse, 0, sizeof(sParse));
   957    953     sParse.db = db;
   958    954     sqlite3RunParser(&sParse, zSql, &zErrMsg);
   959    955   
   960    956     if( db->xTrace && !db->init.busy ){
   961    957       /* Trace only the statment that was compiled.
   962    958       ** Make a copy of that part of the SQL string since zSQL is const

Changes to src/sqlite.h.in.

     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** This header file defines the interface that the SQLite library
    13     13   ** presents to client programs.
    14     14   **
    15         -** @(#) $Id: sqlite.h.in,v 1.104 2004/06/19 08:18:16 danielk1977 Exp $
           15  +** @(#) $Id: sqlite.h.in,v 1.105 2004/06/21 06:50:28 danielk1977 Exp $
    16     16   */
    17     17   #ifndef _SQLITE_H_
    18     18   #define _SQLITE_H_
    19     19   #include <stdarg.h>     /* Needed for the definition of va_list */
    20     20   
    21     21   /*
    22     22   ** Make sure we can call this stuff from C++.
................................................................................
   172    172   ** this optimization, the change count for "DELETE FROM table" will be
   173    173   ** zero regardless of the number of elements that were originally in the
   174    174   ** table. To get an accurate count of the number of rows deleted, use
   175    175   ** "DELETE FROM table WHERE 1" instead.
   176    176   */
   177    177   int sqlite3_changes(sqlite3*);
   178    178   
          179  +/*
          180  +** This function returns the number of database rows that have been
          181  +** modified by INSERT, UPDATE or DELETE statements since the database handle
          182  +** was opened. This includes UPDATE, INSERT and DELETE statements executed
          183  +** as part of trigger programs. All changes are counted as soon as the
          184  +** statement that makes them is completed (when the statement handle is
          185  +** passed to sqlite3_reset() or sqlite_finalise()).
          186  +**
          187  +** SQLite implements the command "DELETE FROM table" without a WHERE clause
          188  +** by dropping and recreating the table.  (This is much faster than going
          189  +** through and deleting individual elements form the table.)  Because of
          190  +** this optimization, the change count for "DELETE FROM table" will be
          191  +** zero regardless of the number of elements that were originally in the
          192  +** table. To get an accurate count of the number of rows deleted, use
          193  +** "DELETE FROM table WHERE 1" instead.
          194  +*/
          195  +int sqlite3_total_changes(sqlite3*);
          196  +
   179    197   /*
   180    198   ** This function returns the number of database rows that were changed
   181         -** by the last INSERT, UPDATE, or DELETE statment executed by sqlite3_exec(),
   182         -** or by the last VM to run to completion. The change count is not updated
   183         -** by SQL statements other than INSERT, UPDATE or DELETE.
          199  +** by the last INSERT, UPDATE, or DELETE statment completed.  The change
          200  +** count is not updated by SQL statements other than INSERT, UPDATE or
          201  +** DELETE.
   184    202   **
   185    203   ** Changes are counted, even if they are later undone by a ROLLBACK or
   186    204   ** ABORT. Changes associated with trigger programs that execute as a
   187    205   ** result of the INSERT, UPDATE, or DELETE statement are not counted.
   188    206   **
   189         -** If a callback invokes sqlite3_exec() recursively, then the changes
   190         -** in the inner, recursive call are counted together with the changes
   191         -** in the outer call.
   192         -**
   193    207   ** SQLite implements the command "DELETE FROM table" without a WHERE clause
   194    208   ** by dropping and recreating the table.  (This is much faster than going
   195    209   ** through and deleting individual elements form the table.)  Because of
   196    210   ** this optimization, the change count for "DELETE FROM table" will be
   197    211   ** zero regardless of the number of elements that were originally in the
   198    212   ** table. To get an accurate count of the number of rows deleted, use
   199    213   ** "DELETE FROM table WHERE 1" instead.
   200         -**
   201         -******* THIS IS AN EXPERIMENTAL API AND IS SUBJECT TO CHANGE ******
   202    214   */
   203         -int sqlite3_last_statement_changes(sqlite3*);
          215  +int sqlite3_changes(sqlite3*);
   204    216   
   205    217   /* This function causes any pending database operation to abort and
   206    218   ** return at its earliest opportunity.  This routine is typically
   207    219   ** called in response to a user action such as pressing "Cancel"
   208    220   ** or Ctrl-C where the user wants a long query operation to halt
   209    221   ** immediately.
   210    222   */

Changes to src/sqliteInt.h.

     7      7   **    May you do good and not evil.
     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** Internal interface definitions for SQLite.
    13     13   **
    14         -** @(#) $Id: sqliteInt.h,v 1.295 2004/06/19 16:06:12 drh Exp $
           14  +** @(#) $Id: sqliteInt.h,v 1.296 2004/06/21 06:50:28 danielk1977 Exp $
    15     15   */
    16     16   #include "config.h"
    17     17   #include "sqlite3.h"
    18     18   #include "hash.h"
    19     19   #include "parse.h"
    20     20   #include <stdio.h>
    21     21   #include <stdlib.h>
................................................................................
   314    314   ** DB_UnresetViews means that one or more views have column names that
   315    315   ** have been filled out.  If the schema changes, these column names might
   316    316   ** changes and so the view will need to be reset.
   317    317   */
   318    318   #define DB_SchemaLoaded    0x0001  /* The schema has been loaded */
   319    319   #define DB_UnresetViews    0x0002  /* Some views have defined column names */
   320    320   
   321         -#if 0
   322         -/*
   323         -** Possible values for the Db.textEnc field.
   324         -*/
   325         -#define TEXT_Utf8          1
   326         -#define TEXT_Utf16le       2
   327         -#define TEXT_Utf16be       3
   328         -#define TEXT_Utf16         (SQLITE_BIGENDIAN?TEXT_Utf16be:TEXT_Utf16le)
   329         -#endif
   330         -
   331    321   #define SQLITE_UTF16NATIVE (SQLITE_BIGENDIAN?SQLITE_UTF16BE:SQLITE_UTF16LE)
   332    322   
   333    323   /*
   334    324   ** An instance of the following structure is used to store the busy-handler
   335    325   ** callback for a given sqlite handle. 
   336    326   **
   337    327   ** The sqlite.busyHandler member of the sqlite struct contains the busy
................................................................................
   390    380     int (*xCommitCallback)(void*);/* Invoked at every commit. */
   391    381     Hash aFunc;                   /* All functions that can be in SQL exprs */
   392    382     Hash aCollSeq;                /* All collating sequences */
   393    383     CollSeq *pDfltColl;           /* The default collating sequence (BINARY) */
   394    384     i64 lastRowid;                /* ROWID of most recent insert (see above) */
   395    385     i64 priorNewRowid;            /* Last randomly generated ROWID */
   396    386     int magic;                    /* Magic number for detect library misuse */
   397         -  int nChange;                  /* Number of rows changed (see above) */
   398         -  int lsChange;                 /* Last statement change count (see above) */
   399         -  int csChange;                 /* Current statement change count (see above) */
   400         -  struct sqlite3InitInfo {       /* Information used during initialization */
   401         -    int iDb;                       /* When back is being initialized */
   402         -    int newTnum;                   /* Rootpage of table being initialized */
   403         -    u8 busy;                       /* TRUE if currently initializing */
          387  +  int nChange;                  /* Value returned by sqlite3_changes() */
          388  +  int nTotalChange;             /* Value returned by sqlite3_total_changes() */
          389  +  struct sqlite3InitInfo {      /* Information used during initialization */
          390  +    int iDb;                    /* When back is being initialized */
          391  +    int newTnum;                /* Rootpage of table being initialized */
          392  +    u8 busy;                    /* TRUE if currently initializing */
   404    393     } init;
   405    394     struct Vdbe *pVdbe;           /* List of active virtual machines */
   406    395     int activeVdbeCnt;            /* Number of vdbes currently executing */
   407    396     void (*xTrace)(void*,const char*);     /* Trace function */
   408    397     void *pTraceArg;                       /* Argument to the trace function */
   409    398   #ifndef SQLITE_OMIT_AUTHORIZATION
   410    399     int (*xAuth)(void*,int,const char*,const char*,const char*,const char*);
................................................................................
  1046   1035   };
  1047   1036   
  1048   1037   /*
  1049   1038   ** Bitfield flags for P2 value in OP_PutIntKey and OP_Delete
  1050   1039   */
  1051   1040   #define OPFLAG_NCHANGE   1    /* Set to update db->nChange */
  1052   1041   #define OPFLAG_LASTROWID 2    /* Set to update db->lastRowid */
  1053         -#define OPFLAG_CSCHANGE  4    /* Set to update db->csChange */
  1054   1042   
  1055   1043   /*
  1056   1044    * Each trigger present in the database schema is stored as an instance of
  1057   1045    * struct Trigger. 
  1058   1046    *
  1059   1047    * Pointers to instances of struct Trigger are stored in two ways.
  1060   1048    * 1. In the "trigHash" hash table (part of the sqlite* that represents the 
................................................................................
  1398   1386   int sqlite3ReadSchema(sqlite *db, char **);
  1399   1387   CollSeq *sqlite3FindCollSeq(sqlite *,u8 enc, const char *,int,int);
  1400   1388   CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char *zName, int nName);
  1401   1389   CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr);
  1402   1390   int sqlite3CheckCollSeq(Parse *, CollSeq *);
  1403   1391   int sqlite3CheckIndexCollSeq(Parse *, Index *);
  1404   1392   int sqlite3CheckObjectName(Parse *, const char *);
         1393  +void sqlite3VdbeSetChanges(sqlite3 *, int);
  1405   1394   
  1406   1395   const void *sqlite3ValueText(sqlite3_value*, u8);
  1407   1396   int sqlite3ValueBytes(sqlite3_value*, u8);
  1408   1397   void sqlite3ValueSetStr(sqlite3_value*, int, const void *,u8, void(*)(void*));
  1409   1398   void sqlite3ValueFree(sqlite3_value*);
  1410   1399   sqlite3_value *sqlite3ValueNew();
  1411   1400   sqlite3_value *sqlite3GetTransientValue(sqlite *db);

Changes to src/tclsqlite.c.

     7      7   **    May you do good and not evil.
     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** A TCL Interface to SQLite
    13     13   **
    14         -** $Id: tclsqlite.c,v 1.89 2004/06/19 08:18:21 danielk1977 Exp $
           14  +** $Id: tclsqlite.c,v 1.90 2004/06/21 06:50:28 danielk1977 Exp $
    15     15   */
    16     16   #ifndef NO_TCL     /* Omit this whole file if TCL is unavailable */
    17     17   
    18     18   #include "sqliteInt.h"
    19     19   #include "tcl.h"
    20     20   #include <stdlib.h>
    21     21   #include <string.h>
................................................................................
    65     65     char *zCommit;        /* The commit hook callback routine */
    66     66     char *zTrace;         /* The trace callback routine */
    67     67     char *zProgress;      /* The progress callback routine */
    68     68     char *zAuth;          /* The authorization callback routine */
    69     69     SqlFunc *pFunc;       /* List of SQL functions */
    70     70     SqlCollate *pCollate; /* List of SQL collation functions */
    71     71     int rc;               /* Return code of most recent sqlite3_exec() */
    72         -  int nChange;          /* Database changes for the most recent eval */
    73     72     Tcl_Obj *pCollateNeeded;  /* Collation needed script */
    74     73   };
    75     74   
    76     75   /*
    77     76   ** An instance of this structure passes information thru the sqlite
    78     77   ** logic from the original TCL command into the callback routine.
    79     78   */
................................................................................
   391    390     SqliteDb *pDb = (SqliteDb*)cd;
   392    391     int choice;
   393    392     int rc = TCL_OK;
   394    393     static const char *DB_strs[] = {
   395    394       "authorizer",         "busy",                   "changes",
   396    395       "close",              "commit_hook",            "complete",
   397    396       "errorcode",          "eval",                   "function",
   398         -    "last_insert_rowid",  "last_statement_changes", "onecolumn",
          397  +    "last_insert_rowid",  "onecolumn",
   399    398       "progress",           "rekey",                  "timeout",
   400    399       "trace",              "collate",                "collation_needed",
   401         -    0                    
          400  +    "total_changes",      0                    
   402    401     };
   403    402     enum DB_enum {
   404    403       DB_AUTHORIZER,        DB_BUSY,                   DB_CHANGES,
   405    404       DB_CLOSE,             DB_COMMIT_HOOK,            DB_COMPLETE,
   406    405       DB_ERRORCODE,         DB_EVAL,                   DB_FUNCTION,
   407         -    DB_LAST_INSERT_ROWID, DB_LAST_STATEMENT_CHANGES, DB_ONECOLUMN,        
          406  +    DB_LAST_INSERT_ROWID, DB_ONECOLUMN,        
   408    407       DB_PROGRESS,          DB_REKEY,                  DB_TIMEOUT,
   409         -    DB_TRACE,             DB_COLLATE,                DB_COLLATION_NEEDED
          408  +    DB_TRACE,             DB_COLLATE,                DB_COLLATION_NEEDED,
          409  +    DB_TOTAL_CHANGES
   410    410     };
   411    411   
   412    412     if( objc<2 ){
   413    413       Tcl_WrongNumArgs(interp, 1, objv, "SUBCOMMAND ...");
   414    414       return TCL_ERROR;
   415    415     }
   416    416     if( Tcl_GetIndexFromObj(interp, objv[1], DB_strs, "option", 0, &choice) ){
................................................................................
   543    543       }else{
   544    544         Tcl_WrongNumArgs(interp, 2, objv, "N CALLBACK");
   545    545         return TCL_ERROR;
   546    546       }
   547    547       break;
   548    548     }
   549    549   
   550         -  /*
   551         -  **     $db changes
          550  +  /*     $db changes
   552    551     **
   553    552     ** Return the number of rows that were modified, inserted, or deleted by
   554         -  ** the most recent "eval".
          553  +  ** the most recent INSERT, UPDATE or DELETE statement, not including 
          554  +  ** any changes made by trigger programs.
   555    555     */
   556    556     case DB_CHANGES: {
   557    557       Tcl_Obj *pResult;
   558         -    int nChange;
   559    558       if( objc!=2 ){
   560    559         Tcl_WrongNumArgs(interp, 2, objv, "");
   561    560         return TCL_ERROR;
   562    561       }
   563         -    /* nChange = sqlite3_changes(pDb->db); */
   564         -    nChange = pDb->nChange;
   565    562       pResult = Tcl_GetObjResult(interp);
   566         -    Tcl_SetIntObj(pResult, nChange);
   567         -    break;
   568         -  }
   569         -
   570         -  /*
   571         -  **     $db last_statement_changes
   572         -  **
   573         -  ** Return the number of rows that were modified, inserted, or deleted by
   574         -  ** the last statment to complete execution (excluding changes due to
   575         -  ** triggers)
   576         -  */
   577         -  case DB_LAST_STATEMENT_CHANGES: {
   578         -    Tcl_Obj *pResult;
   579         -    int lsChange;
   580         -    if( objc!=2 ){
   581         -      Tcl_WrongNumArgs(interp, 2, objv, "");
   582         -      return TCL_ERROR;
   583         -    }
   584         -    lsChange = sqlite3_last_statement_changes(pDb->db);
   585         -    pResult = Tcl_GetObjResult(interp);
   586         -    Tcl_SetIntObj(pResult, lsChange);
          563  +    Tcl_SetIntObj(pResult, sqlite3_changes(pDb->db));
   587    564       break;
   588    565     }
   589    566   
   590    567     /*    $db close
   591    568     **
   592    569     ** Shutdown the database
   593    570     */
................................................................................
   681    658       Tcl_IncrRefCount(pRet);
   682    659   
   683    660       if( objc!=5 && objc!=3 ){
   684    661         Tcl_WrongNumArgs(interp, 2, objv, "SQL ?ARRAY-NAME CODE?");
   685    662         return TCL_ERROR;
   686    663       }
   687    664   
   688         -    pDb->nChange = 0;
   689    665       zSql = Tcl_GetStringFromObj(objv[2], 0);
   690    666       while( zSql[0] ){
   691    667         int i;
   692    668     
   693    669         if( SQLITE_OK!=sqlite3_prepare(pDb->db, zSql, -1, &pStmt, &zLeft) ){
   694    670           Tcl_SetObjResult(interp, dbTextToObj(sqlite3_errmsg(pDb->db)));
   695    671           rc = TCL_ERROR;
................................................................................
   746    722     
   747    723         if( pStmt && SQLITE_OK!=sqlite3_errcode(pDb->db) ){
   748    724           Tcl_SetObjResult(interp, dbTextToObj(sqlite3_errmsg(pDb->db)));
   749    725           rc = TCL_ERROR;
   750    726           break;
   751    727         }
   752    728   
   753         -      pDb->nChange += sqlite3_changes(pDb->db);
   754    729         zSql = zLeft;
   755    730       }
   756    731   
   757    732       if( rc==TCL_OK ){
   758    733         Tcl_SetObjResult(interp, pRet);
   759    734       }
   760    735       Tcl_DecrRefCount(pRet);
................................................................................
   955    930         Tcl_DecrRefCount(pDb->pCollateNeeded);
   956    931       }
   957    932       pDb->pCollateNeeded = Tcl_DuplicateObj(objv[2]);
   958    933       Tcl_IncrRefCount(pDb->pCollateNeeded);
   959    934       sqlite3_collation_needed(pDb->db, pDb, tclCollateNeeded);
   960    935       break;
   961    936     }
          937  +
          938  +  /*
          939  +  **     $db total_changes
          940  +  **
          941  +  ** Return the number of rows that were modified, inserted, or deleted 
          942  +  ** since the database handle was created.
          943  +  */
          944  +  case DB_TOTAL_CHANGES: {
          945  +    Tcl_Obj *pResult;
          946  +    if( objc!=2 ){
          947  +      Tcl_WrongNumArgs(interp, 2, objv, "");
          948  +      return TCL_ERROR;
          949  +    }
          950  +    pResult = Tcl_GetObjResult(interp);
          951  +    Tcl_SetIntObj(pResult, sqlite3_total_changes(pDb->db));
          952  +    break;
          953  +  }
   962    954   
   963    955     } /* End of the SWITCH statement */
   964    956     return rc;
   965    957   }
   966    958   
   967    959   /*
   968    960   **   sqlite DBNAME FILENAME ?MODE? ?-key KEY?

Changes to src/trigger.c.

   646    646   	sqlite3Select(pParse, ss, SRT_Discard, 0, 0, 0, 0, 0);
   647    647   	sqlite3SelectDelete(ss);
   648    648   	break;
   649    649         }
   650    650         case TK_UPDATE: {
   651    651           SrcList *pSrc;
   652    652           pSrc = targetSrcList(pParse, pTriggerStep);
          653  +        sqlite3VdbeAddOp(pParse->pVdbe, OP_ResetCount, 0, 0);
   653    654           sqlite3VdbeAddOp(pParse->pVdbe, OP_ListPush, 0, 0);
   654    655           sqlite3Update(pParse, pSrc,
   655    656   		sqlite3ExprListDup(pTriggerStep->pExprList), 
   656    657   		sqlite3ExprDup(pTriggerStep->pWhere), orconf);
   657    658           sqlite3VdbeAddOp(pParse->pVdbe, OP_ListPop, 0, 0);
          659  +        sqlite3VdbeAddOp(pParse->pVdbe, OP_ResetCount, 1, 0);
   658    660           break;
   659    661         }
   660    662         case TK_INSERT: {
   661    663           SrcList *pSrc;
   662    664           pSrc = targetSrcList(pParse, pTriggerStep);
          665  +        sqlite3VdbeAddOp(pParse->pVdbe, OP_ResetCount, 0, 0);
   663    666           sqlite3Insert(pParse, pSrc,
   664    667             sqlite3ExprListDup(pTriggerStep->pExprList), 
   665    668             sqlite3SelectDup(pTriggerStep->pSelect), 
   666    669             sqlite3IdListDup(pTriggerStep->pIdList), orconf);
          670  +        sqlite3VdbeAddOp(pParse->pVdbe, OP_ResetCount, 1, 0);
   667    671           break;
   668    672         }
   669    673         case TK_DELETE: {
   670    674           SrcList *pSrc;
          675  +        sqlite3VdbeAddOp(pParse->pVdbe, OP_ResetCount, 0, 0);
   671    676           sqlite3VdbeAddOp(pParse->pVdbe, OP_ListPush, 0, 0);
   672    677           pSrc = targetSrcList(pParse, pTriggerStep);
   673    678           sqlite3DeleteFrom(pParse, pSrc, sqlite3ExprDup(pTriggerStep->pWhere));
   674    679           sqlite3VdbeAddOp(pParse->pVdbe, OP_ListPop, 0, 0);
          680  +        sqlite3VdbeAddOp(pParse->pVdbe, OP_ResetCount, 1, 0);
   675    681           break;
   676    682         }
   677    683         default:
   678    684           assert(0);
   679    685       } 
   680    686       pParse->nTab = saveNTab;
   681    687       pTriggerStep = pTriggerStep->pNext;

Changes to src/update.c.

     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** This file contains C code routines that are called by the parser
    13     13   ** to handle UPDATE statements.
    14     14   **
    15         -** $Id: update.c,v 1.84 2004/06/16 12:02:52 danielk1977 Exp $
           15  +** $Id: update.c,v 1.85 2004/06/21 06:50:29 danielk1977 Exp $
    16     16   */
    17     17   #include "sqliteInt.h"
    18     18   
    19     19   /*
    20     20   ** Process an UPDATE statement.
    21     21   **
    22     22   **   UPDATE OR IGNORE table_wxyz SET a=b, c=d WHERE e<5 AND f NOT NULL;
................................................................................
   205    205       sqlite3AuthContextPush(pParse, &sContext, pTab->zName);
   206    206     }
   207    207   
   208    208     /* Begin generating code.
   209    209     */
   210    210     v = sqlite3GetVdbe(pParse);
   211    211     if( v==0 ) goto update_cleanup;
          212  +  sqlite3VdbeCountChanges(v);
   212    213     sqlite3BeginWriteOperation(pParse, 1, pTab->iDb);
   213    214   
   214    215     /* If we are trying to update a view, construct that view into
   215    216     ** a temporary table.
   216    217     */
   217    218     if( isView ){
   218    219       Select *pView;
................................................................................
   436    437       sqlite3VdbeAddOp(v, OP_Close, iCur, 0);
   437    438       pParse->nTab = iCur;
   438    439     }else{
   439    440       sqlite3VdbeAddOp(v, OP_Close, newIdx, 0);
   440    441       sqlite3VdbeAddOp(v, OP_Close, oldIdx, 0);
   441    442     }
   442    443   
   443         -  sqlite3VdbeAddOp(v, OP_SetCounts, 0, 0);
   444    444     sqlite3EndWriteOperation(pParse);
   445    445   
   446    446     /*
   447    447     ** Return the number of rows that were changed.
   448    448     */
   449    449     if( db->flags & SQLITE_CountRows && !pParse->trigStack ){
   450    450       sqlite3VdbeAddOp(v, OP_Callback, 1, 0);

Changes to src/vdbe.c.

    39     39   **
    40     40   ** Various scripts scan this source file in order to generate HTML
    41     41   ** documentation, headers files, or other derived files.  The formatting
    42     42   ** of the code in this file is, therefore, important.  See other comments
    43     43   ** in this file for details.  If in doubt, do not deviate from existing
    44     44   ** commenting and indentation practices when changing or adding code.
    45     45   **
    46         -** $Id: vdbe.c,v 1.381 2004/06/19 15:40:23 drh Exp $
           46  +** $Id: vdbe.c,v 1.382 2004/06/21 06:50:29 danielk1977 Exp $
    47     47   */
    48     48   #include "sqliteInt.h"
    49     49   #include "os.h"
    50     50   #include <ctype.h>
    51     51   #include "vdbeInt.h"
    52     52   
    53     53   /*
................................................................................
  3062   3062   ** Write an entry into the table of cursor P1.  A new entry is
  3063   3063   ** created if it doesn't already exist or the data for an existing
  3064   3064   ** entry is overwritten.  The data is the value on the top of the
  3065   3065   ** stack.  The key is the next value down on the stack.  The key must
  3066   3066   ** be an integer.  The stack is popped twice by this instruction.
  3067   3067   **
  3068   3068   ** If the OPFLAG_NCHANGE flag of P2 is set, then the row change count is
  3069         -** incremented (otherwise not).  If the OPFLAG_CSCHANGE flag is set,
  3070         -** then the current statement change count is incremented (otherwise not).
  3071         -** If the OPFLAG_LASTROWID flag of P2 is set, then rowid is
  3072         -** stored for subsequent return by the sqlite3_last_insert_rowid() function
  3073         -** (otherwise it's unmodified).
         3069  +** incremented (otherwise not).  If the OPFLAG_LASTROWID flag of P2 is set,
         3070  +** then rowid is stored for subsequent return by the
         3071  +** sqlite3_last_insert_rowid() function (otherwise it's unmodified).
  3074   3072   */
  3075   3073   /* Opcode: PutStrKey P1 * *
  3076   3074   **
  3077   3075   ** Write an entry into the table of cursor P1.  A new entry is
  3078   3076   ** created if it doesn't already exist or the data for an existing
  3079   3077   ** entry is overwritten.  The data is the value on the top of the
  3080   3078   ** stack.  The key is the next value down on the stack.  The key must
................................................................................
  3111   3109           nKey = intToKey(pNos->i);
  3112   3110           zKey = 0;
  3113   3111         }else{
  3114   3112           nKey = sizeof(i64);
  3115   3113           zKey = (char*)&iKey;
  3116   3114         }
  3117   3115   
  3118         -      if( pOp->p2 & OPFLAG_NCHANGE ) db->nChange++;
         3116  +      if( pOp->p2 & OPFLAG_NCHANGE ) p->nChange++;
  3119   3117         if( pOp->p2 & OPFLAG_LASTROWID ) db->lastRowid = pNos->i;
  3120         -      if( pOp->p2 & OPFLAG_CSCHANGE ) db->csChange++;
  3121   3118         if( pC->nextRowidValid && pTos->i>=pC->nextRowid ){
  3122   3119           pC->nextRowidValid = 0;
  3123   3120         }
  3124   3121       }
  3125   3122       if( pTos->flags & MEM_Null ){
  3126   3123         pTos->z = 0;
  3127   3124         pTos->n = 0;
................................................................................
  3165   3162   **
  3166   3163   ** The cursor will be left pointing at either the next or the previous
  3167   3164   ** record in the table. If it is left pointing at the next record, then
  3168   3165   ** the next Next instruction will be a no-op.  Hence it is OK to delete
  3169   3166   ** a record from within an Next loop.
  3170   3167   **
  3171   3168   ** If the OPFLAG_NCHANGE flag of P2 is set, then the row change count is
  3172         -** incremented (otherwise not).  If OPFLAG_CSCHANGE flag is set,
  3173         -** then the current statement change count is incremented (otherwise not).
         3169  +** incremented (otherwise not).
  3174   3170   **
  3175   3171   ** If P1 is a pseudo-table, then this instruction is a no-op.
  3176   3172   */
  3177   3173   case OP_Delete: {
  3178   3174     int i = pOp->p1;
  3179   3175     Cursor *pC;
  3180   3176     assert( i>=0 && i<p->nCursor );
................................................................................
  3182   3178     assert( pC!=0 );
  3183   3179     if( pC->pCursor!=0 ){
  3184   3180       sqlite3VdbeCursorMoveto(pC);
  3185   3181       rc = sqlite3BtreeDelete(pC->pCursor);
  3186   3182       pC->nextRowidValid = 0;
  3187   3183       pC->cacheValid = 0;
  3188   3184     }
  3189         -  if( pOp->p2 & OPFLAG_NCHANGE ) db->nChange++;
  3190         -  if( pOp->p2 & OPFLAG_CSCHANGE ) db->csChange++;
         3185  +  if( pOp->p2 & OPFLAG_NCHANGE ) p->nChange++;
  3191   3186     break;
  3192   3187   }
  3193   3188   
  3194         -/* Opcode: SetCounts * * *
         3189  +/* Opcode: ResetCount P1 * *
  3195   3190   **
  3196         -** Called at end of statement.  Updates lsChange (last statement change count)
  3197         -** and resets csChange (current statement change count) to 0.
         3191  +** This opcode resets the VMs internal change counter to 0. If P1 is true,
         3192  +** then the value of the change counter is copied to the database handle
         3193  +** change counter (returned by subsequent calls to sqlite3_changes())
         3194  +** before it is reset. This is used by trigger programs.
  3198   3195   */
  3199         -case OP_SetCounts: {
  3200         -  db->lsChange=db->csChange;
  3201         -  db->csChange=0;
         3196  +case OP_ResetCount: {
         3197  +  if( pOp->p1 ){
         3198  +    sqlite3VdbeSetChanges(p->db, p->nChange);
         3199  +  }
         3200  +  p->nChange = 0;
  3202   3201     break;
  3203   3202   }
  3204   3203   
  3205   3204   /* Opcode: KeyAsData P1 P2 *
  3206   3205   **
  3207   3206   ** Turn the key-as-data mode for cursor P1 either on (if P2==1) or
  3208   3207   ** off (if P2==0).  In key-as-data mode, the OP_Column opcode pulls
................................................................................
  3990   3989   **
  3991   3990   ** Save the current Vdbe list such that it can be restored by a ListPop
  3992   3991   ** opcode. The list is empty after this is executed.
  3993   3992   */
  3994   3993   case OP_ListPush: {
  3995   3994     p->keylistStackDepth++;
  3996   3995     assert(p->keylistStackDepth > 0);
         3996  +
         3997  +  /* FIX ME: This should be allocated at compile time. */
  3997   3998     p->keylistStack = sqliteRealloc(p->keylistStack, 
  3998   3999             sizeof(Keylist *) * p->keylistStackDepth);
  3999   4000     if( p->keylistStack==0 ) goto no_mem;
         4001  +
  4000   4002     p->keylistStack[p->keylistStackDepth - 1] = p->pList;
  4001   4003     p->pList = 0;
  4002   4004     break;
  4003   4005   }
  4004   4006   
  4005   4007   /* Opcode: ListPop * * * 
  4006   4008   **
................................................................................
  4024   4026   **
  4025   4027   ** Save the current Vdbe context such that it can be restored by a ContextPop
  4026   4028   ** opcode. The context stores the last insert row id, the last statement change
  4027   4029   ** count, and the current statement change count.
  4028   4030   */
  4029   4031   case OP_ContextPush: {
  4030   4032     p->contextStackDepth++;
  4031         -  assert(p->contextStackDepth > 0);
         4033  +  assert( p->contextStackDepth>0 );
         4034  +
         4035  +  /* FIX ME: This should be allocated as part of the vdbe at compile-time */
  4032   4036     p->contextStack = sqliteRealloc(p->contextStack, 
  4033   4037             sizeof(Context) * p->contextStackDepth);
  4034   4038     if( p->contextStack==0 ) goto no_mem;
         4039  +
  4035   4040     p->contextStack[p->contextStackDepth - 1].lastRowid = p->db->lastRowid;
         4041  +  p->contextStack[p->contextStackDepth - 1].nChange = p->nChange;
         4042  +
         4043  +#if 0
  4036   4044     p->contextStack[p->contextStackDepth - 1].lsChange = p->db->lsChange;
  4037   4045     p->contextStack[p->contextStackDepth - 1].csChange = p->db->csChange;
         4046  +#endif
  4038   4047     break;
  4039   4048   }
  4040   4049   
  4041   4050   /* Opcode: ContextPop * * * 
  4042   4051   **
  4043   4052   ** Restore the Vdbe context to the state it was in when contextPush was last
  4044   4053   ** executed. The context stores the last insert row id, the last statement
  4045   4054   ** change count, and the current statement change count.
  4046   4055   */
  4047   4056   case OP_ContextPop: {
  4048   4057     assert(p->contextStackDepth > 0);
  4049   4058     p->contextStackDepth--;
  4050   4059     p->db->lastRowid = p->contextStack[p->contextStackDepth].lastRowid;
         4060  +  p->nChange = p->contextStack[p->contextStackDepth].nChange;
         4061  +#if 0
  4051   4062     p->db->lsChange = p->contextStack[p->contextStackDepth].lsChange;
  4052   4063     p->db->csChange = p->contextStack[p->contextStackDepth].csChange;
         4064  +#endif
  4053   4065     if( p->contextStackDepth == 0 ){
  4054   4066       sqliteFree(p->contextStack);
  4055   4067       p->contextStack = 0;
  4056   4068     }
  4057   4069     break;
  4058   4070   }
  4059   4071   

Changes to src/vdbe.h.

    11     11   *************************************************************************
    12     12   ** Header file for the Virtual DataBase Engine (VDBE)
    13     13   **
    14     14   ** This header defines the interface to the virtual database engine
    15     15   ** or VDBE.  The VDBE implements an abstract machine that runs a
    16     16   ** simple program to access and modify the underlying database.
    17     17   **
    18         -** $Id: vdbe.h,v 1.86 2004/06/19 14:49:12 drh Exp $
           18  +** $Id: vdbe.h,v 1.87 2004/06/21 06:50:29 danielk1977 Exp $
    19     19   */
    20     20   #ifndef _SQLITE_VDBE_H_
    21     21   #define _SQLITE_VDBE_H_
    22     22   #include <stdio.h>
    23     23   
    24     24   /*
    25     25   ** A single VDBE is an opaque structure named "Vdbe".  Only routines
................................................................................
   119    119   int sqlite3VdbeCurrentAddr(Vdbe*);
   120    120   void sqlite3VdbeTrace(Vdbe*,FILE*);
   121    121   void sqlite3VdbeCompressSpace(Vdbe*,int);
   122    122   int sqlite3VdbeReset(Vdbe*,char **);
   123    123   int sqliteVdbeSetVariables(Vdbe*,int,const char**);
   124    124   void sqlite3VdbeSetNumCols(Vdbe*,int);
   125    125   int sqlite3VdbeSetColName(Vdbe*, int, const char *, int);
          126  +void sqlite3VdbeCountChanges(Vdbe*);
   126    127   
   127    128   #ifndef NDEBUG
   128    129     void sqlite3VdbeComment(Vdbe*, const char*, ...);
   129    130   # define VdbeComment(X)  sqlite3VdbeComment X
   130    131   #else
   131    132   # define VdbeComment(X)
   132    133   #endif
   133    134   
   134    135   #endif

Changes to src/vdbeInt.h.

   283    283   ** A Context stores the last insert rowid, the last statement change count,
   284    284   ** and the current statement change count (i.e. changes since last statement).
   285    285   ** Elements of Context structure type make up the ContextStack, which is
   286    286   ** updated by the ContextPush and ContextPop opcodes (used by triggers)
   287    287   */
   288    288   typedef struct Context Context;
   289    289   struct Context {
   290         -  int lastRowid;    /* Last insert rowid (from db->lastRowid) */
   291         -  int lsChange;     /* Last statement change count (from db->lsChange) */
   292         -  int csChange;     /* Current statement change count (from db->csChange) */
          290  +  int lastRowid;    /* Last insert rowid (sqlite3.lastRowid) */
          291  +  int nChange;      /* Statement changes (Vdbe.nChanges)     */
   293    292   };
   294    293   
   295    294   /*
   296    295   ** An instance of the virtual machine.  This structure contains the complete
   297    296   ** state of the virtual machine.
   298    297   **
   299    298   ** The "sqlite3_stmt" structure pointer that is returned by sqlite3_compile()
................................................................................
   343    342     int nResColumn;         /* Number of columns in one row of the result set */
   344    343     char **azResColumn;     /* Values for one row of result */ 
   345    344     int popStack;           /* Pop the stack this much on entry to VdbeExec() */
   346    345     char *zErrMsg;          /* Error message written here */
   347    346     u8 resOnStack;          /* True if there are result values on the stack */
   348    347     u8 explain;             /* True if EXPLAIN present on SQL command */
   349    348     u8 autoCommitOn;        /* True if autocommit got turned on by this program */
          349  +  int nChange;            /* Number of db changes made since last reset */
          350  +  u8 changeCntOn;         /* True to update the change-counter */
   350    351   };
   351    352   
   352    353   /*
   353    354   ** The following are allowed values for Vdbe.magic
   354    355   */
   355    356   #define VDBE_MAGIC_INIT     0x26bceaa5    /* Building a VDBE program */
   356    357   #define VDBE_MAGIC_RUN      0xbdf20da3    /* VDBE is ready to execute */

Changes to src/vdbeaux.c.

   641    641     p->rc = SQLITE_OK;
   642    642     p->uniqueCnt = 0;
   643    643     p->returnDepth = 0;
   644    644     p->errorAction = OE_Abort;
   645    645     p->popStack =  0;
   646    646     p->explain |= isExplain;
   647    647     p->magic = VDBE_MAGIC_RUN;
          648  +  p->nChange = 0;
   648    649   #ifdef VDBE_PROFILE
   649    650     {
   650    651       int i;
   651    652       for(i=0; i<p->nOp; i++){
   652    653         p->aOp[i].cnt = 0;
   653    654         p->aOp[i].cycles = 0;
   654    655       }
................................................................................
  1243   1244       Btree *pBt = db->aDb[i].pBt;
  1244   1245       if( pBt ){
  1245   1246         rc = xFunc(pBt);
  1246   1247         if( p->rc==SQLITE_OK ) p->rc = rc;
  1247   1248       }
  1248   1249     }
  1249   1250   
         1251  +  /* If this was an INSERT, UPDATE or DELETE, set the change counter. */
         1252  +  if( p->changeCntOn ){
         1253  +    if( !xFunc || xFunc==sqlite3BtreeCommitStmt ){
         1254  +      sqlite3VdbeSetChanges(db, p->nChange);
         1255  +    }else{
         1256  +      sqlite3VdbeSetChanges(db, 0);
         1257  +    }
         1258  +    p->nChange = 0;
         1259  +  }
  1250   1260   
  1251   1261     if( p->rc!=SQLITE_OK ){
  1252   1262       sqlite3RollbackInternalChanges(db);
  1253   1263     }else if( db->flags & SQLITE_InternChanges ){
  1254   1264       sqlite3CommitInternalChanges(db);
  1255   1265     }
  1256   1266   
................................................................................
  1351   1361     }
  1352   1362     for(i=0; i<p->nOp; i++){
  1353   1363       Op *pOp = &p->aOp[i];
  1354   1364       if( pOp->p3type==P3_DYNAMIC || pOp->p3type==P3_KEYINFO ){
  1355   1365         sqliteFree(pOp->p3);
  1356   1366       }
  1357   1367       if( pOp->p3type==P3_VDBEFUNC ){
  1358         -      int j;
  1359   1368         VdbeFunc *pVdbeFunc = (VdbeFunc *)pOp->p3;
  1360   1369         sqlite3VdbeDeleteAuxData(pVdbeFunc, -1);
  1361   1370         sqliteFree(pVdbeFunc);
  1362   1371       }
  1363   1372   #ifndef NDEBUG
  1364   1373       sqliteFree(pOp->zComment);
  1365   1374   #endif
................................................................................
  1751   1760       return rc;
  1752   1761     }
  1753   1762     lenRowid = sqlite3VdbeIdxRowidLen(m.n, m.z);
  1754   1763     *res = sqlite3VdbeRecordCompare(pC->pKeyInfo, m.n-lenRowid, m.z, nKey, pKey);
  1755   1764     sqlite3VdbeMemRelease(&m);
  1756   1765     return SQLITE_OK;
  1757   1766   }
         1767  +
         1768  +/*
         1769  +** This routine sets the value to be returned by subsequent calls to
         1770  +** sqlite3_changes() on the database handle 'db'. 
         1771  +*/
         1772  +void sqlite3VdbeSetChanges(sqlite3 *db, int nChange){
         1773  +  db->nChange = nChange;
         1774  +  db->nTotalChange += nChange;
         1775  +}
         1776  +
         1777  +/*
         1778  +** Set a flag in the vdbe to update the change counter when it is finalised
         1779  +** or reset.
         1780  +*/
         1781  +void sqlite3VdbeCountChanges(Vdbe *p){
         1782  +  p->changeCntOn = 1;
         1783  +}
         1784  +
         1785  +
         1786  +

Changes to test/capi2.test.

     7      7   #    May you find forgiveness for yourself and forgive others.
     8      8   #    May you share freely, never taking more than you give.
     9      9   #
    10     10   #***********************************************************************
    11     11   # This file implements regression tests for SQLite library.  The
    12     12   # focus of this script testing the callback-free C/C++ API.
    13     13   #
    14         -# $Id: capi2.test,v 1.14 2004/06/19 00:16:31 drh Exp $
           14  +# $Id: capi2.test,v 1.15 2004/06/21 06:50:29 danielk1977 Exp $
    15     15   #
    16     16   
    17     17   set testdir [file dirname $argv0]
    18     18   source $testdir/tester.tcl
    19     19   
    20     20   # proc sqlite_step {stmt N VALS COLS} {
    21     21   #   upvar $VALS vals
................................................................................
   223    223          [sqlite3_column_count $VM] \
   224    224          [get_row_values $VM] \
   225    225          [get_column_names $VM]
   226    226   } {SQLITE_DONE 0 {} {}}
   227    227   
   228    228   # Update for v3 - the change has not actually happened until the query is
   229    229   # finalized. Is this going to cause trouble for anyone? Lee Nelson maybe?
   230         -do_test capi2-3.10b {sqlite3_changes $DB} {1}
          230  +do_test capi2-3.10b {db changes} {0}
   231    231   do_test capi2-3.11 {
   232    232     sqlite3_finalize $VM
   233    233   } {SQLITE_OK}
   234         -do_test capi2-3.11b {sqlite3_changes $DB} {1}
          234  +do_test capi2-3.11b {db changes} {1}
   235    235   do_test capi2-3.12 {
   236    236     sqlite3_finalize $VM
   237    237   } {SQLITE_MISUSE}
   238    238   do_test capi2-3.13 {
   239    239     set VM [sqlite3_prepare $DB {INSERT INTO t1 VALUES(1,3,4)} -1 TAIL]
   240    240     list [sqlite3_step $VM] \
   241    241          [sqlite3_column_count $VM] \
   242    242          [get_row_values $VM] \
   243    243          [get_column_names $VM]
   244    244   } {SQLITE_ERROR 0 {} {}}
   245         -do_test capi2-3.13b {db changes} {0}
          245  +
          246  +# Update for v3: Preparing a statement does not affect the change counter.
          247  +# (Test result changes from 0 to 1).
          248  +do_test capi2-3.13b {db changes} {1}
          249  +
   246    250   do_test capi2-3.14 {
   247    251     list [sqlite3_finalize $VM] [sqlite3_errmsg $DB]
   248    252   } {SQLITE_CONSTRAINT {column a is not unique}}
   249    253   do_test capi2-3.15 {
   250    254     set VM [sqlite3_prepare $DB {CREATE TABLE t2(a NOT NULL, b)} -1 TAIL]
   251    255     set TAIL
   252    256   } {}
................................................................................
   598    602   } {0 21 2 3 22 3 4 23 4 5 24 5 6}
   599    603   do_test capi2-7.10 {
   600    604     stepsql $DB {
   601    605       UPDATE t1 SET a=a-20;
   602    606       SELECT * FROM t1;
   603    607     }
   604    608   } {0 4 1 2 3 2 3 4 3 4 5 4 5 6}
          609  +
          610  +# Update for version 3: A SELECT statement no longer resets the change
          611  +# counter (Test result changes from 0 to 4).
   605    612   do_test capi2-7.11 {
   606    613     sqlite3_changes $DB
   607         -} {0}
          614  +} {4}
          615  +do_test capi2-7.11a {
          616  +  execsql {SELECT count(*) FROM t1}
          617  +} {4}
          618  +
   608    619   do_test capi2-7.12 {
   609    620     set x [stepsql $DB {EXPLAIN SELECT * FROM t1}]
   610    621     lindex $x 0
   611    622   } {0}
   612    623   
   613    624   # Ticket #261 - make sure we can finalize before the end of a query.
   614    625   #

Changes to test/conflict.test.

     9      9   #
    10     10   #***********************************************************************
    11     11   # This file implements regression tests for SQLite library.
    12     12   #
    13     13   # This file implements tests for the conflict resolution extension
    14     14   # to SQLite.
    15     15   #
    16         -# $Id: conflict.test,v 1.21 2004/05/31 08:55:34 danielk1977 Exp $
           16  +# $Id: conflict.test,v 1.22 2004/06/21 06:50:29 danielk1977 Exp $
    17     17   
    18     18   set testdir [file dirname $argv0]
    19     19   source $testdir/tester.tcl
    20     20   
    21     21   # Create tables for the first group of tests.
    22     22   #
    23     23   do_test conflict-1.0 {
................................................................................
   379    379     }
   380    380   } {51}
   381    381   do_test conflict-7.7 {
   382    382     execsql {
   383    383       SELECT count(*) FROM t1;
   384    384     }
   385    385   } {1}
          386  +
          387  +# Update for version 3: A SELECT statement no longer resets the change
          388  +# counter (Test result changes from 0 to 50).
   386    389   do_test conflict-7.7.1 {
   387    390     db changes
   388         -} {0}
          391  +} {50}
   389    392   
   390    393   # Make sure the row count is right for rows that are ignored on
   391    394   # an insert.
   392    395   #
   393    396   do_test conflict-8.1 {
   394    397     execsql {
   395    398       DELETE FROM t1;

Changes to test/insert2.test.

     8      8   #    May you share freely, never taking more than you give.
     9      9   #
    10     10   #***********************************************************************
    11     11   # This file implements regression tests for SQLite library.  The
    12     12   # focus of this file is testing the INSERT statement that takes is
    13     13   # result from a SELECT.
    14     14   #
    15         -# $Id: insert2.test,v 1.10 2002/06/25 13:16:04 drh Exp $
           15  +# $Id: insert2.test,v 1.11 2004/06/21 06:50:29 danielk1977 Exp $
    16     16   
    17     17   set testdir [file dirname $argv0]
    18     18   source $testdir/tester.tcl
    19     19   
    20     20   # Create some tables with data that we can select against
    21     21   #
    22     22   do_test insert2-1.0 {
................................................................................
   121    121   #
   122    122   do_test insert2-3.1 {
   123    123     execsql {
   124    124       SELECT * from t4;
   125    125     }
   126    126   } {1 2}
   127    127   do_test insert2-3.2 {
          128  +  set x [db total_changes]
   128    129     execsql {
   129    130       BEGIN;
   130    131       INSERT INTO t4 VALUES(2,4);
   131    132       INSERT INTO t4 VALUES(3,6);
   132    133       INSERT INTO t4 VALUES(4,8);
   133    134       INSERT INTO t4 VALUES(5,10);
   134    135       INSERT INTO t4 VALUES(6,12);
   135    136       INSERT INTO t4 VALUES(7,14);
   136    137       INSERT INTO t4 VALUES(8,16);
   137    138       INSERT INTO t4 VALUES(9,18);
   138    139       INSERT INTO t4 VALUES(10,20);
   139    140       COMMIT;
   140    141     }
   141         -  db changes
          142  +  expr [db total_changes] - $x
   142    143   } {9}
   143    144   do_test insert2-3.2.1 {
   144    145     execsql {
   145    146       SELECT count(*) FROM t4;
   146    147     }
   147    148   } {10}
   148    149   do_test insert2-3.3 {

Changes to test/laststmtchanges.test.

     3      3   #
     4      4   #    May you do good and not evil.
     5      5   #    May you find forgiveness for yourself and forgive others.
     6      6   #    May you share freely, never taking more than you give.
     7      7   #
     8      8   #***********************************************************************
     9      9   #
    10         -# Tests to make sure that value returned by last_statement_change_count()
    11         -# (LSCC) is updated properly, especially inside triggers
           10  +# Tests to make sure that values returned by changes() and total_changes()
           11  +# are updated properly, especially inside triggers
    12     12   #
    13         -# Note 1: LSCC remains constant within a statement and only updates once
    14         -#           the statement is finished (triggers count as part of statement)
    15         -# Note 2: LSCC is changed within the context of a trigger
    16         -#           much like last_insert_rowid() (see lastinsert.test),
    17         -#           but is restored once the trigger exits
    18         -# Note 3: LSCC is not changed by a change to a view (since everything
    19         -#           is done within instead of trigger context)
           13  +# Note 1: changes() remains constant within a statement and only updates
           14  +#         once the statement is finished (triggers count as part of
           15  +#         statement).
           16  +# Note 2: changes() is changed within the context of a trigger much like 
           17  +#         last_insert_rowid() (see lastinsert.test), but is restored once
           18  +#         the trigger exits.
           19  +# Note 3: changes() is not changed by a change to a view (since everything
           20  +#         is done within instead of trigger context).
    20     21   #
    21     22   
    22     23   set testdir [file dirname $argv0]
    23     24   source $testdir/tester.tcl
    24     25   
    25     26   # ----------------------------------------------------------------------------
    26     27   # 1.x - basic tests (no triggers)
    27     28   
    28         -# LSCC set properly after insert
           29  +# changes() set properly after insert
    29     30   do_test laststmtchanges-1.1 {
    30     31       catchsql {
    31     32           create table t0 (x);
    32     33           insert into t0 values (1);
    33     34           insert into t0 values (1);
    34     35           insert into t0 values (2);
    35     36           insert into t0 values (2);
    36     37           insert into t0 values (1);
    37     38           insert into t0 values (1);
    38     39           insert into t0 values (1);
    39     40           insert into t0 values (2);
    40         -        select last_statement_change_count();
           41  +        select changes(), total_changes();
    41     42       }
    42         -} {0 1}
           43  +} {0 {1 8}}
    43     44   
    44         -# LSCC set properly after update
           45  +# changes() set properly after update
    45     46   do_test laststmtchanges-1.2 {
    46     47       catchsql {
    47     48           update t0 set x=3 where x=1;
    48         -        select last_statement_change_count();
           49  +        select changes(), total_changes();
    49     50       }
    50         -} {0 5}
           51  +} {0 {5 13}}
    51     52   
    52         -# LSCC unchanged within an update statement
           53  +# changes() unchanged within an update statement
    53     54   do_test laststmtchanges-1.3 {
    54     55       catchsql {
    55         -        update t0 set x=x+last_statement_change_count() where x=3;
           56  +        update t0 set x=x+changes() where x=3;
    56     57           select count() from t0 where x=8;
    57     58       }
    58     59   } {0 5}
    59     60   
    60         -# LSCC set properly after update on table where no rows changed
           61  +# changes() set properly after update on table where no rows changed
    61     62   do_test laststmtchanges-1.4 {
    62     63       catchsql {
    63     64           update t0 set x=77 where x=88;
    64         -        select last_statement_change_count();
           65  +        select changes();
    65     66       }
    66     67   } {0 0}
    67     68   
    68         -# LSCC set properly after delete from table
           69  +# changes() set properly after delete from table
    69     70   do_test laststmtchanges-1.5 {
    70     71       catchsql {
    71     72           delete from t0 where x=2;
    72         -        select last_statement_change_count();
           73  +        select changes();
    73     74       }
    74     75   } {0 3}
    75     76   
    76     77   # ----------------------------------------------------------------------------
    77     78   # 2.x - tests with after insert trigger
    78     79   
    79         -# LSCC changed properly after insert into table containing after trigger
           80  +# changes() changed properly after insert into table containing after trigger
    80     81   do_test laststmtchanges-2.1 {
           82  +    set ::tc [db total_changes]
    81     83       catchsql {
    82     84           create table t1 (k integer primary key);
    83     85           create table t2 (k integer primary key, v1, v2);
    84     86           create trigger r1 after insert on t1 for each row begin
    85         -            insert into t2 values (NULL, last_statement_change_count(), NULL);
           87  +            insert into t2 values (NULL, changes(), NULL);
    86     88               update t0 set x=x;
    87         -            update t2 set v2=last_statement_change_count();
           89  +            update t2 set v2=changes();
    88     90           end;
    89     91           insert into t1 values (77);
    90         -        select last_statement_change_count();
           92  +        select changes();
    91     93       }
    92     94   } {0 1}
    93     95   
    94         -# LSCC unchanged upon entry into after insert trigger
           96  +# changes() unchanged upon entry into after insert trigger
    95     97   do_test laststmtchanges-2.2 {
    96     98       catchsql {
    97     99           select v1 from t2;
    98    100       }
    99    101   } {0 3}
   100    102   
   101         -# LSCC changed properly by update within context of after insert trigger
          103  +# changes() changed properly by update within context of after insert trigger
   102    104   do_test laststmtchanges-2.3 {
   103    105       catchsql {
   104    106           select v2 from t2;
   105    107       }
   106    108   } {0 5}
          109  +
          110  +# Total changes caused by firing the trigger above:
          111  +#
          112  +#   1 from "insert into t1 values(77)" + 
          113  +#   1 from "insert into t2 values (NULL, changes(), NULL);" +
          114  +#   5 from "update t0 set x=x;" +
          115  +#   1 from "update t2 set v2=changes();"
          116  +#
          117  +do_test laststmtchanges-2.4 {
          118  +  expr [db total_changes] - $::tc
          119  +} {8}
   107    120   
   108    121   # ----------------------------------------------------------------------------
   109    122   # 3.x - tests with after update trigger
   110    123   
   111         -# LSCC changed properly after update into table containing after trigger
          124  +# changes() changed properly after update into table containing after trigger
   112    125   do_test laststmtchanges-3.1 {
   113    126       catchsql {
   114    127           drop trigger r1;
   115    128           delete from t2; delete from t2;
   116    129           create trigger r1 after update on t1 for each row begin
   117         -            insert into t2 values (NULL, last_statement_change_count(), NULL);
          130  +            insert into t2 values (NULL, changes(), NULL);
   118    131               delete from t0 where oid=1 or oid=2;
   119         -            update t2 set v2=last_statement_change_count();
          132  +            update t2 set v2=changes();
   120    133           end;
   121    134           update t1 set k=k;
   122         -        select last_statement_change_count();
          135  +        select changes();
   123    136       }
   124    137   } {0 1}
   125    138   
   126         -# LSCC unchanged upon entry into after update trigger
          139  +# changes() unchanged upon entry into after update trigger
   127    140   do_test laststmtchanges-3.2 {
   128    141       catchsql {
   129    142           select v1 from t2;
   130    143       }
   131    144   } {0 0}
   132    145   
   133         -# LSCC changed properly by delete within context of after update trigger
          146  +# changes() changed properly by delete within context of after update trigger
   134    147   do_test laststmtchanges-3.3 {
   135    148       catchsql {
   136    149           select v2 from t2;
   137    150       }
   138    151   } {0 2}
   139    152   
   140    153   # ----------------------------------------------------------------------------
   141    154   # 4.x - tests with before delete trigger
   142    155   
   143         -# LSCC changed properly on delete from table containing before trigger
          156  +# changes() changed properly on delete from table containing before trigger
   144    157   do_test laststmtchanges-4.1 {
   145    158       catchsql {
   146    159           drop trigger r1;
   147    160           delete from t2; delete from t2;
   148    161           create trigger r1 before delete on t1 for each row begin
   149         -            insert into t2 values (NULL, last_statement_change_count(), NULL);
          162  +            insert into t2 values (NULL, changes(), NULL);
   150    163               insert into t0 values (5);
   151         -            update t2 set v2=last_statement_change_count();
          164  +            update t2 set v2=changes();
   152    165           end;
   153    166           delete from t1;
   154         -        select last_statement_change_count();
          167  +        select changes();
   155    168       }
   156    169   } {0 1}
   157    170   
   158         -# LSCC unchanged upon entry into before delete trigger
          171  +# changes() unchanged upon entry into before delete trigger
   159    172   do_test laststmtchanges-4.2 {
   160    173       catchsql {
   161    174           select v1 from t2;
   162    175       }
   163    176   } {0 0}
   164    177   
   165         -# LSCC changed properly by insert within context of before delete trigger
          178  +# changes() changed properly by insert within context of before delete trigger
   166    179   do_test laststmtchanges-4.3 {
   167    180       catchsql {
   168    181           select v2 from t2;
   169    182       }
   170    183   } {0 1}
   171    184   
   172    185   # ----------------------------------------------------------------------------
................................................................................
   187    200           insert into t0 values (1);
   188    201           insert into t0 values (1);
   189    202           insert into t0 values (1);
   190    203           insert into t0 values (2);
   191    204           insert into t0 values (2);
   192    205           insert into t0 values (1);
   193    206           create temp trigger r1 instead of insert on v1 for each row begin
   194         -            insert into n1 values (NULL, last_statement_change_count());
          207  +            insert into n1 values (NULL, changes());
   195    208               update t0 set x=x*10 where x=1;
   196         -            insert into n1 values (NULL, last_statement_change_count());
          209  +            insert into n1 values (NULL, changes());
   197    210               insert into t1 values (NEW.k);
   198         -            insert into n1 values (NULL, last_statement_change_count());
          211  +            insert into n1 values (NULL, changes());
   199    212               update t0 set x=x*10 where x=0;
   200    213               insert into v2 values (100+NEW.k);
   201         -            insert into n1 values (NULL, last_statement_change_count());
          214  +            insert into n1 values (NULL, changes());
   202    215           end;
   203    216           create temp trigger r2 instead of insert on v2 for each row begin
   204         -            insert into n2 values (NULL, last_statement_change_count());
          217  +            insert into n2 values (NULL, changes());
   205    218               insert into t2 values (1000+NEW.k);
   206         -            insert into n2 values (NULL, last_statement_change_count());
          219  +            insert into n2 values (NULL, changes());
   207    220               update t0 set x=x*100 where x=0;
   208         -            insert into n2 values (NULL, last_statement_change_count());
          221  +            insert into n2 values (NULL, changes());
   209    222               delete from t0 where x=2;
   210         -            insert into n2 values (NULL, last_statement_change_count());
          223  +            insert into n2 values (NULL, changes());
   211    224           end;
   212    225           insert into t1 values (77);
   213         -        select last_statement_change_count();
          226  +        select changes();
   214    227       }
   215    228   } {0 1}
   216    229   
   217    230   do_test laststmtchanges-5.2 {
   218    231       catchsql {
   219    232           delete from t1 where k=88;
   220         -        select last_statement_change_count();
          233  +        select changes();
   221    234       }
   222    235   } {0 0}
   223    236   
   224    237   do_test laststmtchanges-5.3 {
   225    238       catchsql {
   226    239           insert into v1 values (5);
   227         -        select last_statement_change_count();
          240  +        select changes();
   228    241       }
   229    242   } {0 0}
   230    243   
   231    244   do_test laststmtchanges-5.4 {
   232    245       catchsql {
   233    246           select n from n1;
   234    247       }

Changes to test/tclsqlite.test.

    11     11   # This file implements regression tests for TCL interface to the
    12     12   # SQLite library. 
    13     13   #
    14     14   # Actually, all tests are based on the TCL interface, so the main
    15     15   # interface is pretty well tested.  This file contains some addition
    16     16   # tests for fringe issues that the main test suite does not cover.
    17     17   #
    18         -# $Id: tclsqlite.test,v 1.24 2004/06/19 00:16:31 drh Exp $
           18  +# $Id: tclsqlite.test,v 1.25 2004/06/21 06:50:29 danielk1977 Exp $
    19     19   
    20     20   set testdir [file dirname $argv0]
    21     21   source $testdir/tester.tcl
    22     22   
    23     23   # Check the error messages generated by tclsqlite
    24     24   #
    25     25   if {[sqlite3 -has-codec]} {
................................................................................
    30     30   do_test tcl-1.1 {
    31     31     set v [catch {sqlite3 bogus} msg]
    32     32     lappend v $msg
    33     33   } [list 1 "wrong # args: should be \"$r\""]
    34     34   do_test tcl-1.2 {
    35     35     set v [catch {db bogus} msg]
    36     36     lappend v $msg
    37         -} {1 {bad option "bogus": must be authorizer, busy, changes, close, commit_hook, complete, errorcode, eval, function, last_insert_rowid, last_statement_changes, onecolumn, progress, rekey, timeout, trace, collate, or collation_needed}}
           37  +} {1 {bad option "bogus": must be authorizer, busy, changes, close, commit_hook, complete, errorcode, eval, function, last_insert_rowid, onecolumn, progress, rekey, timeout, trace, collate, collation_needed, or total_changes}}
    38     38   do_test tcl-1.3 {
    39     39     execsql {CREATE TABLE t1(a int, b int)}
    40     40     execsql {INSERT INTO t1 VALUES(10,20)}
    41     41     set v [catch {
    42     42       db eval {SELECT * FROM t1} data {
    43     43         error "The error message"
    44     44       }