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