From b28af71a22dc4ce7194066bbc7d21d6ea3b16815 Mon Sep 17 00:00:00 2001 From: danielk1977 Date: Mon, 21 Jun 2004 06:50:26 +0000 Subject: [PATCH] Update sqlite3_changes() to match the documentation and add sqlite3_total_changes(). (CVS 1645) FossilOrigin-Name: ae2f4a0943854fedbbb6fab1dc3aaf972722ed95 --- manifest | 48 ++++++++-------- manifest.uuid | 2 +- src/delete.c | 9 ++- src/func.c | 29 +++++----- src/insert.c | 11 ++-- src/main.c | 12 ++-- src/sqlite.h.in | 44 +++++++++------ src/sqliteInt.h | 27 +++------ src/tclsqlite.c | 62 +++++++++------------ src/trigger.c | 6 ++ src/update.c | 4 +- src/vdbe.c | 50 ++++++++++------- src/vdbe.h | 3 +- src/vdbeInt.h | 7 ++- src/vdbeaux.c | 31 ++++++++++- test/capi2.test | 21 +++++-- test/conflict.test | 7 ++- test/insert2.test | 5 +- test/laststmtchanges.test | 113 +++++++++++++++++++++----------------- test/tclsqlite.test | 4 +- 20 files changed, 279 insertions(+), 216 deletions(-) diff --git a/manifest b/manifest index ac06a64241..7f99121579 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C fix\sfulltest\serror\sby\srestoring\sunset\s(CVS\s1644) -D 2004-06-20T03:06:18 +C Update\ssqlite3_changes()\sto\smatch\sthe\sdocumentation\sand\sadd\nsqlite3_total_changes().\s(CVS\s1645) +D 2004-06-21T06:50:27 F Makefile.in d69d53c543518c1572ee0a8e8723d7e00bdb2266 F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457 F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd @@ -30,15 +30,15 @@ F src/btree.c 0cf8a52a57a7eb13d50719114ee1fa353e89d7d3 F src/btree.h 32f96abef464cf8765b23ca669acfe90d191fcc5 F src/build.c 2ed1f14a72ce94a2e4adf333272d67a49925304b F src/date.c b3e8b2bef1e3f2ce24e5b057203036defb18c3f1 -F src/delete.c a5191011b7429dff939df631b8bdcc1714b8d7aa +F src/delete.c 19287dd204569519636a04eca2b66c49c26e9266 F src/encode.c a876af473d1d636faa3dca51c7571f2e007eea37 F src/expr.c 9ae0e55a230802da35a55fd6e87533cca0301af9 -F src/func.c e520c64e83b4a3fb93668552891124b453cc0eff +F src/func.c 3d32878eeb4c6a9977c72ec19984d329b6954c7e F src/hash.c 440c2f8cb373ee1b4e13a0988489c7cd95d55b6f F src/hash.h 762d95f1e567664d1eafc1687de755626be962fb -F src/insert.c 1428887f4a7515a7d34e82aaeb76297c79ba378b +F src/insert.c d99ffe87e1e1397f4233afcd06841d52d6b17b18 F src/legacy.c ad23746f15f67e34577621b1875f639c94839e1f -F src/main.c 96387fc23db30d7ce64f62e95a229c3dd9aff397 +F src/main.c b4cd665e7e0af8f47b523e116e3356d0ebf6cef0 F src/md5.c 7ae1c39044b95de2f62e066f47bb1deb880a1070 F src/os.h 1cb5f0293a30288451fe3c0c73815cf208212ed1 F src/os_common.h ba1b7306e16e2091718f2c48db0fe6c1d7a31bb8 @@ -56,26 +56,26 @@ F src/printf.c 823b6a5cbedb6971a9e62f5d83204fe9b0be7c1b F src/random.c eff68e3f257e05e81eae6c4d50a51eb88beb4ff3 F src/select.c 9aa82bbc63983a304bc51d4a7c259e759f92c8dc F src/shell.c 24b641700c9d90f361fcfa4f432c5b4aff704e6d -F src/sqlite.h.in c34414b9f5330f875e26a69fe685e38ca45f11b9 -F src/sqliteInt.h 421687a0b3111d4b3df058aa1a5400739d3d3584 +F src/sqlite.h.in a3d593016d1a1a514d7a26c8a353b58caf62e798 +F src/sqliteInt.h 0d2e3647c0c881826eb07430cd3745c1fee03c27 F src/table.c af14284fa36c8d41f6829e3f2819dce07d3e2de2 -F src/tclsqlite.c ddef9b18271fb46344d3d35446bd7c001465a69a +F src/tclsqlite.c 8d093146332b2f0cbf2a8ebe8597d481619308a3 F src/test1.c ee426e026ad9223483e7a84bb68849fc6e9f542e F src/test2.c db0a0c30b59f1639cb8c2572be06439402833cc8 F src/test3.c 7247090d15a5a43823079b6fd8dad1ed3cccdedf F src/test4.c a921a69821fd30209589228e64f94e9f715b6fe2 F src/test5.c 1b7c275b2929dbd034a567255d2aca339410d1d6 F src/tokenize.c 900374b6b37f04748bcd48c2d29a41c251542935 -F src/trigger.c fb38c34d933f32dbb6c31b48935f33d868cc7658 -F src/update.c f9a03233577e0c3d57234d1957963875fc941da2 +F src/trigger.c 65fa572487f945d3d11ab451f232b430a370bae3 +F src/update.c b66b1896c9da54678ba3eff2bf0b4d291a95986a F src/utf.c 3a2596013e4b9582d075ca742de7f067ff7dee95 F src/util.c 1b3743413e11cae51a899dc03fa9b829a3a1f160 F src/vacuum.c fcb930215a3f6c50087300782555f61ad11dd80c -F src/vdbe.c 3931b2e4dfb23c8808fb4efc4880dda08c8915ad -F src/vdbe.h 9ad64674c4c7acd6744174cab5d34013413ef0d3 -F src/vdbeInt.h d007ccada5e3043816097242a560ed6c7f6483ce +F src/vdbe.c d8e533a537997ddfdf224cc802abaf3aa4448c69 +F src/vdbe.h 05edb8ec5c038e4ea22827350ee75fb20f0dfddf +F src/vdbeInt.h 4d56da610923efa8d4c9db89dff17cb721e69a9b F src/vdbeapi.c 8a9421341e09b506a934132c9015f26362ae8c0e -F src/vdbeaux.c d2d95f1b9341bd3861e5229cb24a821715824449 +F src/vdbeaux.c fa9f0b179a7df3ce3ef42178ec67ace1c9a68e75 F src/vdbemem.c 9359c53386e070fea9f5403cab0c6f0cfe36496b F src/where.c 6507074d8ce3f78e7a4cd33f667f11e62020553e F test/all.test 569a92a8ee88f5300c057cc4a8f50fbbc69a3242 @@ -93,7 +93,7 @@ F test/btree4.test 3797b4305694c7af6828675b0f4b1424b8ca30e4 F test/btree5.test 8e5ff32c02e685d36516c6499add9375fe1377f2 F test/btree6.test a5ede6bfbbb2ec8b27e62813612c0f28e8f3e027 F test/btree7.test 429b96cfef5b51a7d512cfb4b5b3e453384af293 -F test/capi2.test 7a0d71b27cfc5337ec3525c02b9de269b5b9c175 +F test/capi2.test 7ff5ef9efee9f5ad1945e5f80791a7469ae1a040 F test/capi3.test 6528034f21c4e8e404032124cb58b14ce934598c F test/collate1.test 2ee4fa3a47a652ccf56c5ddf65dcc44d9bad82ef F test/collate2.test c1a3b41f761b28853c5696037f92de928f93233b @@ -101,7 +101,7 @@ F test/collate3.test e60b428e07ec945492ba90ff1c895902ee3a8a50 F test/collate4.test 0e9fc08ffcf6eddf72e354a15de06688fa86db31 F test/collate5.test 1dd5f0f508c46667f9d4606c7950c414b0bdc0d5 F test/collate6.test 2a45768914f04c1447a69d1358bbede376552675 -F test/conflict.test 45ce1e44ea748944aed233df8c278a9e1c4c87cc +F test/conflict.test c5b849b01cfbe0a4f63a90cba6f68e2fe3a75f87 F test/crashtest1.c 09c1c7d728ccf4feb9e481671e29dda5669bbcc2 F test/date.test aed5030482ebc02bd8d386c6c86a29f694ab068d F test/delete.test 4f0c86e2bebdc822d179c80697b1ceabe6bbcd07 @@ -114,14 +114,14 @@ F test/hook.test c4102c672d67f8fb60ea459842805abcba69a747 F test/in.test b92a2df9162e1cbd33c6449a29a05e6955b1741a F test/index.test b6941dd532815f278042b85f79b1a6dc16c4d729 F test/insert.test ebbab63db4ad69395a058514bccb3cdb0a029d48 -F test/insert2.test c288375a64dad3295044714f0dfed4a193cf067f +F test/insert2.test ea5d4f8dcbc68d8ad85eaa5f03d9812757610f90 F test/interrupt.test 9142ce4448605127640eda5e283952f75f67ed91 F test/intpkey.test e6e0d7cca0e64ec09cbf683a4712ed2196073742 F test/ioerr.test 7d087bfd1a1a53442940e000df936e0df0c5b886 F test/join.test 9ef6aabaac9de51d5fc41e68d1f4355da05a84cd F test/join2.test c97e4c5aa65dea462145529e58212a709b4722b8 F test/lastinsert.test 31382f88b9b0270333ac9e4a17f2c2f4732da718 -F test/laststmtchanges.test cabd11bdfbaf73a4486c50b58297d9c2038ccc18 +F test/laststmtchanges.test 417aa27eb2b5cdfafb46e390e2c9ddd0a20eba43 F test/limit.test 60d7f856ee7846f7130dee67f10f0e726cd70b5d F test/lock.test 1dbf1d06b0a7eb36237b4f107cfb3da9726b449e F test/main.test e8c4d9ca6d1e5f5e55e6550d31aec488883b2ed9 @@ -153,7 +153,7 @@ F test/sort.test dbd94673b05054e44ca3f08a80faa1e890ef06d8 F test/subselect.test f0fea8cf9f386d416d64d152e3c65f9116d0f50f F test/table.test 06c077c82d1a0df45426518064e674d97def6485 F test/tableapi.test b21ab097e87a5484bb61029e69e1a4e5c5e65ede -F test/tclsqlite.test a69e99b995c913dde3e554da8b3f8f483715fdd3 +F test/tclsqlite.test 2517b10ee2c806fb700548f54540aec7d62ed14a F test/temptable.test 63a16e3ad19adf073cfbcdf7624c92ac5236522c F test/tester.tcl f36cc22d0532725073ca78272d7834d56dceb6d9 F test/thread1.test 776c9e459b75ba905193b351926ac4019b049f35 @@ -225,7 +225,7 @@ F www/tclsqlite.tcl 19191cf2a1010eaeff74c51d83fd5f5a4d899075 F www/vdbe.tcl 59288db1ac5c0616296b26dce071c36cb611dfe9 F www/version3.tcl af528563442e3039928f9018327a18157e53a44f F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4 -P fc3b3a8fe86980db4de402bb8e85f8f739fc3883 -R 306731b1d3a316b30d565222feb5ad7f -U dougcurrie -Z ad297936c1c1ca71d55b605ccce1a407 +P d2ccac9d01994de09a195d71cb63d1bf9fb0d33f +R 2dec0579dc0c3cd8d98bed6d72c511bb +U danielk1977 +Z 2ddd8a9b96a59cb5f116b91751ad2717 diff --git a/manifest.uuid b/manifest.uuid index a2bd5119cd..6f5eb657ce 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -d2ccac9d01994de09a195d71cb63d1bf9fb0d33f \ No newline at end of file +ae2f4a0943854fedbbb6fab1dc3aaf972722ed95 \ No newline at end of file diff --git a/src/delete.c b/src/delete.c index 868bbd2ac8..ec105cbf35 100644 --- a/src/delete.c +++ b/src/delete.c @@ -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.75 2004/06/17 07:53:02 danielk1977 Exp $ +** $Id: delete.c,v 1.76 2004/06/21 06:50:27 danielk1977 Exp $ */ #include "sqliteInt.h" @@ -142,6 +142,7 @@ void sqlite3DeleteFrom( if( v==0 ){ goto delete_from_cleanup; } + sqlite3VdbeCountChanges(v); sqlite3BeginWriteOperation(pParse, row_triggers_exist, pTab->iDb); /* If we are trying to delete from a view, construct that view into @@ -271,7 +272,7 @@ void sqlite3DeleteFrom( } /* Delete the row */ - sqlite3GenerateRowDelete(db, v, pTab, iCur, pParse->trigStack==0); + sqlite3GenerateRowDelete(db, v, pTab, iCur, 1); } /* If there are row triggers, close all cursors then invoke @@ -303,7 +304,6 @@ void sqlite3DeleteFrom( pParse->nTab = iCur; } } - sqlite3VdbeAddOp(v, OP_SetCounts, 0, 0); sqlite3EndWriteOperation(pParse); /* @@ -352,8 +352,7 @@ void sqlite3GenerateRowDelete( int addr; addr = sqlite3VdbeAddOp(v, OP_NotExists, iCur, 0); sqlite3GenerateRowIndexDelete(db, v, pTab, iCur, 0); - sqlite3VdbeAddOp(v, OP_Delete, iCur, - (count?OPFLAG_NCHANGE:0) | OPFLAG_CSCHANGE); + sqlite3VdbeAddOp(v, OP_Delete, iCur, (count?OPFLAG_NCHANGE:0)); sqlite3VdbeChangeP2(v, addr, sqlite3VdbeCurrentAddr(v)); } diff --git a/src/func.c b/src/func.c index 5b5f882fce..6c22ece385 100644 --- a/src/func.c +++ b/src/func.c @@ -16,7 +16,7 @@ ** sqliteRegisterBuildinFunctions() found at the bottom of the file. ** All other code has file scope. ** -** $Id: func.c,v 1.74 2004/06/19 17:33:07 drh Exp $ +** $Id: func.c,v 1.75 2004/06/21 06:50:28 danielk1977 Exp $ */ #include #include @@ -273,10 +273,10 @@ static void last_insert_rowid( } /* -** Implementation of the change_count() SQL function. The return -** value is the same as the sqlite3_changes() API function. +** Implementation of the changes() SQL function. The return value is the +** same as the sqlite3_changes() API function. */ -static void change_count( +static void changes( sqlite3_context *context, int arg, sqlite3_value **argv @@ -286,19 +286,20 @@ static void change_count( } /* -** Implementation of the last_statement_change_count() SQL function. The -** return value is the same as the sqlite3_last_statement_changes() API -** function. +** Implementation of the total_changes() SQL function. The return value is +** the same as the sqlite3_total_changes() API function. */ -static void last_statement_change_count( - sqlite3_context *context, +static void total_changes( + sqlite3_context *context, int arg, sqlite3_value **argv ){ sqlite *db = sqlite3_user_data(context); - sqlite3_result_int(context, sqlite3_last_statement_changes(db)); + sqlite3_result_int(context, sqlite3_total_changes(db)); } +#if 0 + /* ** A LIKE pattern compiles to an instance of the following structure. Refer ** to the comment for compileLike() function for details. @@ -315,9 +316,6 @@ typedef struct LikePattern LikePattern; void deleteLike(void *pLike){ sqliteFree(pLike); } - - -#if 0 /* #define TRACE_LIKE */ #if defined(TRACE_LIKE) && !defined(NDEBUG) char *dumpLike(LikePattern *pLike){ @@ -1041,9 +1039,8 @@ void sqlite3RegisterBuiltinFunctions(sqlite *db){ { "sqlite_version", 0, 0, SQLITE_UTF8, 0, versionFunc}, { "quote", 1, 0, SQLITE_UTF8, 0, quoteFunc }, { "last_insert_rowid", 0, 1, SQLITE_UTF8, 0, last_insert_rowid }, - { "change_count", 0, 1, SQLITE_UTF8, 0, change_count }, - { "last_statement_change_count", 0, 1, SQLITE_UTF8, 0, - last_statement_change_count }, + { "changes", 0, 1, SQLITE_UTF8, 0, changes }, + { "total_changes", 0, 1, SQLITE_UTF8, 0, total_changes }, #ifdef SQLITE_SOUNDEX { "soundex", 1, 0, SQLITE_UTF8, 0, soundexFunc}, #endif diff --git a/src/insert.c b/src/insert.c index ef4f03d7cc..7a79df20e1 100644 --- a/src/insert.c +++ b/src/insert.c @@ -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.112 2004/06/17 07:53:03 danielk1977 Exp $ +** $Id: insert.c,v 1.113 2004/06/21 06:50:28 danielk1977 Exp $ */ #include "sqliteInt.h" @@ -245,6 +245,7 @@ void sqlite3Insert( */ v = sqlite3GetVdbe(pParse); if( v==0 ) goto insert_cleanup; + sqlite3VdbeCountChanges(v); sqlite3BeginWriteOperation(pParse, pSelect || row_triggers_exist, pTab->iDb); /* if there are row triggers, allocate a temp table for new.* references. */ @@ -617,7 +618,6 @@ void sqlite3Insert( } } - sqlite3VdbeAddOp(v, OP_SetCounts, 0, 0); sqlite3EndWriteOperation(pParse); /* @@ -967,6 +967,7 @@ void sqlite3CompleteInsertion( Vdbe *v; int nIdx; Index *pIdx; + int pik_flags; v = sqlite3GetVdbe(pParse); assert( v!=0 ); @@ -983,9 +984,9 @@ void sqlite3CompleteInsertion( sqlite3VdbeAddOp(v, OP_Dup, 1, 0); sqlite3VdbeAddOp(v, OP_PutIntKey, newIdx, 0); } - sqlite3VdbeAddOp(v, OP_PutIntKey, base, - (pParse->trigStack?0:OPFLAG_NCHANGE) | - (isUpdate?0:OPFLAG_LASTROWID) | OPFLAG_CSCHANGE); + pik_flags = (OPFLAG_NCHANGE|(isUpdate?0:OPFLAG_LASTROWID)); + sqlite3VdbeAddOp(v, OP_PutIntKey, base, pik_flags); + if( isUpdate && recnoChng ){ sqlite3VdbeAddOp(v, OP_Pop, 1, 0); } diff --git a/src/main.c b/src/main.c index 2c23bda562..b132d0b93c 100644 --- a/src/main.c +++ b/src/main.c @@ -14,7 +14,7 @@ ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** -** $Id: main.c,v 1.230 2004/06/19 09:35:37 danielk1977 Exp $ +** $Id: main.c,v 1.231 2004/06/21 06:50:28 danielk1977 Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -448,13 +448,10 @@ int sqlite3_changes(sqlite *db){ } /* -** Return the number of changes produced by the last INSERT, UPDATE, or -** DELETE statement to complete execution. The count does not include -** changes due to SQL statements executed in trigger programs that were -** triggered by that statement +** Return the number of changes since the database handle was opened. */ -int sqlite3_last_statement_changes(sqlite *db){ - return db->lsChange; +int sqlite3_total_changes(sqlite3 *db){ + return db->nTotalChange; } /* @@ -952,7 +949,6 @@ int sqlite3_prepare( goto prepare_out; } - if( db->pVdbe==0 ){ db->nChange = 0; } memset(&sParse, 0, sizeof(sParse)); sParse.db = db; sqlite3RunParser(&sParse, zSql, &zErrMsg); diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 29f6d48784..aba3017b6b 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -12,7 +12,7 @@ ** This header file defines the interface that the SQLite library ** presents to client programs. ** -** @(#) $Id: sqlite.h.in,v 1.104 2004/06/19 08:18:16 danielk1977 Exp $ +** @(#) $Id: sqlite.h.in,v 1.105 2004/06/21 06:50:28 danielk1977 Exp $ */ #ifndef _SQLITE_H_ #define _SQLITE_H_ @@ -177,18 +177,12 @@ long long int sqlite3_last_insert_rowid(sqlite3*); int sqlite3_changes(sqlite3*); /* -** This function returns the number of database rows that were changed -** by the last INSERT, UPDATE, or DELETE statment executed by sqlite3_exec(), -** or by the last VM to run to completion. The change count is not updated -** by SQL statements other than INSERT, UPDATE or DELETE. -** -** Changes are counted, even if they are later undone by a ROLLBACK or -** ABORT. Changes associated with trigger programs that execute as a -** result of the INSERT, UPDATE, or DELETE statement are not counted. -** -** If a callback invokes sqlite3_exec() recursively, then the changes -** in the inner, recursive call are counted together with the changes -** in the outer call. +** This function returns the number of database rows that have been +** modified by INSERT, UPDATE or DELETE statements since the database handle +** was opened. This includes UPDATE, INSERT and DELETE statements executed +** as part of trigger programs. All changes are counted as soon as the +** statement that makes them is completed (when the statement handle is +** passed to sqlite3_reset() or sqlite_finalise()). ** ** SQLite implements the command "DELETE FROM table" without a WHERE clause ** by dropping and recreating the table. (This is much faster than going @@ -197,10 +191,28 @@ int sqlite3_changes(sqlite3*); ** 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. -** -******* THIS IS AN EXPERIMENTAL API AND IS SUBJECT TO CHANGE ****** */ -int sqlite3_last_statement_changes(sqlite3*); +int sqlite3_total_changes(sqlite3*); + +/* +** This function returns the number of database rows that were changed +** by the last INSERT, UPDATE, or DELETE statment completed. The change +** count is not updated by SQL statements other than INSERT, UPDATE or +** DELETE. +** +** Changes are counted, even if they are later undone by a ROLLBACK or +** ABORT. Changes associated with trigger programs that execute as a +** result of the INSERT, UPDATE, or DELETE statement are not counted. +** +** 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 sqlite3_changes(sqlite3*); /* This function causes any pending database operation to abort and ** return at its earliest opportunity. This routine is typically diff --git a/src/sqliteInt.h b/src/sqliteInt.h index c8531ab900..d7aa7ba634 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -11,7 +11,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.295 2004/06/19 16:06:12 drh Exp $ +** @(#) $Id: sqliteInt.h,v 1.296 2004/06/21 06:50:28 danielk1977 Exp $ */ #include "config.h" #include "sqlite3.h" @@ -318,16 +318,6 @@ struct Db { #define DB_SchemaLoaded 0x0001 /* The schema has been loaded */ #define DB_UnresetViews 0x0002 /* Some views have defined column names */ -#if 0 -/* -** Possible values for the Db.textEnc field. -*/ -#define TEXT_Utf8 1 -#define TEXT_Utf16le 2 -#define TEXT_Utf16be 3 -#define TEXT_Utf16 (SQLITE_BIGENDIAN?TEXT_Utf16be:TEXT_Utf16le) -#endif - #define SQLITE_UTF16NATIVE (SQLITE_BIGENDIAN?SQLITE_UTF16BE:SQLITE_UTF16LE) /* @@ -394,13 +384,12 @@ struct sqlite { i64 lastRowid; /* ROWID of most recent insert (see above) */ i64 priorNewRowid; /* Last randomly generated ROWID */ int magic; /* Magic number for detect library misuse */ - int nChange; /* Number of rows changed (see above) */ - int lsChange; /* Last statement change count (see above) */ - int csChange; /* Current statement change count (see above) */ - struct sqlite3InitInfo { /* Information used during initialization */ - int iDb; /* When back is being initialized */ - int newTnum; /* Rootpage of table being initialized */ - u8 busy; /* TRUE if currently initializing */ + int nChange; /* Value returned by sqlite3_changes() */ + int nTotalChange; /* Value returned by sqlite3_total_changes() */ + struct sqlite3InitInfo { /* Information used during initialization */ + int iDb; /* When back is being initialized */ + int newTnum; /* Rootpage of table being initialized */ + u8 busy; /* TRUE if currently initializing */ } init; struct Vdbe *pVdbe; /* List of active virtual machines */ int activeVdbeCnt; /* Number of vdbes currently executing */ @@ -1050,7 +1039,6 @@ struct AuthContext { */ #define OPFLAG_NCHANGE 1 /* Set to update db->nChange */ #define OPFLAG_LASTROWID 2 /* Set to update db->lastRowid */ -#define OPFLAG_CSCHANGE 4 /* Set to update db->csChange */ /* * Each trigger present in the database schema is stored as an instance of @@ -1402,6 +1390,7 @@ CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr); int sqlite3CheckCollSeq(Parse *, CollSeq *); int sqlite3CheckIndexCollSeq(Parse *, Index *); int sqlite3CheckObjectName(Parse *, const char *); +void sqlite3VdbeSetChanges(sqlite3 *, int); const void *sqlite3ValueText(sqlite3_value*, u8); int sqlite3ValueBytes(sqlite3_value*, u8); diff --git a/src/tclsqlite.c b/src/tclsqlite.c index 5c033ee1f0..361aa59db4 100644 --- a/src/tclsqlite.c +++ b/src/tclsqlite.c @@ -11,7 +11,7 @@ ************************************************************************* ** A TCL Interface to SQLite ** -** $Id: tclsqlite.c,v 1.89 2004/06/19 08:18:21 danielk1977 Exp $ +** $Id: tclsqlite.c,v 1.90 2004/06/21 06:50:28 danielk1977 Exp $ */ #ifndef NO_TCL /* Omit this whole file if TCL is unavailable */ @@ -69,7 +69,6 @@ struct SqliteDb { SqlFunc *pFunc; /* List of SQL functions */ SqlCollate *pCollate; /* List of SQL collation functions */ int rc; /* Return code of most recent sqlite3_exec() */ - int nChange; /* Database changes for the most recent eval */ Tcl_Obj *pCollateNeeded; /* Collation needed script */ }; @@ -395,18 +394,19 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ "authorizer", "busy", "changes", "close", "commit_hook", "complete", "errorcode", "eval", "function", - "last_insert_rowid", "last_statement_changes", "onecolumn", + "last_insert_rowid", "onecolumn", "progress", "rekey", "timeout", "trace", "collate", "collation_needed", - 0 + "total_changes", 0 }; enum DB_enum { DB_AUTHORIZER, DB_BUSY, DB_CHANGES, DB_CLOSE, DB_COMMIT_HOOK, DB_COMPLETE, DB_ERRORCODE, DB_EVAL, DB_FUNCTION, - DB_LAST_INSERT_ROWID, DB_LAST_STATEMENT_CHANGES, DB_ONECOLUMN, + DB_LAST_INSERT_ROWID, DB_ONECOLUMN, DB_PROGRESS, DB_REKEY, DB_TIMEOUT, - DB_TRACE, DB_COLLATE, DB_COLLATION_NEEDED + DB_TRACE, DB_COLLATE, DB_COLLATION_NEEDED, + DB_TOTAL_CHANGES }; if( objc<2 ){ @@ -547,43 +547,20 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ break; } - /* - ** $db changes + /* $db changes ** ** Return the number of rows that were modified, inserted, or deleted by - ** the most recent "eval". + ** the most recent INSERT, UPDATE or DELETE statement, not including + ** any changes made by trigger programs. */ case DB_CHANGES: { Tcl_Obj *pResult; - int nChange; if( objc!=2 ){ Tcl_WrongNumArgs(interp, 2, objv, ""); return TCL_ERROR; } - /* nChange = sqlite3_changes(pDb->db); */ - nChange = pDb->nChange; pResult = Tcl_GetObjResult(interp); - Tcl_SetIntObj(pResult, nChange); - break; - } - - /* - ** $db last_statement_changes - ** - ** Return the number of rows that were modified, inserted, or deleted by - ** the last statment to complete execution (excluding changes due to - ** triggers) - */ - case DB_LAST_STATEMENT_CHANGES: { - Tcl_Obj *pResult; - int lsChange; - if( objc!=2 ){ - Tcl_WrongNumArgs(interp, 2, objv, ""); - return TCL_ERROR; - } - lsChange = sqlite3_last_statement_changes(pDb->db); - pResult = Tcl_GetObjResult(interp); - Tcl_SetIntObj(pResult, lsChange); + Tcl_SetIntObj(pResult, sqlite3_changes(pDb->db)); break; } @@ -685,7 +662,6 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ return TCL_ERROR; } - pDb->nChange = 0; zSql = Tcl_GetStringFromObj(objv[2], 0); while( zSql[0] ){ int i; @@ -750,7 +726,6 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ break; } - pDb->nChange += sqlite3_changes(pDb->db); zSql = zLeft; } @@ -960,6 +935,23 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ break; } + /* + ** $db total_changes + ** + ** Return the number of rows that were modified, inserted, or deleted + ** since the database handle was created. + */ + case DB_TOTAL_CHANGES: { + Tcl_Obj *pResult; + if( objc!=2 ){ + Tcl_WrongNumArgs(interp, 2, objv, ""); + return TCL_ERROR; + } + pResult = Tcl_GetObjResult(interp); + Tcl_SetIntObj(pResult, sqlite3_total_changes(pDb->db)); + break; + } + } /* End of the SWITCH statement */ return rc; } diff --git a/src/trigger.c b/src/trigger.c index 23c43b764d..19fd50ddd4 100644 --- a/src/trigger.c +++ b/src/trigger.c @@ -650,28 +650,34 @@ static int codeTriggerProgram( case TK_UPDATE: { SrcList *pSrc; pSrc = targetSrcList(pParse, pTriggerStep); + sqlite3VdbeAddOp(pParse->pVdbe, OP_ResetCount, 0, 0); sqlite3VdbeAddOp(pParse->pVdbe, OP_ListPush, 0, 0); sqlite3Update(pParse, pSrc, sqlite3ExprListDup(pTriggerStep->pExprList), sqlite3ExprDup(pTriggerStep->pWhere), orconf); sqlite3VdbeAddOp(pParse->pVdbe, OP_ListPop, 0, 0); + sqlite3VdbeAddOp(pParse->pVdbe, OP_ResetCount, 1, 0); break; } case TK_INSERT: { SrcList *pSrc; pSrc = targetSrcList(pParse, pTriggerStep); + sqlite3VdbeAddOp(pParse->pVdbe, OP_ResetCount, 0, 0); sqlite3Insert(pParse, pSrc, sqlite3ExprListDup(pTriggerStep->pExprList), sqlite3SelectDup(pTriggerStep->pSelect), sqlite3IdListDup(pTriggerStep->pIdList), orconf); + sqlite3VdbeAddOp(pParse->pVdbe, OP_ResetCount, 1, 0); break; } case TK_DELETE: { SrcList *pSrc; + sqlite3VdbeAddOp(pParse->pVdbe, OP_ResetCount, 0, 0); sqlite3VdbeAddOp(pParse->pVdbe, OP_ListPush, 0, 0); pSrc = targetSrcList(pParse, pTriggerStep); sqlite3DeleteFrom(pParse, pSrc, sqlite3ExprDup(pTriggerStep->pWhere)); sqlite3VdbeAddOp(pParse->pVdbe, OP_ListPop, 0, 0); + sqlite3VdbeAddOp(pParse->pVdbe, OP_ResetCount, 1, 0); break; } default: diff --git a/src/update.c b/src/update.c index eae9dab4db..59a373aab6 100644 --- a/src/update.c +++ b/src/update.c @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** to handle UPDATE statements. ** -** $Id: update.c,v 1.84 2004/06/16 12:02:52 danielk1977 Exp $ +** $Id: update.c,v 1.85 2004/06/21 06:50:29 danielk1977 Exp $ */ #include "sqliteInt.h" @@ -209,6 +209,7 @@ void sqlite3Update( */ v = sqlite3GetVdbe(pParse); if( v==0 ) goto update_cleanup; + sqlite3VdbeCountChanges(v); sqlite3BeginWriteOperation(pParse, 1, pTab->iDb); /* If we are trying to update a view, construct that view into @@ -440,7 +441,6 @@ void sqlite3Update( sqlite3VdbeAddOp(v, OP_Close, oldIdx, 0); } - sqlite3VdbeAddOp(v, OP_SetCounts, 0, 0); sqlite3EndWriteOperation(pParse); /* diff --git a/src/vdbe.c b/src/vdbe.c index f821f4f650..68661340dd 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -43,7 +43,7 @@ ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** -** $Id: vdbe.c,v 1.381 2004/06/19 15:40:23 drh Exp $ +** $Id: vdbe.c,v 1.382 2004/06/21 06:50:29 danielk1977 Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -3066,11 +3066,9 @@ case OP_NewRecno: { ** be an integer. The stack is popped twice by this instruction. ** ** If the OPFLAG_NCHANGE flag of P2 is set, then the row change count is -** incremented (otherwise not). If the OPFLAG_CSCHANGE flag is set, -** then the current statement change count is incremented (otherwise not). -** If the OPFLAG_LASTROWID flag of P2 is set, then rowid is -** stored for subsequent return by the sqlite3_last_insert_rowid() function -** (otherwise it's unmodified). +** incremented (otherwise not). If the OPFLAG_LASTROWID flag of P2 is set, +** then rowid is stored for subsequent return by the +** sqlite3_last_insert_rowid() function (otherwise it's unmodified). */ /* Opcode: PutStrKey P1 * * ** @@ -3115,9 +3113,8 @@ case OP_PutStrKey: { zKey = (char*)&iKey; } - if( pOp->p2 & OPFLAG_NCHANGE ) db->nChange++; + if( pOp->p2 & OPFLAG_NCHANGE ) p->nChange++; if( pOp->p2 & OPFLAG_LASTROWID ) db->lastRowid = pNos->i; - if( pOp->p2 & OPFLAG_CSCHANGE ) db->csChange++; if( pC->nextRowidValid && pTos->i>=pC->nextRowid ){ pC->nextRowidValid = 0; } @@ -3169,8 +3166,7 @@ case OP_PutStrKey: { ** a record from within an Next loop. ** ** If the OPFLAG_NCHANGE flag of P2 is set, then the row change count is -** incremented (otherwise not). If OPFLAG_CSCHANGE flag is set, -** then the current statement change count is incremented (otherwise not). +** incremented (otherwise not). ** ** If P1 is a pseudo-table, then this instruction is a no-op. */ @@ -3186,19 +3182,22 @@ case OP_Delete: { pC->nextRowidValid = 0; pC->cacheValid = 0; } - if( pOp->p2 & OPFLAG_NCHANGE ) db->nChange++; - if( pOp->p2 & OPFLAG_CSCHANGE ) db->csChange++; + if( pOp->p2 & OPFLAG_NCHANGE ) p->nChange++; break; } -/* Opcode: SetCounts * * * +/* Opcode: ResetCount P1 * * ** -** Called at end of statement. Updates lsChange (last statement change count) -** and resets csChange (current statement change count) to 0. +** This opcode resets the VMs internal change counter to 0. If P1 is true, +** then the value of the change counter is copied to the database handle +** change counter (returned by subsequent calls to sqlite3_changes()) +** before it is reset. This is used by trigger programs. */ -case OP_SetCounts: { - db->lsChange=db->csChange; - db->csChange=0; +case OP_ResetCount: { + if( pOp->p1 ){ + sqlite3VdbeSetChanges(p->db, p->nChange); + } + p->nChange = 0; break; } @@ -3994,9 +3993,12 @@ case OP_ListReset: { case OP_ListPush: { p->keylistStackDepth++; assert(p->keylistStackDepth > 0); + + /* FIX ME: This should be allocated at compile time. */ p->keylistStack = sqliteRealloc(p->keylistStack, sizeof(Keylist *) * p->keylistStackDepth); if( p->keylistStack==0 ) goto no_mem; + p->keylistStack[p->keylistStackDepth - 1] = p->pList; p->pList = 0; break; @@ -4028,13 +4030,20 @@ case OP_ListPop: { */ case OP_ContextPush: { p->contextStackDepth++; - assert(p->contextStackDepth > 0); + assert( p->contextStackDepth>0 ); + + /* FIX ME: This should be allocated as part of the vdbe at compile-time */ p->contextStack = sqliteRealloc(p->contextStack, sizeof(Context) * p->contextStackDepth); if( p->contextStack==0 ) goto no_mem; + p->contextStack[p->contextStackDepth - 1].lastRowid = p->db->lastRowid; + p->contextStack[p->contextStackDepth - 1].nChange = p->nChange; + +#if 0 p->contextStack[p->contextStackDepth - 1].lsChange = p->db->lsChange; p->contextStack[p->contextStackDepth - 1].csChange = p->db->csChange; +#endif break; } @@ -4048,8 +4057,11 @@ case OP_ContextPop: { assert(p->contextStackDepth > 0); p->contextStackDepth--; p->db->lastRowid = p->contextStack[p->contextStackDepth].lastRowid; + p->nChange = p->contextStack[p->contextStackDepth].nChange; +#if 0 p->db->lsChange = p->contextStack[p->contextStackDepth].lsChange; p->db->csChange = p->contextStack[p->contextStackDepth].csChange; +#endif if( p->contextStackDepth == 0 ){ sqliteFree(p->contextStack); p->contextStack = 0; diff --git a/src/vdbe.h b/src/vdbe.h index 6abe89a6e2..a66bef1df6 100644 --- a/src/vdbe.h +++ b/src/vdbe.h @@ -15,7 +15,7 @@ ** or VDBE. The VDBE implements an abstract machine that runs a ** simple program to access and modify the underlying database. ** -** $Id: vdbe.h,v 1.86 2004/06/19 14:49:12 drh Exp $ +** $Id: vdbe.h,v 1.87 2004/06/21 06:50:29 danielk1977 Exp $ */ #ifndef _SQLITE_VDBE_H_ #define _SQLITE_VDBE_H_ @@ -123,6 +123,7 @@ int sqlite3VdbeReset(Vdbe*,char **); int sqliteVdbeSetVariables(Vdbe*,int,const char**); void sqlite3VdbeSetNumCols(Vdbe*,int); int sqlite3VdbeSetColName(Vdbe*, int, const char *, int); +void sqlite3VdbeCountChanges(Vdbe*); #ifndef NDEBUG void sqlite3VdbeComment(Vdbe*, const char*, ...); diff --git a/src/vdbeInt.h b/src/vdbeInt.h index 02fa033c71..5e71fdf778 100644 --- a/src/vdbeInt.h +++ b/src/vdbeInt.h @@ -287,9 +287,8 @@ struct Keylist { */ typedef struct Context Context; struct Context { - int lastRowid; /* Last insert rowid (from db->lastRowid) */ - int lsChange; /* Last statement change count (from db->lsChange) */ - int csChange; /* Current statement change count (from db->csChange) */ + int lastRowid; /* Last insert rowid (sqlite3.lastRowid) */ + int nChange; /* Statement changes (Vdbe.nChanges) */ }; /* @@ -347,6 +346,8 @@ struct Vdbe { u8 resOnStack; /* True if there are result values on the stack */ u8 explain; /* True if EXPLAIN present on SQL command */ u8 autoCommitOn; /* True if autocommit got turned on by this program */ + int nChange; /* Number of db changes made since last reset */ + u8 changeCntOn; /* True to update the change-counter */ }; /* diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 4a7da7b51c..2445790721 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -645,6 +645,7 @@ void sqlite3VdbeMakeReady( p->popStack = 0; p->explain |= isExplain; p->magic = VDBE_MAGIC_RUN; + p->nChange = 0; #ifdef VDBE_PROFILE { int i; @@ -1247,6 +1248,15 @@ int sqlite3VdbeReset(Vdbe *p, char **pzErrMsg){ } } + /* If this was an INSERT, UPDATE or DELETE, set the change counter. */ + if( p->changeCntOn ){ + if( !xFunc || xFunc==sqlite3BtreeCommitStmt ){ + sqlite3VdbeSetChanges(db, p->nChange); + }else{ + sqlite3VdbeSetChanges(db, 0); + } + p->nChange = 0; + } if( p->rc!=SQLITE_OK ){ sqlite3RollbackInternalChanges(db); @@ -1355,7 +1365,6 @@ void sqlite3VdbeDelete(Vdbe *p){ sqliteFree(pOp->p3); } if( pOp->p3type==P3_VDBEFUNC ){ - int j; VdbeFunc *pVdbeFunc = (VdbeFunc *)pOp->p3; sqlite3VdbeDeleteAuxData(pVdbeFunc, -1); sqliteFree(pVdbeFunc); @@ -1755,3 +1764,23 @@ int sqlite3VdbeIdxKeyCompare( sqlite3VdbeMemRelease(&m); return SQLITE_OK; } + +/* +** This routine sets the value to be returned by subsequent calls to +** sqlite3_changes() on the database handle 'db'. +*/ +void sqlite3VdbeSetChanges(sqlite3 *db, int nChange){ + db->nChange = nChange; + db->nTotalChange += nChange; +} + +/* +** Set a flag in the vdbe to update the change counter when it is finalised +** or reset. +*/ +void sqlite3VdbeCountChanges(Vdbe *p){ + p->changeCntOn = 1; +} + + + diff --git a/test/capi2.test b/test/capi2.test index 4f40174467..7c1e65d6b0 100644 --- a/test/capi2.test +++ b/test/capi2.test @@ -11,7 +11,7 @@ # This file implements regression tests for SQLite library. The # focus of this script testing the callback-free C/C++ API. # -# $Id: capi2.test,v 1.14 2004/06/19 00:16:31 drh Exp $ +# $Id: capi2.test,v 1.15 2004/06/21 06:50:29 danielk1977 Exp $ # set testdir [file dirname $argv0] @@ -227,11 +227,11 @@ do_test capi2-3.10 { # Update for v3 - the change has not actually happened until the query is # finalized. Is this going to cause trouble for anyone? Lee Nelson maybe? -do_test capi2-3.10b {sqlite3_changes $DB} {1} +do_test capi2-3.10b {db changes} {0} do_test capi2-3.11 { sqlite3_finalize $VM } {SQLITE_OK} -do_test capi2-3.11b {sqlite3_changes $DB} {1} +do_test capi2-3.11b {db changes} {1} do_test capi2-3.12 { sqlite3_finalize $VM } {SQLITE_MISUSE} @@ -242,7 +242,11 @@ do_test capi2-3.13 { [get_row_values $VM] \ [get_column_names $VM] } {SQLITE_ERROR 0 {} {}} -do_test capi2-3.13b {db changes} {0} + +# Update for v3: Preparing a statement does not affect the change counter. +# (Test result changes from 0 to 1). +do_test capi2-3.13b {db changes} {1} + do_test capi2-3.14 { list [sqlite3_finalize $VM] [sqlite3_errmsg $DB] } {SQLITE_CONSTRAINT {column a is not unique}} @@ -602,9 +606,16 @@ do_test capi2-7.10 { SELECT * FROM t1; } } {0 4 1 2 3 2 3 4 3 4 5 4 5 6} + +# Update for version 3: A SELECT statement no longer resets the change +# counter (Test result changes from 0 to 4). do_test capi2-7.11 { sqlite3_changes $DB -} {0} +} {4} +do_test capi2-7.11a { + execsql {SELECT count(*) FROM t1} +} {4} + do_test capi2-7.12 { set x [stepsql $DB {EXPLAIN SELECT * FROM t1}] lindex $x 0 diff --git a/test/conflict.test b/test/conflict.test index 89ba507e55..1369b773a6 100644 --- a/test/conflict.test +++ b/test/conflict.test @@ -13,7 +13,7 @@ # This file implements tests for the conflict resolution extension # to SQLite. # -# $Id: conflict.test,v 1.21 2004/05/31 08:55:34 danielk1977 Exp $ +# $Id: conflict.test,v 1.22 2004/06/21 06:50:29 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -383,9 +383,12 @@ do_test conflict-7.7 { SELECT count(*) FROM t1; } } {1} + +# Update for version 3: A SELECT statement no longer resets the change +# counter (Test result changes from 0 to 50). do_test conflict-7.7.1 { db changes -} {0} +} {50} # Make sure the row count is right for rows that are ignored on # an insert. diff --git a/test/insert2.test b/test/insert2.test index 8c30cb0ec9..0cd292f279 100644 --- a/test/insert2.test +++ b/test/insert2.test @@ -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.10 2002/06/25 13:16:04 drh Exp $ +# $Id: insert2.test,v 1.11 2004/06/21 06:50:29 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -125,6 +125,7 @@ do_test insert2-3.1 { } } {1 2} do_test insert2-3.2 { + set x [db total_changes] execsql { BEGIN; INSERT INTO t4 VALUES(2,4); @@ -138,7 +139,7 @@ do_test insert2-3.2 { INSERT INTO t4 VALUES(10,20); COMMIT; } - db changes + expr [db total_changes] - $x } {9} do_test insert2-3.2.1 { execsql { diff --git a/test/laststmtchanges.test b/test/laststmtchanges.test index b7929847be..f7adcd2e79 100644 --- a/test/laststmtchanges.test +++ b/test/laststmtchanges.test @@ -7,16 +7,17 @@ # #*********************************************************************** # -# Tests to make sure that value returned by last_statement_change_count() -# (LSCC) is updated properly, especially inside triggers +# Tests to make sure that values returned by changes() and total_changes() +# are updated properly, especially inside triggers # -# Note 1: LSCC remains constant within a statement and only updates once -# the statement is finished (triggers count as part of statement) -# Note 2: LSCC is changed within the context of a trigger -# much like last_insert_rowid() (see lastinsert.test), -# but is restored once the trigger exits -# Note 3: LSCC is not changed by a change to a view (since everything -# is done within instead of trigger context) +# Note 1: changes() remains constant within a statement and only updates +# once the statement is finished (triggers count as part of +# statement). +# Note 2: changes() is changed within the context of a trigger much like +# last_insert_rowid() (see lastinsert.test), but is restored once +# the trigger exits. +# Note 3: changes() is not changed by a change to a view (since everything +# is done within instead of trigger context). # set testdir [file dirname $argv0] @@ -25,7 +26,7 @@ source $testdir/tester.tcl # ---------------------------------------------------------------------------- # 1.x - basic tests (no triggers) -# LSCC set properly after insert +# changes() set properly after insert do_test laststmtchanges-1.1 { catchsql { create table t0 (x); @@ -37,100 +38,112 @@ do_test laststmtchanges-1.1 { insert into t0 values (1); insert into t0 values (1); insert into t0 values (2); - select last_statement_change_count(); + select changes(), total_changes(); } -} {0 1} +} {0 {1 8}} -# LSCC set properly after update +# changes() set properly after update do_test laststmtchanges-1.2 { catchsql { update t0 set x=3 where x=1; - select last_statement_change_count(); + select changes(), total_changes(); } -} {0 5} +} {0 {5 13}} -# LSCC unchanged within an update statement +# changes() unchanged within an update statement do_test laststmtchanges-1.3 { catchsql { - update t0 set x=x+last_statement_change_count() where x=3; + update t0 set x=x+changes() where x=3; select count() from t0 where x=8; } } {0 5} -# LSCC set properly after update on table where no rows changed +# changes() set properly after update on table where no rows changed do_test laststmtchanges-1.4 { catchsql { update t0 set x=77 where x=88; - select last_statement_change_count(); + select changes(); } } {0 0} -# LSCC set properly after delete from table +# changes() set properly after delete from table do_test laststmtchanges-1.5 { catchsql { delete from t0 where x=2; - select last_statement_change_count(); + select changes(); } } {0 3} # ---------------------------------------------------------------------------- # 2.x - tests with after insert trigger -# LSCC changed properly after insert into table containing after trigger +# changes() changed properly after insert into table containing after trigger do_test laststmtchanges-2.1 { + set ::tc [db total_changes] catchsql { create table t1 (k integer primary key); create table t2 (k integer primary key, v1, v2); create trigger r1 after insert on t1 for each row begin - insert into t2 values (NULL, last_statement_change_count(), NULL); + insert into t2 values (NULL, changes(), NULL); update t0 set x=x; - update t2 set v2=last_statement_change_count(); + update t2 set v2=changes(); end; insert into t1 values (77); - select last_statement_change_count(); + select changes(); } } {0 1} -# LSCC unchanged upon entry into after insert trigger +# changes() unchanged upon entry into after insert trigger do_test laststmtchanges-2.2 { catchsql { select v1 from t2; } } {0 3} -# LSCC changed properly by update within context of after insert trigger +# changes() changed properly by update within context of after insert trigger do_test laststmtchanges-2.3 { catchsql { select v2 from t2; } } {0 5} +# Total changes caused by firing the trigger above: +# +# 1 from "insert into t1 values(77)" + +# 1 from "insert into t2 values (NULL, changes(), NULL);" + +# 5 from "update t0 set x=x;" + +# 1 from "update t2 set v2=changes();" +# +do_test laststmtchanges-2.4 { + expr [db total_changes] - $::tc +} {8} + # ---------------------------------------------------------------------------- # 3.x - tests with after update trigger -# LSCC changed properly after update into table containing after trigger +# changes() changed properly after update into table containing after trigger do_test laststmtchanges-3.1 { catchsql { drop trigger r1; delete from t2; delete from t2; create trigger r1 after update on t1 for each row begin - insert into t2 values (NULL, last_statement_change_count(), NULL); + insert into t2 values (NULL, changes(), NULL); delete from t0 where oid=1 or oid=2; - update t2 set v2=last_statement_change_count(); + update t2 set v2=changes(); end; update t1 set k=k; - select last_statement_change_count(); + select changes(); } } {0 1} -# LSCC unchanged upon entry into after update trigger +# changes() unchanged upon entry into after update trigger do_test laststmtchanges-3.2 { catchsql { select v1 from t2; } } {0 0} -# LSCC changed properly by delete within context of after update trigger +# changes() changed properly by delete within context of after update trigger do_test laststmtchanges-3.3 { catchsql { select v2 from t2; @@ -140,29 +153,29 @@ do_test laststmtchanges-3.3 { # ---------------------------------------------------------------------------- # 4.x - tests with before delete trigger -# LSCC changed properly on delete from table containing before trigger +# changes() changed properly on delete from table containing before trigger do_test laststmtchanges-4.1 { catchsql { drop trigger r1; delete from t2; delete from t2; create trigger r1 before delete on t1 for each row begin - insert into t2 values (NULL, last_statement_change_count(), NULL); + insert into t2 values (NULL, changes(), NULL); insert into t0 values (5); - update t2 set v2=last_statement_change_count(); + update t2 set v2=changes(); end; delete from t1; - select last_statement_change_count(); + select changes(); } } {0 1} -# LSCC unchanged upon entry into before delete trigger +# changes() unchanged upon entry into before delete trigger do_test laststmtchanges-4.2 { catchsql { select v1 from t2; } } {0 0} -# LSCC changed properly by insert within context of before delete trigger +# changes() changed properly by insert within context of before delete trigger do_test laststmtchanges-4.3 { catchsql { select v2 from t2; @@ -191,40 +204,40 @@ do_test laststmtchanges-5.1 { insert into t0 values (2); insert into t0 values (1); create temp trigger r1 instead of insert on v1 for each row begin - insert into n1 values (NULL, last_statement_change_count()); + insert into n1 values (NULL, changes()); update t0 set x=x*10 where x=1; - insert into n1 values (NULL, last_statement_change_count()); + insert into n1 values (NULL, changes()); insert into t1 values (NEW.k); - insert into n1 values (NULL, last_statement_change_count()); + insert into n1 values (NULL, changes()); update t0 set x=x*10 where x=0; insert into v2 values (100+NEW.k); - insert into n1 values (NULL, last_statement_change_count()); + insert into n1 values (NULL, changes()); end; create temp trigger r2 instead of insert on v2 for each row begin - insert into n2 values (NULL, last_statement_change_count()); + insert into n2 values (NULL, changes()); insert into t2 values (1000+NEW.k); - insert into n2 values (NULL, last_statement_change_count()); + insert into n2 values (NULL, changes()); update t0 set x=x*100 where x=0; - insert into n2 values (NULL, last_statement_change_count()); + insert into n2 values (NULL, changes()); delete from t0 where x=2; - insert into n2 values (NULL, last_statement_change_count()); + insert into n2 values (NULL, changes()); end; insert into t1 values (77); - select last_statement_change_count(); + select changes(); } } {0 1} do_test laststmtchanges-5.2 { catchsql { delete from t1 where k=88; - select last_statement_change_count(); + select changes(); } } {0 0} do_test laststmtchanges-5.3 { catchsql { insert into v1 values (5); - select last_statement_change_count(); + select changes(); } } {0 0} diff --git a/test/tclsqlite.test b/test/tclsqlite.test index 2920d97d0d..8533a256a9 100644 --- a/test/tclsqlite.test +++ b/test/tclsqlite.test @@ -15,7 +15,7 @@ # interface is pretty well tested. This file contains some addition # tests for fringe issues that the main test suite does not cover. # -# $Id: tclsqlite.test,v 1.24 2004/06/19 00:16:31 drh Exp $ +# $Id: tclsqlite.test,v 1.25 2004/06/21 06:50:29 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -34,7 +34,7 @@ do_test tcl-1.1 { do_test tcl-1.2 { set v [catch {db bogus} msg] lappend v $msg -} {1 {bad option "bogus": must be authorizer, busy, changes, close, commit_hook, complete, errorcode, eval, function, last_insert_rowid, last_statement_changes, onecolumn, progress, rekey, timeout, trace, collate, or collation_needed}} +} {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}} do_test tcl-1.3 { execsql {CREATE TABLE t1(a int, b int)} execsql {INSERT INTO t1 VALUES(10,20)}