mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-05 15:55:57 +03:00
Fixed behaviour of last_insert_rowid() with triggers and add last_statement_change_count() function that works correctly with triggers. (CVS 1251)
FossilOrigin-Name: 3383413a53bff0fef0765144de3bb9a298a5bb5c
This commit is contained in:
32
manifest
32
manifest
@@ -1,5 +1,5 @@
|
|||||||
C The\sname\sof\sa\sresult\scolumn\sis\snow\sthe\sname\sof\scolumn\sit\soriginated\sfrom,\sby\ndefault.\s\sThis\scan\sbe\sturned\soff\swith\sPRAGMA\sshort_column_names=OFF.\s\sThis\nis\sto\sbe\smore\slike\sPostgreSQL.\s\sMore\stesting\sneeded.\s(CVS\s1250)
|
C Fixed\sbehaviour\sof\slast_insert_rowid()\swith\striggers\sand\sadd\slast_statement_change_count()\sfunction\sthat\sworks\scorrectly\swith\striggers.\s(CVS\s1251)
|
||||||
D 2004-02-20T14:50:58
|
D 2004-02-20T22:53:39
|
||||||
F Makefile.in cfd75c46b335881999333a9e4b982fa8491f200b
|
F Makefile.in cfd75c46b335881999333a9e4b982fa8491f200b
|
||||||
F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
|
F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
|
||||||
F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
|
F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
|
||||||
@@ -17,7 +17,7 @@ F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895
|
|||||||
F libtool bbbea7d79c23323e4100103836028e4fad0d9242
|
F libtool bbbea7d79c23323e4100103836028e4fad0d9242
|
||||||
F ltmain.sh abfb9387049fff6996afc6e325736597795baf11
|
F ltmain.sh abfb9387049fff6996afc6e325736597795baf11
|
||||||
F main.mk d88d460c46a12ceb33daad7a7a8725e4bc2dbaad
|
F main.mk d88d460c46a12ceb33daad7a7a8725e4bc2dbaad
|
||||||
F publish.sh fe03c30027c68d610a1b51c282feb24def55ce93
|
F publish.sh d413bc45500e6d76db0535e46628fa5c88df1c6f
|
||||||
F spec.template a38492f1c1dd349fc24cb0565e08afc53045304b
|
F spec.template a38492f1c1dd349fc24cb0565e08afc53045304b
|
||||||
F sqlite.1 83f4a9d37bdf2b7ef079a82d54eaf2e3509ee6ea
|
F sqlite.1 83f4a9d37bdf2b7ef079a82d54eaf2e3509ee6ea
|
||||||
F sqlite.pc.in 30552343140c53304c2a658c080fbe810cd09ca2
|
F sqlite.pc.in 30552343140c53304c2a658c080fbe810cd09ca2
|
||||||
@@ -29,14 +29,14 @@ F src/btree_rb.c 32b2cb4285c0fbd53b89de021637b63d52257e54
|
|||||||
F src/build.c e6d71a3babd1f523abdd806555be3430adbd69eb
|
F src/build.c e6d71a3babd1f523abdd806555be3430adbd69eb
|
||||||
F src/copy.c 391ce142f6b1faa093867ecee134f61a5028a9af
|
F src/copy.c 391ce142f6b1faa093867ecee134f61a5028a9af
|
||||||
F src/date.c c9d2bfd40b1c95f8f97d53a5eba981d7167c7b61
|
F src/date.c c9d2bfd40b1c95f8f97d53a5eba981d7167c7b61
|
||||||
F src/delete.c b8e3fc122f4e103130d764085c3fd7b697b301c4
|
F src/delete.c 8e2ff752bf485906effcc64f267cdd7227463567
|
||||||
F src/encode.c 9e70ea1e4e746f23f18180949e94f1bb1c2220d3
|
F src/encode.c 9e70ea1e4e746f23f18180949e94f1bb1c2220d3
|
||||||
F src/expr.c fdd57e18cf6f2dea42e1e1930930b32ec6351c47
|
F src/expr.c fdd57e18cf6f2dea42e1e1930930b32ec6351c47
|
||||||
F src/func.c cbc5edd10c82a5193b9ca0726873328be445e6c1
|
F src/func.c 36504a3458a5501ce960c46c74ead32aab9b306a
|
||||||
F src/hash.c 9b56ef3b291e25168f630d5643a4264ec011c70e
|
F src/hash.c 9b56ef3b291e25168f630d5643a4264ec011c70e
|
||||||
F src/hash.h 3247573ab95b9dd90bcca0307a75d9a16da1ccc7
|
F src/hash.h 3247573ab95b9dd90bcca0307a75d9a16da1ccc7
|
||||||
F src/insert.c f0a95cb6e6b0aacc916c76a89649196e4f10adca
|
F src/insert.c ad2902c171d23b92e2b350db2da86e36062e044b
|
||||||
F src/main.c 8d348b97fa48353eee0c5ab0081fc498129954fc
|
F src/main.c ab7f1aae3fff4adbf3b5d518267a1160d7760a6b
|
||||||
F src/md5.c fe4f9c9c6f71dfc26af8da63e4d04489b1430565
|
F src/md5.c fe4f9c9c6f71dfc26af8da63e4d04489b1430565
|
||||||
F src/os.c f5fc4954725b2fcd852979f2746085fe8ca27710
|
F src/os.c f5fc4954725b2fcd852979f2746085fe8ca27710
|
||||||
F src/os.h 250a3789be609adfee5c5aa20137ce8683276f24
|
F src/os.h 250a3789be609adfee5c5aa20137ce8683276f24
|
||||||
@@ -49,7 +49,7 @@ F src/random.c 775913e0b7fbd6295d21f12a7bd35b46387c44b2
|
|||||||
F src/select.c 9a41dace754f0dab5e991e402c05fa3c24d04f19
|
F src/select.c 9a41dace754f0dab5e991e402c05fa3c24d04f19
|
||||||
F src/shell.c c3d3404fa82bb0808444fda9884d1bb572fd18b9
|
F src/shell.c c3d3404fa82bb0808444fda9884d1bb572fd18b9
|
||||||
F src/sqlite.h.in 64f016cd5ce190643a0f47760188fdf4e0b2227e
|
F src/sqlite.h.in 64f016cd5ce190643a0f47760188fdf4e0b2227e
|
||||||
F src/sqliteInt.h 2e30f2bf445d3b797149cdf8b246f40f117e16b4
|
F src/sqliteInt.h d943f207ab70368e83722a4f1e30cfe01f6da23a
|
||||||
F src/table.c d845cb101b5afc1f7fea083c99e3d2fa7998d895
|
F src/table.c d845cb101b5afc1f7fea083c99e3d2fa7998d895
|
||||||
F src/tclsqlite.c b84dafe3a8532ff534c36e96bd38880e4b9cedf3
|
F src/tclsqlite.c b84dafe3a8532ff534c36e96bd38880e4b9cedf3
|
||||||
F src/test1.c 56e9a156df3ad5e4e98df776776e963effc727f7
|
F src/test1.c 56e9a156df3ad5e4e98df776776e963effc727f7
|
||||||
@@ -57,13 +57,13 @@ F src/test2.c 75819b0f2c63c6a0fd6995445881f2eb94036996
|
|||||||
F src/test3.c 30985ebdfaf3ee1462a9b0652d3efbdc8d9798f5
|
F src/test3.c 30985ebdfaf3ee1462a9b0652d3efbdc8d9798f5
|
||||||
F src/test4.c dcbbbb382626fd466a7c46907f74db35fc8bad64
|
F src/test4.c dcbbbb382626fd466a7c46907f74db35fc8bad64
|
||||||
F src/tokenize.c 6676b946fd8825b67ab52140af4fdc57a70bda48
|
F src/tokenize.c 6676b946fd8825b67ab52140af4fdc57a70bda48
|
||||||
F src/trigger.c c647a442427fb8c1cd761eb03b1710c9d5675a8b
|
F src/trigger.c 0d4f05097be308ea440629d17fdf3fd2a7244eba
|
||||||
F src/update.c 10459f44c9eb46c70b1c63e79cc35f3256f09986
|
F src/update.c e6eed1a4a429cc28f57533365c72293794c904cf
|
||||||
F src/util.c 64995b5949a5d377629ffd2598747bc771cade1e
|
F src/util.c 64995b5949a5d377629ffd2598747bc771cade1e
|
||||||
F src/vacuum.c d9e80c2b36ee1f623dbf1bdf3cedad24a23f87ac
|
F src/vacuum.c d9e80c2b36ee1f623dbf1bdf3cedad24a23f87ac
|
||||||
F src/vdbe.c e1825bcb40da6dd8429b24f404dc31265face31e
|
F src/vdbe.c f14e8e2ef82cb8480394697c40644d70195598e5
|
||||||
F src/vdbe.h b9f6f1b5f9d1bfceb8bda5e396877ba584c4519c
|
F src/vdbe.h b9f6f1b5f9d1bfceb8bda5e396877ba584c4519c
|
||||||
F src/vdbeInt.h af83bd700b1cc10b9cad2af146002927e0d421c9
|
F src/vdbeInt.h b40ff02ce39fd076e6ff3369e19c1bbfe1986682
|
||||||
F src/vdbeaux.c 9f8c7eeeeabd5c7b7fd10adb106212651c53796a
|
F src/vdbeaux.c 9f8c7eeeeabd5c7b7fd10adb106212651c53796a
|
||||||
F src/where.c 1302d728bd338c237e6a8282e4e3eadbbdf11e45
|
F src/where.c 1302d728bd338c237e6a8282e4e3eadbbdf11e45
|
||||||
F test/all.test 569a92a8ee88f5300c057cc4a8f50fbbc69a3242
|
F test/all.test 569a92a8ee88f5300c057cc4a8f50fbbc69a3242
|
||||||
@@ -186,7 +186,7 @@ F www/sqlite.tcl 3c83b08cf9f18aa2d69453ff441a36c40e431604
|
|||||||
F www/tclsqlite.tcl b9271d44dcf147a93c98f8ecf28c927307abd6da
|
F www/tclsqlite.tcl b9271d44dcf147a93c98f8ecf28c927307abd6da
|
||||||
F www/vdbe.tcl 9b9095d4495f37697fd1935d10e14c6015e80aa1
|
F www/vdbe.tcl 9b9095d4495f37697fd1935d10e14c6015e80aa1
|
||||||
F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4
|
F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4
|
||||||
P 8d3e924975681a871e0eeac3b6a62cffdb947ac7
|
P 574dd444e7ff00e0fccc3436fe617ad832daae40
|
||||||
R 25fc9e67ed64c9634c3063950c1dbf75
|
R 2d08fc4d8b9780421fb79aa060691994
|
||||||
U drh
|
U rdc
|
||||||
Z a53a93fc0bf92133df676d6edc4a0f50
|
Z c0c95fab98bfcf50f66a4b79678cfbb0
|
||||||
|
@@ -1 +1 @@
|
|||||||
574dd444e7ff00e0fccc3436fe617ad832daae40
|
3383413a53bff0fef0765144de3bb9a298a5bb5c
|
@@ -119,6 +119,9 @@ sqlite_trace
|
|||||||
sqlite_compile
|
sqlite_compile
|
||||||
sqlite_step
|
sqlite_step
|
||||||
sqlite_finalize
|
sqlite_finalize
|
||||||
|
sqlite_reset
|
||||||
|
sqlite_bind
|
||||||
|
sqlite_last_statement_changes
|
||||||
END_OF_FILE
|
END_OF_FILE
|
||||||
i386-mingw32msvc-dllwrap \
|
i386-mingw32msvc-dllwrap \
|
||||||
--def sqlite.def -v --export-all \
|
--def sqlite.def -v --export-all \
|
||||||
|
@@ -12,7 +12,7 @@
|
|||||||
** This file contains C code routines that are called by the parser
|
** This file contains C code routines that are called by the parser
|
||||||
** to handle DELETE FROM statements.
|
** to handle DELETE FROM statements.
|
||||||
**
|
**
|
||||||
** $Id: delete.c,v 1.59 2004/02/16 03:44:02 drh Exp $
|
** $Id: delete.c,v 1.60 2004/02/20 22:53:39 rdc Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
|
|
||||||
@@ -299,6 +299,7 @@ void sqliteDeleteFrom(
|
|||||||
pParse->nTab = iCur;
|
pParse->nTab = iCur;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
sqliteVdbeAddOp(v, OP_SetCounts, 0, 0);
|
||||||
sqliteEndWriteOperation(pParse);
|
sqliteEndWriteOperation(pParse);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -347,7 +348,8 @@ void sqliteGenerateRowDelete(
|
|||||||
int addr;
|
int addr;
|
||||||
addr = sqliteVdbeAddOp(v, OP_NotExists, iCur, 0);
|
addr = sqliteVdbeAddOp(v, OP_NotExists, iCur, 0);
|
||||||
sqliteGenerateRowIndexDelete(db, v, pTab, iCur, 0);
|
sqliteGenerateRowIndexDelete(db, v, pTab, iCur, 0);
|
||||||
sqliteVdbeAddOp(v, OP_Delete, iCur, count);
|
sqliteVdbeAddOp(v, OP_Delete, iCur,
|
||||||
|
(count?OPFLAG_NCHANGE:0) | OPFLAG_CSCHANGE);
|
||||||
sqliteVdbeChangeP2(v, addr, sqliteVdbeCurrentAddr(v));
|
sqliteVdbeChangeP2(v, addr, sqliteVdbeCurrentAddr(v));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
18
src/func.c
18
src/func.c
@@ -16,7 +16,7 @@
|
|||||||
** sqliteRegisterBuildinFunctions() found at the bottom of the file.
|
** sqliteRegisterBuildinFunctions() found at the bottom of the file.
|
||||||
** All other code has file scope.
|
** All other code has file scope.
|
||||||
**
|
**
|
||||||
** $Id: func.c,v 1.39 2004/02/11 09:46:32 drh Exp $
|
** $Id: func.c,v 1.40 2004/02/20 22:53:39 rdc Exp $
|
||||||
*/
|
*/
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
@@ -209,6 +209,16 @@ static void last_insert_rowid(sqlite_func *context, int arg, const char **argv){
|
|||||||
sqlite_set_result_int(context, sqlite_last_insert_rowid(db));
|
sqlite_set_result_int(context, sqlite_last_insert_rowid(db));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void change_count(sqlite_func *context, int arg, const char **argv){
|
||||||
|
sqlite *db = sqlite_user_data(context);
|
||||||
|
sqlite_set_result_int(context, sqlite_changes(db));
|
||||||
|
}
|
||||||
|
static void last_statement_change_count(sqlite_func *context, int arg,
|
||||||
|
const char **argv){
|
||||||
|
sqlite *db = sqlite_user_data(context);
|
||||||
|
sqlite_set_result_int(context, sqlite_last_statement_changes(db));
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Implementation of the like() SQL function. This function implements
|
** Implementation of the like() SQL function. This function implements
|
||||||
** the build-in LIKE operator. The first argument to the function is the
|
** the build-in LIKE operator. The first argument to the function is the
|
||||||
@@ -613,6 +623,12 @@ void sqliteRegisterBuiltinFunctions(sqlite *db){
|
|||||||
sqlite_create_function(db, "last_insert_rowid", 0,
|
sqlite_create_function(db, "last_insert_rowid", 0,
|
||||||
last_insert_rowid, db);
|
last_insert_rowid, db);
|
||||||
sqlite_function_type(db, "last_insert_rowid", SQLITE_NUMERIC);
|
sqlite_function_type(db, "last_insert_rowid", SQLITE_NUMERIC);
|
||||||
|
sqlite_create_function(db, "change_count", 0, change_count, db);
|
||||||
|
sqlite_function_type(db, "change_count", SQLITE_NUMERIC);
|
||||||
|
sqlite_create_function(db, "last_statement_change_count", 0,
|
||||||
|
last_statement_change_count, db);
|
||||||
|
sqlite_function_type(db, "last_statement_change_count", SQLITE_NUMERIC);
|
||||||
|
|
||||||
for(i=0; i<sizeof(aAggs)/sizeof(aAggs[0]); i++){
|
for(i=0; i<sizeof(aAggs)/sizeof(aAggs[0]); i++){
|
||||||
sqlite_create_aggregate(db, aAggs[i].zName,
|
sqlite_create_aggregate(db, aAggs[i].zName,
|
||||||
aAggs[i].nArg, aAggs[i].xStep, aAggs[i].xFinalize, 0);
|
aAggs[i].nArg, aAggs[i].xStep, aAggs[i].xFinalize, 0);
|
||||||
|
@@ -12,7 +12,7 @@
|
|||||||
** This file contains C code routines that are called by the parser
|
** This file contains C code routines that are called by the parser
|
||||||
** to handle INSERT statements in SQLite.
|
** to handle INSERT statements in SQLite.
|
||||||
**
|
**
|
||||||
** $Id: insert.c,v 1.91 2004/02/16 03:44:02 drh Exp $
|
** $Id: insert.c,v 1.92 2004/02/20 22:53:39 rdc Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
|
|
||||||
@@ -535,6 +535,7 @@ void sqliteInsert(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sqliteVdbeAddOp(v, OP_SetCounts, 0, 0);
|
||||||
sqliteEndWriteOperation(pParse);
|
sqliteEndWriteOperation(pParse);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -906,7 +907,9 @@ void sqliteCompleteInsertion(
|
|||||||
sqliteVdbeAddOp(v, OP_Dup, 1, 0);
|
sqliteVdbeAddOp(v, OP_Dup, 1, 0);
|
||||||
sqliteVdbeAddOp(v, OP_PutIntKey, newIdx, 0);
|
sqliteVdbeAddOp(v, OP_PutIntKey, newIdx, 0);
|
||||||
}
|
}
|
||||||
sqliteVdbeAddOp(v, OP_PutIntKey, base, pParse->trigStack?0:1);
|
sqliteVdbeAddOp(v, OP_PutIntKey, base,
|
||||||
|
(pParse->trigStack?0:OPFLAG_NCHANGE) |
|
||||||
|
(isUpdate?0:OPFLAG_LASTROWID) | OPFLAG_CSCHANGE);
|
||||||
if( isUpdate && recnoChng ){
|
if( isUpdate && recnoChng ){
|
||||||
sqliteVdbeAddOp(v, OP_Pop, 1, 0);
|
sqliteVdbeAddOp(v, OP_Pop, 1, 0);
|
||||||
}
|
}
|
||||||
|
@@ -14,7 +14,7 @@
|
|||||||
** other files are for internal use by SQLite and should not be
|
** other files are for internal use by SQLite and should not be
|
||||||
** accessed by users of the library.
|
** accessed by users of the library.
|
||||||
**
|
**
|
||||||
** $Id: main.c,v 1.157 2004/02/20 14:50:58 drh Exp $
|
** $Id: main.c,v 1.158 2004/02/20 22:53:39 rdc Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
@@ -545,6 +545,10 @@ int sqlite_changes(sqlite *db){
|
|||||||
return db->nChange;
|
return db->nChange;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int sqlite_last_statement_changes(sqlite *db){
|
||||||
|
return db->lsChange;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Close an existing SQLite database
|
** Close an existing SQLite database
|
||||||
*/
|
*/
|
||||||
|
@@ -11,7 +11,7 @@
|
|||||||
*************************************************************************
|
*************************************************************************
|
||||||
** Internal interface definitions for SQLite.
|
** Internal interface definitions for SQLite.
|
||||||
**
|
**
|
||||||
** @(#) $Id: sqliteInt.h,v 1.214 2004/02/20 14:50:58 drh Exp $
|
** @(#) $Id: sqliteInt.h,v 1.215 2004/02/20 22:53:39 rdc Exp $
|
||||||
*/
|
*/
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "sqlite.h"
|
#include "sqlite.h"
|
||||||
@@ -309,6 +309,24 @@ struct Db {
|
|||||||
** are stored. If 1, then a file is created to hold those tables. If
|
** are stored. If 1, then a file is created to hold those tables. If
|
||||||
** 2, then they are held in memory. 0 means use the default value in
|
** 2, then they are held in memory. 0 means use the default value in
|
||||||
** the TEMP_STORE macro.
|
** the TEMP_STORE macro.
|
||||||
|
**
|
||||||
|
** The sqlite.lastRowid records the last insert rowid generated by an
|
||||||
|
** insert statement. Inserts on views do not affect its value. Each
|
||||||
|
** trigger has its own context, so that lastRowid can be updated inside
|
||||||
|
** triggers as usual. The previous value will be restored once the trigger
|
||||||
|
** exits. Upon entering a before or instead of trigger, lastRowid is no
|
||||||
|
** longer (since after version 2.8.12) reset to -1.
|
||||||
|
**
|
||||||
|
** The sqlite.nChange does not count changes within triggers and keeps no
|
||||||
|
** context. It is reset at start of sqlite_exec.
|
||||||
|
** The sqlite.lsChange represents the number of changes made by the last
|
||||||
|
** insert, update, or delete statement. It remains constant throughout the
|
||||||
|
** length of a statement and is then updated by OP_SetCounts. It keeps a
|
||||||
|
** context stack just like lastRowid so that the count of changes
|
||||||
|
** within a trigger is not seen outside the trigger. Changes to views do not
|
||||||
|
** affect the value of lsChange.
|
||||||
|
** The sqlite.csChange keeps track of the number of current changes (since
|
||||||
|
** the last statement) and is used to update sqlite_lsChange.
|
||||||
*/
|
*/
|
||||||
struct sqlite {
|
struct sqlite {
|
||||||
int nDb; /* Number of backends currently in use */
|
int nDb; /* Number of backends currently in use */
|
||||||
@@ -328,10 +346,12 @@ struct sqlite {
|
|||||||
void *pCommitArg; /* Argument to xCommitCallback() */
|
void *pCommitArg; /* Argument to xCommitCallback() */
|
||||||
int (*xCommitCallback)(void*);/* Invoked at every commit. */
|
int (*xCommitCallback)(void*);/* Invoked at every commit. */
|
||||||
Hash aFunc; /* All functions that can be in SQL exprs */
|
Hash aFunc; /* All functions that can be in SQL exprs */
|
||||||
int lastRowid; /* ROWID of most recent insert */
|
int lastRowid; /* ROWID of most recent insert (see above) */
|
||||||
int priorNewRowid; /* Last randomly generated ROWID */
|
int priorNewRowid; /* Last randomly generated ROWID */
|
||||||
int magic; /* Magic number for detect library misuse */
|
int magic; /* Magic number for detect library misuse */
|
||||||
int nChange; /* Number of rows changed */
|
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 sqliteInitInfo { /* Information used during initialization */
|
struct sqliteInitInfo { /* Information used during initialization */
|
||||||
int iDb; /* When back is being initialized */
|
int iDb; /* When back is being initialized */
|
||||||
int newTnum; /* Rootpage of table being initialized */
|
int newTnum; /* Rootpage of table being initialized */
|
||||||
@@ -907,6 +927,13 @@ struct AuthContext {
|
|||||||
Parse *pParse; /* The Parse structure */
|
Parse *pParse; /* The Parse structure */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Bitfield flags for P2 value in OP_PutIntKey and OP_Delete
|
||||||
|
*/
|
||||||
|
#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
|
* Each trigger present in the database schema is stored as an instance of
|
||||||
* struct Trigger.
|
* struct Trigger.
|
||||||
|
@@ -746,7 +746,9 @@ int sqliteCodeRowTrigger(
|
|||||||
sqliteExprIfFalse(pParse, whenExpr, endTrigger, 1);
|
sqliteExprIfFalse(pParse, whenExpr, endTrigger, 1);
|
||||||
sqliteExprDelete(whenExpr);
|
sqliteExprDelete(whenExpr);
|
||||||
|
|
||||||
|
sqliteVdbeAddOp(pParse->pVdbe, OP_ContextPush, 0, 0);
|
||||||
codeTriggerProgram(pParse, pTrigger->step_list, orconf);
|
codeTriggerProgram(pParse, pTrigger->step_list, orconf);
|
||||||
|
sqliteVdbeAddOp(pParse->pVdbe, OP_ContextPop, 0, 0);
|
||||||
|
|
||||||
/* Pop the entry off the trigger stack */
|
/* Pop the entry off the trigger stack */
|
||||||
pParse->trigStack = pParse->trigStack->pNext;
|
pParse->trigStack = pParse->trigStack->pNext;
|
||||||
|
@@ -12,7 +12,7 @@
|
|||||||
** This file contains C code routines that are called by the parser
|
** This file contains C code routines that are called by the parser
|
||||||
** to handle UPDATE statements.
|
** to handle UPDATE statements.
|
||||||
**
|
**
|
||||||
** $Id: update.c,v 1.68 2004/02/16 03:44:02 drh Exp $
|
** $Id: update.c,v 1.69 2004/02/20 22:53:39 rdc Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
|
|
||||||
@@ -430,6 +430,7 @@ void sqliteUpdate(
|
|||||||
sqliteVdbeAddOp(v, OP_Close, oldIdx, 0);
|
sqliteVdbeAddOp(v, OP_Close, oldIdx, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sqliteVdbeAddOp(v, OP_SetCounts, 0, 0);
|
||||||
sqliteEndWriteOperation(pParse);
|
sqliteEndWriteOperation(pParse);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
74
src/vdbe.c
74
src/vdbe.c
@@ -43,7 +43,7 @@
|
|||||||
** in this file for details. If in doubt, do not deviate from existing
|
** in this file for details. If in doubt, do not deviate from existing
|
||||||
** commenting and indentation practices when changing or adding code.
|
** commenting and indentation practices when changing or adding code.
|
||||||
**
|
**
|
||||||
** $Id: vdbe.c,v 1.265 2004/02/16 03:44:02 drh Exp $
|
** $Id: vdbe.c,v 1.266 2004/02/20 22:53:39 rdc Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
@@ -2895,9 +2895,12 @@ case OP_NewRecno: {
|
|||||||
** stack. The key is the next value down on the stack. The key must
|
** 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.
|
** be an integer. The stack is popped twice by this instruction.
|
||||||
**
|
**
|
||||||
** If P2==1 then the row change count is incremented. If P2==0 the
|
** If the OPFLAG_NCHANGE flag of P2 is set, then the row change count is
|
||||||
** row change count is unmodified. The rowid is stored for subsequent
|
** incremented (otherwise not). If the OPFLAG_CSCHANGE flag is set,
|
||||||
** return by the sqlite_last_insert_rowid() function if P2 is 1.
|
** 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 sqlite_last_insert_rowid() function
|
||||||
|
** (otherwise it's unmodified).
|
||||||
*/
|
*/
|
||||||
/* Opcode: PutStrKey P1 * *
|
/* Opcode: PutStrKey P1 * *
|
||||||
**
|
**
|
||||||
@@ -2928,10 +2931,9 @@ case OP_PutStrKey: {
|
|||||||
nKey = sizeof(int);
|
nKey = sizeof(int);
|
||||||
iKey = intToKey(pNos->i);
|
iKey = intToKey(pNos->i);
|
||||||
zKey = (char*)&iKey;
|
zKey = (char*)&iKey;
|
||||||
if( pOp->p2 ){
|
if( pOp->p2 & OPFLAG_NCHANGE ) db->nChange++;
|
||||||
db->nChange++;
|
if( pOp->p2 & OPFLAG_LASTROWID ) db->lastRowid = pNos->i;
|
||||||
db->lastRowid = pNos->i;
|
if( pOp->p2 & OPFLAG_CSCHANGE ) db->csChange++;
|
||||||
}
|
|
||||||
if( pC->nextRowidValid && pTos->i>=pC->nextRowid ){
|
if( pC->nextRowidValid && pTos->i>=pC->nextRowid ){
|
||||||
pC->nextRowidValid = 0;
|
pC->nextRowidValid = 0;
|
||||||
}
|
}
|
||||||
@@ -2980,8 +2982,9 @@ case OP_PutStrKey: {
|
|||||||
** the next Next instruction will be a no-op. Hence it is OK to delete
|
** the next Next instruction will be a no-op. Hence it is OK to delete
|
||||||
** a record from within an Next loop.
|
** a record from within an Next loop.
|
||||||
**
|
**
|
||||||
** The row change counter is incremented if P2==1 and is unmodified
|
** If the OPFLAG_NCHANGE flag of P2 is set, then the row change count is
|
||||||
** if P2==0.
|
** incremented (otherwise not). If OPFLAG_CSCHANGE flag is set,
|
||||||
|
** then the current statement change count is incremented (otherwise not).
|
||||||
**
|
**
|
||||||
** If P1 is a pseudo-table, then this instruction is a no-op.
|
** If P1 is a pseudo-table, then this instruction is a no-op.
|
||||||
*/
|
*/
|
||||||
@@ -2995,7 +2998,19 @@ case OP_Delete: {
|
|||||||
rc = sqliteBtreeDelete(pC->pCursor);
|
rc = sqliteBtreeDelete(pC->pCursor);
|
||||||
pC->nextRowidValid = 0;
|
pC->nextRowidValid = 0;
|
||||||
}
|
}
|
||||||
if( pOp->p2 ) db->nChange++;
|
if( pOp->p2 & OPFLAG_NCHANGE ) db->nChange++;
|
||||||
|
if( pOp->p2 & OPFLAG_CSCHANGE ) db->csChange++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Opcode: SetCounts * * *
|
||||||
|
**
|
||||||
|
** Called at end of statement. Updates lsChange (last statement change count)
|
||||||
|
** and resets csChange (current statement change count) to 0.
|
||||||
|
*/
|
||||||
|
case OP_SetCounts: {
|
||||||
|
db->lsChange=db->csChange;
|
||||||
|
db->csChange=0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3850,6 +3865,43 @@ case OP_ListPop: {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Opcode: ContextPush * * *
|
||||||
|
**
|
||||||
|
** Save the current Vdbe context such that it can be restored by a ContextPop
|
||||||
|
** opcode. The context stores the last insert row id, the last statement change
|
||||||
|
** count, and the current statement change count.
|
||||||
|
*/
|
||||||
|
case OP_ContextPush: {
|
||||||
|
p->contextStackDepth++;
|
||||||
|
assert(p->contextStackDepth > 0);
|
||||||
|
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].lsChange = p->db->lsChange;
|
||||||
|
p->contextStack[p->contextStackDepth - 1].csChange = p->db->csChange;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Opcode: ContextPop * * *
|
||||||
|
**
|
||||||
|
** Restore the Vdbe context to the state it was in when contextPush was last
|
||||||
|
** executed. The context stores the last insert row id, the last statement
|
||||||
|
** change count, and the current statement change count.
|
||||||
|
*/
|
||||||
|
case OP_ContextPop: {
|
||||||
|
assert(p->contextStackDepth > 0);
|
||||||
|
p->contextStackDepth--;
|
||||||
|
p->db->lastRowid = p->contextStack[p->contextStackDepth].lastRowid;
|
||||||
|
p->db->lsChange = p->contextStack[p->contextStackDepth].lsChange;
|
||||||
|
p->db->csChange = p->contextStack[p->contextStackDepth].csChange;
|
||||||
|
if( p->contextStackDepth == 0 ){
|
||||||
|
sqliteFree(p->contextStack);
|
||||||
|
p->contextStack = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* Opcode: SortPut * * *
|
/* Opcode: SortPut * * *
|
||||||
**
|
**
|
||||||
** The TOS is the key and the NOS is the data. Pop both from the stack
|
** The TOS is the key and the NOS is the data. Pop both from the stack
|
||||||
|
@@ -207,6 +207,19 @@ struct Keylist {
|
|||||||
int aKey[1]; /* One or more keys. Extra space allocated as needed */
|
int aKey[1]; /* One or more keys. Extra space allocated as needed */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
** A Context stores the last insert rowid, the last statement change count,
|
||||||
|
** and the current statement change count (i.e. changes since last statement).
|
||||||
|
** Elements of Context structure type make up the ContextStack, which is
|
||||||
|
** updated by the ContextPush and ContextPop opcodes (used by triggers)
|
||||||
|
*/
|
||||||
|
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) */
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** An instance of the virtual machine. This structure contains the complete
|
** An instance of the virtual machine. This structure contains the complete
|
||||||
** state of the virtual machine.
|
** state of the virtual machine.
|
||||||
@@ -250,6 +263,8 @@ struct Vdbe {
|
|||||||
Keylist *pList; /* A list of ROWIDs */
|
Keylist *pList; /* A list of ROWIDs */
|
||||||
int keylistStackDepth; /* The size of the "keylist" stack */
|
int keylistStackDepth; /* The size of the "keylist" stack */
|
||||||
Keylist **keylistStack; /* The stack used by opcodes ListPush & ListPop */
|
Keylist **keylistStack; /* The stack used by opcodes ListPush & ListPop */
|
||||||
|
int contextStackDepth; /* The size of the "context" stack */
|
||||||
|
Context *contextStack; /* Stack used by opcodes ContextPush & ContextPop*/
|
||||||
int pc; /* The program counter */
|
int pc; /* The program counter */
|
||||||
int rc; /* Value to return */
|
int rc; /* Value to return */
|
||||||
unsigned uniqueCnt; /* Used by OP_MakeRecord when P2!=0 */
|
unsigned uniqueCnt; /* Used by OP_MakeRecord when P2!=0 */
|
||||||
|
Reference in New Issue
Block a user