Update sqlite3_changes() to match the documentation and add
sqlite3_total_changes(). (CVS 1645) FossilOrigin-Name: ae2f4a0943854fedbbb6fab1dc3aaf972722ed95
This commit is contained in:
parent
d664d9a2bb
commit
b28af71a22
48
manifest
48
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
|
||||
|
@ -1 +1 @@
|
||||
d2ccac9d01994de09a195d71cb63d1bf9fb0d33f
|
||||
ae2f4a0943854fedbbb6fab1dc3aaf972722ed95
|
@ -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));
|
||||
}
|
||||
|
||||
|
29
src/func.c
29
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 <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(
|
||||
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
|
||||
|
11
src/insert.c
11
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);
|
||||
}
|
||||
|
12
src/main.c
12
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);
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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:
|
||||
|
@ -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);
|
||||
|
||||
/*
|
||||
|
50
src/vdbe.c
50
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;
|
||||
|
@ -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*, ...);
|
||||
|
@ -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 */
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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 {
|
||||
|
@ -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}
|
||||
|
||||
|
@ -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)}
|
||||
|
Loading…
Reference in New Issue
Block a user