1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-08 14:02:16 +03:00

Provide the BTREE_SEEK_EQ hint to the b-tree layer.

FossilOrigin-Name: e750830f1e61160c0c67e35b13e50b35a95b50e1
This commit is contained in:
drh
2015-03-20 14:57:50 +00:00
parent 80103fc614
commit e0997b341b
7 changed files with 74 additions and 25 deletions

View File

@@ -1,5 +1,5 @@
C Fix\sa\sproblem\scausing\scollation\ssequence\snames\sto\sbe\sdequoted\smultiple\stimes\sunder\ssome\scircumstances. C Provide\sthe\sBTREE_SEEK_EQ\shint\sto\sthe\sb-tree\slayer.
D 2015-03-20T08:43:59.683 D 2015-03-20T14:57:50.128
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 88a3e6261286db378fdffa1124cad11b3c05f5bb F Makefile.in 88a3e6261286db378fdffa1124cad11b3c05f5bb
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -173,8 +173,8 @@ F src/auth.c b56c78ebe40a2110fd361379f7e8162d23f92240
F src/backup.c ff743689c4d6c5cb55ad42ed9d174b2b3e71f1e3 F src/backup.c ff743689c4d6c5cb55ad42ed9d174b2b3e71f1e3
F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb
F src/btmutex.c 45a968cc85afed9b5e6cf55bf1f42f8d18107f79 F src/btmutex.c 45a968cc85afed9b5e6cf55bf1f42f8d18107f79
F src/btree.c a31ac00e30fb7bb49e90e48ce29ef8a61591be96 F src/btree.c d4d52fb14e863cff9dbc7c746e9048ec0967a555
F src/btree.h 9cbbb92aab22ef8b50493c40aa3f8de87c43a2fb F src/btree.h 969adc948e89e449220ff0ff724c94bb2a52e9f1
F src/btreeInt.h 2bfefc01875d8da066504c233ec259fcb3b2ef72 F src/btreeInt.h 2bfefc01875d8da066504c233ec259fcb3b2ef72
F src/build.c ba45ebd02904e84d98839a6ea74c3eb948596587 F src/build.c ba45ebd02904e84d98839a6ea74c3eb948596587
F src/callback.c 7b44ce59674338ad48b0e84e7b72f935ea4f68b0 F src/callback.c 7b44ce59674338ad48b0e84e7b72f935ea4f68b0
@@ -235,7 +235,7 @@ F src/shell.c d1ecce877f899abc97cabdf6a0b8323b8c5a0b69
F src/sqlite.h.in 2d48e05677d0f9b06b7757662eef3cebea02d837 F src/sqlite.h.in 2d48e05677d0f9b06b7757662eef3cebea02d837
F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad F src/sqlite3.rc 992c9f5fb8285ae285d6be28240a7e8d3a7f2bad
F src/sqlite3ext.h 17d487c3c91b0b8c584a32fbeb393f6f795eea7d F src/sqlite3ext.h 17d487c3c91b0b8c584a32fbeb393f6f795eea7d
F src/sqliteInt.h 0f36b72dbaee2306cd4df055e5e6125b3d7a2420 F src/sqliteInt.h f2300529f3592323a98fd7acccec63d0e9082dc5
F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46 F src/sqliteLimit.h 216557999cb45f2e3578ed53ebefe228d779cb46
F src/status.c 81712116e826b0089bb221b018929536b2b5406f F src/status.c 81712116e826b0089bb221b018929536b2b5406f
F src/table.c e7a09215315a978057fb42c640f890160dbcc45e F src/table.c e7a09215315a978057fb42c640f890160dbcc45e
@@ -293,7 +293,7 @@ F src/update.c 3c4ecc282accf12d39edb8d524cf089645e55a13
F src/utf.c fc6b889ba0779b7722634cdeaa25f1930d93820c F src/utf.c fc6b889ba0779b7722634cdeaa25f1930d93820c
F src/util.c 98a7627ca48ad3265b6940915a1d08355eb3fc7e F src/util.c 98a7627ca48ad3265b6940915a1d08355eb3fc7e
F src/vacuum.c 9460b9de7b2d4e34b0d374894aa6c8a0632be8ec F src/vacuum.c 9460b9de7b2d4e34b0d374894aa6c8a0632be8ec
F src/vdbe.c b32dc2efe94a2c31ab4584066d47af2b56391f39 F src/vdbe.c 64d8325aed2020a8aa3bd1f6352d0b129299b2fa
F src/vdbe.h 6fc69d9c5e146302c56e163cb4b31d1ee64a18c3 F src/vdbe.h 6fc69d9c5e146302c56e163cb4b31d1ee64a18c3
F src/vdbeInt.h bb56fd199d8af1a2c1b9639ee2f70724b4338e3a F src/vdbeInt.h bb56fd199d8af1a2c1b9639ee2f70724b4338e3a
F src/vdbeapi.c 583d56b129dd27f12bed518270de9ebe521e6a75 F src/vdbeapi.c 583d56b129dd27f12bed518270de9ebe521e6a75
@@ -307,7 +307,7 @@ F src/vxworks.h c18586c8edc1bddbc15c004fa16aeb1e1342b4fb
F src/wal.c 878c8e1a51cb2ec45c395d26b7d5cd9e1a098e4a F src/wal.c 878c8e1a51cb2ec45c395d26b7d5cd9e1a098e4a
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4 F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
F src/walker.c c253b95b4ee44b21c406e2a1052636c31ea27804 F src/walker.c c253b95b4ee44b21c406e2a1052636c31ea27804
F src/where.c 6dc10d180e88dc0b3655296d0d1059cbaf4e237a F src/where.c 85d832efa5ef57de542db7f430b72fecd3af8b38
F src/whereInt.h cbe4aa57326998d89e7698ca65bb7c28541d483c F src/whereInt.h cbe4aa57326998d89e7698ca65bb7c28541d483c
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
@@ -1246,7 +1246,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
P b74cb0a92bba69f8ea705adf4695d03ea4470984 P eddc05e7bb31fae74daa86e0504a3478b99fa0f2
R 0d4dc41d235c1c2ad9a38ee6dff0fe2f R 6b21b0e98ee76d198c2b5163fdb0b4f7
U dan U drh
Z 56b5996883845a15ff92eed0154203c2 Z 5cff4e9435b6ae28710f92cbaff291bb

View File

@@ -1 +1 @@
eddc05e7bb31fae74daa86e0504a3478b99fa0f2 e750830f1e61160c0c67e35b13e50b35a95b50e1

View File

@@ -7480,7 +7480,8 @@ static int balance(BtCursor *pCur){
** pSpace buffer passed to the latter call to balance_nonroot(). ** pSpace buffer passed to the latter call to balance_nonroot().
*/ */
u8 *pSpace = sqlite3PageMalloc(pCur->pBt->pageSize); u8 *pSpace = sqlite3PageMalloc(pCur->pBt->pageSize);
rc = balance_nonroot(pParent, iIdx, pSpace, iPage==1, pCur->hints); rc = balance_nonroot(pParent, iIdx, pSpace, iPage==1,
pCur->hints&BTREE_BULKLOAD);
if( pFree ){ if( pFree ){
/* If pFree is not NULL, it points to the pSpace buffer used /* If pFree is not NULL, it points to the pSpace buffer used
** by a previous call to balance_nonroot(). Its contents are ** by a previous call to balance_nonroot(). Its contents are
@@ -9143,14 +9144,23 @@ int sqlite3BtreeSetVersion(Btree *pBtree, int iVersion){
} }
/* /*
** set the mask of hint flags for cursor pCsr. Currently the only valid ** set the mask of hint flags for cursor pCsr.
** values are 0 and BTREE_BULKLOAD.
*/ */
void sqlite3BtreeCursorHints(BtCursor *pCsr, unsigned int mask){ void sqlite3BtreeCursorHints(BtCursor *pCsr, unsigned int mask){
assert( mask==BTREE_BULKLOAD || mask==0 ); assert( mask==BTREE_BULKLOAD || mask==BTREE_SEEK_EQ || mask==0 );
pCsr->hints = mask; pCsr->hints = mask;
} }
#ifdef SQLITE_DEBUG
/*
** Return true if the cursor has a hint specified. This routine is
** only used from within assert() statements
*/
int sqlite3BtreeCursorHasHint(BtCursor *pCsr, unsigned int mask){
return (pCsr->hints & mask)!=0;
}
#endif
/* /*
** Return true if the given Btree is read-only. ** Return true if the given Btree is read-only.
*/ */

View File

@@ -152,8 +152,18 @@ int sqlite3BtreeNewDb(Btree *p);
/* /*
** Values that may be OR'd together to form the second argument of an ** Values that may be OR'd together to form the second argument of an
** sqlite3BtreeCursorHints() call. ** sqlite3BtreeCursorHints() call.
**
** The BTREE_BULKLOAD flag is set on index cursors when the index is going
** to be filled with content that is already in sorted order.
**
** The BTREE_SEEK_EQ flag is set on cursors that will get OP_SeekGE or
** OP_SeekLE opcodes for a range search, but where the range of entries
** selected will all have the same key. In other words, the cursor will
** be used only for equality key searches.
**
*/ */
#define BTREE_BULKLOAD 0x00000001 #define BTREE_BULKLOAD 0x00000001 /* Used to full index in sorted order */
#define BTREE_SEEK_EQ 0x00000002 /* EQ seeks only - no range seeks */
int sqlite3BtreeCursor( int sqlite3BtreeCursor(
Btree*, /* BTree containing table to open */ Btree*, /* BTree containing table to open */
@@ -199,6 +209,9 @@ void sqlite3BtreeIncrblobCursor(BtCursor *);
void sqlite3BtreeClearCursor(BtCursor *); void sqlite3BtreeClearCursor(BtCursor *);
int sqlite3BtreeSetVersion(Btree *pBt, int iVersion); int sqlite3BtreeSetVersion(Btree *pBt, int iVersion);
void sqlite3BtreeCursorHints(BtCursor *, unsigned int mask); void sqlite3BtreeCursorHints(BtCursor *, unsigned int mask);
#ifdef SQLITE_DEBUG
int sqlite3BtreeCursorHasHint(BtCursor*, unsigned int mask);
#endif
int sqlite3BtreeIsReadonly(Btree *pBt); int sqlite3BtreeIsReadonly(Btree *pBt);
int sqlite3HeaderSizeBtree(void); int sqlite3HeaderSizeBtree(void);

View File

@@ -2692,7 +2692,8 @@ struct AuthContext {
#define OPFLAG_LENGTHARG 0x40 /* OP_Column only used for length() */ #define OPFLAG_LENGTHARG 0x40 /* OP_Column only used for length() */
#define OPFLAG_TYPEOFARG 0x80 /* OP_Column only used for typeof() */ #define OPFLAG_TYPEOFARG 0x80 /* OP_Column only used for typeof() */
#define OPFLAG_BULKCSR 0x01 /* OP_Open** used to open bulk cursor */ #define OPFLAG_BULKCSR 0x01 /* OP_Open** used to open bulk cursor */
#define OPFLAG_P2ISREG 0x02 /* P2 to OP_Open** is a register number */ #define OPFLAG_SEEKEQ 0x02 /* OP_Open** cursor uses EQ seek only */
#define OPFLAG_P2ISREG 0x04 /* P2 to OP_Open** is a register number */
#define OPFLAG_PERMUTE 0x01 /* OP_Compare: use the permutation */ #define OPFLAG_PERMUTE 0x01 /* OP_Compare: use the permutation */
/* /*

View File

@@ -3237,12 +3237,12 @@ case OP_SetCookie: { /* in3 */
case OP_ReopenIdx: { case OP_ReopenIdx: {
VdbeCursor *pCur; VdbeCursor *pCur;
assert( pOp->p5==0 ); assert( pOp->p5==0 || pOp->p5==OPFLAG_SEEKEQ );
assert( pOp->p4type==P4_KEYINFO ); assert( pOp->p4type==P4_KEYINFO );
pCur = p->apCsr[pOp->p1]; pCur = p->apCsr[pOp->p1];
if( pCur && pCur->pgnoRoot==(u32)pOp->p2 ){ if( pCur && pCur->pgnoRoot==(u32)pOp->p2 ){
assert( pCur->iDb==pOp->p3 ); /* Guaranteed by the code generator */ assert( pCur->iDb==pOp->p3 ); /* Guaranteed by the code generator */
break; goto open_cursor_set_hints;
} }
/* If the cursor is not currently open or is open on a different /* If the cursor is not currently open or is open on a different
** index, then fall through into OP_OpenRead to force a reopen */ ** index, then fall through into OP_OpenRead to force a reopen */
@@ -3258,8 +3258,8 @@ case OP_OpenWrite: {
VdbeCursor *pCur; VdbeCursor *pCur;
Db *pDb; Db *pDb;
assert( (pOp->p5&(OPFLAG_P2ISREG|OPFLAG_BULKCSR))==pOp->p5 ); assert( (pOp->p5&(OPFLAG_P2ISREG|OPFLAG_BULKCSR|OPFLAG_SEEKEQ))==pOp->p5 );
assert( pOp->opcode==OP_OpenWrite || pOp->p5==0 ); assert( pOp->opcode==OP_OpenWrite || pOp->p5==0 || pOp->p5==OPFLAG_SEEKEQ );
assert( p->bIsReader ); assert( p->bIsReader );
assert( pOp->opcode==OP_OpenRead || pOp->opcode==OP_ReopenIdx assert( pOp->opcode==OP_OpenRead || pOp->opcode==OP_ReopenIdx
|| p->readOnly==0 ); || p->readOnly==0 );
@@ -3322,14 +3322,17 @@ case OP_OpenWrite: {
pCur->pgnoRoot = p2; pCur->pgnoRoot = p2;
rc = sqlite3BtreeCursor(pX, p2, wrFlag, pKeyInfo, pCur->pCursor); rc = sqlite3BtreeCursor(pX, p2, wrFlag, pKeyInfo, pCur->pCursor);
pCur->pKeyInfo = pKeyInfo; pCur->pKeyInfo = pKeyInfo;
assert( OPFLAG_BULKCSR==BTREE_BULKLOAD );
sqlite3BtreeCursorHints(pCur->pCursor, (pOp->p5 & OPFLAG_BULKCSR));
/* Set the VdbeCursor.isTable variable. Previous versions of /* Set the VdbeCursor.isTable variable. Previous versions of
** SQLite used to check if the root-page flags were sane at this point ** SQLite used to check if the root-page flags were sane at this point
** and report database corruption if they were not, but this check has ** and report database corruption if they were not, but this check has
** since moved into the btree layer. */ ** since moved into the btree layer. */
pCur->isTable = pOp->p4type!=P4_KEYINFO; pCur->isTable = pOp->p4type!=P4_KEYINFO;
open_cursor_set_hints:
assert( OPFLAG_BULKCSR==BTREE_BULKLOAD );
assert( OPFLAG_SEEKEQ==BTREE_SEEK_EQ );
sqlite3BtreeCursorHints(pCur->pCursor,
(pOp->p5 & (OPFLAG_BULKCSR|OPFLAG_SEEKEQ)));
break; break;
} }
@@ -3590,6 +3593,22 @@ case OP_SeekGT: { /* jump, in3 */
#ifdef SQLITE_DEBUG #ifdef SQLITE_DEBUG
pC->seekOp = pOp->opcode; pC->seekOp = pOp->opcode;
#endif #endif
/* For a cursor with the BTREE_SEEK_EQ hint, only the OP_SeekGE and
** OP_SeekLE opcodes are allowed, and these must be immediately followed
** by an OP_IdxGT or OP_IdxLT opcode, respectively, with the same key.
*/
#ifdef SQLITE_DEBUG
if( sqlite3BtreeCursorHasHint(pC->pCursor, BTREE_SEEK_EQ) ){
assert( pOp->opcode==OP_SeekGE || pOp->opcode==OP_SeekLE );
assert( pOp[1].opcode==OP_IdxLT || pOp[1].opcode==OP_IdxGT );
assert( pOp[1].p1==pOp[0].p1 );
assert( pOp[1].p2==pOp[0].p2 );
assert( pOp[1].p3==pOp[0].p3 );
assert( pOp[1].p4.i==pOp[0].p4.i );
}
#endif
if( pC->isTable ){ if( pC->isTable ){
/* The input value in P3 might be of any type: integer, real, string, /* The input value in P3 might be of any type: integer, real, string,
** blob, or NULL. But it needs to be an integer before we can do ** blob, or NULL. But it needs to be an integer before we can do

View File

@@ -6801,6 +6801,12 @@ WhereInfo *sqlite3WhereBegin(
if( op ){ if( op ){
sqlite3VdbeAddOp3(v, op, iIndexCur, pIx->tnum, iDb); sqlite3VdbeAddOp3(v, op, iIndexCur, pIx->tnum, iDb);
sqlite3VdbeSetP4KeyInfo(pParse, pIx); sqlite3VdbeSetP4KeyInfo(pParse, pIx);
if( (pLoop->wsFlags & WHERE_CONSTRAINT)!=0
&& (pLoop->wsFlags & (WHERE_COLUMN_RANGE|WHERE_SKIPSCAN))==0
&& (pWInfo->wctrlFlags&WHERE_ORDERBY_MIN)==0
){
sqlite3VdbeChangeP5(v, OPFLAG_SEEKEQ); /* Hint to COMDB2 */
}
VdbeComment((v, "%s", pIx->zName)); VdbeComment((v, "%s", pIx->zName));
} }
} }