mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-05 15:55:57 +03:00
If the SQLITE_ENABLE_CURSOR_HINTS macro is defined, then invoke the
sqlite3BtreeCursorHint() interface to provide hints to the storage engine about rows that need not be returned. Hints can be disabled using SQLITE_TESTCTRL_OPTIMIZATIONS with SQLITE_CursorHints (0x2000). Cursor hints are not used by the built-in storage engine of SQLite but might be useful to applications that provide their own storage engine. The current code is work-in-progrss and contains bugs. FossilOrigin-Name: 3a9bec524ef2de44028b4058e67dc962082888d3
This commit is contained in:
27
manifest
27
manifest
@@ -1,5 +1,5 @@
|
|||||||
C Increase\sthe\sversion\snumber\sto\s3.8.3.
|
C If\sthe\sSQLITE_ENABLE_CURSOR_HINTS\smacro\sis\sdefined,\sthen\sinvoke\sthe\nsqlite3BtreeCursorHint()\sinterface\sto\sprovide\shints\sto\sthe\sstorage\sengine\nabout\srows\sthat\sneed\snot\sbe\sreturned.\s\sHints\scan\sbe\sdisabled\susing\nSQLITE_TESTCTRL_OPTIMIZATIONS\swith\sSQLITE_CursorHints\s(0x2000).\s\sCursor\nhints\sare\snot\sused\sby\sthe\sbuilt-in\sstorage\sengine\sof\sSQLite\sbut\smight\nbe\suseful\sto\sapplications\sthat\sprovide\stheir\sown\sstorage\sengine.\s\sThe\ncurrent\scode\sis\swork-in-progrss\sand\scontains\sbugs.
|
||||||
D 2013-12-07T17:01:23.631
|
D 2013-12-07T20:39:19.762
|
||||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||||
F Makefile.in e1a9b4258bbde53f5636f4e238c65b7e11459e2b
|
F Makefile.in e1a9b4258bbde53f5636f4e238c65b7e11459e2b
|
||||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||||
@@ -166,8 +166,8 @@ F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
|
|||||||
F src/backup.c 1809a7caa2504233bdddd12f5018422421789537
|
F src/backup.c 1809a7caa2504233bdddd12f5018422421789537
|
||||||
F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb
|
F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb
|
||||||
F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7
|
F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7
|
||||||
F src/btree.c 4037f58ef3f4459d0b9bb1fc1aee1136277d9ba6
|
F src/btree.c 9e6d189894f54744d1a20c63de5afb66342f0904
|
||||||
F src/btree.h a61ddebc78c66795a2b93181321a116746302cc9
|
F src/btree.h 450f1c6022ec89da529a57f3e704e87c6c14b34d
|
||||||
F src/btreeInt.h f038e818bfadf75afbd09819ed93c26a333d39e0
|
F src/btreeInt.h f038e818bfadf75afbd09819ed93c26a333d39e0
|
||||||
F src/build.c 9b40580b62916612678bdb69ce0286e39c29a862
|
F src/build.c 9b40580b62916612678bdb69ce0286e39c29a862
|
||||||
F src/callback.c f99a8957ba2adf369645fac0db09ad8adcf1caa2
|
F src/callback.c f99a8957ba2adf369645fac0db09ad8adcf1caa2
|
||||||
@@ -224,7 +224,7 @@ F src/shell.c 936a72ff784efff3832cce274a96ed0b036e6758
|
|||||||
F src/sqlite.h.in 125dc0b76f0116f1cd6f13536db52ba981e1c5bd
|
F src/sqlite.h.in 125dc0b76f0116f1cd6f13536db52ba981e1c5bd
|
||||||
F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e
|
F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e
|
||||||
F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc
|
F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc
|
||||||
F src/sqliteInt.h f3a5d663fe9c6c0b2ee7fc2e20a6204eaea5bc7c
|
F src/sqliteInt.h 081102b2fb2aedc0c67d7a631d16a1fb34accc85
|
||||||
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
|
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
|
||||||
F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158
|
F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158
|
||||||
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
|
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
|
||||||
@@ -280,11 +280,11 @@ F src/update.c d1c2477dcf14d90999d1935af4efb4806553250b
|
|||||||
F src/utf.c 6fc6c88d50448c469c5c196acf21617a24f90269
|
F src/utf.c 6fc6c88d50448c469c5c196acf21617a24f90269
|
||||||
F src/util.c 76ed0519296e3f62e97e57dab1999e34184c8e49
|
F src/util.c 76ed0519296e3f62e97e57dab1999e34184c8e49
|
||||||
F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179
|
F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179
|
||||||
F src/vdbe.c 54894fde8dc806d259e015ac7c9680145e725835
|
F src/vdbe.c 88a037e01278bd8c8093bb3399b250cb02c6e865
|
||||||
F src/vdbe.h c06f0813f853566457ce9cfb1a4a4bc39a5da644
|
F src/vdbe.h 57b87844270b2e92647b8b82a8948f7a29efae8d
|
||||||
F src/vdbeInt.h 05fbda0e061dbc4aaa2709a8cccf3515c245b263
|
F src/vdbeInt.h 05fbda0e061dbc4aaa2709a8cccf3515c245b263
|
||||||
F src/vdbeapi.c 93a22a9ba2abe292d5c2cf304d7eb2e894dde0ed
|
F src/vdbeapi.c 93a22a9ba2abe292d5c2cf304d7eb2e894dde0ed
|
||||||
F src/vdbeaux.c 09b79d475f5af2b3b5068f639609d88e0ced9d95
|
F src/vdbeaux.c c7c9219cb31cef9917db3b3b41604ac74c5bc41b
|
||||||
F src/vdbeblob.c 8cd05a5630e6d5563ad017bf82edaf812b28acde
|
F src/vdbeblob.c 8cd05a5630e6d5563ad017bf82edaf812b28acde
|
||||||
F src/vdbemem.c 20e349d2ca928802fc8f2d42a2cc488fd6981d3f
|
F src/vdbemem.c 20e349d2ca928802fc8f2d42a2cc488fd6981d3f
|
||||||
F src/vdbesort.c 9d83601f9d6243fe70dd0169a2820c5ddfd48147
|
F src/vdbesort.c 9d83601f9d6243fe70dd0169a2820c5ddfd48147
|
||||||
@@ -293,7 +293,7 @@ F src/vtab.c 21b932841e51ebd7d075e2d0ad1415dce8d2d5fd
|
|||||||
F src/wal.c 7dc3966ef98b74422267e7e6e46e07ff6c6eb1b4
|
F src/wal.c 7dc3966ef98b74422267e7e6e46e07ff6c6eb1b4
|
||||||
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
|
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
|
||||||
F src/walker.c e9e593d5bb798c3e67fc3893dfe7055c9e7d8d74
|
F src/walker.c e9e593d5bb798c3e67fc3893dfe7055c9e7d8d74
|
||||||
F src/where.c e6a4e713abe6f995495ea53dd6a5e48f88b53883
|
F src/where.c c3bdcd3886e93c129d0ed5a8db17cabde6ea7e73
|
||||||
F src/whereInt.h 96a75c61f1d2b9d4a8e4bb17d89deb0cf7cba358
|
F src/whereInt.h 96a75c61f1d2b9d4a8e4bb17d89deb0cf7cba358
|
||||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||||
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
||||||
@@ -1146,7 +1146,10 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381
|
|||||||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||||
F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01
|
F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01
|
||||||
F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff
|
F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff
|
||||||
P 369a23e00644f3ff8b6a2d2ed73b8cb65e9f124b
|
P 23d00f22872a907a8ebf5b80689ff7aa66686a07
|
||||||
R 0fdea442d6dfa8b801d4e6d289982778
|
R d784a3d34f33a329aefe46bc5926417e
|
||||||
|
T *branch * cursor-hints
|
||||||
|
T *sym-cursor-hints *
|
||||||
|
T -sym-trunk *
|
||||||
U drh
|
U drh
|
||||||
Z 0e445b98f25b8020cec84ec084909f7b
|
Z c7784e25ec311e9981c59aaad7fb1809
|
||||||
|
@@ -1 +1 @@
|
|||||||
23d00f22872a907a8ebf5b80689ff7aa66686a07
|
3a9bec524ef2de44028b4058e67dc962082888d3
|
15
src/btree.c
15
src/btree.c
@@ -764,6 +764,21 @@ int sqlite3BtreeCursorHasMoved(BtCursor *pCur, int *pHasMoved){
|
|||||||
return SQLITE_OK;
|
return SQLITE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef SQLITE_ENABLE_CURSOR_HINTS
|
||||||
|
/*
|
||||||
|
** Give a hint to the cursor that it only has to deliver rows for which
|
||||||
|
** the expression pExpr is true. Within this expression, rows of the
|
||||||
|
** cursor are identified by Expr.op==TK_COLUMN with Expr.iTable==iTable.
|
||||||
|
**
|
||||||
|
** This interfaces is not used by the standard storage engine of SQLite.
|
||||||
|
** It is only useful to application that replace SQLite's built-in storage
|
||||||
|
** engine with their own.
|
||||||
|
*/
|
||||||
|
void sqlite3BtreeCursorHint(BtCursor *pCur, int iTable, const Expr *pExpr){
|
||||||
|
/* Alternative storage engines might use this. */
|
||||||
|
}
|
||||||
|
#endif /* SQLITE_ENABLE_CURSOR_HINTS */
|
||||||
|
|
||||||
#ifndef SQLITE_OMIT_AUTOVACUUM
|
#ifndef SQLITE_OMIT_AUTOVACUUM
|
||||||
/*
|
/*
|
||||||
** Given a page number of a regular database page, return the page
|
** Given a page number of a regular database page, return the page
|
||||||
|
@@ -167,6 +167,9 @@ int sqlite3BtreeMovetoUnpacked(
|
|||||||
int *pRes
|
int *pRes
|
||||||
);
|
);
|
||||||
int sqlite3BtreeCursorHasMoved(BtCursor*, int*);
|
int sqlite3BtreeCursorHasMoved(BtCursor*, int*);
|
||||||
|
#ifdef SQLITE_ENABLE_CURSOR_HINTS
|
||||||
|
void sqlite3BtreeCursorHint(BtCursor*, int, const Expr*);
|
||||||
|
#endif
|
||||||
int sqlite3BtreeDelete(BtCursor*);
|
int sqlite3BtreeDelete(BtCursor*);
|
||||||
int sqlite3BtreeInsert(BtCursor*, const void *pKey, i64 nKey,
|
int sqlite3BtreeInsert(BtCursor*, const void *pKey, i64 nKey,
|
||||||
const void *pData, int nData,
|
const void *pData, int nData,
|
||||||
|
@@ -1064,6 +1064,7 @@ struct sqlite3 {
|
|||||||
#define SQLITE_OmitNoopJoin 0x0400 /* Omit unused tables in joins */
|
#define SQLITE_OmitNoopJoin 0x0400 /* Omit unused tables in joins */
|
||||||
#define SQLITE_Stat3 0x0800 /* Use the SQLITE_STAT3 table */
|
#define SQLITE_Stat3 0x0800 /* Use the SQLITE_STAT3 table */
|
||||||
#define SQLITE_AdjustOutEst 0x1000 /* Adjust output estimates using WHERE */
|
#define SQLITE_AdjustOutEst 0x1000 /* Adjust output estimates using WHERE */
|
||||||
|
#define SQLITE_CursorHints 0x2000 /* Add OP_CursorHint opcodes */
|
||||||
#define SQLITE_AllOpts 0xffff /* All optimizations */
|
#define SQLITE_AllOpts 0xffff /* All optimizations */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
18
src/vdbe.c
18
src/vdbe.c
@@ -6170,6 +6170,24 @@ case OP_Trace: {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef SQLITE_ENABLE_CURSOR_HINTS
|
||||||
|
/* Opcode: CursorHint P1 P2 * P4 *
|
||||||
|
**
|
||||||
|
** Provide a hint to cursor P1 that it only needs to return rows that
|
||||||
|
** satisfy the Expr tree given in P4. P2 is the table number of cursor P1
|
||||||
|
** such that references to cursor P1 in the Expr tree are given by
|
||||||
|
** Expr.iTable==P2.
|
||||||
|
*/
|
||||||
|
case OP_CursorHint: {
|
||||||
|
VdbeCursor *pC;
|
||||||
|
|
||||||
|
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
|
||||||
|
assert( pOp->p4type==P4_EXPR );
|
||||||
|
pC = p->apCsr[pOp->p1];
|
||||||
|
if( pC ) sqlite3BtreeCursorHint(pC->pCursor, pOp->p2, pOp->p4.pExpr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif /* SQLITE_ENABLE_CURSOR_HINTS */
|
||||||
|
|
||||||
/* Opcode: Noop * * * * *
|
/* Opcode: Noop * * * * *
|
||||||
**
|
**
|
||||||
|
@@ -59,6 +59,9 @@ struct VdbeOp {
|
|||||||
KeyInfo *pKeyInfo; /* Used when p4type is P4_KEYINFO */
|
KeyInfo *pKeyInfo; /* Used when p4type is P4_KEYINFO */
|
||||||
int *ai; /* Used when p4type is P4_INTARRAY */
|
int *ai; /* Used when p4type is P4_INTARRAY */
|
||||||
SubProgram *pProgram; /* Used when p4type is P4_SUBPROGRAM */
|
SubProgram *pProgram; /* Used when p4type is P4_SUBPROGRAM */
|
||||||
|
#ifdef SQLITE_ENABLE_CURSOR_HINTS
|
||||||
|
Expr *pExpr; /* Used when p4type is P4_EXPR */
|
||||||
|
#endif
|
||||||
int (*xAdvance)(BtCursor *, int *);
|
int (*xAdvance)(BtCursor *, int *);
|
||||||
} p4;
|
} p4;
|
||||||
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
|
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
|
||||||
@@ -106,6 +109,7 @@ typedef struct VdbeOpList VdbeOpList;
|
|||||||
#define P4_COLLSEQ (-4) /* P4 is a pointer to a CollSeq structure */
|
#define P4_COLLSEQ (-4) /* P4 is a pointer to a CollSeq structure */
|
||||||
#define P4_FUNCDEF (-5) /* P4 is a pointer to a FuncDef structure */
|
#define P4_FUNCDEF (-5) /* P4 is a pointer to a FuncDef structure */
|
||||||
#define P4_KEYINFO (-6) /* P4 is a pointer to a KeyInfo structure */
|
#define P4_KEYINFO (-6) /* P4 is a pointer to a KeyInfo structure */
|
||||||
|
#define P4_EXPR (-7) /* P4 is a pointer to an Expr tree */
|
||||||
#define P4_MEM (-8) /* P4 is a pointer to a Mem* structure */
|
#define P4_MEM (-8) /* P4 is a pointer to a Mem* structure */
|
||||||
#define P4_TRANSIENT 0 /* P4 is a pointer to a transient string */
|
#define P4_TRANSIENT 0 /* P4 is a pointer to a transient string */
|
||||||
#define P4_VTAB (-10) /* P4 is a pointer to an sqlite3_vtab structure */
|
#define P4_VTAB (-10) /* P4 is a pointer to an sqlite3_vtab structure */
|
||||||
|
@@ -639,6 +639,12 @@ static void freeP4(sqlite3 *db, int p4type, void *p4){
|
|||||||
if( db->pnBytesFreed==0 ) sqlite3KeyInfoUnref((KeyInfo*)p4);
|
if( db->pnBytesFreed==0 ) sqlite3KeyInfoUnref((KeyInfo*)p4);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#ifdef SQLITE_ENABLE_CURSOR_HINTS
|
||||||
|
case P4_EXPR: {
|
||||||
|
sqlite3ExprDelete(db, (Expr*)p4);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
case P4_MPRINTF: {
|
case P4_MPRINTF: {
|
||||||
if( db->pnBytesFreed==0 ) sqlite3_free(p4);
|
if( db->pnBytesFreed==0 ) sqlite3_free(p4);
|
||||||
break;
|
break;
|
||||||
@@ -756,6 +762,15 @@ void sqlite3VdbeChangeP4(Vdbe *p, int addr, const char *zP4, int n){
|
|||||||
}else if( n==P4_KEYINFO ){
|
}else if( n==P4_KEYINFO ){
|
||||||
pOp->p4.p = (void*)zP4;
|
pOp->p4.p = (void*)zP4;
|
||||||
pOp->p4type = P4_KEYINFO;
|
pOp->p4type = P4_KEYINFO;
|
||||||
|
#ifdef SQLITE_ENABLE_CURSOR_HINTS
|
||||||
|
}else if( n==P4_EXPR ){
|
||||||
|
/* Responsibility for deleting the Expr tree is handed over to the
|
||||||
|
** VDBE by this operation. The caller should have already invoked
|
||||||
|
** sqlite3ExprDup() or whatever other routine is needed to make a
|
||||||
|
** private copy of the tree. */
|
||||||
|
pOp->p4.pExpr = (Expr*)zP4;
|
||||||
|
pOp->p4type = P4_EXPR;
|
||||||
|
#endif
|
||||||
}else if( n==P4_VTAB ){
|
}else if( n==P4_VTAB ){
|
||||||
pOp->p4.p = (void*)zP4;
|
pOp->p4.p = (void*)zP4;
|
||||||
pOp->p4type = P4_VTAB;
|
pOp->p4type = P4_VTAB;
|
||||||
@@ -973,6 +988,12 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){
|
|||||||
assert( i<nTemp );
|
assert( i<nTemp );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#ifdef SQLITE_ENABLE_CURSOR_HINTS
|
||||||
|
case P4_EXPR: {
|
||||||
|
sqlite3_snprintf(nTemp, zTemp, "(expr)");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
case P4_COLLSEQ: {
|
case P4_COLLSEQ: {
|
||||||
CollSeq *pColl = pOp->p4.pColl;
|
CollSeq *pColl = pOp->p4.pColl;
|
||||||
sqlite3_snprintf(nTemp, zTemp, "(%.20s)", pColl->zName);
|
sqlite3_snprintf(nTemp, zTemp, "(%.20s)", pColl->zName);
|
||||||
|
46
src/where.c
46
src/where.c
@@ -2715,6 +2715,49 @@ static void explainOneScan(
|
|||||||
# define explainOneScan(u,v,w,x,y,z)
|
# define explainOneScan(u,v,w,x,y,z)
|
||||||
#endif /* SQLITE_OMIT_EXPLAIN */
|
#endif /* SQLITE_OMIT_EXPLAIN */
|
||||||
|
|
||||||
|
#ifdef SQLITE_ENABLE_CURSOR_HINTS
|
||||||
|
/*
|
||||||
|
** Insert an OP_CursorHint instruction if it is appropriate to do so.
|
||||||
|
*/
|
||||||
|
static void codeCursorHint(
|
||||||
|
WhereInfo *pWInfo,
|
||||||
|
int iLevel
|
||||||
|
){
|
||||||
|
Parse *pParse = pWInfo->pParse;
|
||||||
|
sqlite3 *db = pParse->db;
|
||||||
|
Vdbe *v = pParse->pVdbe;
|
||||||
|
WhereLevel *pLevel;
|
||||||
|
Expr *pExpr = 0;
|
||||||
|
int iCur;
|
||||||
|
Bitmask msk;
|
||||||
|
WhereClause *pWC;
|
||||||
|
WhereTerm *pTerm;
|
||||||
|
WhereLoop *pWLoop;
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
if( OptimizationDisabled(db, SQLITE_CursorHints) ) return;
|
||||||
|
pLevel = &pWInfo->a[iLevel];
|
||||||
|
pWLoop = pLevel->pWLoop;
|
||||||
|
iCur = pWInfo->pTabList->a[pLevel->iFrom].iCursor;
|
||||||
|
msk = ~getMask(&pWInfo->sMaskSet, iCur);
|
||||||
|
pWC = &pWInfo->sWC;
|
||||||
|
for(i=0; i<pWC->nTerm; i++){
|
||||||
|
pTerm = &pWC->a[i];
|
||||||
|
if( pTerm->prereqAll & msk ) continue;
|
||||||
|
if( ExprHasProperty(pTerm->pExpr, EP_FromJoin) ) continue;
|
||||||
|
for(j=0; j<pWLoop->nLTerm && pWLoop->aLTerm[j]!=pTerm; j++){}
|
||||||
|
if( j<pWLoop->nLTerm ) continue;
|
||||||
|
pExpr = sqlite3ExprAnd(db, pExpr, sqlite3ExprDup(db, pTerm->pExpr, 0));
|
||||||
|
}
|
||||||
|
if( pExpr!=0 ){
|
||||||
|
sqlite3VdbeAddOp4(v, OP_CursorHint, pLevel->iTabCur, iCur, 0,
|
||||||
|
(const char*)pExpr, P4_EXPR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
# define codeCursorHint(A,B) /* No-op */
|
||||||
|
#endif /* SQLITE_ENABLE_CURSOR_HINTS */
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Generate code for the start of the iLevel-th loop in the WHERE clause
|
** Generate code for the start of the iLevel-th loop in the WHERE clause
|
||||||
@@ -2876,6 +2919,7 @@ static Bitmask codeOneLoopStart(
|
|||||||
pStart = pEnd;
|
pStart = pEnd;
|
||||||
pEnd = pTerm;
|
pEnd = pTerm;
|
||||||
}
|
}
|
||||||
|
codeCursorHint(pWInfo, iLevel);
|
||||||
if( pStart ){
|
if( pStart ){
|
||||||
Expr *pX; /* The expression that defines the start bound */
|
Expr *pX; /* The expression that defines the start bound */
|
||||||
int r1, rTemp; /* Registers for holding the start boundary */
|
int r1, rTemp; /* Registers for holding the start boundary */
|
||||||
@@ -3061,6 +3105,7 @@ static Bitmask codeOneLoopStart(
|
|||||||
start_constraints = pRangeStart || nEq>0;
|
start_constraints = pRangeStart || nEq>0;
|
||||||
|
|
||||||
/* Seek the index cursor to the start of the range. */
|
/* Seek the index cursor to the start of the range. */
|
||||||
|
codeCursorHint(pWInfo, iLevel);
|
||||||
nConstraint = nEq;
|
nConstraint = nEq;
|
||||||
if( pRangeStart ){
|
if( pRangeStart ){
|
||||||
Expr *pRight = pRangeStart->pExpr->pRight;
|
Expr *pRight = pRangeStart->pExpr->pRight;
|
||||||
@@ -3408,6 +3453,7 @@ static Bitmask codeOneLoopStart(
|
|||||||
static const u8 aStep[] = { OP_Next, OP_Prev };
|
static const u8 aStep[] = { OP_Next, OP_Prev };
|
||||||
static const u8 aStart[] = { OP_Rewind, OP_Last };
|
static const u8 aStart[] = { OP_Rewind, OP_Last };
|
||||||
assert( bRev==0 || bRev==1 );
|
assert( bRev==0 || bRev==1 );
|
||||||
|
codeCursorHint(pWInfo, iLevel);
|
||||||
pLevel->op = aStep[bRev];
|
pLevel->op = aStep[bRev];
|
||||||
pLevel->p1 = iCur;
|
pLevel->p1 = iCur;
|
||||||
pLevel->p2 = 1 + sqlite3VdbeAddOp2(v, aStart[bRev], iCur, addrBrk);
|
pLevel->p2 = 1 + sqlite3VdbeAddOp2(v, aStart[bRev], iCur, addrBrk);
|
||||||
|
Reference in New Issue
Block a user