Update sqlite3_changes() to match the documentation and add

sqlite3_total_changes(). (CVS 1645)

FossilOrigin-Name: ae2f4a0943854fedbbb6fab1dc3aaf972722ed95
This commit is contained in:
danielk1977 2004-06-21 06:50:26 +00:00
parent d664d9a2bb
commit b28af71a22
20 changed files with 279 additions and 216 deletions

View File

@ -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

View File

@ -1 +1 @@
d2ccac9d01994de09a195d71cb63d1bf9fb0d33f
ae2f4a0943854fedbbb6fab1dc3aaf972722ed95

View File

@ -12,7 +12,7 @@
** This file contains C code routines that are called by the parser
** to handle DELETE FROM statements.
**
** $Id: delete.c,v 1.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));
}

View File

@ -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 <ctype.h>
#include <math.h>
@ -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(
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

View File

@ -12,7 +12,7 @@
** This file contains C code routines that are called by the parser
** to handle INSERT statements in SQLite.
**
** $Id: insert.c,v 1.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);
}

View File

@ -14,7 +14,7 @@
** other files are for internal use by SQLite and should not be
** accessed by users of the library.
**
** $Id: main.c,v 1.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);

View File

@ -12,7 +12,7 @@
** This header file defines the interface that the SQLite library
** presents to client programs.
**
** @(#) $Id: sqlite.h.in,v 1.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

View File

@ -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);

View File

@ -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;
}

View File

@ -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:

View File

@ -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);
/*

View File

@ -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;

View File

@ -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*, ...);

View File

@ -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 */
};
/*

View File

@ -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;
}

View File

@ -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

View File

@ -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.

View File

@ -12,7 +12,7 @@
# focus of this file is testing the INSERT statement that takes is
# result from a SELECT.
#
# $Id: insert2.test,v 1.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 {

View File

@ -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}

View File

@ -15,7 +15,7 @@
# interface is pretty well tested. This file contains some addition
# tests for fringe issues that the main test suite does not cover.
#
# $Id: tclsqlite.test,v 1.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)}