diff --git a/manifest b/manifest index 2d6c790f7c..ce9b7c0d87 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -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 @@ -83,20 +83,20 @@ F src/analyze.c cb25936f0148ee65c825a49f8064292a98050a50 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 @@ -164,7 +164,7 @@ F src/test_tclvar.c b2d1115e4d489179d3f029e765211b2ad527ba59 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 @@ -172,7 +172,7 @@ F src/vdbe.c 56a6e80d3357622305cffe6ea509e5d643e7dadb 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 @@ -603,7 +603,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130 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 diff --git a/manifest.uuid b/manifest.uuid index 9d5e3c6aef..f54999a4f8 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -de54dad800f0b62740ad4ebb3780464b44eb6dff \ No newline at end of file +f1966a8a47fca85f7862c0797a527ab01ac8b0c1 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 4590bdde5b..7734de4e3b 100644 --- a/src/btree.c +++ b/src/btree.c @@ -9,7 +9,7 @@ ** 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. @@ -6229,7 +6229,9 @@ int sqlite3BtreeFlags(BtCursor *pCur){ /* 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; diff --git a/src/delete.c b/src/delete.c index f2a63d51f7..6dd0902e05 100644 --- a/src/delete.c +++ b/src/delete.c @@ -12,7 +12,7 @@ ** 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" @@ -175,6 +175,9 @@ void sqlite3DeleteFrom( */ 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; @@ -293,19 +296,26 @@ void sqlite3DeleteFrom( */ 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); @@ -329,21 +339,6 @@ void sqlite3DeleteFrom( } 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) ){ @@ -360,13 +355,6 @@ void sqlite3DeleteFrom( ** 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); @@ -377,7 +365,7 @@ void sqlite3DeleteFrom( 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); } diff --git a/src/insert.c b/src/insert.c index 6e3440deaa..26eb7a28cb 100644 --- a/src/insert.c +++ b/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.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" @@ -625,8 +625,8 @@ void sqlite3Insert( 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); } @@ -713,14 +713,6 @@ void sqlite3Insert( } } - /* 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 @@ -827,14 +819,6 @@ void sqlite3Insert( } 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) ){ @@ -855,7 +839,7 @@ void sqlite3Insert( 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++){ diff --git a/src/update.c b/src/update.c index 0edc861b44..7c6017a7ef 100644 --- a/src/update.c +++ b/src/update.c @@ -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.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" @@ -298,7 +298,16 @@ void sqlite3Update( /* 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, @@ -347,27 +356,50 @@ void sqlite3Update( 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); - - /* The top of the update loop for when there are triggers. - */ - 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); + 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 ); + } + } + + } + + /* Jump back to this point if a trigger encounters an IGNORE constraint. */ + if( triggers_exist ){ + sqlite3VdbeResolveLabel(v, addr); + } + + /* 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 @@ -410,9 +442,6 @@ void sqlite3Update( } 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); @@ -423,33 +452,6 @@ void sqlite3Update( } 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 @@ -457,11 +459,6 @@ void sqlite3Update( ** 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); @@ -520,13 +517,6 @@ void sqlite3Update( ** 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); } @@ -537,15 +527,14 @@ void sqlite3Update( 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); } diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 69d1612a75..fbcb881b01 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -701,10 +701,12 @@ static char *displayP3(Op *pOp, char *zTemp, int nTemp){ } } assert( zP3!=0 ); +#ifdef SQLITE_DEBUG if( pOp->zComment && zP3==zTemp && (nP3 = strlen(zP3))0 ? " " : "", pOp->zComment); } +#endif return zP3; } #endif