aboutsummaryrefslogtreecommitdiff
path: root/src/wherecode.c
diff options
context:
space:
mode:
authordan <dan@noemail.net>2016-01-29 19:29:45 +0000
committerdan <dan@noemail.net>2016-01-29 19:29:45 +0000
commitde892d96604b09cf959cd317243a2176b3d9531a (patch)
tree678387b77b15ed2894b38764e87e550042dbd976 /src/wherecode.c
parent65875f37bc26aa5ebda3f13ebf0571c2618d90db (diff)
downloadsqlite-de892d96604b09cf959cd317243a2176b3d9531a.tar.gz
sqlite-de892d96604b09cf959cd317243a2176b3d9531a.zip
Experimental attempt to make better use of covering indexes within OR queries.
FossilOrigin-Name: a323ac3a9d42bd5cb38d724c7e1180584b91054c
Diffstat (limited to 'src/wherecode.c')
-rw-r--r--src/wherecode.c50
1 files changed, 49 insertions, 1 deletions
diff --git a/src/wherecode.c b/src/wherecode.c
index 4fd7399ef..eacd6d08d 100644
--- a/src/wherecode.c
+++ b/src/wherecode.c
@@ -747,6 +747,54 @@ static void codeCursorHint(
#endif /* SQLITE_ENABLE_CURSOR_HINTS */
/*
+** Cursor iCur is open on an intkey b-tree (a table). Register iRowid contains
+** a rowid value just read from cursor iIdxCur, open on index pIdx. This
+** function generates code to do a deferred seek of cursor iCur to the
+** rowid stored in register iRowid.
+**
+** Normally, this is just:
+**
+** OP_Seek $iCur $iRowid
+**
+** However, if the scan currently being coded is a branch of an OR-loop and
+** the statement currently being coded is a SELECT, then P3 of the OP_Seek
+** is set to iIdxCur and P4 is set to point to an array of integers
+** containing one entry for each column of the table cursor iCur is open
+** on. For each table column, if the column is the i'th column of the
+** index, then the corresponding array entry is set to (i+1). If the column
+** does not appear in the index at all, the array entry is set to 0.
+*/
+static void codeDeferredSeek(
+ WhereInfo *pWInfo, /* Where clause context */
+ Index *pIdx, /* Index scan is using */
+ int iCur, /* Cursor for IPK b-tree */
+ int iRowid, /* Register containing rowid to seek to */
+ int iIdxCur /* Index cursor */
+){
+ Parse *pParse = pWInfo->pParse; /* Parse context */
+ Vdbe *v = pParse->pVdbe; /* Vdbe to generate code within */
+
+ assert( iIdxCur>0 );
+ assert( pIdx->aiColumn[pIdx->nColumn-1]==-1 );
+
+ sqlite3VdbeAddOp3(v, OP_Seek, iCur, iRowid, iIdxCur);
+ if( (pWInfo->wctrlFlags & WHERE_FORCE_TABLE)
+ && sqlite3ParseToplevel(pParse)->writeMask==0
+ ){
+ int i;
+ Table *pTab = pIdx->pTable;
+ int *ai = (int*)sqlite3DbMallocZero(pParse->db, sizeof(int) * pTab->nCol);
+ if( ai ){
+ for(i=0; i<pIdx->nColumn-1; i++){
+ assert( pIdx->aiColumn[i]<pTab->nCol );
+ if( pIdx->aiColumn[i]>=0 ) ai[pIdx->aiColumn[i]] = i+1;
+ }
+ sqlite3VdbeChangeP4(v, -1, (char*)ai, P4_INTARRAY);
+ }
+ }
+}
+
+/*
** Generate code for the start of the iLevel-th loop in the WHERE clause
** implementation described by pWInfo.
*/
@@ -1232,7 +1280,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, iRowidReg);
VdbeCoverage(v);
}else{
- sqlite3VdbeAddOp2(v, OP_Seek, iCur, iRowidReg); /* Deferred seek */
+ codeDeferredSeek(pWInfo, pIdx, iCur, iRowidReg, iIdxCur);
}
}else if( iCur!=iIdxCur ){
Index *pPk = sqlite3PrimaryKeyIndex(pIdx->pTable);