-C Add\ssome\sextra\stests\sfor\sthe\srecent\strigger\scompilation\soptimization.\s(CVS\s4653)
-D 2008-01-02T04:41:25
+C Take\sadvantage\sof\sthe\sfact\sthat\sb-tree\scursors\sneed\snot\sbe\sclosed\swhile\sother\scursors\smodify\stheir\stables\sto\ssimplify\strigger\sprogram\sgeneration\scode.\s(CVS\s4654)
+D 2008-01-02T11:50:51
F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7
F Makefile.in 30789bf70614bad659351660d76b8e533f3340e9
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
F src/attach.c 95658e74e3e0d1cbdb8658817516d4d1467fc13d
F src/auth.c c8b2ab5c8bad4bd90ed7c294694f48269162c627
F src/btmutex.c 5d39da37c9d1282f3c6f9967afae6a34ee36b7ff
-F src/btree.c 6c3ded4f31046de72993a440921ad50a7eb4a65d
+F src/btree.c 5164b32950cfd41f2c5c31e8ff82c4a499918aef
F src/btree.h 19dcf5ad23c17b98855da548e9a8e3eb4429d5eb
F src/btreeInt.h 1c5a9da165718ef7de81e35ce9ab5d9ba9283f76
F src/build.c cbfd98ceb95c61c226cd60a845fa7967b66c8931
F src/callback.c 77b302b0d41468dcda78c70e706e5b84577f0fa0
F src/complete.c 4cf68fd75d60257524cbe74f87351b9848399131
F src/date.c 49c5a6d2de6c12000905b4d36868b07d3011bbf6
-F src/delete.c a4843531af1354882ea7dbe53fa5f46b581ae73c
+F src/delete.c e750b537a77da4971c39e3fbb569de55fe4cf095
F src/experimental.c 1b2d1a6cd62ecc39610e97670332ca073c50792b
F src/expr.c c3fb939d6801071ce19243521ca444eca40b057a
F src/func.c 996071cf0af9d967e58b69fce1909555059ebc7d
F src/hash.c 45a7005aac044b6c86bd7e49c44bc15d30006d6c
F src/hash.h 031cd9f915aff27e12262cb9eb570ac1b8326b53
-F src/insert.c 355c482603c8c5151b23c3c7661cf1044ec34d29
+F src/insert.c 1946d8c7431fc2b614a4b15155f960f999b14ba5
F src/journal.c 807bed7a158979ac8d63953e1774e8d85bff65e2
F src/legacy.c 4ac53191fad2e3c4d59bde1228879b2dc5a96d66
F src/limits.h 71ab25f17e35e0a9f3f6f234b8ed49cc56731d35
F src/test_thread.c e297dd41db0b249646e69f97d36ec13e56e8b730
F src/tokenize.c a4e04438c11fed2c67ec47fe3edbef9cca2d1b48
F src/trigger.c f8e2d42cf1782ffc14a9d7cee1d1a406f9b0c8c4
-F src/update.c fee857007be57b68a7539c26cc5563d8fbaf3f82
+F src/update.c 24ab2157d360bc20ac4447f50d3a70cd993a7d98
F src/utf.c ef4b7d83bae533b76c3e1bf635b113fdad86a736
F src/util.c 05f31144bbd3f1a24f4139ae029c42545cb72624
F src/vacuum.c 25ffbd766f25bca099ead1c1e11f5528c86102b8
F src/vdbe.h a042e6d3b567ac81f182ca5b4639807621355822
F src/vdbeInt.h 2985f1369273e635898cf5952237efcb3fdb21f3
F src/vdbeapi.c 4acfaab3e10c99eb66c5332979d7b14a1c3505ae
-F src/vdbeaux.c bca64691ad6bb11e45b5ccf494d9f088d23b3575
+F src/vdbeaux.c 9c2ce05e86502ac3dd148ed13535886e82678e04
F src/vdbeblob.c 82f51cdf9b0c0af729732fde48c824e498c0a1ca
F src/vdbefifo.c 334c838c8f42d61a94813d136019ee566b5dc2f6
F src/vdbemem.c 123994fcd344993d2fb050a83b91b341bbbd08b4
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
-P 051ec01f2799e095516015f2ef0180e50fac387c
-R b1162a1e7d20a24c20501e40bc7dde0f
+P de54dad800f0b62740ad4ebb3780464b44eb6dff
+R a86b5c6a0f11cd9be312d89f90e2feb5
U danielk1977
-Z 75dbf0acf2e3e5d3feebf07dfd171fca
+Z 5595cb26a9237dd9d189ded057a3e630
-de54dad800f0b62740ad4ebb3780464b44eb6dff
\ No newline at end of file
+f1966a8a47fca85f7862c0797a527ab01ac8b0c1
\ No newline at end of file
** May you share freely, never taking more than you give.
**
*************************************************************************
-** $Id: btree.c,v 1.435 2008/01/01 06:19:02 danielk1977 Exp $
+** $Id: btree.c,v 1.436 2008/01/02 11:50:51 danielk1977 Exp $
**
** This file implements a external (disk-based) database using BTrees.
** See the header comment on "btreeInt.h" for additional information.
/* TODO: What about CURSOR_REQUIRESEEK state? Probably need to call
** restoreOrClearCursorPosition() here.
*/
- MemPage *pPage = pCur->pPage;
+ MemPage *pPage;
+ restoreOrClearCursorPosition(pCur);
+ pPage = pCur->pPage;
assert( cursorHoldsMutex(pCur) );
assert( pPage->pBt==pCur->pBt );
return pPage ? pPage->aData[pPage->hdrOffset] : 0;
** This file contains C code routines that are called by the parser
** in order to generate code for DELETE FROM statements.
**
-** $Id: delete.c,v 1.136 2008/01/02 00:34:37 drh Exp $
+** $Id: delete.c,v 1.137 2008/01/02 11:50:51 danielk1977 Exp $
*/
#include "sqliteInt.h"
*/
assert( pTabList->nSrc==1 );
iCur = pTabList->a[0].iCursor = pParse->nTab++;
+ for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
+ pParse->nTab++;
+ }
memset(&sNC, 0, sizeof(sNC));
sNC.pParse = pParse;
sNC.pSrcList = pTabList;
*/
end = sqlite3VdbeMakeLabel(v);
- /* This is the beginning of the delete loop when there are
- ** row triggers.
+ if( !isView ){
+ /* Open cursors for the table we are deleting from and
+ ** all its indices.
+ */
+ sqlite3OpenTableAndIndices(pParse, pTab, iCur, OP_OpenWrite);
+ }
+
+ /* This is the beginning of the delete loop. If a trigger encounters
+ ** an IGNORE constraint, it jumps back to here.
*/
if( triggers_exist ){
- int mem1 = pParse->nMem++;
- int addr_rowdata;
- u32 mask;
sqlite3VdbeResolveLabel(v, addr);
- addr = sqlite3VdbeAddOp(v, OP_FifoRead, 0, end);
- sqlite3VdbeAddOp(v, OP_StackDepth, -1, 0);
- sqlite3VdbeAddOp(v, OP_MemStore, mem1, 0);
+ }
+ addr = sqlite3VdbeAddOp(v, OP_FifoRead, 0, end);
+ sqlite3VdbeAddOp(v, OP_StackDepth, -1, 0);
+
+ if( triggers_exist ){
+ int mem1 = pParse->nMem++;
if( !isView ){
- sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenRead);
+ sqlite3VdbeAddOp(v, OP_MemStore, mem1, 0);
}
sqlite3VdbeAddOp(v, OP_NotExists, iCur, addr);
sqlite3VdbeAddOp(v, OP_Rowid, iCur, 0);
}
if( !isView ){
- /* Open cursors for the table we are deleting from and all its
- ** indices. If there are row triggers, this happens inside the
- ** OP_FifoRead loop because the cursor have to all be closed
- ** before the trigger fires. If there are no row triggers, the
- ** cursors are opened only once on the outside the loop.
- */
- sqlite3OpenTableAndIndices(pParse, pTab, iCur, OP_OpenWrite);
-
- /* This is the beginning of the delete loop when there are no
- ** row triggers */
- if( !triggers_exist ){
- addr = sqlite3VdbeAddOp(v, OP_FifoRead, 0, end);
- sqlite3VdbeAddOp(v, OP_StackDepth, -1, 0);
- }
-
/* Delete the row */
#ifndef SQLITE_OMIT_VIRTUALTABLE
if( IsVirtual(pTab) ){
** the AFTER triggers
*/
if( triggers_exist ){
- if( !isView ){
- for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
- sqlite3VdbeAddOp(v, OP_Close, iCur + i, pIdx->tnum);
- }
- sqlite3VdbeAddOp(v, OP_Close, iCur, 0);
- }
-
/* Jump back and run the AFTER triggers */
sqlite3VdbeAddOp(v, OP_Goto, 0, iBeginAfterTrigger);
sqlite3VdbeJumpHere(v, iEndAfterTrigger);
sqlite3VdbeResolveLabel(v, end);
/* Close the cursors after the loop if there are no row triggers */
- if( !triggers_exist && !IsVirtual(pTab) ){
+ if( !isView && !IsVirtual(pTab) ){
for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
sqlite3VdbeAddOp(v, OP_Close, iCur + i, pIdx->tnum);
}
** This file contains C code routines that are called by the parser
** to handle INSERT statements in SQLite.
**
-** $Id: insert.c,v 1.199 2008/01/02 00:34:37 drh Exp $
+** $Id: insert.c,v 1.200 2008/01/02 11:50:51 danielk1977 Exp $
*/
#include "sqliteInt.h"
sqlite3VdbeAddOp(v, OP_MemInt, 0, iCntMem);
}
- /* Open tables and indices if there are no row triggers */
- if( !triggers_exist ){
+ /* If this is not a view, open the table and and all indices */
+ if( !isView ){
base = pParse->nTab;
sqlite3OpenTableAndIndices(pParse, pTab, base, OP_OpenWrite);
}
}
}
- /* If any triggers exists, the opening of tables and indices is deferred
- ** until now.
- */
- if( triggers_exist && !isView ){
- base = pParse->nTab;
- sqlite3OpenTableAndIndices(pParse, pTab, base, OP_OpenWrite);
- }
-
/* Push the record number for the new entry onto the stack. The
** record number is a randomly generate integer created by NewRowid
** except when the table has an INTEGER PRIMARY KEY column, in which
}
if( triggers_exist ){
- /* Close all tables opened */
- if( !isView ){
- sqlite3VdbeAddOp(v, OP_Close, base, 0);
- for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){
- sqlite3VdbeAddOp(v, OP_Close, idx+base, 0);
- }
- }
-
/* Code AFTER triggers */
if( sqlite3CodeRowTrigger(pParse, TK_INSERT, 0, TRIGGER_AFTER, pTab,
newIdx, -1, onError, endOfLoop, 0, 0) ){
sqlite3VdbeResolveLabel(v, iCleanup);
}
- if( !triggers_exist && !IsVirtual(pTab) ){
+ if( !IsVirtual(pTab) && !isView ){
/* Close all tables opened */
sqlite3VdbeAddOp(v, OP_Close, base, 0);
for(idx=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, idx++){
** This file contains C code routines that are called by the parser
** to handle UPDATE statements.
**
-** $Id: update.c,v 1.146 2008/01/02 00:34:37 drh Exp $
+** $Id: update.c,v 1.147 2008/01/02 11:50:51 danielk1977 Exp $
*/
#include "sqliteInt.h"
/* Generate the code for triggers.
*/
if( triggers_exist ){
- int iGoto = sqlite3VdbeAddOp(v, OP_Goto, 0, 0);
+ int iGoto;
+
+ /* Create pseudo-tables for NEW and OLD
+ */
+ sqlite3VdbeAddOp(v, OP_OpenPseudo, oldIdx, 0);
+ sqlite3VdbeAddOp(v, OP_SetNumColumns, oldIdx, pTab->nCol);
+ sqlite3VdbeAddOp(v, OP_OpenPseudo, newIdx, 0);
+ sqlite3VdbeAddOp(v, OP_SetNumColumns, newIdx, pTab->nCol);
+
+ iGoto = sqlite3VdbeAddOp(v, OP_Goto, 0, 0);
addr = sqlite3VdbeMakeLabel(v);
iBeginBeforeTrigger = sqlite3VdbeCurrentAddr(v);
if( sqlite3CodeRowTrigger(pParse, TK_UPDATE, pChanges, TRIGGER_BEFORE, pTab,
sqlite3VdbeAddOp(v, OP_MemInt, 0, memCnt);
}
- if( triggers_exist ){
- /* Create pseudo-tables for NEW and OLD
+ if( !isView && !IsVirtual(pTab) ){
+ /*
+ ** Open every index that needs updating. Note that if any
+ ** index could potentially invoke a REPLACE conflict resolution
+ ** action, then we need to open all indices because we might need
+ ** to be deleting some records.
*/
- sqlite3VdbeAddOp(v, OP_OpenPseudo, oldIdx, 0);
- sqlite3VdbeAddOp(v, OP_SetNumColumns, oldIdx, pTab->nCol);
- sqlite3VdbeAddOp(v, OP_OpenPseudo, newIdx, 0);
- sqlite3VdbeAddOp(v, OP_SetNumColumns, newIdx, pTab->nCol);
+ sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenWrite);
+ if( onError==OE_Replace ){
+ openAll = 1;
+ }else{
+ openAll = 0;
+ for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
+ if( pIdx->onError==OE_Replace ){
+ openAll = 1;
+ break;
+ }
+ }
+ }
+ for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
+ if( openAll || aIdxUsed[i] ){
+ KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx);
+ sqlite3VdbeAddOp(v, OP_Integer, iDb, 0);
+ sqlite3VdbeOp3(v, OP_OpenWrite, iCur+i+1, pIdx->tnum,
+ (char*)pKey, P3_KEYINFO_HANDOFF);
+ assert( pParse->nTab>iCur+i+1 );
+ }
+ }
- /* The top of the update loop for when there are triggers.
- */
+ }
+
+ /* Jump back to this point if a trigger encounters an IGNORE constraint. */
+ if( triggers_exist ){
sqlite3VdbeResolveLabel(v, addr);
- addr = sqlite3VdbeAddOp(v, OP_FifoRead, 0, 0);
- sqlite3VdbeAddOp(v, OP_StackDepth, -1, 0);
- sqlite3VdbeAddOp(v, OP_MemStore, mem1, 0);
-
- if( !isView ){
- /* Open a cursor and make it point to the record that is
- ** being updated.
- */
- sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenRead);
- }
+ }
+
+ /* Top of the update loop */
+ addr = sqlite3VdbeAddOp(v, OP_FifoRead, 0, 0);
+ sqlite3VdbeAddOp(v, OP_StackDepth, -1, 0);
+ sqlite3VdbeAddOp(v, OP_MemStore, mem1, 0);
+
+ if( triggers_exist ){
+ /* Make cursor iCur point to the record that is being updated.
+ */
sqlite3VdbeAddOp(v, OP_NotExists, iCur, addr);
/* Generate the OLD table
}
if( pParse->nErr ) goto update_cleanup;
sqlite3VdbeAddOp(v, OP_Insert, newIdx, 0);
- if( !isView ){
- sqlite3VdbeAddOp(v, OP_Close, iCur, 0);
- }
sqlite3VdbeAddOp(v, OP_Goto, 0, iBeginBeforeTrigger);
sqlite3VdbeJumpHere(v, iEndBeforeTrigger);
}
if( !isView && !IsVirtual(pTab) ){
- /*
- ** Open every index that needs updating. Note that if any
- ** index could potentially invoke a REPLACE conflict resolution
- ** action, then we need to open all indices because we might need
- ** to be deleting some records.
- */
- sqlite3OpenTable(pParse, iCur, iDb, pTab, OP_OpenWrite);
- if( onError==OE_Replace ){
- openAll = 1;
- }else{
- openAll = 0;
- for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
- if( pIdx->onError==OE_Replace ){
- openAll = 1;
- break;
- }
- }
- }
- for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
- if( openAll || aIdxUsed[i] ){
- KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx);
- sqlite3VdbeAddOp(v, OP_Integer, iDb, 0);
- sqlite3VdbeOp3(v, OP_OpenWrite, iCur+i+1, pIdx->tnum,
- (char*)pKey, P3_KEYINFO_HANDOFF);
- assert( pParse->nTab>iCur+i+1 );
- }
- }
/* Loop over every record that needs updating. We have to load
** the old data for each record to be updated because some columns
** Also, the old data is needed to delete the old index entries.
** So make the cursor point at the old record.
*/
- if( !triggers_exist ){
- addr = sqlite3VdbeAddOp(v, OP_FifoRead, 0, 0);
- sqlite3VdbeAddOp(v, OP_StackDepth, -1, 0);
- sqlite3VdbeAddOp(v, OP_MemStore, mem1, 0);
- }
sqlite3VdbeAddOp(v, OP_NotExists, iCur, addr);
sqlite3VdbeAddOp(v, OP_MemLoad, mem1, 0);
** through the loop. The fire the after triggers.
*/
if( triggers_exist ){
- if( !isView ){
- for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
- if( openAll || aIdxUsed[i] )
- sqlite3VdbeAddOp(v, OP_Close, iCur+i+1, 0);
- }
- sqlite3VdbeAddOp(v, OP_Close, iCur, 0);
- }
sqlite3VdbeAddOp(v, OP_Goto, 0, iBeginAfterTrigger);
sqlite3VdbeJumpHere(v, iEndAfterTrigger);
}
sqlite3VdbeAddOp(v, OP_Goto, 0, addr);
sqlite3VdbeJumpHere(v, addr);
- /* Close all tables if there were no FOR EACH ROW triggers */
- if( !triggers_exist ){
- for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
- if( openAll || aIdxUsed[i] ){
- sqlite3VdbeAddOp(v, OP_Close, iCur+i+1, 0);
- }
+ /* Close all tables */
+ for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
+ if( openAll || aIdxUsed[i] ){
+ sqlite3VdbeAddOp(v, OP_Close, iCur+i+1, 0);
}
- sqlite3VdbeAddOp(v, OP_Close, iCur, 0);
- }else{
+ }
+ sqlite3VdbeAddOp(v, OP_Close, iCur, 0);
+ if( triggers_exist ){
sqlite3VdbeAddOp(v, OP_Close, newIdx, 0);
sqlite3VdbeAddOp(v, OP_Close, oldIdx, 0);
}
}
}
assert( zP3!=0 );
+#ifdef SQLITE_DEBUG
if( pOp->zComment && zP3==zTemp && (nP3 = strlen(zP3))<nTemp ){
sqlite3_snprintf(nTemp-nP3, &zP3[nP3], "%s# %s",
nP3>0 ? " " : "", pOp->zComment);
}
+#endif
return zP3;
}
#endif