From e14006d0de810c1bc04986c6d85381a8a0468666 Mon Sep 17 00:00:00 2001 From: drh Date: Tue, 25 Mar 2008 17:23:32 +0000 Subject: [PATCH] Modify the {quote: IdxDelete} opcode so that it takes an array of registers rather than a record formed using {quote: MakeRecord.} This avoids a needless packing and unpacking of the record to be deleted. (CVS 4916) FossilOrigin-Name: ee381b43563e1b0637ee74389d076dff77deddf9 --- manifest | 36 +++++------ manifest.uuid | 2 +- src/btree.c | 50 ++++++++++------ src/btree.h | 13 +++- src/build.c | 4 +- src/delete.c | 21 +++---- src/pragma.c | 4 +- src/select.c | 9 +-- src/sqliteInt.h | 4 +- src/test3.c | 6 +- src/vdbe.c | 33 +++++++---- src/vdbe.h | 10 ++-- src/vdbeInt.h | 22 +++++++ src/vdbeaux.c | 154 +++++++----------------------------------------- 14 files changed, 154 insertions(+), 214 deletions(-) diff --git a/manifest b/manifest index 1afbe0a693..3b36663289 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Test\sstring\svalues\spassed\sto\sbind_text()\sand\sresult_text()\sfor\sa\snul-terminator.\s(CVS\s4915) -D 2008-03-25T16:16:29 +C Modify\sthe\s{quote:\sIdxDelete}\sopcode\sso\sthat\sit\stakes\san\sarray\sof\sregisters\srather\r\nthan\sa\srecord\sformed\susing\s{quote:\sMakeRecord.}\s\sThis\savoids\sa\sneedless\spacking\r\nand\sunpacking\sof\sthe\srecord\sto\sbe\sdeleted.\s(CVS\s4916) +D 2008-03-25T17:23:33 F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7 F Makefile.in cf434ce8ca902e69126ae0f94fc9f7dc7428a5fa F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 @@ -86,14 +86,14 @@ F src/attach.c bdc75e759ca25a16f4dc7fbdbc6d37ad2561bb24 F src/auth.c c8b2ab5c8bad4bd90ed7c294694f48269162c627 F src/bitvec.c 49817d442e51e4123585f3cf3c2afc293a3c91e2 F src/btmutex.c 483ced3c52205b04b97df69161fadbf87f4f1ea2 -F src/btree.c 366f5f66ebb3dfdc8513242d4aecbfb402dcc0a9 -F src/btree.h e02869e1e7753ad5b3c7cb7852e952c95c2e609a +F src/btree.c 6e60d634d236232efbb289b800dd76e72a5ecf9d +F src/btree.h c66cb17c6fffa84a88926dbef173bab4ae692fd4 F src/btreeInt.h d232be68a7ab2a24376dc6332a869e717551b0bd -F src/build.c d0715b3454b140cb405412e3029ec7c0fb434efd +F src/build.c 4e6321d112f0ed1070c579677573e4eb76cda1fd F src/callback.c 77b302b0d41468dcda78c70e706e5b84577f0fa0 F src/complete.c 4cf68fd75d60257524cbe74f87351b9848399131 F src/date.c e41ce4513fb0e359dc678d6bddb4ace135fe365d -F src/delete.c 526b783b71b9885b201d74720d44a386b971dc01 +F src/delete.c 3dc7d7cc46c8675219a7776b7c67b626bba530df F src/experimental.c 1b2d1a6cd62ecc39610e97670332ca073c50792b F src/expr.c 7e56d2a24af8137f4bebbfa1d7dd1dcf70107c88 F src/fault.c c28478c7190daef16be09d261c5461638b4d686c @@ -131,22 +131,22 @@ F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b F src/pager.c 22241b59c80ca083a96816df434adb8c097afcd4 F src/pager.h b1e2258f03878c14b06a95bfa362e8c5c9638170 F src/parse.y b0ee84d94218046ea88c2a6561005710d127ca7d -F src/pragma.c f64eed914518c28d1863356163dea1e6f58e28f2 +F src/pragma.c 99cec6d99d0241436494aab15b05da97b0e70683 F src/prepare.c 185fb47f1fb3e45a345d523eb391d673f5eb367c F src/printf.c 05d2b44d7b5b80c8a4a09108ddad9c20e254370d F src/random.c 2b2db2de4ab491f5a14d3480466f8f4b5a5db74a -F src/select.c c06849a0d0ad408fbdd8180439176e94aae43e56 +F src/select.c 831714d4f09f4b9f4be43d2399eff12dcf281c86 F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96 F src/shell.c 22297fffa6f00a6c6d44020fa13b1184a1bb372d F src/sqlite.h.in 61d8d1cefcbf0803c03c2179be138a78bfd1d335 F src/sqlite3ext.h faacd0e6a81aabee0861c6d7883c9172e74ef5b3 -F src/sqliteInt.h 07b472437b2d7297c300f8b7cea5205984fa64d1 +F src/sqliteInt.h 50a9313829041721d34f20c8be4562c3197dcff9 F src/sqliteLimit.h eecbc288b410ae5565e71aaa4a439aae57bb0707 F src/table.c 2c48c575dd59b3a6c5c306bc55f51a9402cf429a F src/tclsqlite.c 1367762764772a233643524c3585b4711a9adcda F src/test1.c 342a2628310fa709074d979e695a28a3bb570834 F src/test2.c f0808cc643528b9620e4059ca9bda8346f526121 -F src/test3.c 31027a4a190d2f3c1e479ea2d750e696160bbf04 +F src/test3.c c715b5a8a6415d7b2c67f97c394eef488b6f7e63 F src/test4.c c2c0f5dc907f1346f5d4b65eb5799f11eb9e4071 F src/test5.c 3a6a5717a149d7ca2e6d14f5be72cf7555d54dc4 F src/test6.c 62281c0a9ac0265e579065942f7de4e080f8eb05 @@ -174,11 +174,11 @@ F src/update.c 2aefd3c9277792e9fa2414dfe14202119fa49fe7 F src/utf.c 32b00d6e19010025e58f2ecb2f921d5e126771b4 F src/util.c dba9e04121eb17ec4643d6ca231ff859452cf0e2 F src/vacuum.c 3524411bfb58aac0d87eadd3e5b7cd532772af30 -F src/vdbe.c bdcbf54cf944a99b004e87a523736dd326fa34be -F src/vdbe.h 0fef6798be121ed2b5a547a5cb85e0824ec3971f -F src/vdbeInt.h 4bbec80d55d179ab8438ac9822416d9111638919 +F src/vdbe.c 0068703495a197e7b77dbdff604b42896722a1cc +F src/vdbe.h ecca2e1c1ac1066f4e68ad38068a20ea32ea7063 +F src/vdbeInt.h 4d767f189a1d13ff8d4881de60aacc470e54f5b8 F src/vdbeapi.c b9e9d7a58690c1e1ae66de7232edccf4793ad817 -F src/vdbeaux.c c071014d81c1d4b2c381247c16a3e86182951e51 +F src/vdbeaux.c e45929a3b5e59e8f2d69b7d6164c9a636149e1df F src/vdbeblob.c cc713c142c3d4952b380c98ee035f850830ddbdb F src/vdbefifo.c a30c237b2a3577e1415fb6e288cbb6b8ed1e5736 F src/vdbemem.c d48a71d66a7afd564b6537ab7e7442f7729fa5af @@ -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 fe1bc0f3b7cd87cd65f7d03b91095b59788a6f8d -R 033bb4545035899c2c5396ecb143bb5f -U danielk1977 -Z 09f5af34fae3a95557976f8d7d3936e3 +P 24c3ebc0c5c53c234516d16dce761d713fb29578 +R 66dfc33f9c0d1eba54064363b17cc27e +U drh +Z 040d5190ae2e9926a42f3065a9864529 diff --git a/manifest.uuid b/manifest.uuid index 8bf67601ed..6d2ac4b616 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -24c3ebc0c5c53c234516d16dce761d713fb29578 \ No newline at end of file +ee381b43563e1b0637ee74389d076dff77deddf9 \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 27450094f3..b889096a65 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.446 2008/03/25 14:24:57 danielk1977 Exp $ +** $Id: btree.c,v 1.447 2008/03/25 17:23:33 drh Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** See the header comment on "btreeInt.h" for additional information. @@ -379,7 +379,7 @@ int sqlite3BtreeRestoreOrClearCursorPosition(BtCursor *pCur){ } #endif pCur->eState = CURSOR_INVALID; - rc = sqlite3BtreeMoveto(pCur, pCur->pKey, pCur->nKey, 0, &pCur->skip); + rc = sqlite3BtreeMoveto(pCur, pCur->pKey, 0, pCur->nKey, 0, &pCur->skip); if( rc==SQLITE_OK ){ sqlite3_free(pCur->pKey); pCur->pKey = 0; @@ -3548,12 +3548,13 @@ int sqlite3BtreeLast(BtCursor *pCur, int *pRes){ return rc; } -/* Move the cursor so that it points to an entry near pKey/nKey. -** Return a success code. +/* Move the cursor so that it points to an entry near the key +** specified by pKey/nKey/pUnKey. Return a success code. ** -** For INTKEY tables, only the nKey parameter is used. pKey is -** ignored. For other tables, nKey is the number of bytes of data -** in pKey. +** For INTKEY tables, only the nKey parameter is used. pKey +** and pUnKey must be NULL. For index tables, either pUnKey +** must point to a key that has already been unpacked, or else +** pKey/nKey describes a blob containing the key. ** ** If an exact match is not found, then the cursor is always ** left pointing at a leaf page which would hold the entry if it @@ -3578,12 +3579,12 @@ int sqlite3BtreeLast(BtCursor *pCur, int *pRes){ int sqlite3BtreeMoveto( BtCursor *pCur, /* The cursor to be moved */ const void *pKey, /* The key content for indices. Not used by tables */ + UnpackedRecord *pUnKey,/* Unpacked version of pKey */ i64 nKey, /* Size of pKey. Or the key for tables */ int biasRight, /* If true, bias the search to the high end */ int *pRes /* Search result flag */ ){ int rc; - VdbeParsedRecord *pPKey; char aSpace[200]; assert( cursorHoldsMutex(pCur) ); @@ -3600,11 +3601,22 @@ int sqlite3BtreeMoveto( return SQLITE_OK; } if( pCur->pPage->intKey ){ - pPKey = 0; - }else{ - pPKey = sqlite3VdbeRecordParse(pCur->pKeyInfo, nKey, pKey, + /* We are given an SQL table to search. The key is the integer + ** rowid contained in nKey. pKey and pUnKey should both be NULL */ + assert( pUnKey==0 ); + assert( pKey==0 ); + }else if( pUnKey==0 ){ + /* We are to search an SQL index using a key encoded as a blob. + ** The blob is found at pKey and is nKey bytes in length. Unpack + ** this key so that we can use it. */ + assert( pKey!=0 ); + pUnKey = sqlite3VdbeRecordUnpack(pCur->pKeyInfo, nKey, pKey, aSpace, sizeof(aSpace)); - if( pPKey==0 ) return SQLITE_NOMEM; + if( pUnKey==0 ) return SQLITE_NOMEM; + }else{ + /* We are to search an SQL index using a key that is already unpacked + ** and handed to us in pUnKey. */ + assert( pKey==0 ); } for(;;){ int lwr, upr; @@ -3613,7 +3625,7 @@ int sqlite3BtreeMoveto( int c = -1; /* pRes return if table is empty must be -1 */ lwr = 0; upr = pPage->nCell-1; - if( !pPage->intKey && pKey==0 ){ + if( !pPage->intKey && pUnKey==0 ){ rc = SQLITE_CORRUPT_BKPT; goto moveto_finish; } @@ -3646,7 +3658,7 @@ int sqlite3BtreeMoveto( pCellKey = (void *)fetchPayload(pCur, &available, 0); nCellKey = pCur->info.nKey; if( available>=nCellKey ){ - c = sqlite3VdbeRecordCompareParsed(nCellKey, pCellKey, pPKey); + c = sqlite3VdbeRecordCompare(nCellKey, pCellKey, pUnKey); }else{ pCellKey = sqlite3_malloc( nCellKey ); if( pCellKey==0 ){ @@ -3654,7 +3666,7 @@ int sqlite3BtreeMoveto( goto moveto_finish; } rc = sqlite3BtreeKey(pCur, 0, nCellKey, (void *)pCellKey); - c = sqlite3VdbeRecordCompareParsed(nCellKey, pCellKey, pPKey); + c = sqlite3VdbeRecordCompare(nCellKey, pCellKey, pUnKey); sqlite3_free(pCellKey); if( rc ) goto moveto_finish; } @@ -3701,7 +3713,11 @@ int sqlite3BtreeMoveto( if( rc ) goto moveto_finish; } moveto_finish: - sqlite3VdbeRecordUnparse(pPKey); + if( pKey ){ + /* If we created our own unpacked key at the top of this + ** procedure, then destroy that key before returning. */ + sqlite3VdbeDeleteUnpackedRecord(pUnKey); + } return rc; } @@ -5619,7 +5635,7 @@ int sqlite3BtreeInsert( clearCursorPosition(pCur); if( SQLITE_OK!=(rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur)) || - SQLITE_OK!=(rc = sqlite3BtreeMoveto(pCur, pKey, nKey, appendBias, &loc)) + SQLITE_OK!=(rc = sqlite3BtreeMoveto(pCur, pKey, 0, nKey, appendBias, &loc)) ){ return rc; } diff --git a/src/btree.h b/src/btree.h index 97298da0e5..2f9bbcd080 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.96 2008/03/25 09:47:35 danielk1977 Exp $ +** @(#) $Id: btree.h,v 1.97 2008/03/25 17:23:33 drh Exp $ */ #ifndef _BTREE_H_ #define _BTREE_H_ @@ -127,6 +127,8 @@ int sqlite3BtreeGetMeta(Btree*, int idx, u32 *pValue); int sqlite3BtreeUpdateMeta(Btree*, int idx, u32 value); void sqlite3BtreeTripAllCursors(Btree*, int); +struct UnpackedRecord; /* Forward declaration. Definition in vdbeaux.c. */ + int sqlite3BtreeCursor( Btree*, /* BTree containing table to open */ int iTable, /* Index of root page */ @@ -137,7 +139,14 @@ int sqlite3BtreeCursor( int sqlite3BtreeCursorSize(); int sqlite3BtreeCloseCursor(BtCursor*); -int sqlite3BtreeMoveto(BtCursor*,const void *pKey,i64 nKey,int bias,int *pRes); +int sqlite3BtreeMoveto( + BtCursor*, + const void *pKey, + struct UnpackedRecord *pUnKey, + i64 nKey, + int bias, + int *pRes +); int sqlite3BtreeDelete(BtCursor*); int sqlite3BtreeInsert(BtCursor*, const void *pKey, i64 nKey, const void *pData, int nData, diff --git a/src/build.c b/src/build.c index 6b247901fd..72fe620e09 100644 --- a/src/build.c +++ b/src/build.c @@ -22,7 +22,7 @@ ** COMMIT ** ROLLBACK ** -** $Id: build.c,v 1.476 2008/03/25 09:47:35 danielk1977 Exp $ +** $Id: build.c,v 1.477 2008/03/25 17:23:33 drh Exp $ */ #include "sqliteInt.h" #include @@ -2278,7 +2278,7 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){ sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead); addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iTab, 0); regRecord = sqlite3GetTempReg(pParse); - regIdxKey = sqlite3GenerateIndexKey(pParse, pIndex, iTab, regRecord); + regIdxKey = sqlite3GenerateIndexKey(pParse, pIndex, iTab, regRecord, 1); if( pIndex->onError!=OE_None ){ int j1, j2; int regRowid; diff --git a/src/delete.c b/src/delete.c index 6a07384aee..e91ec74a52 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.163 2008/03/25 09:47:35 danielk1977 Exp $ +** $Id: delete.c,v 1.164 2008/03/25 17:23:33 drh Exp $ */ #include "sqliteInt.h" @@ -488,18 +488,16 @@ void sqlite3GenerateRowIndexDelete( Index *pIdx; int r1; - r1 = sqlite3GetTempReg(pParse); for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){ if( aRegIdx!=0 && aRegIdx[i-1]==0 ) continue; - sqlite3GenerateIndexKey(pParse, pIdx, iCur, r1); - sqlite3VdbeAddOp2(pParse->pVdbe, OP_IdxDelete, iCur+i, r1); + r1 = sqlite3GenerateIndexKey(pParse, pIdx, iCur, r1, 0); + sqlite3VdbeAddOp3(pParse->pVdbe, OP_IdxDelete, iCur+i, r1,pIdx->nColumn+1); } - sqlite3ReleaseTempReg(pParse, r1); } /* -** Generate code that will assemble an index key and put it on the top -** of the tack. The key with be for index pIdx which is an index on pTab. +** Generate code that will assemble an index key and put it in register +** regOut. The key with be for index pIdx which is an index on pTab. ** iCur is the index of a cursor open on the pTab table and pointing to ** the entry that needs indexing. ** @@ -512,7 +510,8 @@ int sqlite3GenerateIndexKey( Parse *pParse, /* Parsing context */ Index *pIdx, /* The index for which to generate a key */ int iCur, /* Cursor number for the pIdx->pTable table */ - int regOut /* Write the new index key to this register */ + int regOut, /* Write the new index key to this register */ + int doMakeRec /* Run the OP_MakeRecord instruction if true */ ){ Vdbe *v = pParse->pVdbe; int j; @@ -532,8 +531,10 @@ int sqlite3GenerateIndexKey( sqlite3ColumnDefault(v, pTab, idx); } } - sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol+1, regOut); - sqlite3IndexAffinityStr(v, pIdx); + if( doMakeRec ){ + sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol+1, regOut); + sqlite3IndexAffinityStr(v, pIdx); + } sqlite3ReleaseTempRange(pParse, regBase, nCol+1); return regBase; } diff --git a/src/pragma.c b/src/pragma.c index 98d7d2a0ff..8c396b3b42 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -11,7 +11,7 @@ ************************************************************************* ** This file contains code used to implement the PRAGMA command. ** -** $Id: pragma.c,v 1.172 2008/03/20 11:04:21 danielk1977 Exp $ +** $Id: pragma.c,v 1.173 2008/03/25 17:23:33 drh Exp $ */ #include "sqliteInt.h" #include @@ -941,7 +941,7 @@ void sqlite3Pragma( { OP_IfPos, 1, 0, 0}, /* 9 */ { OP_Halt, 0, 0, 0}, }; - sqlite3GenerateIndexKey(pParse, pIdx, 1, 3); + sqlite3GenerateIndexKey(pParse, pIdx, 1, 3, 1); jmp2 = sqlite3VdbeAddOp3(v, OP_Found, j+2, 0, 3); addr = sqlite3VdbeAddOpList(v, ArraySize(idxErr), idxErr); sqlite3VdbeChangeP4(v, addr+1, "rowid ", P4_STATIC); diff --git a/src/select.c b/src/select.c index 3df5f40559..8167056ba4 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.418 2008/03/25 09:47:35 danielk1977 Exp $ +** $Id: select.c,v 1.419 2008/03/25 17:23:33 drh Exp $ */ #include "sqliteInt.h" @@ -598,12 +598,7 @@ static void selectInnerLoop( ** the temporary table iParm. */ case SRT_Except: { - int r1; - r1 = sqlite3GetTempReg(pParse); - sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nColumn, r1); - sqlite3VdbeChangeP4(v, -1, aff, P4_STATIC); - sqlite3VdbeAddOp2(v, OP_IdxDelete, iParm, r1); - sqlite3ReleaseTempReg(pParse, r1); + sqlite3VdbeAddOp3(v, OP_IdxDelete, iParm, regResult, nColumn); break; } #endif diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 8f6b5bdd62..b5abcd6612 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -11,7 +11,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.679 2008/03/21 16:45:47 drh Exp $ +** @(#) $Id: sqliteInt.h,v 1.680 2008/03/25 17:23:33 drh Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ @@ -1863,7 +1863,7 @@ int sqlite3ExprIsInteger(Expr*, int*); int sqlite3IsRowid(const char*); void sqlite3GenerateRowDelete(Parse*, Table*, int, int, int); void sqlite3GenerateRowIndexDelete(Parse*, Table*, int, int*); -int sqlite3GenerateIndexKey(Parse*, Index*, int, int); +int sqlite3GenerateIndexKey(Parse*, Index*, int, int, int); void sqlite3GenerateConstraintChecks(Parse*,Table*,int,int, int*,int,int,int,int); void sqlite3CompleteInsertion(Parse*, Table*, int, int, int*,int,int,int,int); diff --git a/src/test3.c b/src/test3.c index e3922f67d8..e147bc9c32 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.93 2008/03/25 09:47:35 danielk1977 Exp $ +** $Id: test3.c,v 1.94 2008/03/25 17:23:33 drh Exp $ */ #include "sqliteInt.h" #include "btreeInt.h" @@ -788,9 +788,9 @@ static int btree_move_to( sqlite3BtreeLeave(pCur->pBtree); return TCL_ERROR; } - rc = sqlite3BtreeMoveto(pCur, 0, iKey, 0, &res); + rc = sqlite3BtreeMoveto(pCur, 0, 0, iKey, 0, &res); }else{ - rc = sqlite3BtreeMoveto(pCur, argv[2], strlen(argv[2]), 0, &res); + rc = sqlite3BtreeMoveto(pCur, argv[2], 0, strlen(argv[2]), 0, &res); } sqlite3BtreeLeave(pCur->pBtree); if( rc ){ diff --git a/src/vdbe.c b/src/vdbe.c index e491340fae..72657ce36f 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.717 2008/03/25 09:47:35 danielk1977 Exp $ +** $Id: vdbe.c,v 1.718 2008/03/25 17:23:33 drh Exp $ */ #include "sqliteInt.h" #include @@ -2794,7 +2794,7 @@ case OP_MoveGt: { /* jump, in3 */ pC->deferredMoveto = 1; break; } - rc = sqlite3BtreeMoveto(pC->pCursor, 0, (u64)iKey, 0, &res); + rc = sqlite3BtreeMoveto(pC->pCursor, 0, 0, (u64)iKey, 0, &res); if( rc!=SQLITE_OK ){ goto abort_due_to_error; } @@ -2803,7 +2803,7 @@ case OP_MoveGt: { /* jump, in3 */ }else{ assert( pIn3->flags & MEM_Blob ); ExpandBlob(pIn3); - rc = sqlite3BtreeMoveto(pC->pCursor, pIn3->z, pIn3->n, 0, &res); + rc = sqlite3BtreeMoveto(pC->pCursor, pIn3->z, 0, pIn3->n, 0, &res); if( rc!=SQLITE_OK ){ goto abort_due_to_error; } @@ -2888,7 +2888,7 @@ case OP_Found: { /* jump, in3 */ if( pOp->opcode==OP_Found ){ pC->pKeyInfo->prefixIsEqual = 1; } - rc = sqlite3BtreeMoveto(pC->pCursor, pIn3->z, pIn3->n, 0, &res); + rc = sqlite3BtreeMoveto(pC->pCursor, pIn3->z, 0, pIn3->n, 0, &res); pC->pKeyInfo->prefixIsEqual = 0; if( rc!=SQLITE_OK ){ break; @@ -2965,7 +2965,7 @@ case OP_IsUnique: { /* jump, in3 */ */ assert( pCx->deferredMoveto==0 ); pCx->cacheStatus = CACHE_STALE; - rc = sqlite3BtreeMoveto(pCrsr, zKey, len, 0, &res); + rc = sqlite3BtreeMoveto(pCrsr, zKey, 0, len, 0, &res); if( rc!=SQLITE_OK ){ goto abort_due_to_error; } @@ -3033,7 +3033,7 @@ case OP_NotExists: { /* jump, in3 */ assert( pIn3->flags & MEM_Int ); assert( p->apCsr[i]->isTable ); iKey = intToKey(pIn3->u.i); - rc = sqlite3BtreeMoveto(pCrsr, 0, iKey, 0,&res); + rc = sqlite3BtreeMoveto(pCrsr, 0, 0, iKey, 0,&res); pC->lastRowid = pIn3->u.i; pC->rowidIsValid = res==0; pC->nullRow = 0; @@ -3203,7 +3203,7 @@ case OP_NewRowid: { /* out2-prerelease */ } if( v==0 ) continue; x = intToKey(v); - rx = sqlite3BtreeMoveto(pC->pCursor, 0, (u64)x, 0, &res); + rx = sqlite3BtreeMoveto(pC->pCursor, 0, 0, (u64)x, 0, &res); cnt++; }while( cnt<100 && rx==SQLITE_OK && res==0 ); db->priorNewRowid = v; @@ -3676,22 +3676,29 @@ case OP_IdxInsert: { /* in2 */ break; } -/* Opcode: IdxDelete P1 P2 * * * +/* Opcode: IdxDeleteM P1 P2 P3 * * ** -** The content of register P2 is an index key built using the -** MakeIdxRec opcode. This opcode removes that entry from the +** The content of P3 registers starting at register P2 form +** an unpacked index key. This opcode removes that entry from the ** index opened by cursor P1. */ -case OP_IdxDelete: { /* in2 */ +case OP_IdxDelete: { int i = pOp->p1; Cursor *pC; BtCursor *pCrsr; - assert( pIn2->flags & MEM_Blob ); + assert( pOp->p3>0 ); + assert( pOp->p2>0 && pOp->p2+pOp->p3<=p->nMem ); assert( i>=0 && inCursor ); assert( p->apCsr[i]!=0 ); if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){ int res; - rc = sqlite3BtreeMoveto(pCrsr, pIn2->z, pIn2->n, 0, &res); + UnpackedRecord r; + r.pKeyInfo = pC->pKeyInfo; + r.nField = pOp->p3; + r.needFree = 0; + r.needDestroy = 0; + r.aMem = &p->aMem[pOp->p2]; + rc = sqlite3BtreeMoveto(pCrsr, 0, &r, 0, 0, &res); if( rc==SQLITE_OK && res==0 ){ rc = sqlite3BtreeDelete(pCrsr); } diff --git a/src/vdbe.h b/src/vdbe.h index 5a5193ebaa..ad6d870042 100644 --- a/src/vdbe.h +++ b/src/vdbe.h @@ -15,7 +15,7 @@ ** or VDBE. The VDBE implements an abstract machine that runs a ** simple program to access and modify the underlying database. ** -** $Id: vdbe.h,v 1.127 2008/03/25 00:22:21 drh Exp $ +** $Id: vdbe.h,v 1.128 2008/03/25 17:23:34 drh Exp $ */ #ifndef _SQLITE_VDBE_H_ #define _SQLITE_VDBE_H_ @@ -34,7 +34,7 @@ typedef struct Vdbe Vdbe; */ typedef struct VdbeFunc VdbeFunc; typedef struct Mem Mem; -typedef struct VdbeParsedRecord VdbeParsedRecord; +typedef struct UnpackedRecord UnpackedRecord; /* ** A single instruction of the virtual machine has an opcode @@ -182,9 +182,9 @@ sqlite3 *sqlite3VdbeDb(Vdbe*); void sqlite3VdbeSetSql(Vdbe*, const char *z, int n); void sqlite3VdbeSwap(Vdbe*,Vdbe*); -VdbeParsedRecord *sqlite3VdbeRecordParse(KeyInfo*,int,const void*,void*,int); -void sqlite3VdbeRecordUnparse(VdbeParsedRecord*); -int sqlite3VdbeRecordCompareParsed(int,const void*,VdbeParsedRecord*); +UnpackedRecord *sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,void*,int); +void sqlite3VdbeDeleteUnpackedRecord(UnpackedRecord*); +int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*); #ifndef NDEBUG diff --git a/src/vdbeInt.h b/src/vdbeInt.h index 4985283cc7..08821f2661 100644 --- a/src/vdbeInt.h +++ b/src/vdbeInt.h @@ -335,6 +335,28 @@ struct Vdbe { #endif }; +/* +** An instance of the following structure holds information about a +** single index record that has already been parsed out into individual +** values. +** +** A record is an object that contains one or more fields of data. +** Records are used to store the content of a table row and to store +** the key of an index. A blob encoding of a record is created by +** the OP_MakeRecord opcode of the VDBE and is disassemblied by the +** OP_Column opcode. +** +** This structure holds a record that has already been disassembled +** into its constitutent fields. +*/ +struct UnpackedRecord { + KeyInfo *pKeyInfo; /* Collation and sort-order information */ + u16 nField; /* Number of entries in apMem[] */ + u8 needFree; /* True if memory obtained from sqlite3_malloc() */ + u8 needDestroy; /* True if apMem[]s should be destroyed on close */ + Mem *aMem; /* Values */ +}; + /* ** The following are allowed values for Vdbe.magic */ diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 7e7824a017..9399315cf5 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -1803,7 +1803,7 @@ int sqlite3VdbeCursorMoveto(Cursor *p){ extern int sqlite3_search_count; #endif assert( p->isTable ); - rc = sqlite3BtreeMoveto(p->pCursor, 0, p->movetoTarget, 0, &res); + rc = sqlite3BtreeMoveto(p->pCursor, 0, 0, p->movetoTarget, 0, &res); if( rc ) return rc; *p->pIncrKey = 0; p->lastRowid = keyToInt(p->movetoTarget); @@ -2143,120 +2143,9 @@ int sqlite3VdbeSerialGet( */ #define GetVarint(A,B) ((B = *(A))<=0x7f ? 1 : sqlite3GetVarint32(A, &B)) -#if 0 -/* -** This function compares the two table rows or index records specified by -** {nKey1, pKey1} and {nKey2, pKey2}, returning a negative, zero -** or positive integer if {nKey1, pKey1} is less than, equal to or -** greater than {nKey2, pKey2}. Both Key1 and Key2 must be byte strings -** composed by the OP_MakeRecord opcode of the VDBE. -** -** Key1 and Key2 do not have to contain the same number of fields. -** But if the lengths differ, Key2 must be the shorter of the two. -*/ -int sqlite3VdbeRecordCompare( - void *userData, - int nKey1, const void *pKey1, - int nKey2, const void *pKey2 -){ - KeyInfo *pKeyInfo = (KeyInfo*)userData; - u32 d1, d2; /* Offset into aKey[] of next data element */ - u32 idx1, idx2; /* Offset into aKey[] of next header element */ - u32 szHdr1, szHdr2; /* Number of bytes in header */ - int i = 0; - int nField; - int rc = 0; - const unsigned char *aKey1 = (const unsigned char *)pKey1; - const unsigned char *aKey2 = (const unsigned char *)pKey2; - - Mem mem1; - Mem mem2; - mem1.enc = pKeyInfo->enc; - mem1.db = pKeyInfo->db; - mem1.flags = 0; - mem2.enc = pKeyInfo->enc; - mem2.db = pKeyInfo->db; - mem2.flags = 0; - - idx1 = GetVarint(aKey1, szHdr1); - d1 = szHdr1; - idx2 = GetVarint(aKey2, szHdr2); - d2 = szHdr2; - nField = pKeyInfo->nField; - while( idx1=nKey1 && sqlite3VdbeSerialTypeLen(serial_type1)>0 ) break; - idx2 += GetVarint( aKey2+idx2, serial_type2 ); - if( d2>=nKey2 && sqlite3VdbeSerialTypeLen(serial_type2)>0 ) break; - - /* Extract the values to be compared. - */ - d1 += sqlite3VdbeSerialGet(&aKey1[d1], serial_type1, &mem1); - d2 += sqlite3VdbeSerialGet(&aKey2[d2], serial_type2, &mem2); - - /* Do the comparison - */ - rc = sqlite3MemCompare(&mem1, &mem2, iaColl[i] : 0); - if( mem1.flags&MEM_Dyn ) sqlite3VdbeMemRelease(&mem1); - if( mem2.flags&MEM_Dyn ) sqlite3VdbeMemRelease(&mem2); - if( rc!=0 ){ - break; - } - i++; - } - - /* One of the keys ran out of fields, but all the fields up to that point - ** were equal. If the incrKey flag is true, then the second key is - ** treated as larger. - */ - if( rc==0 ){ - if( pKeyInfo->incrKey ){ - rc = -1; - }else if( !pKeyInfo->prefixIsEqual ){ - if( d1aSortOrder && inField - && pKeyInfo->aSortOrder[i] ){ - rc = -rc; - } - - return rc; -} -#endif - -/* -** An instance of the following structure holds information about a -** single index record that has already been parsed out into individual -** values. -** -** A record is an object that contains one or more fields of data. -** Records are used to store the content of a table row and to store -** the key of an index. A blob encoding of a record is created by -** the OP_MakeRecord opcode of the VDBE and is disassemblied by the -** OP_Column opcode. -** -** This structure holds a record that has already been disassembled -** into its constitutent fields. -*/ -struct VdbeParsedRecord { - KeyInfo *pKeyInfo; /* Collation and sort-order information */ - u16 nField; /* Number of entries in apMem[] */ - u8 needFree; /* True if memory obtained from sqlite3_malloc() */ - u8 needDestroy; /* True if apMem[]s should be destroyed on close */ - Mem *apMem[1]; /* Values */ -}; - /* ** Given the nKey-byte encoding of a record in pKey[], parse the -** record into a VdbeParsedRecord structure. Return a pointer to +** record into a UnpackedRecord structure. Return a pointer to ** that structure. ** ** The calling function might provide szSpace bytes of memory @@ -2265,9 +2154,9 @@ struct VdbeParsedRecord { ** not big enough, space is obtained from sqlite3_malloc(). ** ** The returned structure should be closed by a call to -** sqlite3VdbeRecordUnparse(). +** sqlite3VdbeDeleteUnpackedRecord(). */ -VdbeParsedRecord *sqlite3VdbeRecordParse( +UnpackedRecord *sqlite3VdbeRecordUnpack( KeyInfo *pKeyInfo, /* Information about the record format */ int nKey, /* Size of the binary record */ const void *pKey, /* The binary record */ @@ -2275,14 +2164,13 @@ VdbeParsedRecord *sqlite3VdbeRecordParse( int szSpace /* Size of pSpace[] in bytes */ ){ const unsigned char *aKey = (const unsigned char *)pKey; - VdbeParsedRecord *p; + UnpackedRecord *p; int nByte; int i, idx, d; u32 szHdr; Mem *pMem; - nByte = sizeof(*p) + sizeof(Mem*)*pKeyInfo->nField - + sizeof(Mem)*(pKeyInfo->nField+1); + nByte = sizeof(*p) + sizeof(Mem)*(pKeyInfo->nField+1); if( nByte>szSpace ){ p = sqlite3DbMallocRaw(pKeyInfo->db, nByte); if( p==0 ) return 0; @@ -2294,7 +2182,7 @@ VdbeParsedRecord *sqlite3VdbeRecordParse( p->pKeyInfo = pKeyInfo; p->nField = pKeyInfo->nField + 1; p->needDestroy = 1; - pMem = (Mem*)&p->apMem[pKeyInfo->nField+1]; + p->aMem = pMem = (Mem*)&p[1]; idx = GetVarint(aKey, szHdr); d = szHdr; i = 0; @@ -2307,22 +2195,24 @@ VdbeParsedRecord *sqlite3VdbeRecordParse( pMem->db = pKeyInfo->db; pMem->flags = 0; d += sqlite3VdbeSerialGet(&aKey[d], serial_type, pMem); - p->apMem[i++] = pMem++; + pMem++; + i++; } p->nField = i; return (void*)p; } /* -** This routine destroys a VdbeParsedRecord object +** This routine destroys a UnpackedRecord object */ -void sqlite3VdbeRecordUnparse(VdbeParsedRecord *p){ +void sqlite3VdbeDeleteUnpackedRecord(UnpackedRecord *p){ if( p ){ if( p->needDestroy ){ int i; - for(i=0; inField; i++){ - if( p->apMem[i]->flags & MEM_Dyn ){ - sqlite3VdbeMemRelease(p->apMem[i]); + Mem *pMem; + for(i=0, pMem=p->aMem; inField; i++, pMem++){ + if( pMem->flags & MEM_Dyn ){ + sqlite3VdbeMemRelease(pMem); } } } @@ -2351,9 +2241,9 @@ void sqlite3VdbeRecordUnparse(VdbeParsedRecord *p){ ** separately and submit the parsed version. In this way, we avoid ** parsing the same Key2 multiple times in a row. */ -int sqlite3VdbeRecordCompareParsed( +int sqlite3VdbeRecordCompare( int nKey1, const void *pKey1, - VdbeParsedRecord *pPKey2 + UnpackedRecord *pPKey2 ){ u32 d1; /* Offset into aKey[] of next data element */ u32 idx1; /* Offset into aKey[] of next header element */ @@ -2386,7 +2276,7 @@ int sqlite3VdbeRecordCompareParsed( /* Do the comparison */ - rc = sqlite3MemCompare(&mem1, pPKey2->apMem[i], + rc = sqlite3MemCompare(&mem1, &pPKey2->aMem[i], iaColl[i] : 0); if( mem1.flags&MEM_Dyn ) sqlite3VdbeMemRelease(&mem1); if( rc!=0 ){ @@ -2483,7 +2373,7 @@ int sqlite3VdbeIdxKeyCompare( BtCursor *pCur = pC->pCursor; int lenRowid; Mem m; - VdbeParsedRecord *pRec; + UnpackedRecord *pRec; char zSpace[200]; sqlite3BtreeKeySize(pCur, &nCellKey); @@ -2498,13 +2388,13 @@ int sqlite3VdbeIdxKeyCompare( return rc; } lenRowid = sqlite3VdbeIdxRowidLen((u8*)m.z); - pRec = sqlite3VdbeRecordParse(pC->pKeyInfo, nKey, pKey, + pRec = sqlite3VdbeRecordUnpack(pC->pKeyInfo, nKey, pKey, zSpace, sizeof(zSpace)); if( pRec==0 ){ return SQLITE_NOMEM; } - *res = sqlite3VdbeRecordCompareParsed(m.n-lenRowid, m.z, pRec); - sqlite3VdbeRecordUnparse(pRec); + *res = sqlite3VdbeRecordCompare(m.n-lenRowid, m.z, pRec); + sqlite3VdbeDeleteUnpackedRecord(pRec); sqlite3VdbeMemRelease(&m); return SQLITE_OK; }