From: danielk1977 Date: Tue, 25 Mar 2008 09:47:35 +0000 (+0000) Subject: Use a vdbe memory cell to allocate the space required for vdbe cursors. (CVS 4912) X-Git-Tag: version-3.6.10~1265 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=cd3e8f7ce94b2c87ceeeb3da3e2344e1397ec2ab;p=thirdparty%2Fsqlite.git Use a vdbe memory cell to allocate the space required for vdbe cursors. (CVS 4912) FossilOrigin-Name: 047153648155654b0cd70b811935209d2e21776c --- diff --git a/manifest b/manifest index 5e186a34f1..70cbfeb320 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Removed\sthe\sdirect\sbtree\stests\s-\spart\sof\sthe\songoing\seffort\sto\stest\sby\ncalling\sonly\spublic\sinterfaces.\s\sModify\sthe\ssqlite3VdbeRecordCompare\ninterface\sto\sused\sa\spre-parsed\ssecond\skey\s-\sresulting\sin\sa\s13%\nperformance\simprovement\son\sspeed1p.test.\s(CVS\s4911) -D 2008-03-25T00:22:21 +C Use\sa\svdbe\smemory\scell\sto\sallocate\sthe\sspace\srequired\sfor\svdbe\scursors.\s(CVS\s4912) +D 2008-03-25T09:47:35 F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7 F Makefile.in cf434ce8ca902e69126ae0f94fc9f7dc7428a5fa F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 @@ -81,26 +81,26 @@ F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc F sqlite3.def a1be7b9a4b8b51ac41c6ff6e8e44a14ef66b338b F sqlite3.pc.in 32b8a014799c2028c8e0c9cc5659718262fc493f F src/alter.c b42d782906fc3b92c331efbe06e9389617b47ce7 -F src/analyze.c a78ac494668581fe7f54ee63700815bb0ea34261 +F src/analyze.c 9ee63497ee720728abe630d169ab91323ac7519c F src/attach.c bdc75e759ca25a16f4dc7fbdbc6d37ad2561bb24 F src/auth.c c8b2ab5c8bad4bd90ed7c294694f48269162c627 F src/bitvec.c 49817d442e51e4123585f3cf3c2afc293a3c91e2 F src/btmutex.c 483ced3c52205b04b97df69161fadbf87f4f1ea2 -F src/btree.c 984962aa403be49d79784f01cc9887d16cd841ed -F src/btree.h ca065a5910e6dd3b91b88ff9d729450a8b8eda1f +F src/btree.c 5e3f25567d0d7228d151620637c3df9243ab324e +F src/btree.h e02869e1e7753ad5b3c7cb7852e952c95c2e609a F src/btreeInt.h c2deca3e778e2a1e6196343b8087a868f4faa19a -F src/build.c 31ed5af4e8ac40c30bb0f88d7fec75e72cc16e0e +F src/build.c d0715b3454b140cb405412e3029ec7c0fb434efd F src/callback.c 77b302b0d41468dcda78c70e706e5b84577f0fa0 F src/complete.c 4cf68fd75d60257524cbe74f87351b9848399131 F src/date.c e41ce4513fb0e359dc678d6bddb4ace135fe365d -F src/delete.c 217cd5559e00bb135dc626d4ea4ac713604729e8 +F src/delete.c 526b783b71b9885b201d74720d44a386b971dc01 F src/experimental.c 1b2d1a6cd62ecc39610e97670332ca073c50792b -F src/expr.c 8758d120f03f5856b594724732e42497efe00731 +F src/expr.c 7e56d2a24af8137f4bebbfa1d7dd1dcf70107c88 F src/fault.c c28478c7190daef16be09d261c5461638b4d686c F src/func.c c9e8c7ff4c45027edee89bde7adbf86a3a3b2afe F src/hash.c 53655c312280211444bfe23af6490a460aec2980 F src/hash.h 031cd9f915aff27e12262cb9eb570ac1b8326b53 -F src/insert.c 358c80592c20a61a8d5b4a127215b5e25de652f4 +F src/insert.c c491fbd4f852f0ba82e26b4aad279b2611c51e94 F src/journal.c 807bed7a158979ac8d63953e1774e8d85bff65e2 F src/legacy.c 8267890e6a0a71f13b680794520999c642299081 F src/loadext.c f26b22f7c84153c9d5dbd7c240848823c6e6b6dc @@ -132,10 +132,10 @@ F src/pager.c 22241b59c80ca083a96816df434adb8c097afcd4 F src/pager.h b1e2258f03878c14b06a95bfa362e8c5c9638170 F src/parse.y b0ee84d94218046ea88c2a6561005710d127ca7d F src/pragma.c f64eed914518c28d1863356163dea1e6f58e28f2 -F src/prepare.c f7fc2eb7418dcaa63e22b66c5ecf478e658ecd8f +F src/prepare.c 185fb47f1fb3e45a345d523eb391d673f5eb367c F src/printf.c 05d2b44d7b5b80c8a4a09108ddad9c20e254370d F src/random.c 2b2db2de4ab491f5a14d3480466f8f4b5a5db74a -F src/select.c 35063b078beafe9aa35344a8ce039210920d7fea +F src/select.c c06849a0d0ad408fbdd8180439176e94aae43e56 F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96 F src/shell.c 22297fffa6f00a6c6d44020fa13b1184a1bb372d F src/sqlite.h.in 61d8d1cefcbf0803c03c2179be138a78bfd1d335 @@ -146,7 +146,7 @@ F src/table.c 2c48c575dd59b3a6c5c306bc55f51a9402cf429a F src/tclsqlite.c d42912617d4734b8f9195416badf5b27e512ded2 F src/test1.c 342a2628310fa709074d979e695a28a3bb570834 F src/test2.c f0808cc643528b9620e4059ca9bda8346f526121 -F src/test3.c 9bf750645412effca0b2567b8b833e1e91377b47 +F src/test3.c 31027a4a190d2f3c1e479ea2d750e696160bbf04 F src/test4.c c2c0f5dc907f1346f5d4b65eb5799f11eb9e4071 F src/test5.c 3a6a5717a149d7ca2e6d14f5be72cf7555d54dc4 F src/test6.c 62281c0a9ac0265e579065942f7de4e080f8eb05 @@ -161,7 +161,7 @@ F src/test_devsym.c cee1aecaa90c895030399ca4ae38f84a08038f8a F src/test_func.c 9e9b33ff083b65da91c389cece903bc32de06f01 F src/test_hexio.c 1a1cd8324d57585ea86b922f609fa1fbaaf9662d F src/test_loadext.c 22065d601a18878e5542191001f0eaa5d77c0ed8 -F src/test_malloc.c 52d8d7003c0b2183fd67de45c8b64ee7eb2656ea +F src/test_malloc.c eedcc63c9f3111f2ebf6137b117e5644b3bb4c5d F src/test_md5.c bca40b727c57462ddb415e57c5323445a1bb1a40 F src/test_onefile.c 2fea6d22f13f5f286356c80c77ffd41f995f2b7a F src/test_schema.c 12c9de7661d6294eec2d57afbb52e2af1128084f @@ -170,20 +170,20 @@ F src/test_tclvar.c b2d1115e4d489179d3f029e765211b2ad527ba59 F src/test_thread.c e297dd41db0b249646e69f97d36ec13e56e8b730 F src/tokenize.c 13113f94bd1c15dea9e922f08b10f3eee6863474 F src/trigger.c 9bd3b6fa0beff4a02d262c96466f752ec15a7fc3 -F src/update.c d2c59643af98f966c2a04d392463089b715ca18f +F src/update.c 2aefd3c9277792e9fa2414dfe14202119fa49fe7 F src/utf.c 32b00d6e19010025e58f2ecb2f921d5e126771b4 F src/util.c dba9e04121eb17ec4643d6ca231ff859452cf0e2 F src/vacuum.c 3524411bfb58aac0d87eadd3e5b7cd532772af30 -F src/vdbe.c d81771c67e67f9a25af1d53e5c22299becef1322 +F src/vdbe.c bdcbf54cf944a99b004e87a523736dd326fa34be F src/vdbe.h 0fef6798be121ed2b5a547a5cb85e0824ec3971f F src/vdbeInt.h 4bbec80d55d179ab8438ac9822416d9111638919 F src/vdbeapi.c b9e9d7a58690c1e1ae66de7232edccf4793ad817 -F src/vdbeaux.c f3ee532bfdf191f0d2a8c4d1a50816cdd1a235d2 -F src/vdbeblob.c 63c750acc7b5012479f508c0e9627372a82cb65d +F src/vdbeaux.c c071014d81c1d4b2c381247c16a3e86182951e51 +F src/vdbeblob.c cc713c142c3d4952b380c98ee035f850830ddbdb F src/vdbefifo.c a30c237b2a3577e1415fb6e288cbb6b8ed1e5736 F src/vdbemem.c 67662aac917b627356262f9501591206db2a8845 F src/vtab.c 00cd16317b29495c185ff40e4b227917d5a371b2 -F src/where.c 78d6689d7154d8d41c1a913e17bce9a320981653 +F src/where.c f18bac2f87c965811727be1be05deeaf5229fcd0 F tclinstaller.tcl 4356d9d94d2b5ed5e68f9f0c80c4df3048dd7617 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 F test/all.test d12210212bada2bde6d5aeb90969b86c1aa977d2 @@ -617,7 +617,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5 -P 1ed695f560a58786f2a8467c601f281c67034fd4 -R 4b7a149e165aca7212e2405c0ae3196c -U drh -Z f27434cb523b0af2e9a84163450beba5 +P 0e1d84f2f456e7680bb667266745b629ddf3605f +R 284330e7bdf139254e19bec086a6e3bc +U danielk1977 +Z a0d2b0847845caa52b53bf4be4058830 diff --git a/manifest.uuid b/manifest.uuid index da0b9c2f08..e56b6809b9 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -0e1d84f2f456e7680bb667266745b629ddf3605f \ No newline at end of file +047153648155654b0cd70b811935209d2e21776c \ No newline at end of file diff --git a/src/analyze.c b/src/analyze.c index 4168fe669b..aeb9972745 100644 --- a/src/analyze.c +++ b/src/analyze.c @@ -11,7 +11,7 @@ ************************************************************************* ** This file contains code associated with the ANALYZE command. ** -** @(#) $Id: analyze.c,v 1.41 2008/01/25 15:04:49 drh Exp $ +** @(#) $Id: analyze.c,v 1.42 2008/03/25 09:47:35 danielk1977 Exp $ */ #ifndef SQLITE_OMIT_ANALYZE #include "sqliteInt.h" @@ -74,9 +74,9 @@ static void openStatTable( if( !createStat1 ){ sqlite3TableLock(pParse, iDb, iRootPage, 1, "sqlite_stat1"); } + sqlite3VdbeAddOp2(v, OP_SetNumColumns, 0, 3); sqlite3VdbeAddOp3(v, OP_OpenWrite, iStatCur, iRootPage, iDb); sqlite3VdbeChangeP5(v, createStat1); - sqlite3VdbeAddOp2(v, OP_SetNumColumns, iStatCur, 3); } /* @@ -130,17 +130,17 @@ static void analyzeOneTable( /* Open a cursor to the index to be analyzed */ assert( iDb==sqlite3SchemaToIndex(pParse->db, pIdx->pSchema) ); + nCol = pIdx->nColumn; + sqlite3VdbeAddOp2(v, OP_SetNumColumns, 0, nCol+1); sqlite3VdbeAddOp4(v, OP_OpenRead, iIdxCur, pIdx->tnum, iDb, (char *)pKey, P4_KEYINFO_HANDOFF); VdbeComment((v, "%s", pIdx->zName)); - nCol = pIdx->nColumn; regFields = iMem+nCol*2; regTemp = regRowid = regCol = regFields+3; regRec = regCol+1; if( regRec>pParse->nMem ){ pParse->nMem = regRec; } - sqlite3VdbeAddOp2(v, OP_SetNumColumns, iIdxCur, nCol+1); /* Memory cells are used as follows: ** diff --git a/src/btree.c b/src/btree.c index 38aa3474e3..869e4e9371 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.443 2008/03/25 00:22:21 drh Exp $ +** $Id: btree.c,v 1.444 2008/03/25 09:47:35 danielk1977 Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** See the header comment on "btreeInt.h" for additional information. @@ -2677,18 +2677,16 @@ int sqlite3BtreeRollbackStmt(Btree *p){ ** will not work correctly. */ static int btreeCursor( - Btree *p, /* The btree */ - int iTable, /* Root page of table to open */ - int wrFlag, /* 1 to write. 0 read-only */ - struct KeyInfo *pKeyInfo, /* First arg to comparison function */ - BtCursor **ppCur /* Write new cursor here */ + Btree *p, /* The btree */ + int iTable, /* Root page of table to open */ + int wrFlag, /* 1 to write. 0 read-only */ + struct KeyInfo *pKeyInfo, /* First arg to comparison function */ + BtCursor *pCur /* Space for new cursor */ ){ int rc; - BtCursor *pCur; BtShared *pBt = p->pBt; assert( sqlite3BtreeHoldsMutex(p) ); - *ppCur = 0; if( wrFlag ){ if( pBt->readOnly ){ return SQLITE_READONLY; @@ -2707,11 +2705,6 @@ static int btreeCursor( return SQLITE_READONLY; } } - pCur = sqlite3MallocZero( sizeof(*pCur) ); - if( pCur==0 ){ - rc = SQLITE_NOMEM; - goto create_cursor_exception; - } pCur->pgnoRoot = (Pgno)iTable; if( iTable==1 && sqlite3PagerPagecount(pBt->pPager)==0 ){ rc = SQLITE_EMPTY; @@ -2736,32 +2729,34 @@ static int btreeCursor( } pBt->pCursor = pCur; pCur->eState = CURSOR_INVALID; - *ppCur = pCur; return SQLITE_OK; create_cursor_exception: if( pCur ){ releasePage(pCur->pPage); - sqlite3_free(pCur); } unlockBtreeIfUnused(pBt); return rc; } int sqlite3BtreeCursor( - Btree *p, /* The btree */ - int iTable, /* Root page of table to open */ - int wrFlag, /* 1 to write. 0 read-only */ - struct KeyInfo *pKeyInfo, /* First arg to xCompare() */ - BtCursor **ppCur /* Write new cursor here */ + Btree *p, /* The btree */ + int iTable, /* Root page of table to open */ + int wrFlag, /* 1 to write. 0 read-only */ + struct KeyInfo *pKeyInfo, /* First arg to xCompare() */ + BtCursor *pCur /* Write new cursor here */ ){ int rc; sqlite3BtreeEnter(p); p->pBt->db = p->db; - rc = btreeCursor(p, iTable, wrFlag, pKeyInfo, ppCur); + rc = btreeCursor(p, iTable, wrFlag, pKeyInfo, pCur); sqlite3BtreeLeave(p); return rc; } +int sqlite3BtreeCursorSize(){ + return sizeof(BtCursor); +} + /* @@ -2769,25 +2764,26 @@ int sqlite3BtreeCursor( ** when the last cursor is closed. */ int sqlite3BtreeCloseCursor(BtCursor *pCur){ - BtShared *pBt = pCur->pBt; Btree *pBtree = pCur->pBtree; - - sqlite3BtreeEnter(pBtree); - pBt->db = pBtree->db; - clearCursorPosition(pCur); - if( pCur->pPrev ){ - pCur->pPrev->pNext = pCur->pNext; - }else{ - pBt->pCursor = pCur->pNext; - } - if( pCur->pNext ){ - pCur->pNext->pPrev = pCur->pPrev; + if( pBtree ){ + BtShared *pBt = pCur->pBt; + sqlite3BtreeEnter(pBtree); + pBt->db = pBtree->db; + clearCursorPosition(pCur); + if( pCur->pPrev ){ + pCur->pPrev->pNext = pCur->pNext; + }else{ + pBt->pCursor = pCur->pNext; + } + if( pCur->pNext ){ + pCur->pNext->pPrev = pCur->pPrev; + } + releasePage(pCur->pPage); + unlockBtreeIfUnused(pBt); + invalidateOverflowCache(pCur); + /* sqlite3_free(pCur); */ + sqlite3BtreeLeave(pBtree); } - releasePage(pCur->pPage); - unlockBtreeIfUnused(pBt); - invalidateOverflowCache(pCur); - sqlite3_free(pCur); - sqlite3BtreeLeave(pBtree); return SQLITE_OK; } diff --git a/src/btree.h b/src/btree.h index 51d0b7717c..97298da0e5 100644 --- a/src/btree.h +++ b/src/btree.h @@ -13,7 +13,7 @@ ** subsystem. See comments in the source code for a detailed description ** of what each interface routine does. ** -** @(#) $Id: btree.h,v 1.95 2008/03/25 00:22:21 drh Exp $ +** @(#) $Id: btree.h,v 1.96 2008/03/25 09:47:35 danielk1977 Exp $ */ #ifndef _BTREE_H_ #define _BTREE_H_ @@ -128,12 +128,13 @@ int sqlite3BtreeUpdateMeta(Btree*, int idx, u32 value); void sqlite3BtreeTripAllCursors(Btree*, int); int sqlite3BtreeCursor( - Btree*, /* BTree containing table to open */ - int iTable, /* Index of root page */ - int wrFlag, /* 1 for writing. 0 for read-only */ - struct KeyInfo*, /* First argument to compare function */ - BtCursor **ppCursor /* Returned cursor */ + Btree*, /* BTree containing table to open */ + int iTable, /* Index of root page */ + int wrFlag, /* 1 for writing. 0 for read-only */ + struct KeyInfo*, /* First argument to compare function */ + BtCursor *pCursor /* Space to write cursor structure */ ); +int sqlite3BtreeCursorSize(); int sqlite3BtreeCloseCursor(BtCursor*); int sqlite3BtreeMoveto(BtCursor*,const void *pKey,i64 nKey,int bias,int *pRes); diff --git a/src/build.c b/src/build.c index edf4337033..6b247901fd 100644 --- a/src/build.c +++ b/src/build.c @@ -22,7 +22,7 @@ ** COMMIT ** ROLLBACK ** -** $Id: build.c,v 1.475 2008/03/20 14:03:29 drh Exp $ +** $Id: build.c,v 1.476 2008/03/25 09:47:35 danielk1977 Exp $ */ #include "sqliteInt.h" #include @@ -608,8 +608,8 @@ char *sqlite3NameFromToken(sqlite3 *db, Token *pName){ void sqlite3OpenMasterTable(Parse *p, int iDb){ Vdbe *v = sqlite3GetVdbe(p); sqlite3TableLock(p, iDb, MASTER_ROOT, 1, SCHEMA_TABLE(iDb)); + sqlite3VdbeAddOp2(v, OP_SetNumColumns, 0, 5);/* sqlite_master has 5 columns */ sqlite3VdbeAddOp3(v, OP_OpenWrite, 0, MASTER_ROOT, iDb); - sqlite3VdbeAddOp2(v, OP_SetNumColumns, 0, 5); /* sqlite_master has 5 columns */ } /* diff --git a/src/delete.c b/src/delete.c index dd97f18c3b..6a07384aee 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.162 2008/03/19 20:42:14 drh Exp $ +** $Id: delete.c,v 1.163 2008/03/25 09:47:35 danielk1977 Exp $ */ #include "sqliteInt.h" @@ -75,9 +75,9 @@ void sqlite3OpenTable( v = sqlite3GetVdbe(p); assert( opcode==OP_OpenWrite || opcode==OP_OpenRead ); sqlite3TableLock(p, iDb, pTab->tnum, (opcode==OP_OpenWrite), pTab->zName); + sqlite3VdbeAddOp2(v, OP_SetNumColumns, 0, pTab->nCol); sqlite3VdbeAddOp3(v, opcode, iCur, pTab->tnum, iDb); VdbeComment((v, "%s", pTab->zName)); - sqlite3VdbeAddOp2(v, OP_SetNumColumns, iCur, pTab->nCol); } @@ -322,8 +322,8 @@ void sqlite3DeleteFrom( /* Open the pseudo-table used to store OLD if there are triggers. */ if( triggers_exist ){ + sqlite3VdbeAddOp2(v, OP_SetNumColumns, 0, pTab->nCol); sqlite3VdbeAddOp1(v, OP_OpenPseudo, oldIdx); - sqlite3VdbeAddOp2(v, OP_SetNumColumns, oldIdx, pTab->nCol); } /* Delete every item whose key was written to the list during the diff --git a/src/expr.c b/src/expr.c index 7ee47a4e7a..d35b3cd8e1 100644 --- a/src/expr.c +++ b/src/expr.c @@ -12,7 +12,7 @@ ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. ** -** $Id: expr.c,v 1.356 2008/03/20 16:30:18 drh Exp $ +** $Id: expr.c,v 1.357 2008/03/25 09:47:35 danielk1977 Exp $ */ #include "sqliteInt.h" #include @@ -1639,11 +1639,11 @@ int sqlite3FindInIndex(Parse *pParse, Expr *pX, int mustBeUnique){ iAddr = sqlite3VdbeAddOp1(v, OP_If, iMem); sqlite3VdbeAddOp2(v, OP_Integer, 1, iMem); + sqlite3VdbeAddOp2(v, OP_SetNumColumns, 0, pIdx->nColumn); sqlite3VdbeAddOp4(v, OP_OpenRead, iTab, pIdx->tnum, iDb, pKey,P4_KEYINFO_HANDOFF); VdbeComment((v, "%s", pIdx->zName)); eType = IN_INDEX_INDEX; - sqlite3VdbeAddOp2(v, OP_SetNumColumns, iTab, pIdx->nColumn); sqlite3VdbeJumpHere(v, iAddr); } @@ -1719,10 +1719,9 @@ void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){ ** is used. */ pExpr->iTable = pParse->nTab++; - addr = sqlite3VdbeAddOp1(v, OP_OpenEphemeral, pExpr->iTable); + addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pExpr->iTable, 1); memset(&keyInfo, 0, sizeof(keyInfo)); keyInfo.nField = 1; - sqlite3VdbeAddOp2(v, OP_SetNumColumns, pExpr->iTable, 1); if( pExpr->pSelect ){ /* Case 1: expr IN (SELECT ...) diff --git a/src/insert.c b/src/insert.c index 9a2cb56ad4..f7950d0578 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.232 2008/03/19 20:42:14 drh Exp $ +** $Id: insert.c,v 1.233 2008/03/25 09:47:35 danielk1977 Exp $ */ #include "sqliteInt.h" @@ -537,8 +537,7 @@ void sqlite3Insert( ** back up and execute the SELECT code above. */ sqlite3VdbeJumpHere(v, iInitCode); - sqlite3VdbeAddOp2(v, OP_OpenEphemeral, srcTab, 0); - sqlite3VdbeAddOp2(v, OP_SetNumColumns, srcTab, nColumn); + sqlite3VdbeAddOp2(v, OP_OpenEphemeral, srcTab, nColumn); sqlite3VdbeAddOp2(v, OP_Goto, 0, iSelectLoop); sqlite3VdbeResolveLabel(v, iCleanup); }else{ @@ -629,8 +628,8 @@ void sqlite3Insert( /* Open the temp table for FOR EACH ROW triggers */ if( triggers_exist ){ + sqlite3VdbeAddOp2(v, OP_SetNumColumns, 0, pTab->nCol); sqlite3VdbeAddOp2(v, OP_OpenPseudo, newIdx, 0); - sqlite3VdbeAddOp2(v, OP_SetNumColumns, newIdx, pTab->nCol); } /* Initialize the count of rows to be inserted diff --git a/src/prepare.c b/src/prepare.c index 19eb4dfa0a..bdb3d37c02 100644 --- a/src/prepare.c +++ b/src/prepare.c @@ -13,7 +13,7 @@ ** interface, and routines that contribute to loading the database schema ** from disk. ** -** $Id: prepare.c,v 1.81 2008/03/25 00:22:21 drh Exp $ +** $Id: prepare.c,v 1.82 2008/03/25 09:47:35 danielk1977 Exp $ */ #include "sqliteInt.h" #include @@ -207,12 +207,16 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ } return SQLITE_OK; } + curMain = sqlite3MallocZero(sqlite3BtreeCursorSize()); + if( !curMain ){ + rc = SQLITE_NOMEM; + goto error_out; + } sqlite3BtreeEnter(pDb->pBt); - rc = sqlite3BtreeCursor(pDb->pBt, MASTER_ROOT, 0, 0, &curMain); + rc = sqlite3BtreeCursor(pDb->pBt, MASTER_ROOT, 0, 0, curMain); if( rc!=SQLITE_OK && rc!=SQLITE_EMPTY ){ sqlite3SetString(pzErrMsg, sqlite3ErrStr(rc), (char*)0); - sqlite3BtreeLeave(pDb->pBt); - goto error_out; + goto leave_error_out; } /* Get the database meta information. @@ -239,9 +243,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ } if( rc ){ sqlite3SetString(pzErrMsg, sqlite3ErrStr(rc), (char*)0); - sqlite3BtreeCloseCursor(curMain); - sqlite3BtreeLeave(pDb->pBt); - goto error_out; + goto leave_error_out; } }else{ memset(meta, 0, sizeof(meta)); @@ -261,11 +263,10 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ }else{ /* If opening an attached database, the encoding much match ENC(db) */ if( meta[4]!=ENC(db) ){ - sqlite3BtreeCloseCursor(curMain); sqlite3SetString(pzErrMsg, "attached databases must use the same" " text encoding as main database", (char*)0); - sqlite3BtreeLeave(pDb->pBt); - return SQLITE_ERROR; + rc = SQLITE_ERROR; + goto leave_error_out; } } }else{ @@ -290,10 +291,9 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ pDb->pSchema->file_format = 1; } if( pDb->pSchema->file_format>SQLITE_MAX_FILE_FORMAT ){ - sqlite3BtreeCloseCursor(curMain); sqlite3SetString(pzErrMsg, "unsupported file format", (char*)0); - sqlite3BtreeLeave(pDb->pBt); - return SQLITE_ERROR; + rc = SQLITE_ERROR; + goto leave_error_out; } /* Ticket #2804: When we open a database in the newer file format, @@ -336,7 +336,6 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ sqlite3AnalysisLoad(db, iDb); } #endif - sqlite3BtreeCloseCursor(curMain); } if( db->mallocFailed ){ /* sqlite3SetString(pzErrMsg, "out of memory", (char*)0); */ @@ -355,6 +354,14 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ DbSetProperty(db, iDb, DB_SchemaLoaded); rc = SQLITE_OK; } + + /* Jump here for an error that occurs after successfully allocating + ** curMain and calling sqlite3BtreeEnter(). For an error that occurs + ** before that point, jump to error_out. + */ +leave_error_out: + sqlite3BtreeCloseCursor(curMain); + sqlite3_free(curMain); sqlite3BtreeLeave(pDb->pBt); error_out: @@ -441,23 +448,32 @@ static int schemaIsValid(sqlite3 *db){ int cookie; int allOk = 1; - assert( sqlite3_mutex_held(db->mutex) ); - for(iDb=0; allOk && iDbnDb; iDb++){ - Btree *pBt; - pBt = db->aDb[iDb].pBt; - if( pBt==0 ) continue; - rc = sqlite3BtreeCursor(pBt, MASTER_ROOT, 0, 0, &curTemp); - if( rc==SQLITE_OK ){ - rc = sqlite3BtreeGetMeta(pBt, 1, (u32 *)&cookie); - if( rc==SQLITE_OK && cookie!=db->aDb[iDb].pSchema->schema_cookie ){ - allOk = 0; + curTemp = (BtCursor *)sqlite3_malloc(sqlite3BtreeCursorSize()); + if( curTemp ){ + assert( sqlite3_mutex_held(db->mutex) ); + for(iDb=0; allOk && iDbnDb; iDb++){ + Btree *pBt; + pBt = db->aDb[iDb].pBt; + if( pBt==0 ) continue; + memset(curTemp, 0, sqlite3BtreeCursorSize()); + rc = sqlite3BtreeCursor(pBt, MASTER_ROOT, 0, 0, curTemp); + if( rc==SQLITE_OK ){ + rc = sqlite3BtreeGetMeta(pBt, 1, (u32 *)&cookie); + if( rc==SQLITE_OK && cookie!=db->aDb[iDb].pSchema->schema_cookie ){ + allOk = 0; + } + sqlite3BtreeCloseCursor(curTemp); + } + if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){ + db->mallocFailed = 1; } - sqlite3BtreeCloseCursor(curTemp); - } - if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ){ - db->mallocFailed = 1; } + sqlite3_free(curTemp); + }else{ + allOk = 0; + db->mallocFailed = 1; } + return allOk; } diff --git a/src/select.c b/src/select.c index 18532b585a..3df5f40559 100644 --- a/src/select.c +++ b/src/select.c @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** to handle SELECT statements in SQLite. ** -** $Id: select.c,v 1.417 2008/03/22 01:07:18 drh Exp $ +** $Id: select.c,v 1.418 2008/03/25 09:47:35 danielk1977 Exp $ */ #include "sqliteInt.h" @@ -789,8 +789,8 @@ static void generateSortTail( iTab = pOrderBy->iECursor; if( eDest==SRT_Callback || eDest==SRT_Subroutine ){ pseudoTab = pParse->nTab++; + sqlite3VdbeAddOp2(v, OP_SetNumColumns, 0, nColumn); sqlite3VdbeAddOp2(v, OP_OpenPseudo, pseudoTab, 0); - sqlite3VdbeAddOp2(v, OP_SetNumColumns, pseudoTab, nColumn); } addr = 1 + sqlite3VdbeAddOp2(v, OP_Sort, iTab, brk); codeOffset(v, p, cont); @@ -3316,10 +3316,9 @@ int sqlite3Select( */ sAggInfo.sortingIdx = pParse->nTab++; pKeyInfo = keyInfoFromExprList(pParse, pGroupBy); - addrSortingIdx = - sqlite3VdbeAddOp4(v, OP_OpenEphemeral, sAggInfo.sortingIdx, - sAggInfo.nSortingColumn, 0, - (char*)pKeyInfo, P4_KEYINFO_HANDOFF); + addrSortingIdx = sqlite3VdbeAddOp4(v, OP_OpenEphemeral, + sAggInfo.sortingIdx, sAggInfo.nSortingColumn, + 0, (char*)pKeyInfo, P4_KEYINFO_HANDOFF); /* Initialize memory locations used by GROUP BY aggregate processing */ diff --git a/src/test3.c b/src/test3.c index 8a907070bc..e3922f67d8 100644 --- a/src/test3.c +++ b/src/test3.c @@ -13,7 +13,7 @@ ** is not included in the SQLite library. It is used for automated ** testing of the SQLite library. ** -** $Id: test3.c,v 1.92 2008/03/25 00:22:21 drh Exp $ +** $Id: test3.c,v 1.93 2008/03/25 09:47:35 danielk1977 Exp $ */ #include "sqliteInt.h" #include "btreeInt.h" @@ -711,10 +711,13 @@ static int btree_cursor( pBt = sqlite3TextToPtr(argv[1]); if( Tcl_GetInt(interp, argv[2], &iTable) ) return TCL_ERROR; if( Tcl_GetBoolean(interp, argv[3], &wrFlag) ) return TCL_ERROR; + pCur = (BtCursor *)ckalloc(sqlite3BtreeCursorSize()); + memset(pCur, 0, sqlite3BtreeCursorSize()); sqlite3BtreeEnter(pBt); - rc = sqlite3BtreeCursor(pBt, iTable, wrFlag, 0, &pCur); + rc = sqlite3BtreeCursor(pBt, iTable, wrFlag, 0, pCur); sqlite3BtreeLeave(pBt); if( rc ){ + ckfree((char *)pCur); Tcl_AppendResult(interp, errorName(rc), 0); return TCL_ERROR; } @@ -748,6 +751,7 @@ static int btree_close_cursor( sqlite3BtreeEnter(pBt); rc = sqlite3BtreeCloseCursor(pCur); sqlite3BtreeLeave(pBt); + ckfree((char *)pCur); if( rc ){ Tcl_AppendResult(interp, errorName(rc), 0); return TCL_ERROR; diff --git a/src/test_malloc.c b/src/test_malloc.c index ce2f718be0..3595a0651f 100644 --- a/src/test_malloc.c +++ b/src/test_malloc.c @@ -13,7 +13,7 @@ ** This file contains code used to implement test interfaces to the ** memory allocation subsystem. ** -** $Id: test_malloc.c,v 1.18 2008/03/21 14:22:44 danielk1977 Exp $ +** $Id: test_malloc.c,v 1.19 2008/03/25 09:47:35 danielk1977 Exp $ */ #include "sqliteInt.h" #include "tcl.h" @@ -507,7 +507,7 @@ static int test_memdebug_settitle( return TCL_OK; } -#define MALLOC_LOG_FRAMES 5 +#define MALLOC_LOG_FRAMES 10 static Tcl_HashTable aMallocLog; static int mallocLogEnabled = 0; diff --git a/src/update.c b/src/update.c index f6faca257e..6f479a55db 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.172 2008/03/19 20:42:14 drh Exp $ +** $Id: update.c,v 1.173 2008/03/25 09:47:35 danielk1977 Exp $ */ #include "sqliteInt.h" @@ -302,10 +302,10 @@ void sqlite3Update( /* Create pseudo-tables for NEW and OLD */ + sqlite3VdbeAddOp2(v, OP_SetNumColumns, 0, pTab->nCol); sqlite3VdbeAddOp2(v, OP_OpenPseudo, oldIdx, 0); - sqlite3VdbeAddOp2(v, OP_SetNumColumns, oldIdx, pTab->nCol); + sqlite3VdbeAddOp2(v, OP_SetNumColumns, 0, pTab->nCol); sqlite3VdbeAddOp2(v, OP_OpenPseudo, newIdx, 0); - sqlite3VdbeAddOp2(v, OP_SetNumColumns, newIdx, pTab->nCol); iGoto = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0); addr = sqlite3VdbeMakeLabel(v); diff --git a/src/vdbe.c b/src/vdbe.c index 5256b655df..e491340fae 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -43,7 +43,7 @@ ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** -** $Id: vdbe.c,v 1.716 2008/03/25 00:22:21 drh Exp $ +** $Id: vdbe.c,v 1.717 2008/03/25 09:47:35 danielk1977 Exp $ */ #include "sqliteInt.h" #include @@ -208,15 +208,66 @@ int sqlite3VdbeOpcodeHasProperty(int opcode, int mask){ ** Allocate cursor number iCur. Return a pointer to it. Return NULL ** if we run out of memory. */ -static Cursor *allocateCursor(Vdbe *p, int iCur, int iDb){ - Cursor *pCx; +static Cursor *allocateCursor( + Vdbe *p, + int iCur, + Op *pOp, + int iDb, + int isBtreeCursor +){ + /* Find the memory cell that will be used to store the blob of memory + ** required for this Cursor structure. It is convenient to use a + ** vdbe memory cell to manage the memory allocation required for a + ** Cursor structure for the following reasons: + ** + ** * Sometimes cursor numbers are used for a couple of different + ** purposes in a vdbe program. The different uses might require + ** different sized allocations. Memory cells provide growable + ** allocations. + ** + ** * When using ENABLE_MEMORY_MANAGEMENT, memory cell buffers can + ** be freed lazily via the sqlite3_release_memory() API. This + ** minimizes the number of malloc calls made by the system. + ** + ** Memory cells for cursors are allocated at the top of the address + ** space. Memory cell (p->nMem) corresponds to cursor 0. Space for + ** cursor 1 is managed by memory cell (p->nMem-1), etc. + */ + Mem *pMem = &p->aMem[p->nMem-iCur]; + + Cursor *pCx = 0; + /* If the opcode of pOp is OP_SetNumColumns, then pOp->p2 contains + ** the number of fields in the records contained in the table or + ** index being opened. Use this to reserve space for the + ** Cursor.aType[] array. + */ + int nField = 0; + if( pOp->opcode==OP_SetNumColumns || pOp->opcode==OP_OpenEphemeral ){ + nField = pOp->p2; + } + + + int nByte = + sizeof(Cursor) + + (isBtreeCursor?sqlite3BtreeCursorSize():0) + + 2*nField*sizeof(u32); + assert( iCurnCursor ); if( p->apCsr[iCur] ){ sqlite3VdbeFreeCursor(p, p->apCsr[iCur]); + p->apCsr[iCur] = 0; } - p->apCsr[iCur] = pCx = sqlite3MallocZero( sizeof(Cursor) ); - if( pCx ){ + if( SQLITE_OK==sqlite3VdbeMemGrow(pMem, nByte, 0) ){ + p->apCsr[iCur] = pCx = (Cursor *)pMem->z; + memset(pMem->z, 0, nByte); pCx->iDb = iDb; + pCx->nField = nField; + if( nField ){ + pCx->aType = (u32 *)&pMem->z[sizeof(Cursor)]; + } + if( isBtreeCursor ){ + pCx->pCursor = (BtCursor *)&pMem->z[sizeof(Cursor)+2*nField*sizeof(u32)]; + } } return pCx; } @@ -1773,22 +1824,23 @@ case OP_NotNull: { /* same as TK_NOTNULL, jump, in1 */ break; } -/* Opcode: SetNumColumns P1 P2 * * * +/* Opcode: SetNumColumns * P2 * * * +** +** This opcode sets the number of columns for the cursor opened by the +** following instruction to P2. ** -** Before the OP_Column opcode can be executed on a cursor, this -** opcode must be called to set the number of fields in the table. +** An OP_SetNumColumns is only useful if it occurs immediately before +** one of the following opcodes: ** -** This opcode sets the number of columns for cursor P1 to P2. +** OpenRead +** OpenWrite +** OpenPseudo ** -** If OP_KeyAsData is to be applied to cursor P1, it must be executed -** before this op-code. +** If the OP_Column opcode is to be executed on a cursor, then +** this opcode must be present immediately before the opcode that +** opens the cursor. */ case OP_SetNumColumns: { - Cursor *pC; - assert( (pOp->p1)nCursor ); - assert( p->apCsr[pOp->p1]!=0 ); - pC = p->apCsr[pOp->p1]; - pC->nField = pOp->p2; break; } @@ -1893,8 +1945,8 @@ case OP_Column: { /* Read and parse the table header. Store the results of the parse ** into the record header cache fields of the cursor. */ + aType = pC->aType; if( pC->cacheStatus==p->cacheCtr ){ - aType = pC->aType; aOffset = pC->aOffset; }else{ u8 *zIdx; /* Index into header */ @@ -1903,13 +1955,7 @@ case OP_Column: { int szHdrSz; /* Size of the header size field at start of record */ int avail; /* Number of bytes of available data */ - aType = pC->aType; - if( aType==0 ){ - pC->aType = aType = sqlite3DbMallocRaw(db, 2*nField*sizeof(aType) ); - } - if( aType==0 ){ - goto no_mem; - } + assert(aType); pC->aOffset = aOffset = &aType[nField]; pC->payloadSize = payloadSize; pC->cacheStatus = p->cacheCtr; @@ -2515,10 +2561,10 @@ case OP_OpenWrite: { assert( p2>=2 ); } assert( i>=0 ); - pCur = allocateCursor(p, i, iDb); + pCur = allocateCursor(p, i, &pOp[-1], iDb, 1); if( pCur==0 ) goto no_mem; pCur->nullRow = 1; - rc = sqlite3BtreeCursor(pX, p2, wrFlag, pOp->p4.p, &pCur->pCursor); + rc = sqlite3BtreeCursor(pX, p2, wrFlag, pOp->p4.p, pCur->pCursor); if( pOp->p4type==P4_KEYINFO ){ pCur->pKeyInfo = pOp->p4.pKeyInfo; pCur->pIncrKey = &pCur->pKeyInfo->incrKey; @@ -2561,6 +2607,7 @@ case OP_OpenWrite: { case SQLITE_EMPTY: { pCur->isTable = pOp->p4type!=P4_KEYINFO; pCur->isIndex = !pCur->isTable; + pCur->pCursor = 0; rc = SQLITE_OK; break; } @@ -2600,7 +2647,7 @@ case OP_OpenEphemeral: { SQLITE_OPEN_TRANSIENT_DB; assert( i>=0 ); - pCx = allocateCursor(p, i, -1); + pCx = allocateCursor(p, i, pOp, -1, 1); if( pCx==0 ) goto no_mem; pCx->nullRow = 1; rc = sqlite3BtreeFactory(db, 0, 1, SQLITE_DEFAULT_TEMP_CACHE_SIZE, openFlags, @@ -2621,19 +2668,18 @@ case OP_OpenEphemeral: { if( rc==SQLITE_OK ){ assert( pgno==MASTER_ROOT+1 ); rc = sqlite3BtreeCursor(pCx->pBt, pgno, 1, - (KeyInfo*)pOp->p4.z, &pCx->pCursor); + (KeyInfo*)pOp->p4.z, pCx->pCursor); pCx->pKeyInfo = pOp->p4.pKeyInfo; pCx->pKeyInfo->enc = ENC(p->db); pCx->pIncrKey = &pCx->pKeyInfo->incrKey; } pCx->isTable = 0; }else{ - rc = sqlite3BtreeCursor(pCx->pBt, MASTER_ROOT, 1, 0, &pCx->pCursor); + rc = sqlite3BtreeCursor(pCx->pBt, MASTER_ROOT, 1, 0, pCx->pCursor); pCx->isTable = 1; pCx->pIncrKey = &pCx->bogusIncrKey; } } - pCx->nField = pOp->p2; pCx->isIndex = !pCx->isTable; break; } @@ -2654,7 +2700,7 @@ case OP_OpenPseudo: { int i = pOp->p1; Cursor *pCx; assert( i>=0 ); - pCx = allocateCursor(p, i, -1); + pCx = allocateCursor(p, i, &pOp[-1], -1, 0); if( pCx==0 ) goto no_mem; pCx->nullRow = 1; pCx->pseudoTable = 1; @@ -4390,7 +4436,7 @@ case OP_VOpen: { pVtabCursor->pVtab = pVtab; /* Initialise vdbe cursor object */ - pCur = allocateCursor(p, pOp->p1, -1); + pCur = allocateCursor(p, pOp->p1, &pOp[-1], -1, 0); if( pCur ){ pCur->pVtabCursor = pVtabCursor; pCur->pModule = pVtabCursor->pVtab->pModule; diff --git a/src/vdbeaux.c b/src/vdbeaux.c index be7c276422..7e7824a017 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -958,6 +958,17 @@ void sqlite3VdbeMakeReady( */ p->magic = VDBE_MAGIC_RUN; + /* For each cursor required, also allocate a memory cell. Memory + ** cells (nMem+1-nCursor)..nMem, inclusive, will never be used by + ** the vdbe program. Instead they are used to allocate space for + ** Cursor/BtCursor structures. The blob of memory associated with + ** cursor 0 is stored in memory cell nMem. Memory cell (nMem-1) + ** stores the blob of memory associated with cursor 1, etc. + ** + ** See also: allocateCursor(). + */ + nMem += nCursor; + /* ** Allocation space for registers. */ @@ -1026,8 +1037,8 @@ void sqlite3VdbeMakeReady( } /* -** Close a VDBE cursor and release all the resources that cursor happens -** to hold. +** Close a VDBE cursor and release all the resources that cursor +** happens to hold. */ void sqlite3VdbeFreeCursor(Vdbe *p, Cursor *pCx){ if( pCx==0 ){ @@ -1051,8 +1062,9 @@ void sqlite3VdbeFreeCursor(Vdbe *p, Cursor *pCx){ } #endif sqlite3_free(pCx->pData); - sqlite3_free(pCx->aType); - sqlite3_free(pCx); + memset(pCx, 0, sizeof(Cursor)); + /* sqlite3_free(pCx->aType); */ + /* sqlite3_free(pCx); */ } /* @@ -1084,6 +1096,7 @@ static void Cleanup(Vdbe *p){ for(i=1; i<=p->nMem; i++){ MemSetTypeFlag(&p->aMem[i], MEM_Null); } + releaseMemArray(&p->aMem[1], p->nMem); sqlite3VdbeFifoClear(&p->sFifo); if( p->contextStack ){ diff --git a/src/vdbeblob.c b/src/vdbeblob.c index 70d5ed81ff..1d456ad314 100644 --- a/src/vdbeblob.c +++ b/src/vdbeblob.c @@ -12,7 +12,7 @@ ** ** This file contains code used to implement incremental BLOB I/O. ** -** $Id: vdbeblob.c,v 1.20 2008/01/25 15:04:50 drh Exp $ +** $Id: vdbeblob.c,v 1.21 2008/03/25 09:47:35 danielk1977 Exp $ */ #include "sqliteInt.h" @@ -70,16 +70,17 @@ int sqlite3_blob_open( /* One of the following two instructions is replaced by an ** OP_Noop before exection. */ - {OP_OpenRead, 0, 0, 0}, /* 2: Open cursor 0 for reading */ - {OP_OpenWrite, 0, 0, 0}, /* 3: Open cursor 0 for read/write */ + {OP_SetNumColumns, 0, 0, 0}, /* 2: Num cols for cursor */ + {OP_OpenRead, 0, 0, 0}, /* 3: Open cursor 0 for reading */ {OP_SetNumColumns, 0, 0, 0}, /* 4: Num cols for cursor */ - - {OP_Variable, 1, 1, 0}, /* 5: Push the rowid to the stack */ - {OP_NotExists, 0, 10, 1}, /* 6: Seek the cursor */ - {OP_Column, 0, 0, 1}, /* 7 */ - {OP_ResultRow, 1, 0, 0}, /* 8 */ - {OP_Close, 0, 0, 0}, /* 9 */ - {OP_Halt, 0, 0, 0}, /* 10 */ + {OP_OpenWrite, 0, 0, 0}, /* 5: Open cursor 0 for read/write */ + + {OP_Variable, 1, 1, 0}, /* 6: Push the rowid to the stack */ + {OP_NotExists, 0, 10, 1}, /* 7: Seek the cursor */ + {OP_Column, 0, 0, 1}, /* 8 */ + {OP_ResultRow, 1, 0, 0}, /* 9 */ + {OP_Close, 0, 0, 0}, /* 10 */ + {OP_Halt, 0, 0, 0}, /* 11 */ }; Vdbe *v = 0; @@ -168,9 +169,9 @@ int sqlite3_blob_open( /* Remove either the OP_OpenWrite or OpenRead. Set the P2 ** parameter of the other to pTab->tnum. */ - sqlite3VdbeChangeToNoop(v, (flags ? 2 : 3), 1); - sqlite3VdbeChangeP2(v, (flags ? 3 : 2), pTab->tnum); - sqlite3VdbeChangeP3(v, (flags ? 3 : 2), iDb); + sqlite3VdbeChangeToNoop(v, (flags ? 3 : 5), 1); + sqlite3VdbeChangeP2(v, (flags ? 5 : 3), pTab->tnum); + sqlite3VdbeChangeP3(v, (flags ? 5 : 3), iDb); /* Configure the OP_SetNumColumns. Configure the cursor to ** think that the table has one more column than it really @@ -179,7 +180,7 @@ int sqlite3_blob_open( ** we can invoke OP_Column to fill in the vdbe cursors type ** and offset cache without causing any IO. */ - sqlite3VdbeChangeP2(v, 4, pTab->nCol+1); + sqlite3VdbeChangeP2(v, flags ? 4 : 2, pTab->nCol+1); if( !db->mallocFailed ){ sqlite3VdbeMakeReady(v, 1, 1, 1, 0); } diff --git a/src/where.c b/src/where.c index bcb7785098..71bc51bc4e 100644 --- a/src/where.c +++ b/src/where.c @@ -16,7 +16,7 @@ ** so is applicable. Because this module is responsible for selecting ** indices, you might also think of this module as the "query optimizer". ** -** $Id: where.c,v 1.290 2008/03/17 17:08:33 drh Exp $ +** $Id: where.c,v 1.291 2008/03/25 09:47:35 danielk1977 Exp $ */ #include "sqliteInt.h" @@ -2223,7 +2223,7 @@ WhereInfo *sqlite3WhereBegin( Bitmask b = pTabItem->colUsed; int n = 0; for(; b; b=b>>1, n++){} - sqlite3VdbeChangeP2(v, sqlite3VdbeCurrentAddr(v)-1, n); + sqlite3VdbeChangeP2(v, sqlite3VdbeCurrentAddr(v)-2, n); assert( n<=pTab->nCol ); } }else{ @@ -2233,10 +2233,10 @@ WhereInfo *sqlite3WhereBegin( if( (pIx = pLevel->pIdx)!=0 ){ KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIx); assert( pIx->pSchema==pTab->pSchema ); + sqlite3VdbeAddOp2(v, OP_SetNumColumns, 0, pIx->nColumn+1); sqlite3VdbeAddOp4(v, OP_OpenRead, iIdxCur, pIx->tnum, iDb, (char*)pKey, P4_KEYINFO_HANDOFF); VdbeComment((v, "%s", pIx->zName)); - sqlite3VdbeAddOp2(v, OP_SetNumColumns, iIdxCur, pIx->nColumn+1); } sqlite3CodeVerifySchema(pParse, iDb); }