mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-08 14:02:16 +03:00
Add the OP_ReopenIdx opcode that works like OP_OpenRead except that it becomes
a no-op if the cursor is already open on the same index. Update the OR-optimization logic to make use of OP_ReopenIdx in order to avoid unnecessary cursor open requests sent to the B-Tree layer. FossilOrigin-Name: 77f412caf0192d3e7fecb377d6d72123d8b64424
This commit is contained in:
19
manifest
19
manifest
@@ -1,5 +1,5 @@
|
|||||||
C The\soptimization\sof\scheck-in\s[b67a6e33f2]\sdoes\snot\swork\s(it\sgenerates\nincorrect\sVDBE\scode)\sif\san\sOR\sterm\sis\sAND-ed\swith\sa\sconstant\sexpression.\nSo\sback\sthat\soptimization\sout\sand\sadd\sa\stest\scase\sto\smake\ssure\sit\sdoes\snot\nget\sadded\sback\sin.
|
C Add\sthe\sOP_ReopenIdx\sopcode\sthat\sworks\slike\sOP_OpenRead\sexcept\sthat\sit\sbecomes\na\sno-op\sif\sthe\scursor\sis\salready\sopen\son\sthe\ssame\sindex.\s\sUpdate\sthe\nOR-optimization\slogic\sto\smake\suse\sof\sOP_ReopenIdx\sin\sorder\sto\savoid\nunnecessary\scursor\sopen\srequests\ssent\sto\sthe\sB-Tree\slayer.
|
||||||
D 2014-07-22T19:14:42.618
|
D 2014-07-22T20:02:19.743
|
||||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||||
F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308
|
F Makefile.in 5eb79e334a5de69c87740edd56af6527dd219308
|
||||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||||
@@ -227,7 +227,7 @@ F src/shell.c 566aee8213372a2e81ba0eb34e9759f7b2574009
|
|||||||
F src/sqlite.h.in fd8e3a36b0aded082dc93a4b89c1e85324b4cf75
|
F src/sqlite.h.in fd8e3a36b0aded082dc93a4b89c1e85324b4cf75
|
||||||
F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e
|
F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e
|
||||||
F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc
|
F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc
|
||||||
F src/sqliteInt.h 5dbcdcf81cb15e77df16f88699a15f7af491c580
|
F src/sqliteInt.h b72a09326d7cbd8375ec3d9a04ea5e0cf476beb3
|
||||||
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
|
||||||
@@ -283,9 +283,9 @@ F src/update.c 01564b3c430f6c7b0a35afaf7aba7987206fa3a5
|
|||||||
F src/utf.c a0314e637768a030e6e84a957d0c4f6ba910cc05
|
F src/utf.c a0314e637768a030e6e84a957d0c4f6ba910cc05
|
||||||
F src/util.c 049fe1d3c0e2209c1bee107aec2fcff6285f909f
|
F src/util.c 049fe1d3c0e2209c1bee107aec2fcff6285f909f
|
||||||
F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179
|
F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179
|
||||||
F src/vdbe.c 2f3f0582dfacce292d3d6f22d129fe1abe3ddd00
|
F src/vdbe.c fa74c6563486022920db4d73897bd9b837c7441d
|
||||||
F src/vdbe.h c63fad052c9e7388d551e556e119c0bcf6bebdf8
|
F src/vdbe.h c63fad052c9e7388d551e556e119c0bcf6bebdf8
|
||||||
F src/vdbeInt.h 5df5e9afe9b7839cd17256220fc4f7af84b8b1cd
|
F src/vdbeInt.h f41a7cf5a40e7abd994d5fe3a04589ae3e1154e7
|
||||||
F src/vdbeapi.c 24e40422382beb774daab11fe9fe9d37e8a04949
|
F src/vdbeapi.c 24e40422382beb774daab11fe9fe9d37e8a04949
|
||||||
F src/vdbeaux.c 1ffe0bbc3a2c8aedd95622de9be6b6d07b3d3c6b
|
F src/vdbeaux.c 1ffe0bbc3a2c8aedd95622de9be6b6d07b3d3c6b
|
||||||
F src/vdbeblob.c 9205ce9d3b064d9600f8418a897fc88b5687d9ac
|
F src/vdbeblob.c 9205ce9d3b064d9600f8418a897fc88b5687d9ac
|
||||||
@@ -296,7 +296,7 @@ F src/vtab.c 21b932841e51ebd7d075e2d0ad1415dce8d2d5fd
|
|||||||
F src/wal.c 264df50a1b33124130b23180ded2e2c5663c652a
|
F src/wal.c 264df50a1b33124130b23180ded2e2c5663c652a
|
||||||
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
|
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
|
||||||
F src/walker.c 11edb74d587bc87b33ca96a5173e3ec1b8389e45
|
F src/walker.c 11edb74d587bc87b33ca96a5173e3ec1b8389e45
|
||||||
F src/where.c 4e7e6bc639a938eb35c433bdca2aad80478fece4
|
F src/where.c 0ffd586e04cd069ed6ce7f820194ccaa6cbd669e
|
||||||
F src/whereInt.h 929c1349b5355fd44f22cee5c14d72b3329c58a6
|
F src/whereInt.h 929c1349b5355fd44f22cee5c14d72b3329c58a6
|
||||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||||
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
||||||
@@ -1183,8 +1183,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 438c348a40383796a710499e4e1b7a6b08f75778
|
P eed754fe93644f4df082eac0c0a7ffc5c78ccd10
|
||||||
Q -b67a6e33f23ce5f5d9a545fa9d6700a7ed636901
|
R 09dedf30e4922c66cabf472458c9ab58
|
||||||
R 086bb10698e6defd83e7aae53f79809b
|
|
||||||
U drh
|
U drh
|
||||||
Z 6c73d4c61d83e0b2dc5ff58e1c82716d
|
Z 96627cd265c0a3b75631b3111ef23fd4
|
||||||
|
@@ -1 +1 @@
|
|||||||
eed754fe93644f4df082eac0c0a7ffc5c78ccd10
|
77f412caf0192d3e7fecb377d6d72123d8b64424
|
@@ -2136,6 +2136,7 @@ struct SrcList {
|
|||||||
#define WHERE_DISTINCTBY 0x0200 /* pOrderby is really a DISTINCT clause */
|
#define WHERE_DISTINCTBY 0x0200 /* pOrderby is really a DISTINCT clause */
|
||||||
#define WHERE_WANT_DISTINCT 0x0400 /* All output needs to be distinct */
|
#define WHERE_WANT_DISTINCT 0x0400 /* All output needs to be distinct */
|
||||||
#define WHERE_SORTBYGROUP 0x0800 /* Support sqlite3WhereIsSorted() */
|
#define WHERE_SORTBYGROUP 0x0800 /* Support sqlite3WhereIsSorted() */
|
||||||
|
#define WHERE_REOPEN_IDX 0x1000 /* Try to use OP_ReopenIdx */
|
||||||
|
|
||||||
/* Allowed return values from sqlite3WhereIsDistinct()
|
/* Allowed return values from sqlite3WhereIsDistinct()
|
||||||
*/
|
*/
|
||||||
|
33
src/vdbe.c
33
src/vdbe.c
@@ -3205,7 +3205,21 @@ case OP_SetCookie: { /* in3 */
|
|||||||
** sequence of the index being opened. Otherwise, if P4 is an integer
|
** sequence of the index being opened. Otherwise, if P4 is an integer
|
||||||
** value, it is set to the number of columns in the table.
|
** value, it is set to the number of columns in the table.
|
||||||
**
|
**
|
||||||
** See also OpenWrite.
|
** See also: OpenWrite, ReopenIdx
|
||||||
|
*/
|
||||||
|
/* Opcode: ReopenIdx P1 P2 P3 P4 P5
|
||||||
|
** Synopsis: root=P2 iDb=P3
|
||||||
|
**
|
||||||
|
** The ReopenIdx opcode works exactly like ReadOpen except that it first
|
||||||
|
** checks to see if the cursor on P1 is already open with a root page
|
||||||
|
** number of P2 and if it is this opcode becomes a no-op. In other words,
|
||||||
|
** if the cursor is already open, do not reopen it.
|
||||||
|
**
|
||||||
|
** The ReopenIdx opcode may only be used with P5==0 and with P4 being
|
||||||
|
** a P4_KEYINFO object. Furthermore, the P3 value must be the same as
|
||||||
|
** every other ReopenIdx or OpenRead for the same cursor number.
|
||||||
|
**
|
||||||
|
** See the OpenRead opcode documentation for additional information.
|
||||||
*/
|
*/
|
||||||
/* Opcode: OpenWrite P1 P2 P3 P4 P5
|
/* Opcode: OpenWrite P1 P2 P3 P4 P5
|
||||||
** Synopsis: root=P2 iDb=P3
|
** Synopsis: root=P2 iDb=P3
|
||||||
@@ -3227,6 +3241,19 @@ case OP_SetCookie: { /* in3 */
|
|||||||
**
|
**
|
||||||
** See also OpenRead.
|
** See also OpenRead.
|
||||||
*/
|
*/
|
||||||
|
case OP_ReopenIdx: {
|
||||||
|
VdbeCursor *pCur;
|
||||||
|
|
||||||
|
assert( pOp->p5==0 );
|
||||||
|
assert( pOp->p4type==P4_KEYINFO );
|
||||||
|
pCur = p->apCsr[pOp->p1];
|
||||||
|
if( pCur && pCur->pgnoRoot==pOp->p2 ){
|
||||||
|
assert( pCur->iDb==pOp->p3 ); /* Guaranteed by the code generator */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* If the cursor is not currently open or is open on a different
|
||||||
|
** index, then fall through into OP_OpenRead to force a reopen */
|
||||||
|
}
|
||||||
case OP_OpenRead:
|
case OP_OpenRead:
|
||||||
case OP_OpenWrite: {
|
case OP_OpenWrite: {
|
||||||
int nField;
|
int nField;
|
||||||
@@ -3241,7 +3268,8 @@ case OP_OpenWrite: {
|
|||||||
assert( (pOp->p5&(OPFLAG_P2ISREG|OPFLAG_BULKCSR))==pOp->p5 );
|
assert( (pOp->p5&(OPFLAG_P2ISREG|OPFLAG_BULKCSR))==pOp->p5 );
|
||||||
assert( pOp->opcode==OP_OpenWrite || pOp->p5==0 );
|
assert( pOp->opcode==OP_OpenWrite || pOp->p5==0 );
|
||||||
assert( p->bIsReader );
|
assert( p->bIsReader );
|
||||||
assert( pOp->opcode==OP_OpenRead || p->readOnly==0 );
|
assert( pOp->opcode==OP_OpenRead || pOp->opcode==OP_ReopenIdx
|
||||||
|
|| p->readOnly==0 );
|
||||||
|
|
||||||
if( p->expired ){
|
if( p->expired ){
|
||||||
rc = SQLITE_ABORT;
|
rc = SQLITE_ABORT;
|
||||||
@@ -3298,6 +3326,7 @@ case OP_OpenWrite: {
|
|||||||
if( pCur==0 ) goto no_mem;
|
if( pCur==0 ) goto no_mem;
|
||||||
pCur->nullRow = 1;
|
pCur->nullRow = 1;
|
||||||
pCur->isOrdered = 1;
|
pCur->isOrdered = 1;
|
||||||
|
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 );
|
assert( OPFLAG_BULKCSR==BTREE_BULKLOAD );
|
||||||
|
@@ -76,6 +76,7 @@ struct VdbeCursor {
|
|||||||
Bool useRandomRowid:1;/* Generate new record numbers semi-randomly */
|
Bool useRandomRowid:1;/* Generate new record numbers semi-randomly */
|
||||||
Bool isTable:1; /* True if a table requiring integer keys */
|
Bool isTable:1; /* True if a table requiring integer keys */
|
||||||
Bool isOrdered:1; /* True if the underlying table is BTREE_UNORDERED */
|
Bool isOrdered:1; /* True if the underlying table is BTREE_UNORDERED */
|
||||||
|
Pgno pgnoRoot; /* Root page of the open btree cursor */
|
||||||
sqlite3_vtab_cursor *pVtabCursor; /* The cursor for a virtual table */
|
sqlite3_vtab_cursor *pVtabCursor; /* The cursor for a virtual table */
|
||||||
i64 seqCount; /* Sequence counter */
|
i64 seqCount; /* Sequence counter */
|
||||||
i64 movetoTarget; /* Argument to the deferred sqlite3BtreeMoveto() */
|
i64 movetoTarget; /* Argument to the deferred sqlite3BtreeMoveto() */
|
||||||
|
@@ -3422,6 +3422,7 @@ static Bitmask codeOneLoopStart(
|
|||||||
int iRetInit; /* Address of regReturn init */
|
int iRetInit; /* Address of regReturn init */
|
||||||
int untestedTerms = 0; /* Some terms not completely tested */
|
int untestedTerms = 0; /* Some terms not completely tested */
|
||||||
int ii; /* Loop counter */
|
int ii; /* Loop counter */
|
||||||
|
u16 wctrlFlags; /* Flags for sub-WHERE clause */
|
||||||
Expr *pAndExpr = 0; /* An ".. AND (...)" expression */
|
Expr *pAndExpr = 0; /* An ".. AND (...)" expression */
|
||||||
Table *pTab = pTabItem->pTab;
|
Table *pTab = pTabItem->pTab;
|
||||||
|
|
||||||
@@ -3517,6 +3518,8 @@ static Bitmask codeOneLoopStart(
|
|||||||
** eliminating duplicates from other WHERE clauses, the action for each
|
** eliminating duplicates from other WHERE clauses, the action for each
|
||||||
** sub-WHERE clause is to to invoke the main loop body as a subroutine.
|
** sub-WHERE clause is to to invoke the main loop body as a subroutine.
|
||||||
*/
|
*/
|
||||||
|
wctrlFlags = WHERE_OMIT_OPEN_CLOSE | WHERE_AND_ONLY |
|
||||||
|
WHERE_FORCE_TABLE | WHERE_ONETABLE_ONLY;
|
||||||
for(ii=0; ii<pOrWc->nTerm; ii++){
|
for(ii=0; ii<pOrWc->nTerm; ii++){
|
||||||
WhereTerm *pOrTerm = &pOrWc->a[ii];
|
WhereTerm *pOrTerm = &pOrWc->a[ii];
|
||||||
if( pOrTerm->leftCursor==iCur || (pOrTerm->eOperator & WO_AND)!=0 ){
|
if( pOrTerm->leftCursor==iCur || (pOrTerm->eOperator & WO_AND)!=0 ){
|
||||||
@@ -3529,8 +3532,7 @@ static Bitmask codeOneLoopStart(
|
|||||||
}
|
}
|
||||||
/* Loop through table entries that match term pOrTerm. */
|
/* Loop through table entries that match term pOrTerm. */
|
||||||
pSubWInfo = sqlite3WhereBegin(pParse, pOrTab, pOrExpr, 0, 0,
|
pSubWInfo = sqlite3WhereBegin(pParse, pOrTab, pOrExpr, 0, 0,
|
||||||
WHERE_OMIT_OPEN_CLOSE | WHERE_AND_ONLY |
|
wctrlFlags, iCovCur);
|
||||||
WHERE_FORCE_TABLE | WHERE_ONETABLE_ONLY, iCovCur);
|
|
||||||
assert( pSubWInfo || pParse->nErr || db->mallocFailed );
|
assert( pSubWInfo || pParse->nErr || db->mallocFailed );
|
||||||
if( pSubWInfo ){
|
if( pSubWInfo ){
|
||||||
WhereLoop *pSubLoop;
|
WhereLoop *pSubLoop;
|
||||||
@@ -3621,6 +3623,7 @@ static Bitmask codeOneLoopStart(
|
|||||||
){
|
){
|
||||||
assert( pSubWInfo->a[0].iIdxCur==iCovCur );
|
assert( pSubWInfo->a[0].iIdxCur==iCovCur );
|
||||||
pCov = pSubLoop->u.btree.pIndex;
|
pCov = pSubLoop->u.btree.pIndex;
|
||||||
|
wctrlFlags |= WHERE_REOPEN_IDX;
|
||||||
}else{
|
}else{
|
||||||
pCov = 0;
|
pCov = 0;
|
||||||
}
|
}
|
||||||
@@ -6219,6 +6222,7 @@ WhereInfo *sqlite3WhereBegin(
|
|||||||
pWInfo->aiCurOnePass[1] = iIndexCur;
|
pWInfo->aiCurOnePass[1] = iIndexCur;
|
||||||
}else if( iIdxCur && (wctrlFlags & WHERE_ONETABLE_ONLY)!=0 ){
|
}else if( iIdxCur && (wctrlFlags & WHERE_ONETABLE_ONLY)!=0 ){
|
||||||
iIndexCur = iIdxCur;
|
iIndexCur = iIdxCur;
|
||||||
|
if( wctrlFlags & WHERE_REOPEN_IDX ) op = OP_ReopenIdx;
|
||||||
}else{
|
}else{
|
||||||
iIndexCur = pParse->nTab++;
|
iIndexCur = pParse->nTab++;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user