Combine the OP_Statement and OP_Transaction opcodes.

FossilOrigin-Name: aec9dbd8d21c55c3945287a3dfa55d3ed168f977
This commit is contained in:
dan 2009-09-08 19:15:01 +00:00
parent 2283d46cd6
commit e0af83aca6
15 changed files with 114 additions and 128 deletions

View File

@ -1,5 +1,5 @@
C If\srecursive-triggers\sare\senabled,\sfire\sDELETE\striggers\sif\sdatabase\srows\sare\sremoved\sas\sa\sresult\sof\sOR\sREPLACE\sconflict\sresolution.
D 2009-09-08T15:55:16
C Combine\sthe\sOP_Statement\sand\sOP_Transaction\sopcodes.
D 2009-09-08T19:15:01
F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
F Makefile.in 73ddeec9dd10b85876c5c2ce1fdce627e1dcc7f8
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@ -99,7 +99,7 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc
F sqlite3.pc.in ae6f59a76e862f5c561eb32a380228a02afc3cad
F src/alter.c 55b601857d924e07c91cfa69e9b2cb5093498c93
F src/alter.c 0bbc34296384ae85e0e5e857aa605614ca2d404c
F src/analyze.c 5a8b8aa3d170eac5e71af45458cec61f83c623ee
F src/attach.c 13995348fc5a26cdd136a50806faf292aabc173f
F src/auth.c d6a88bf8e81e6a079ccb8881002b327e42ec46b9
@ -109,19 +109,19 @@ F src/btmutex.c 0f43a75bb5b8147b386e8e1c3e71ba734e3863b7
F src/btree.c 873a82706e07604a638e02e12617983df8e8070a
F src/btree.h 577448a890c2ab9b21e6ab74f073526184bceebe
F src/btreeInt.h 1c86297e69380f6577e7ae67452597dd8d5c2705
F src/build.c df8dfff696329c192240e3d532f9dad0ef5abace
F src/build.c 1a21d6dcb6a60b065f5407c6a5f2d021f946fa34
F src/callback.c f49c305dc94b78da948953c392963929c0e70f9b
F src/complete.c 5ad5c6cd4548211867c204c41a126d73a9fbcea0
F src/date.c ab5f7137656652a48434d64f96bdcdc823bb23b3
F src/delete.c 4c9b899246a12795ae7f145ad7c5c3ac563fa05f
F src/expr.c 2605f0f161442e3153e0c41e987525260e9ad306
F src/delete.c 70abd255f094f37411d7c76c65874cf86d435529
F src/expr.c 638b599adad562d41c3bf90f542f9419664aa7b8
F src/fault.c dc88c821842157460750d2d61a8a8b4197d047ff
F src/func.c e536218d193b8d326aab91120bc4c6f28aa2b606
F src/global.c 271952d199a8cc59d4ce840b3bbbfd2f30c8ba32
F src/hash.c ebcaa921ffd9d86f7ea5ae16a0a29d1c871130a7
F src/hash.h 35b216c13343d0b4f87d9f21969ac55ad72174e1
F src/hwtime.h 4a1d45f4cae1f402ea19686acf24acf4f0cb53cb
F src/insert.c 5cf80f9b4222c2145cab299e9b829385846b6937
F src/insert.c 755028b84a6442b684ee24b445daee612d9aa539
F src/journal.c e00df0c0da8413ab6e1bb7d7cab5665d4a9000d0
F src/legacy.c 303b4ffcf1ae652fcf5ef635846c563c254564f6
F src/lempar.c 0c4d1ab0a5ef2b0381eb81a732c54f68f27a574d
@ -163,7 +163,7 @@ F src/select.c a7a075456d4e640ffd7d0a33202d306c69c88f72
F src/shell.c db2643650b9268df89a4bedca3f1c6d9e786f1bb
F src/sqlite.h.in e5949b46f9a05aadde22848f92fae5c9ba87ee0e
F src/sqlite3ext.h 1db7d63ab5de4b3e6b83dd03d1a4e64fef6d2a17
F src/sqliteInt.h b39de08df1442d48a6ea85c227c609e696a85b89
F src/sqliteInt.h 66914c7a4a8ad427dc3705e13df95763003ea8fb
F src/sqliteLimit.h be44f7f46c14bb4c21870074b1e6f1ac0abd6701
F src/status.c 237b193efae0cf6ac3f0817a208de6c6c6ef6d76
F src/table.c cc86ad3d6ad54df7c63a3e807b5783c90411a08d
@ -201,16 +201,16 @@ F src/test_thread.c b8a1ab7ca1a632f18e8a361880d5d65eeea08eac
F src/test_wsd.c 3ae5101de6cbfda2720152ab659ea84079719241
F src/tokenize.c af8a56e6a50c5042fc305bfa796275e9bf26ff2b
F src/trigger.c 054c08339b3471c785f1cf041ed878a425850e33
F src/update.c 3e97974baa914f32d4ae690fa0cb7281aff8cd39
F src/update.c 7a2c0dad3badd60320ff12bb42ca1446c1f7da28
F src/utf.c 99cf927eabb104621ba889ac0dd075fc1657ad30
F src/util.c 59d4e9456bf1fe581f415a783fa0cee6115c8f35
F src/vacuum.c 3fe0eebea6d2311c1c2ab2962887d11f7a4dcfb0
F src/vdbe.c 5dc91d9b7da2277b72721948134fd800918cca35
F src/vdbe.h 080fe6bc1264438becb8bf9b9f3c84074c336b78
F src/vdbe.c aba680ec9cf68890f3600a4c0c1936b1d789d111
F src/vdbe.h afd9c99544fd916c93c6de5b1d11490899e483ea
F src/vdbeInt.h 004dbb28a9195b6c85fe3255c7cc300ffd8b9453
F src/vdbeapi.c 8d5013ab6104be757c208a70ffb191cc27d2b688
F src/vdbeaux.c ec1545ece73dd739c9043f14963fb3f20d3880d6
F src/vdbeblob.c f93cb60ac388633ed3bde8a94ef161ad2dbfb689
F src/vdbeapi.c b7e5f34436e298e2b0168e71323b5d97f7e9b080
F src/vdbeaux.c 75dff9148f3bcdb5772ca00be774f7194a4fce61
F src/vdbeblob.c 4d6b702ca714a2d52552eee72d3e3191f8444eab
F src/vdbemem.c 0ff2b209fccade3ff6709286057b82ed7f6c1e70
F src/vtab.c 3e54fe39374e5feb8b174de32a90e7a21966025d
F src/walker.c 1edca756275f158b80f20eb6f104c8d3fcc96a04
@ -682,7 +682,7 @@ F test/trigger8.test 30cb0530bd7c4728055420e3f739aa00412eafa4
F test/trigger9.test 5b0789f1c5c4600961f8e68511b825b87be53e31
F test/triggerA.test 0718ad2d9bfef27c7af00e636df79bee6b988da7
F test/triggerB.test 56780c031b454abac2340dbb3b71ac5c56c3d7fe
F test/triggerC.test 3e13e9a87939797115343b261a3f893c71304106
F test/triggerC.test 427f3036f0d1a8e65db99d3e98b9c34edf559104
F test/types.test 9a825ec8eea4e965d7113b74c76a78bb5240f2ac
F test/types2.test 3555aacf8ed8dc883356e59efc314707e6247a84
F test/types3.test a0f66bf12f80fad89493535474f7a6d16fa58150
@ -750,7 +750,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
P 4ab8c841f818326b0b04b95e3edd828c77f109d9
R 3fb4417640a30cdf072206af6c01b085
P 85cb0c94a63eda5f059ebe40887c7af9b4869893
R 6a11a24dc821178a3e61515331c83e2c
U dan
Z 8bcac683a9d824da75eea0a85386a639
Z 33e8150d74d6f5afb30b73dad757212c

View File

@ -1 +1 @@
85cb0c94a63eda5f059ebe40887c7af9b4869893
aec9dbd8d21c55c3945287a3dfa55d3ed168f977

View File

@ -362,6 +362,7 @@ void sqlite3AlterRenameTable(
int i = ++pParse->nMem;
sqlite3VdbeAddOp4(v, OP_String8, 0, i, 0, zName, 0);
sqlite3VdbeAddOp4(v, OP_VRename, i, 0, 0,(const char*)pVTab, P4_VTAB);
sqlite3MayAbort(pParse);
}
#endif

View File

@ -195,7 +195,8 @@ void sqlite3FinishCoding(Parse *pParse){
#endif
assert( pParse->iCacheLevel==0 ); /* Disables and re-enables match */
sqlite3VdbeMakeReady(v, pParse->nVar, pParse->nMem,
pParse->nTab, pParse->nMaxArg, pParse->explain);
pParse->nTab, pParse->nMaxArg, pParse->explain,
pParse->isMultiWrite && pParse->mayAbort);
pParse->rc = SQLITE_DONE;
pParse->colNamesSet = 0;
}else if( pParse->rc==SQLITE_OK ){
@ -1878,6 +1879,7 @@ static void destroyRootPage(Parse *pParse, int iTable, int iDb){
Vdbe *v = sqlite3GetVdbe(pParse);
int r1 = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp3(v, OP_Destroy, iTable, r1, iDb);
sqlite3MayAbort(pParse);
#ifndef SQLITE_OMIT_AUTOVACUUM
/* OP_Destroy stores an in integer r1. If this integer
** is non-zero, then it is the root page number of a table moved to
@ -2319,8 +2321,8 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
** since sqlite3ReleaseTempRange() was called, it is safe to do so.
*/
sqlite3VdbeAddOp4(v, OP_IsUnique, iIdx, j2, regRowid, pRegKey, P4_INT32);
sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CONSTRAINT, OE_Abort, 0,
"indexed columns are not unique", P4_STATIC);
sqlite3HaltConstraint(
pParse, OE_Abort, "indexed columns are not unique", P4_STATIC);
}
sqlite3VdbeAddOp2(v, OP_IdxInsert, iIdx, regRecord);
sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
@ -3465,12 +3467,29 @@ void sqlite3BeginWriteOperation(Parse *pParse, int setStatement, int iDb){
Parse *pToplevel = sqlite3ParseToplevel(pParse);
sqlite3CodeVerifySchema(pParse, iDb);
pToplevel->writeMask |= 1<<iDb;
if( setStatement && pParse->nested==0 && pParse==pToplevel ){
/* Every place where this routine is called with setStatement!=0 has
** already successfully created a VDBE. */
assert( pParse->pVdbe );
sqlite3VdbeAddOp1(pParse->pVdbe, OP_Statement, iDb);
pToplevel->isMultiWrite |= setStatement;
}
/*
** Set the "may throw abort exception" flag for the statement currently
** being coded.
*/
void sqlite3MayAbort(Parse *pParse){
Parse *pToplevel = sqlite3ParseToplevel(pParse);
pToplevel->mayAbort = 1;
}
/*
** Code an OP_Halt that causes the vdbe to return an SQLITE_CONSTRAINT
** error. The onError parameter determines which (if any) of the statement
** and/or current transaction is rolled back.
*/
void sqlite3HaltConstraint(Parse *pParse, int onError, char *p4, int p4type){
Vdbe *v = sqlite3GetVdbe(pParse);
if( onError==OE_Abort ){
sqlite3MayAbort(pParse);
}
sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CONSTRAINT, onError, 0, p4, p4type);
}
/*

View File

@ -392,6 +392,7 @@ void sqlite3DeleteFrom(
const char *pVTab = (const char *)sqlite3GetVTable(db, pTab);
sqlite3VtabMakeWritable(pParse, pTab);
sqlite3VdbeAddOp4(v, OP_VUpdate, 0, 1, iRowid, pVTab, P4_VTAB);
sqlite3MayAbort(pParse);
}else
#endif
{

View File

@ -2692,20 +2692,27 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
}
#ifndef SQLITE_OMIT_TRIGGER
case TK_RAISE: {
int vrc;
if( !pParse->pTriggerTab ){
sqlite3ErrorMsg(pParse,
"RAISE() may only be used within a trigger-program");
return 0;
}
assert( pExpr->affinity==OE_Rollback
|| pExpr->affinity==OE_Abort
|| pExpr->affinity==OE_Fail
|| pExpr->affinity==OE_Ignore
);
if( !pParse->pTriggerTab ){
sqlite3ErrorMsg(pParse,
"RAISE() may only be used within a trigger-program");
return 0;
}
if( pExpr->affinity==OE_Abort ){
sqlite3MayAbort(pParse);
}
assert( !ExprHasProperty(pExpr, EP_IntValue) );
vrc = (pExpr->affinity==OE_Ignore ? SQLITE_OK : SQLITE_CONSTRAINT);
sqlite3VdbeAddOp4(v, OP_Halt, vrc, pExpr->affinity, 0, pExpr->u.zToken,0);
if( pExpr->affinity==OE_Ignore ){
sqlite3VdbeAddOp4(
v, OP_Halt, SQLITE_OK, OE_Ignore, 0, pExpr->u.zToken,0);
}else{
sqlite3HaltConstraint(pParse, pExpr->affinity, pExpr->u.zToken, 0);
}
break;
}
#endif

View File

@ -971,6 +971,7 @@ void sqlite3Insert(
const char *pVTab = (const char *)sqlite3GetVTable(db, pTab);
sqlite3VtabMakeWritable(pParse, pTab);
sqlite3VdbeAddOp4(v, OP_VUpdate, 1, pTab->nCol+2, regIns, pVTab, P4_VTAB);
sqlite3MayAbort(pParse);
}else
#endif
{
@ -1169,8 +1170,9 @@ void sqlite3GenerateConstraintChecks(
assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail
|| onError==OE_Ignore || onError==OE_Replace );
switch( onError ){
case OE_Rollback:
case OE_Abort:
sqlite3MayAbort(pParse);
case OE_Rollback:
case OE_Fail: {
char *zMsg;
j1 = sqlite3VdbeAddOp3(v, OP_HaltIfNull,
@ -1205,7 +1207,7 @@ void sqlite3GenerateConstraintChecks(
if( onError==OE_Ignore ){
sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest);
}else{
sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_CONSTRAINT, onError);
sqlite3HaltConstraint(pParse, onError, 0, 0);
}
sqlite3VdbeResolveLabel(v, allOk);
}
@ -1236,8 +1238,8 @@ void sqlite3GenerateConstraintChecks(
case OE_Rollback:
case OE_Abort:
case OE_Fail: {
sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CONSTRAINT, onError, 0,
"PRIMARY KEY must be unique", P4_STATIC);
sqlite3HaltConstraint(
pParse, onError, "PRIMARY KEY must be unique", P4_STATIC);
break;
}
case OE_Replace: {
@ -1350,7 +1352,7 @@ void sqlite3GenerateConstraintChecks(
sqlite3StrAccumAppend(&errMsg,
pIdx->nColumn>1 ? " are not unique" : " is not unique", -1);
zErr = sqlite3StrAccumFinish(&errMsg);
sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CONSTRAINT, onError, 0, zErr, 0);
sqlite3HaltConstraint(pParse, onError, zErr, 0);
sqlite3DbFree(errMsg.db, zErr);
break;
}
@ -1747,8 +1749,8 @@ static int xferOptimization(
if( pDest->iPKey>=0 ){
addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid);
addr2 = sqlite3VdbeAddOp3(v, OP_NotExists, iDest, 0, regRowid);
sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CONSTRAINT, onError, 0,
"PRIMARY KEY must be unique", P4_STATIC);
sqlite3HaltConstraint(
pParse, onError, "PRIMARY KEY must be unique", P4_STATIC);
sqlite3VdbeJumpHere(v, addr2);
autoIncStep(pParse, regAutoinc, regRowid);
}else if( pDest->pIndex==0 ){

View File

@ -2097,6 +2097,8 @@ struct Parse {
} aColCache[SQLITE_N_COLCACHE]; /* One for each column cache entry */
u32 writeMask; /* Start a write transaction on these databases */
u32 cookieMask; /* Bitmask of schema verified databases */
u8 isMultiWrite; /* True if statement may affect/insert multiple rows */
u8 mayAbort; /* True if statement may throw an ABORT exception */
int cookieGoto; /* Address of OP_Goto to cookie verifier subroutine */
int cookieValue[SQLITE_MAX_ATTACHED+2]; /* Values of cookies to verify */
#ifndef SQLITE_OMIT_SHARED_CACHE
@ -2655,6 +2657,8 @@ void sqlite3GenerateConstraintChecks(Parse*,Table*,int,int,
void sqlite3CompleteInsertion(Parse*, Table*, int, int, int*, int, int, int);
int sqlite3OpenTableAndIndices(Parse*, Table*, int, int);
void sqlite3BeginWriteOperation(Parse*, int, int);
void sqlite3MayAbort(Parse *);
void sqlite3HaltConstraint(Parse*, int, char*, int);
Expr *sqlite3ExprDup(sqlite3*,Expr*,int);
ExprList *sqlite3ExprListDup(sqlite3*,ExprList*,int);
SrcList *sqlite3SrcListDup(sqlite3*,SrcList*,int);

View File

@ -586,6 +586,7 @@ static void updateVirtualTable(
}
sqlite3VtabMakeWritable(pParse, pTab);
sqlite3VdbeAddOp4(v, OP_VUpdate, 0, pTab->nCol+2, iReg, pVTab, P4_VTAB);
sqlite3MayAbort(pParse);
sqlite3VdbeAddOp2(v, OP_Next, ephemTab, addr+1);
sqlite3VdbeJumpHere(v, addr);
sqlite3VdbeAddOp2(v, OP_Close, ephemTab, 0);

View File

@ -2452,46 +2452,6 @@ case OP_Count: { /* out2-prerelease */
}
#endif
/* Opcode: Statement P1 * * * *
**
** Begin an individual statement transaction which is part of a larger
** transaction. This is needed so that the statement
** can be rolled back after an error without having to roll back the
** entire transaction. The statement transaction will automatically
** commit when the VDBE halts.
**
** If the database connection is currently in autocommit mode (that
** is to say, if it is in between BEGIN and COMMIT)
** and if there are no other active statements on the same database
** connection, then this operation is a no-op. No statement transaction
** is needed since any error can use the normal ROLLBACK process to
** undo changes.
**
** If a statement transaction is started, then a statement journal file
** will be allocated and initialized.
**
** The statement is begun on the database file with index P1. The main
** database file has an index of 0 and the file used for temporary tables
** has an index of 1.
*/
case OP_Statement: {
Btree *pBt;
if( db->autoCommit==0 || db->activeVdbeCnt>1 ){
assert( pOp->p1>=0 && pOp->p1<db->nDb );
assert( db->aDb[pOp->p1].pBt!=0 );
pBt = db->aDb[pOp->p1].pBt;
assert( sqlite3BtreeIsInTrans(pBt) );
assert( (p->btreeMask & (1<<pOp->p1))!=0 );
if( p->iStatement==0 ){
assert( db->nStatement>=0 && db->nSavepoint>=0 );
db->nStatement++;
p->iStatement = db->nSavepoint + db->nStatement;
}
rc = sqlite3BtreeBeginStmt(pBt, p->iStatement);
}
break;
}
/* Opcode: Savepoint P1 * * P4 *
**
** Open, release or rollback the savepoint named by parameter P4, depending
@ -2720,6 +2680,16 @@ case OP_AutoCommit: {
** database. If P2 is 2 or greater then an EXCLUSIVE lock is also obtained
** on the file.
**
** If a write-transaction is started and the Vdbe.usesStmtJournal flag is
** true (this flag is set if the Vdbe may modify more than one row and may
** throw an ABORT exception), a statement transaction may also be opened.
** More specifically, a statement transaction is opened iff the database
** connection is currently not in autocommit mode, or if there are other
** active statements. A statement transaction allows the affects of this
** VDBE to be rolled back after an error without having to roll back the
** entire transaction. If no error is encountered, the statement transaction
** will automatically commit when the VDBE halts.
**
** If P2 is zero, then a read-lock is obtained on the database file.
*/
case OP_Transaction: {
@ -2739,6 +2709,18 @@ case OP_Transaction: {
if( rc!=SQLITE_OK && rc!=SQLITE_READONLY /* && rc!=SQLITE_BUSY */ ){
goto abort_due_to_error;
}
if( pOp->p2 && p->usesStmtJournal
&& (db->autoCommit==0 || db->activeVdbeCnt>1)
){
assert( sqlite3BtreeIsInTrans(pBt) );
if( p->iStatement==0 ){
assert( db->nStatement>=0 && db->nSavepoint>=0 );
db->nStatement++;
p->iStatement = db->nSavepoint + db->nStatement;
}
rc = sqlite3BtreeBeginStmt(pBt, p->iStatement);
}
}
break;
}

View File

@ -184,7 +184,7 @@ void sqlite3VdbeUsesBtree(Vdbe*, int);
VdbeOp *sqlite3VdbeGetOp(Vdbe*, int);
int sqlite3VdbeMakeLabel(Vdbe*);
void sqlite3VdbeDelete(Vdbe*);
void sqlite3VdbeMakeReady(Vdbe*,int,int,int,int,int);
void sqlite3VdbeMakeReady(Vdbe*,int,int,int,int,int,int);
int sqlite3VdbeFinalize(Vdbe*);
void sqlite3VdbeResolveLabel(Vdbe*, int);
int sqlite3VdbeCurrentAddr(Vdbe*);

View File

@ -76,7 +76,7 @@ int sqlite3_reset(sqlite3_stmt *pStmt){
Vdbe *v = (Vdbe*)pStmt;
sqlite3_mutex_enter(v->db->mutex);
rc = sqlite3VdbeReset(v);
sqlite3VdbeMakeReady(v, -1, 0, 0, 0, 0);
sqlite3VdbeMakeReady(v, -1, 0, 0, 0, 0, 0);
assert( (rc & (v->db->errMask))==rc );
rc = sqlite3ApiExit(v->db, rc);
sqlite3_mutex_leave(v->db->mutex);

View File

@ -250,29 +250,13 @@ void sqlite3VdbeResolveLabel(Vdbe *p, int x){
** Variable *pMaxFuncArgs is set to the maximum value of any P2 argument
** to an OP_Function, OP_AggStep or OP_VFilter opcode. This is used by
** sqlite3VdbeMakeReady() to size the Vdbe.apArg[] array.
**
** This routine also does the following optimization: It scans for
** instructions that might cause a statement rollback. Such instructions
** are:
**
** * OP_Halt with P1=SQLITE_CONSTRAINT and P2=OE_Abort.
** * OP_Destroy
** * OP_VUpdate
** * OP_VRename
**
** If no such instruction is found, then every Statement instruction
** is changed to a Noop. In this way, we avoid creating the statement
** journal file unnecessarily.
*/
static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){
int i;
int nMaxArgs = *pMaxFuncArgs;
Op *pOp;
int *aLabel = p->aLabel;
int doesStatementRollback = 0;
int hasStatementBegin = 0;
p->readOnly = 1;
p->usesStmtJournal = 0;
for(pOp=p->aOp, i=p->nOp-1; i>=0; i--, pOp++){
u8 opcode = pOp->opcode;
@ -282,21 +266,9 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){
}else if( opcode==OP_VUpdate ){
if( pOp->p2>nMaxArgs ) nMaxArgs = pOp->p2;
#endif
}
if( opcode==OP_Halt ){
if( pOp->p1==SQLITE_CONSTRAINT && pOp->p2==OE_Abort ){
doesStatementRollback = 1;
}
}else if( opcode==OP_Statement ){
hasStatementBegin = 1;
p->usesStmtJournal = 1;
}else if( opcode==OP_Destroy || opcode==OP_Program ){
doesStatementRollback = 1;
}else if( opcode==OP_Transaction && pOp->p2!=0 ){
p->readOnly = 0;
#ifndef SQLITE_OMIT_VIRTUALTABLE
}else if( opcode==OP_VUpdate || opcode==OP_VRename ){
doesStatementRollback = 1;
}else if( opcode==OP_VFilter ){
int n;
assert( p->nOp - i >= 3 );
@ -315,20 +287,6 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){
p->aLabel = 0;
*pMaxFuncArgs = nMaxArgs;
/* If we never rollback a statement transaction, then statement
** transactions are not needed. So change every OP_Statement
** opcode into an OP_Noop. This avoid a call to sqlite3OsOpenExclusive()
** which can be expensive on some platforms.
*/
if( hasStatementBegin && !doesStatementRollback ){
p->usesStmtJournal = 0;
for(pOp=p->aOp, i=p->nOp-1; i>=0; i--, pOp++){
if( pOp->opcode==OP_Statement ){
pOp->opcode = OP_Noop;
}
}
}
}
/*
@ -1237,7 +1195,8 @@ void sqlite3VdbeMakeReady(
int nMem, /* Number of memory cells to allocate */
int nCursor, /* Number of cursors to allocate */
int nArg, /* Maximum number of args in SubPrograms */
int isExplain /* True if the EXPLAIN keywords is present */
int isExplain, /* True if the EXPLAIN keywords is present */
int usesStmtJournal /* True to set Vdbe.usesStmtJournal */
){
int n;
sqlite3 *db = p->db;
@ -1273,6 +1232,7 @@ void sqlite3VdbeMakeReady(
u8 *zEnd = (u8 *)&p->aOp[p->nOpAlloc];
int nByte;
resolveP2Values(p, &nArg);
p->usesStmtJournal = usesStmtJournal;
if( isExplain && nMem<10 ){
nMem = 10;
}

View File

@ -204,7 +204,7 @@ int sqlite3_blob_open(
sqlite3VdbeChangeP4(v, 3+flags, SQLITE_INT_TO_PTR(pTab->nCol+1),P4_INT32);
sqlite3VdbeChangeP2(v, 7, pTab->nCol);
if( !db->mallocFailed ){
sqlite3VdbeMakeReady(v, 1, 1, 1, 0, 0);
sqlite3VdbeMakeReady(v, 1, 1, 1, 0, 0, 0);
}
}

View File

@ -34,6 +34,9 @@ ifcapable {!trigger} {
# REPLACE conflict resolution. And that they are not fired
# if recursive triggers are not enabled.
#
# triggerC-6.*: Test that the recursive_triggers pragma returns correct
# results when invoked without an argument.
#
# Enable recursive triggers for this file.
#
@ -660,5 +663,11 @@ do_test triggerC-6.3 {
}
} {1}
#-------------------------------------------------------------------------
# Test some of the "undefined behaviour" associated with triggers. The
# undefined behaviour occurs when a row being updated or deleted is
# manipulated by a BEFORE trigger.
#
finish_test