From e4d90813075a8e86d04f7e0fc7e3d9f6a7977f68 Mon Sep 17 00:00:00 2001 From: drh Date: Thu, 29 Mar 2007 05:51:49 +0000 Subject: [PATCH] Change BtreeMoveto so that it can be biased to the right or to the center. Use a right bias when appending and a center bias when searching. This gives about a 15% reduction in calls to sqlite3VdbeRecordCompare. (CVS 3741) FossilOrigin-Name: ad4a6b1a91bcefd8a4c75e8dc99c1153c72c31a3 --- manifest | 32 ++++++++++++++++---------------- manifest.uuid | 2 +- src/analyze.c | 4 ++-- src/btree.c | 23 +++++++++++++++++------ src/btree.h | 6 +++--- src/build.c | 4 ++-- src/insert.c | 40 +++++++++++++++++++++++++++++----------- src/select.c | 6 +++--- src/sqliteInt.h | 5 +++-- src/test3.c | 10 +++++----- src/update.c | 4 ++-- src/vdbe.c | 28 ++++++++++++++++------------ src/vdbeaux.c | 4 ++-- 13 files changed, 101 insertions(+), 67 deletions(-) diff --git a/manifest b/manifest index d0324205cb..6fdaea8eaf 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Bias\sthe\sb-tree\sbinary\ssearch\stoward\sthe\shigh\send.\s\sThe\scommon\scase\sis\sto\nappend\sdata\sand\sthis\sheuristic\smakes\sappend\srun\smuch\sfaster\sbecause\sthere\nare\sfewer\scomparisons.\s(CVS\s3740) -D 2007-03-29T04:43:26 +C Change\sBtreeMoveto\sso\sthat\sit\scan\sbe\sbiased\sto\sthe\sright\sor\sto\sthe\scenter.\nUse\sa\sright\sbias\swhen\sappending\sand\sa\scenter\sbias\swhen\ssearching.\s\sThis\ngives\sabout\sa\s15%\sreduction\sin\scalls\sto\ssqlite3VdbeRecordCompare.\s(CVS\s3741) +D 2007-03-29T05:51:49 F Makefile.in 1fe3d0b46e40fd684e1e61f8e8056cefed16de9f F Makefile.linux-gcc 2d8574d1ba75f129aba2019f0b959db380a90935 F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028 @@ -55,12 +55,12 @@ F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc F sqlite3.def a96c1d0d39362b763d2ddba220a32da41a15c4b4 F sqlite3.pc.in 985b9bf34192a549d7d370e0f0b6b34a4f61369a F src/alter.c 2c79ec40f65e33deaf90ca493422c74586e481a3 -F src/analyze.c 7d2b7ab9a9c2fd6e55700f69064dfdd3e36d7a8a +F src/analyze.c 4bbf5ddf9680587c6d4917e02e378b6037be3651 F src/attach.c a16ada4a4654a0d126b8223ec9494ebb81bc5c3c F src/auth.c 902f4722661c796b97f007d9606bd7529c02597f -F src/btree.c 434a3584766e85ca3b23d37adb9c457d83f5cf19 -F src/btree.h 066444ee25bd6e6accb997bfd2cf5ace14dbcd00 -F src/build.c d178bd7c8117f5f47694da9a0d5f336e85528180 +F src/btree.c 6619f15c3afacd19e42c7e01ad14df41bf2dc55d +F src/btree.h 540dcbbf83435b77d4b6ef87f909c6cecad4dac9 +F src/build.c ad3374b5409554e504300f77e1fbc6b4c106a57f F src/callback.c 31d22b4919c7645cbcbb1591ce2453e8c677c558 F src/complete.c 7d1a44be8f37de125fcafd3d3a018690b3799675 F src/date.c 393c73fc027597e008dcd81454544659e978b05c @@ -70,7 +70,7 @@ F src/expr.c a8740c24af3f39f2d502be1a1c640c96435eaac0 F src/func.c 94372fe3cf26b81d4dcdc15f98ff240c37c8c708 F src/hash.c 449f3d6620193aa557f5d86cbc5cc6b87702b185 F src/hash.h 1b3f7e2609141fd571f62199fc38687d262e9564 -F src/insert.c 80b1cc840c769b283475ae4a7b4771ba1f7659a2 +F src/insert.c bdd1e2b48fede8ed1c25ca32747b9050bcbe2594 F src/legacy.c 2631df6a861f830d6b1c0fe92b9fdd745b2c0cd6 F src/loadext.c c186ad5c9e8a0aaa73d0caf5f604d112e45e8b89 F src/main.c ed005bbc1d94670c8d9e2b93d446bd493119c44c @@ -93,17 +93,17 @@ F src/pragma.c 9cb8b94e7d38ba35a86037bd517d07ba9870b4b2 F src/prepare.c 37207b2b2ccb41d379b01dd62231686bcc48ef1f F src/printf.c aade23a789d7cc88b397ec0d33a0a01a33a7a9c1 F src/random.c 6119474a6f6917f708c1dee25b9a8e519a620e88 -F src/select.c 4d68a0d7f98fb59bcedd0be69750e0445b05899c +F src/select.c 30af458c6a0a4a283c67b56c70ff0712b67d42ae F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96 F src/shell.c 3ae4654560e91220a95738a73d135d91d937cda1 F src/sqlite.h.in 02d1159bc8f7387008df9766c79038fce8a9d3a7 F src/sqlite3ext.h 832e13de075d920e2c76584e2b7af1054bb212df -F src/sqliteInt.h ace601a40db30d667422c79a7db57e7dabb48038 +F src/sqliteInt.h c8d0e5ce27a862836de70fc3eadc1e65cea7e3d8 F src/table.c 6d0da66dde26ee75614ed8f584a1996467088d06 F src/tclsqlite.c cd2b3b86ab07c0e0779f6c6e71e72c6c7dc1e704 F src/test1.c 439bba8da10fbc61c731019cf2894e6057578878 F src/test2.c dc48c84ce68b3bc2f2d01871d709f20dc77003b0 -F src/test3.c b40ca2eb1390a4c5a41bc8c545284a32aca69991 +F src/test3.c 65f92247cf8592854e9bf5115b3fb711f8b33280 F src/test4.c 8b784cd82de158a2317cb4ac4bc86f91ad315e25 F src/test5.c 7162f8526affb771c4ed256826eee7bb9eca265f F src/test6.c 5957d249d437e4db74045ce2f1f661648d94bf94 @@ -118,15 +118,15 @@ F src/test_server.c a6460daed0b92ecbc2531b6dc73717470e7a648c F src/test_tclvar.c 315e77c17f128ff8c06b38c08617fd07c825a95b F src/tokenize.c bb1732ef2b6fc2143f93ff28a45d3dcb04c1d396 F src/trigger.c 8c55d31876013ed4e97ee7ce24478fbe00db49bb -F src/update.c 876b3142b8db9ce6ddf8374a2ced65e576acabc7 +F src/update.c 3359041db390a8f856d67272f299600e2104f350 F src/utf.c 67ecb1032bc0b42c105e88d65ef9d9f626eb0e1f F src/util.c 8e8180ee5597f2474c1da311ff3c464b6966c0f1 F src/vacuum.c 8bd895d29e7074e78d4e80f948e35ddc9cf2beef -F src/vdbe.c 9fc4520600f364ec510e7c74733dc2b77430b92a +F src/vdbe.c e214ce8f760f839d7171714f895e362facaae4dd F src/vdbe.h 0025259af1939fb264a545816c69e4b5b8d52691 F src/vdbeInt.h b2ca85ca8abfbba86e380b06c7673dc81c6784c3 F src/vdbeapi.c 6cff63a5b3a52af04b2bef0f7e27ed7ea6f85183 -F src/vdbeaux.c 1a50dce809a2f5c2d32e8096166b59016dab1b45 +F src/vdbeaux.c 2cf328d44683f1d6b537809536873b1999be6f20 F src/vdbefifo.c 3ca8049c561d5d67cbcb94dc909ae9bb68c0bf8f F src/vdbemem.c 58a8be2231b0b13e2e77098debe173e79d22f791 F src/vtab.c 7fbda947e28cbe7adb3ba752a76ca9ef29936750 @@ -442,7 +442,7 @@ F www/tclsqlite.tcl bb0d1357328a42b1993d78573e587c6dcbc964b9 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513 -P e72c81dbb309709462e49c4e3e90c3e16ead1265 -R 2f8c0ebcc5b977db1cd11a734857a630 +P a9877f616b24737152627841fcbd80cc28426f1e +R 63136fc2c62ce921e31331d55ad9708c U drh -Z f092376d9c3cfc91e80b8841598ffc58 +Z ae6ac3fd2b6690aaaa258fb90ac6d9d8 diff --git a/manifest.uuid b/manifest.uuid index 1de5ee3b4c..8a89783592 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -a9877f616b24737152627841fcbd80cc28426f1e \ No newline at end of file +ad4a6b1a91bcefd8a4c75e8dc99c1153c72c31a3 \ No newline at end of file diff --git a/src/analyze.c b/src/analyze.c index 3d27134e4a..abbbf0fd52 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.16 2006/01/10 17:58:23 danielk1977 Exp $ +** @(#) $Id: analyze.c,v 1.17 2007/03/29 05:51:49 drh Exp $ */ #ifndef SQLITE_OMIT_ANALYZE #include "sqliteInt.h" @@ -211,7 +211,7 @@ static void analyzeOneTable( } } sqlite3VdbeOp3(v, OP_MakeRecord, 3, 0, "aaa", 0); - sqlite3VdbeAddOp(v, OP_Insert, iStatCur, 0); + sqlite3VdbeAddOp(v, OP_Insert, iStatCur, OPFLAG_APPEND); sqlite3VdbeJumpHere(v, addr); } } diff --git a/src/btree.c b/src/btree.c index f75cbe376e..ac999e1cd2 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.344 2007/03/29 04:43:26 drh Exp $ +** $Id: btree.c,v 1.345 2007/03/29 05:51:49 drh Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** For a detailed discussion of BTrees, refer to @@ -728,7 +728,7 @@ static int restoreOrClearCursorPositionX(BtCursor *pCur, int doSeek){ assert( pCur->eState==CURSOR_REQUIRESEEK ); pCur->eState = CURSOR_INVALID; if( doSeek ){ - rc = sqlite3BtreeMoveto(pCur, pCur->pKey, pCur->nKey, &pCur->skip); + rc = sqlite3BtreeMoveto(pCur, pCur->pKey, pCur->nKey, 0, &pCur->skip); } if( rc==SQLITE_OK ){ sqliteFree(pCur->pKey); @@ -3303,7 +3303,13 @@ int sqlite3BtreeLast(BtCursor *pCur, int *pRes){ ** *pRes>0 The cursor is left pointing at an entry that ** is larger than pKey. */ -int sqlite3BtreeMoveto(BtCursor *pCur, const void *pKey, i64 nKey, int *pRes){ +int sqlite3BtreeMoveto( + BtCursor *pCur, /* The cursor to be moved */ + const void *pKey, /* The key content for indices. Not used by tables */ + 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; rc = moveToRoot(pCur); if( rc ) return rc; @@ -3324,7 +3330,11 @@ int sqlite3BtreeMoveto(BtCursor *pCur, const void *pKey, i64 nKey, int *pRes){ if( !pPage->intKey && pKey==0 ){ return SQLITE_CORRUPT_BKPT; } - pCur->idx = upr; + if( biasRight ){ + pCur->idx = upr; + }else{ + pCur->idx = (upr+lwr)/2; + } if( lwr<=upr ) for(;;){ void *pCellKey; i64 nCellKey; @@ -5182,7 +5192,8 @@ static int checkReadLocks(Btree *pBtree, Pgno pgnoRoot, BtCursor *pExclude){ int sqlite3BtreeInsert( BtCursor *pCur, /* Insert data into the table of this cursor */ const void *pKey, i64 nKey, /* The key of the new record */ - const void *pData, int nData /* The data of the new record */ + const void *pData, int nData, /* The data of the new record */ + int appendBias /* True if this is likely an append */ ){ int rc; int loc; @@ -5208,7 +5219,7 @@ int sqlite3BtreeInsert( restoreOrClearCursorPosition(pCur, 0); if( SQLITE_OK!=(rc = saveAllCursors(pBt, pCur->pgnoRoot, pCur)) || - SQLITE_OK!=(rc = sqlite3BtreeMoveto(pCur, pKey, nKey, &loc)) + SQLITE_OK!=(rc = sqlite3BtreeMoveto(pCur, pKey, nKey, appendBias, &loc)) ){ return rc; } diff --git a/src/btree.h b/src/btree.h index 8a05759ee9..513e9a0826 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.72 2007/01/27 02:24:55 drh Exp $ +** @(#) $Id: btree.h,v 1.73 2007/03/29 05:51:49 drh Exp $ */ #ifndef _BTREE_H_ #define _BTREE_H_ @@ -114,10 +114,10 @@ void sqlite3BtreeSetCompare( ); int sqlite3BtreeCloseCursor(BtCursor*); -int sqlite3BtreeMoveto(BtCursor*, const void *pKey, i64 nKey, int *pRes); +int sqlite3BtreeMoveto(BtCursor*,const void *pKey,i64 nKey,int bias,int *pRes); int sqlite3BtreeDelete(BtCursor*); int sqlite3BtreeInsert(BtCursor*, const void *pKey, i64 nKey, - const void *pData, int nData); + const void *pData, int nData, int bias); int sqlite3BtreeFirst(BtCursor*, int *pRes); int sqlite3BtreeLast(BtCursor*, int *pRes); int sqlite3BtreeNext(BtCursor*, int *pRes); diff --git a/src/build.c b/src/build.c index de3629be7c..cc38cf72ec 100644 --- a/src/build.c +++ b/src/build.c @@ -22,7 +22,7 @@ ** COMMIT ** ROLLBACK ** -** $Id: build.c,v 1.417 2007/03/27 13:36:37 drh Exp $ +** $Id: build.c,v 1.418 2007/03/29 05:51:49 drh Exp $ */ #include "sqliteInt.h" #include @@ -887,7 +887,7 @@ void sqlite3StartTable( sqlite3VdbeAddOp(v, OP_NewRowid, 0, 0); sqlite3VdbeAddOp(v, OP_Dup, 0, 0); sqlite3VdbeAddOp(v, OP_Null, 0, 0); - sqlite3VdbeAddOp(v, OP_Insert, 0, 0); + sqlite3VdbeAddOp(v, OP_Insert, 0, OPFLAG_APPEND); sqlite3VdbeAddOp(v, OP_Close, 0, 0); sqlite3VdbeAddOp(v, OP_Pull, 1, 0); } diff --git a/src/insert.c b/src/insert.c index e69f9c85cd..0d0bc0782a 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.179 2007/03/29 00:08:25 drh Exp $ +** $Id: insert.c,v 1.180 2007/03/29 05:51:49 drh Exp $ */ #include "sqliteInt.h" @@ -205,7 +205,7 @@ static void autoIncEnd( sqlite3VdbeOp3(v, OP_String8, 0, 0, pTab->zName, 0); sqlite3VdbeAddOp(v, OP_MemLoad, memId, 0); sqlite3VdbeAddOp(v, OP_MakeRecord, 2, 0); - sqlite3VdbeAddOp(v, OP_Insert, iCur, 0); + sqlite3VdbeAddOp(v, OP_Insert, iCur, OPFLAG_APPEND); sqlite3VdbeAddOp(v, OP_Close, iCur, 0); } } @@ -346,6 +346,7 @@ void sqlite3Insert( int newIdx = -1; /* Cursor for the NEW table */ Db *pDb; /* The database containing table being inserted into */ int counterMem = 0; /* Memory cell holding AUTOINCREMENT counter */ + int appendFlag = 0; /* True if the insert is likely to be an append */ int iDb; #ifndef SQLITE_OMIT_TRIGGER @@ -489,7 +490,7 @@ void sqlite3Insert( sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, 0); sqlite3VdbeAddOp(v, OP_NewRowid, srcTab, 0); sqlite3VdbeAddOp(v, OP_Pull, 1, 0); - sqlite3VdbeAddOp(v, OP_Insert, srcTab, 0); + sqlite3VdbeAddOp(v, OP_Insert, srcTab, OPFLAG_APPEND); sqlite3VdbeAddOp(v, OP_Return, 0, 0); /* The following code runs first because the GOTO at the very top @@ -701,19 +702,30 @@ void sqlite3Insert( }else if( pSelect ){ sqlite3VdbeAddOp(v, OP_Dup, nColumn - keyColumn - 1, 1); }else{ + VdbeOp *pOp; sqlite3ExprCode(pParse, pList->a[keyColumn].pExpr); + pOp = sqlite3VdbeGetOp(v, sqlite3VdbeCurrentAddr(v) - 1); + if( pOp->opcode==OP_Null ){ + appendFlag = 1; + pOp->opcode = OP_NewRowid; + pOp->p1 = base; + pOp->p2 = counterMem; + } } /* If the PRIMARY KEY expression is NULL, then use OP_NewRowid ** to generate a unique primary key value. */ - sqlite3VdbeAddOp(v, OP_NotNull, -1, sqlite3VdbeCurrentAddr(v)+3); - sqlite3VdbeAddOp(v, OP_Pop, 1, 0); - sqlite3VdbeAddOp(v, OP_NewRowid, base, counterMem); - sqlite3VdbeAddOp(v, OP_MustBeInt, 0, 0); + if( !appendFlag ){ + sqlite3VdbeAddOp(v, OP_NotNull, -1, sqlite3VdbeCurrentAddr(v)+3); + sqlite3VdbeAddOp(v, OP_Pop, 1, 0); + sqlite3VdbeAddOp(v, OP_NewRowid, base, counterMem); + sqlite3VdbeAddOp(v, OP_MustBeInt, 0, 0); + } }else if( IsVirtual(pTab) ){ sqlite3VdbeAddOp(v, OP_Null, 0, 0); }else{ sqlite3VdbeAddOp(v, OP_NewRowid, base, counterMem); + appendFlag = 1; } autoIncStep(pParse, counterMem); @@ -761,7 +773,8 @@ void sqlite3Insert( sqlite3GenerateConstraintChecks(pParse, pTab, base, 0, keyColumn>=0, 0, onError, endOfLoop); sqlite3CompleteInsertion(pParse, pTab, base, 0,0,0, - (triggers_exist & TRIGGER_AFTER)!=0 ? newIdx : -1); + (triggers_exist & TRIGGER_AFTER)!=0 ? newIdx : -1, + appendFlag); } } @@ -1172,7 +1185,8 @@ void sqlite3CompleteInsertion( char *aIdxUsed, /* Which indices are used. NULL means all are used */ int rowidChng, /* True if the record number will change */ int isUpdate, /* True for UPDATE, False for INSERT */ - int newIdx /* Index of NEW table for triggers. -1 if none */ + int newIdx, /* Index of NEW table for triggers. -1 if none */ + int appendBias /* True if this is likely to be an append */ ){ int i; Vdbe *v; @@ -1203,6 +1217,9 @@ void sqlite3CompleteInsertion( pik_flags = OPFLAG_NCHANGE; pik_flags |= (isUpdate?OPFLAG_ISUPDATE:OPFLAG_LASTROWID); } + if( appendBias ){ + pik_flags |= OPFLAG_APPEND; + } sqlite3VdbeAddOp(v, OP_Insert, base, pik_flags); if( !pParse->nested ){ sqlite3VdbeChangeP3(v, -1, pTab->zName, P3_STATIC); @@ -1515,7 +1532,8 @@ static int xferOptimization( addr1 = sqlite3VdbeAddOp(v, OP_Rowid, iSrc, 0); } sqlite3VdbeAddOp(v, OP_RowData, iSrc, 0); - sqlite3VdbeOp3(v, OP_Insert, iDest, OPFLAG_NCHANGE|OPFLAG_LASTROWID, + sqlite3VdbeOp3(v, OP_Insert, iDest, + OPFLAG_NCHANGE|OPFLAG_LASTROWID|OPFLAG_APPEND, pDest->zName, 0); sqlite3VdbeAddOp(v, OP_Next, iSrc, addr1); autoIncEnd(pParse, iDbDest, pDest, counterMem); @@ -1545,7 +1563,7 @@ static int xferOptimization( "UNIQUE constraint failed", P3_STATIC); sqlite3VdbeJumpHere(v, addr2); } - sqlite3VdbeAddOp(v, OP_IdxInsert, iDest, 0); + sqlite3VdbeAddOp(v, OP_IdxInsert, iDest, 1); sqlite3VdbeAddOp(v, OP_Next, iSrc, addr1+1); sqlite3VdbeJumpHere(v, addr1); } diff --git a/src/select.c b/src/select.c index d7fb3f1790..b5062393a3 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.330 2007/03/02 07:27:00 danielk1977 Exp $ +** $Id: select.c,v 1.331 2007/03/29 05:51:49 drh Exp $ */ #include "sqliteInt.h" @@ -535,7 +535,7 @@ static int selectInnerLoop( }else{ sqlite3VdbeAddOp(v, OP_NewRowid, iParm, 0); sqlite3VdbeAddOp(v, OP_Pull, 1, 0); - sqlite3VdbeAddOp(v, OP_Insert, iParm, 0); + sqlite3VdbeAddOp(v, OP_Insert, iParm, OPFLAG_APPEND); } break; } @@ -714,7 +714,7 @@ static void generateSortTail( case SRT_EphemTab: { sqlite3VdbeAddOp(v, OP_NewRowid, iParm, 0); sqlite3VdbeAddOp(v, OP_Pull, 1, 0); - sqlite3VdbeAddOp(v, OP_Insert, iParm, 0); + sqlite3VdbeAddOp(v, OP_Insert, iParm, OPFLAG_APPEND); break; } #ifndef SQLITE_OMIT_SUBQUERY diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 354e242e92..71c21eac28 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -11,7 +11,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.546 2007/03/28 14:30:07 drh Exp $ +** @(#) $Id: sqliteInt.h,v 1.547 2007/03/29 05:51:49 drh Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ @@ -1376,6 +1376,7 @@ struct AuthContext { #define OPFLAG_NCHANGE 1 /* Set to update db->nChange */ #define OPFLAG_LASTROWID 2 /* Set to update db->lastRowid */ #define OPFLAG_ISUPDATE 4 /* This OP_Insert is an sql UPDATE */ +#define OPFLAG_APPEND 8 /* This is likely to be an append */ /* * Each trigger present in the database schema is stored as an instance of @@ -1692,7 +1693,7 @@ void sqlite3GenerateRowDelete(sqlite3*, Vdbe*, Table*, int, int); void sqlite3GenerateRowIndexDelete(Vdbe*, Table*, int, char*); void sqlite3GenerateIndexKey(Vdbe*, Index*, int); void sqlite3GenerateConstraintChecks(Parse*,Table*,int,char*,int,int,int,int); -void sqlite3CompleteInsertion(Parse*, Table*, int, char*, int, int, int); +void sqlite3CompleteInsertion(Parse*, Table*, int, char*, int, int, int, int); void sqlite3OpenTableAndIndices(Parse*, Table*, int, int); void sqlite3BeginWriteOperation(Parse*, int, int); Expr *sqlite3ExprDup(Expr*); diff --git a/src/test3.c b/src/test3.c index 8dd510a9b2..fba3fa2eca 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.72 2007/03/26 22:05:02 drh Exp $ +** $Id: test3.c,v 1.73 2007/03/29 05:51:49 drh Exp $ */ #include "sqliteInt.h" #include "pager.h" @@ -706,9 +706,9 @@ static int btree_move_to( if( sqlite3BtreeFlags(pCur) & BTREE_INTKEY ){ int iKey; if( Tcl_GetInt(interp, argv[2], &iKey) ) return TCL_ERROR; - rc = sqlite3BtreeMoveto(pCur, 0, iKey, &res); + rc = sqlite3BtreeMoveto(pCur, 0, iKey, 0, &res); }else{ - rc = sqlite3BtreeMoveto(pCur, argv[2], strlen(argv[2]), &res); + rc = sqlite3BtreeMoveto(pCur, argv[2], strlen(argv[2]), 0, &res); } if( rc ){ Tcl_AppendResult(interp, errorName(rc), 0); @@ -775,7 +775,7 @@ static int btree_insert( unsigned char *pBuf; if( Tcl_GetWideIntFromObj(interp, objv[2], &iKey) ) return TCL_ERROR; pBuf = Tcl_GetByteArrayFromObj(objv[3], &len); - rc = sqlite3BtreeInsert(pCur, 0, iKey, pBuf, len); + rc = sqlite3BtreeInsert(pCur, 0, iKey, pBuf, len, 0); }else{ int keylen; int dlen; @@ -783,7 +783,7 @@ static int btree_insert( unsigned char *pDBuf; pKBuf = Tcl_GetByteArrayFromObj(objv[2], &keylen); pDBuf = Tcl_GetByteArrayFromObj(objv[3], &dlen); - rc = sqlite3BtreeInsert(pCur, pKBuf, keylen, pDBuf, dlen); + rc = sqlite3BtreeInsert(pCur, pKBuf, keylen, pDBuf, dlen, 0); } if( rc ){ Tcl_AppendResult(interp, errorName(rc), 0); diff --git a/src/update.c b/src/update.c index bff7bdf033..b1896a2c12 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.136 2007/02/21 17:04:04 danielk1977 Exp $ +** $Id: update.c,v 1.137 2007/03/29 05:51:49 drh Exp $ */ #include "sqliteInt.h" @@ -465,7 +465,7 @@ void sqlite3Update( /* Create the new index entries and the new record. */ - sqlite3CompleteInsertion(pParse, pTab, iCur, aIdxUsed, chngRowid, 1, -1); + sqlite3CompleteInsertion(pParse, pTab, iCur, aIdxUsed, chngRowid, 1, -1, 0); } /* Increment the row counter diff --git a/src/vdbe.c b/src/vdbe.c index ad0588a7c2..535c4118b5 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.595 2007/03/28 14:30:07 drh Exp $ +** $Id: vdbe.c,v 1.596 2007/03/29 05:51:49 drh Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -2834,7 +2834,7 @@ case OP_MoveGt: { /* no-push */ pTos--; break; } - rc = sqlite3BtreeMoveto(pC->pCursor, 0, (u64)iKey, &res); + rc = sqlite3BtreeMoveto(pC->pCursor, 0, (u64)iKey, 0, &res); if( rc!=SQLITE_OK ){ goto abort_due_to_error; } @@ -2843,7 +2843,7 @@ case OP_MoveGt: { /* no-push */ }else{ assert( pTos->flags & MEM_Blob ); /* Stringify(pTos, encoding); */ - rc = sqlite3BtreeMoveto(pC->pCursor, pTos->z, pTos->n, &res); + rc = sqlite3BtreeMoveto(pC->pCursor, pTos->z, pTos->n, 0, &res); if( rc!=SQLITE_OK ){ goto abort_due_to_error; } @@ -2950,7 +2950,7 @@ case OP_Found: { /* no-push */ int res, rx; assert( pC->isTable==0 ); Stringify(pTos, encoding); - rx = sqlite3BtreeMoveto(pC->pCursor, pTos->z, pTos->n, &res); + rx = sqlite3BtreeMoveto(pC->pCursor, pTos->z, pTos->n, 0, &res); alreadyExists = rx==SQLITE_OK && res==0; pC->deferredMoveto = 0; pC->cacheStatus = CACHE_STALE; @@ -3028,7 +3028,7 @@ case OP_IsUnique: { /* no-push */ */ assert( pCx->deferredMoveto==0 ); pCx->cacheStatus = CACHE_STALE; - rc = sqlite3BtreeMoveto(pCrsr, zKey, len, &res); + rc = sqlite3BtreeMoveto(pCrsr, zKey, len, 0, &res); if( rc!=SQLITE_OK ){ goto abort_due_to_error; } @@ -3098,7 +3098,7 @@ case OP_NotExists: { /* no-push */ assert( pTos->flags & MEM_Int ); assert( p->apCsr[i]->isTable ); iKey = intToKey(pTos->i); - rc = sqlite3BtreeMoveto(pCrsr, 0, iKey, &res); + rc = sqlite3BtreeMoveto(pCrsr, 0, iKey, 0,&res); pC->lastRowid = pTos->i; pC->rowidIsValid = res==0; pC->nullRow = 0; @@ -3270,7 +3270,7 @@ case OP_NewRowid: { } if( v==0 ) continue; x = intToKey(v); - rx = sqlite3BtreeMoveto(pC->pCursor, 0, (u64)x, &res); + rx = sqlite3BtreeMoveto(pC->pCursor, 0, (u64)x, 0, &res); cnt++; }while( cnt<1000 && rx==SQLITE_OK && res==0 ); db->priorNewRowid = v; @@ -3350,7 +3350,9 @@ case OP_Insert: { /* no-push */ } pC->nullRow = 0; }else{ - rc = sqlite3BtreeInsert(pC->pCursor, 0, iKey, pTos->z, pTos->n); + rc = sqlite3BtreeInsert(pC->pCursor, 0, iKey, + pTos->z, pTos->n, + pOp->p2 & OPFLAG_APPEND); } pC->rowidIsValid = 0; @@ -3704,12 +3706,15 @@ case OP_Next: { /* no-push */ break; } -/* Opcode: IdxInsert P1 * * +/* Opcode: IdxInsert P1 P2 * ** ** The top of the stack holds a SQL index key made using either the ** MakeIdxRec or MakeRecord instructions. This opcode writes that key ** into the index P1. Data for the entry is nil. ** +** P2 is a flag that provides a hint to the b-tree layer that this +** insert is likely to be an append. +** ** This instruction only works for indices. The equivalent instruction ** for tables is OP_Insert. */ @@ -3721,12 +3726,11 @@ case OP_IdxInsert: { /* no-push */ assert( i>=0 && inCursor ); assert( p->apCsr[i]!=0 ); assert( pTos->flags & MEM_Blob ); - assert( pOp->p2==0 ); if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){ int nKey = pTos->n; const char *zKey = pTos->z; assert( pC->isTable==0 ); - rc = sqlite3BtreeInsert(pCrsr, zKey, nKey, "", 0); + rc = sqlite3BtreeInsert(pCrsr, zKey, nKey, "", 0, pOp->p2); assert( pC->deferredMoveto==0 ); pC->cacheStatus = CACHE_STALE; } @@ -3751,7 +3755,7 @@ case OP_IdxDelete: { /* no-push */ assert( p->apCsr[i]!=0 ); if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){ int res; - rc = sqlite3BtreeMoveto(pCrsr, pTos->z, pTos->n, &res); + rc = sqlite3BtreeMoveto(pCrsr, pTos->z, pTos->n, 0, &res); if( rc==SQLITE_OK && res==0 ){ rc = sqlite3BtreeDelete(pCrsr); } diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 7172766031..70977f8df4 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -1663,10 +1663,10 @@ int sqlite3VdbeCursorMoveto(Cursor *p){ #endif assert( p->isTable ); if( p->isTable ){ - rc = sqlite3BtreeMoveto(p->pCursor, 0, p->movetoTarget, &res); + rc = sqlite3BtreeMoveto(p->pCursor, 0, p->movetoTarget, 0, &res); }else{ rc = sqlite3BtreeMoveto(p->pCursor,(char*)&p->movetoTarget, - sizeof(i64),&res); + sizeof(i64), 0, &res); } if( rc ) return rc; *p->pIncrKey = 0; -- 2.47.2