]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Add some support for OR terms to sqlite3_whereinfo_hook().
authordan <dan@noemail.net>
Tue, 4 Apr 2017 17:50:31 +0000 (17:50 +0000)
committerdan <dan@noemail.net>
Tue, 4 Apr 2017 17:50:31 +0000 (17:50 +0000)
FossilOrigin-Name: 5cd070000da1d9e399090677b4db75dc5639c33211385d6eb84f14a4d0b617cd

manifest
manifest.uuid
src/shell_indexes.c
src/where.c
test/shell6.test

index fc73fb3e18c769dc26b764adaad0c6a3dcd37117..0e690d166db2b3df63281b96b1cc6721d59dd129 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Add\sthe\ssqlite3_whereinfo_hook()\sAPI\s-\san\sexperimental\sAPI\sreplacing\sthe\nDBCONFIG_WHEREINFO\shack\son\sthis\sbranch.
-D 2017-04-04T04:23:06.108
+C Add\ssome\ssupport\sfor\sOR\sterms\sto\ssqlite3_whereinfo_hook().
+D 2017-04-04T17:50:31.913
 F Makefile.in 1cc758ce3374a32425e4d130c2fe7b026b20de5b8843243de75f087c0a2661fb
 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
 F Makefile.msc a4c0613a18663bda56d8cf76079ab6590a7c3602e54befb4bbdef76bcaa38b6a
@@ -403,7 +403,7 @@ F src/resolve.c 3e518b962d932a997fae373366880fc028c75706
 F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac
 F src/select.c 2496d0cc6368dabe7ad2e4c7f5ed3ad9aa3b4d11cd90f33fa1d1ef72493f43aa
 F src/shell.c e524688c2544167f835ba43e24309f8707ca60c8ab6eb5c263a12c8618a233b8
-F src/shell_indexes.c 12cc58b62492bddc88f879086b4cd1045dbfd4e52040ecb6c39b971a6aac80ba
+F src/shell_indexes.c d40ea0a81112df7bdccd7232238bee0bbb39699085ea78cc08fd863bf052a63b
 F src/sqlite.h.in ae5c9cbf2e77492c319fca08769575d9695e64718a16d32324944d24e291bcf7
 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
 F src/sqlite3ext.h 58fd0676d3111d02e62e5a35992a7d3da5d3f88753acc174f2d37b774fbbdd28
@@ -483,7 +483,7 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
 F src/wal.c 40c543f0a2195d1b0dc88ef12142bea690009344
 F src/wal.h 06b2a0b599cc0f53ea97f497cf8c6b758c999f71
 F src/walker.c b71a992b413b3a022572eccf29ef4b4890223791
-F src/where.c cbd1e8562fa37de359963749e1dc3d0dd1a42a894d10a62928bffc709490fde6
+F src/where.c be352441558b55e21964ff53f0483776594789d0ede12dd9c58b022873c858f8
 F src/whereInt.h 2d50c2b74a33be44cb68fdecee30b4d93552f1f4
 F src/wherecode.c 677e95413c472c0b413023b6b69a47f40fce1b04
 F src/whereexpr.c 130cdd1a43af71b19755270fb1224874cf55158c
@@ -1120,7 +1120,7 @@ F test/shell2.test e242a9912f44f4c23c3d1d802a83e934e84c853b
 F test/shell3.test 9b95ba643eaa228376f06a898fb410ee9b6e57c1
 F test/shell4.test 89ad573879a745974ff2df20ff97c5d6ffffbd5d
 F test/shell5.test 50a732c1c2158b1cd62cf53975ce1ea7ce6b9dc9
-F test/shell6.test 05c2488ff2bb11ac300b9170e8f5b6e03d58982c77035cdca5dbf036f0d3c5b7
+F test/shell6.test 081067c1afcb38da50134ffd5ccc0a59ede14f41959486f733ffbba689c0ccfa
 F test/shell7.test 07751911b294698e0c5df67bcbd29e7d2f0f2907
 F test/shortread1.test bb591ef20f0fd9ed26d0d12e80eee6d7ac8897a3
 F test/show_speedtest1_rtree.tcl 32e6c5f073d7426148a6936a0408f4b5b169aba5
@@ -1571,7 +1571,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P cb721d0b36268a7b0ef493fa4d7f6bcbaa9ead8b1990e3c3fae015fa1d545226
-R 061e66f6528edc67cfbe5cb82be7b02d
+P a54aef35da11f7508a8888a159372036a362fc52afa1df752dc835db334c4330
+R 51e547bc1c25ea79dd375d8f020224f3
 U dan
-Z d08fd2524fbe07ca7104a150ba1edcbe
+Z fe378068686ea107c39185021a17b4ae
index 64b0731eb56bc5d7915c2c8e0bb4de9c40afc6aa..7669c54b05f7b7ba993bbef3e1b15f74466505c8 100644 (file)
@@ -1 +1 @@
-a54aef35da11f7508a8888a159372036a362fc52afa1df752dc835db334c4330
\ No newline at end of file
+5cd070000da1d9e399090677b4db75dc5639c33211385d6eb84f14a4d0b617cd
\ No newline at end of file
index efdc24fac3c4e2b94c42625e2445db819d086fd0..e061f04d3f7f93ba31e27152fce9e080f6df1481 100644 (file)
@@ -175,9 +175,6 @@ static void idxWhereInfo(
     eOp==SQLITE_WHEREINFO_EQUALS ? "EQUALS" :
     eOp==SQLITE_WHEREINFO_RANGE ? "RANGE" :
     eOp==SQLITE_WHEREINFO_ORDERBY ? "ORDERBY" :
-    eOp==SQLITE_WHEREINFO_NEXTOR ? "NEXTOR" :
-    eOp==SQLITE_WHEREINFO_ENDOR ? "ENDOR" :
-    eOp==SQLITE_WHEREINFO_BEGINOR ? "BEGINOR" :
     "!error!";
   printf("op=%s zVal=%s iVal=%d mask=%llx\n", zOp, zVal, iVal, mask);
 #endif
@@ -630,7 +627,9 @@ static int idxCreateFromCons(
         rc = SQLITE_NOMEM;
       }else{
         rc = sqlite3_exec(dbm, zIdx, 0, 0, pCtx->pzErrmsg);
-        /* printf("%s\n", zIdx); */
+#if 0
+        printf("CANDIDATE: %s\n", zIdx);
+#endif
       }
     }
     if( rc==SQLITE_OK && pCtx->iIdxRowid==0 ){
index ba2ccfe65e178480e2a0fa93ca3f8092663c4be9..a423fa183915b04a11cef0f40d9fad428b1907ed 100644 (file)
@@ -4278,6 +4278,7 @@ static int whereShortCut(WhereLoopBuilder *pBuilder){
 }
 
 #ifdef SQLITE_ENABLE_WHEREINFO_HOOK
+
 static void whereTraceWC(
   Parse *pParse, 
   struct SrcList_item *pItem,
@@ -4285,7 +4286,7 @@ static void whereTraceWC(
 ){
   sqlite3 *db = pParse->db;
   Table *pTab = pItem->pTab;
-  void (*x)(void*, int, const char*, int, i64) = db->xWhereInfo;
+  void (*x)(void*, int, const char*, int, u64) = db->xWhereInfo;
   void *pCtx = db->pWhereInfoCtx;
   int ii;
 
@@ -4311,6 +4312,109 @@ static void whereTraceWC(
   }
 }
 
+/*
+** If there are any OR terms in WHERE clause pWC, make the associated
+** where-info hook callbacks.
+*/
+static void whereTraceOR(
+  Parse *pParse, 
+  struct SrcList_item *pItem,
+  WhereClause *pWC
+){
+  sqlite3 *db = pParse->db;
+  WhereClause tempWC;
+  struct TermAndIdx {
+    WhereTerm *pTerm;
+    int iIdx;
+  } aOr[4];
+  int nOr = 0;
+  Table *pTab = pItem->pTab;
+  int iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
+  int ii;
+
+  memset(aOr, 0, sizeof(aOr));
+
+  /* Iterate through OR nodes */
+  for(ii=0; ii<pWC->nTerm; ii++){
+    WhereTerm *pTerm = &pWC->a[ii];
+    if( pTerm->eOperator & WO_OR ){
+      /* Check that each branch of this OR term contains at least
+      ** one reference to the table currently being processed. If that
+      ** is not the case, this term can be ignored.  */
+      WhereClause * const pOrWC = &pTerm->u.pOrInfo->wc;
+      WhereTerm * const pOrWCEnd = &pOrWC->a[pOrWC->nTerm];
+      WhereTerm *pOrTerm;
+      WhereClause *pTermWC;
+      WhereScan scan;
+
+      for(pOrTerm=pOrWC->a; pOrTerm<pOrWCEnd; pOrTerm++){
+        int iCol;
+        if( (pOrTerm->eOperator & WO_AND)!=0 ){
+          pTermWC = &pOrTerm->u.pAndInfo->wc;
+        }else{
+          tempWC.pWInfo = pWC->pWInfo;
+          tempWC.pOuter = pWC;
+          tempWC.op = TK_AND;
+          tempWC.nTerm = 1;
+          tempWC.a = pOrTerm;
+          pTermWC = &tempWC;
+        }
+
+        for(iCol=0; iCol<pTab->nCol; iCol++){
+          int iCsr = pItem->iCursor;
+          if( !whereScanInit(&scan, pTermWC, iCsr, iCol, WO_SINGLE, 0) ){
+            break;
+          }
+        }
+        if( iCol==pTab->nCol ) break;
+      }
+
+      if( pOrTerm==pOrWCEnd ){
+        aOr[nOr].pTerm = pTerm;
+        aOr[nOr].iIdx = pOrWC->nTerm;
+        nOr++;
+        if( nOr==ArraySize(aOr) ) break;
+      }
+    }
+  }
+
+  while( 1 ){
+    for(ii=0; ii<nOr; ii++){
+      if( aOr[ii].iIdx==0 ){
+        aOr[ii].iIdx = aOr[ii].pTerm->u.pOrInfo->wc.nTerm;
+      }else{
+        aOr[ii].iIdx--;
+        break;
+      }
+    }
+    if( ii==nOr ) break;
+
+    /* Table name callback */
+    db->xWhereInfo(db->pWhereInfoCtx, 
+        SQLITE_WHEREINFO_TABLE, pTab->zName, iDb, pItem->colUsed
+    );
+    /* whereTraceWC(pParse, pItem, pWC); */
+    for(ii=0; ii<nOr; ii++){
+      WhereClause * const pOrWC = &aOr[ii].pTerm->u.pOrInfo->wc;
+      if( aOr[ii].iIdx<pOrWC->nTerm ){
+        WhereClause *pTermWC;
+        WhereTerm *pOrTerm = &pOrWC->a[aOr[ii].iIdx];
+        if( (pOrTerm->eOperator & WO_AND)!=0 ){
+          pTermWC = &pOrTerm->u.pAndInfo->wc;
+        }else{
+          tempWC.pWInfo = pWC->pWInfo;
+          tempWC.pOuter = pWC;
+          tempWC.op = TK_AND;
+          tempWC.nTerm = 1;
+          tempWC.a = pOrTerm;
+          pTermWC = &tempWC;
+        }
+        whereTraceWC(pParse, pItem, pTermWC);
+      }
+    }
+  }
+}
+
 /*
 ** If there is a where-info hook attached to the database handle, issue all
 ** required callbacks for the current sqlite3WhereBegin() call.
@@ -4321,16 +4425,16 @@ static void whereTraceBuilder(
 ){
   sqlite3 *db = pParse->db;
   if( db->xWhereInfo && db->init.busy==0 ){
-    void (*x)(void*, int, const char*, int, i64) = db->xWhereInfo;
+    void (*x)(void*, int, const char*, int, u64) = db->xWhereInfo;
     void *pCtx = db->pWhereInfoCtx;
     int ii;
-    int nTab = p->pWInfo->pTabList->nSrc;
+    SrcList *pTabList = p->pWInfo->pTabList;
 
     /* Loop through each element of the FROM clause. Ignore any sub-selects
     ** or views. Invoke the xWhereInfo() callback multiple times for each
     ** real table.  */
-    for(ii=0; ii<p->pWInfo->pTabList->nSrc; ii++){
-      struct SrcList_item *pItem = &p->pWInfo->pTabList->a[ii];
+    for(ii=0; ii<pTabList->nSrc; ii++){
+      struct SrcList_item *pItem = &pTabList->a[ii];
       if( pItem->pSelect==0 ){
         Table *pTab = pItem->pTab;
         int iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
@@ -4357,6 +4461,9 @@ static void whereTraceBuilder(
 
         /* WHERE callbacks */
         whereTraceWC(pParse, pItem, p->pWC);
+
+        /* OR-clause processing */
+        whereTraceOR(pParse, pItem, p->pWC);
       }
     }
   }
index 19b094a80deec533e3ae2cfe63cad31e66da6960..c44ccf0bd16483f83304076742d39ba27350bc56 100644 (file)
@@ -188,4 +188,18 @@ do_setup_rec_test 10.1 {
   0|1|0|SEARCH TABLE t5 USING COVERING INDEX t5_idx_000123a7 (a=? AND b=?)
 }
 
+# OR terms.
+#
+do_setup_rec_test 11.1 {
+  CREATE TABLE t7(a, b);
+} {
+  SELECT * FROM t7 WHERE a=? OR b=?
+} {
+  CREATE INDEX t7_idx_00000061 ON t7(a) 
+  CREATE INDEX t7_idx_00000062 ON t7(b)
+  0|0|0|SEARCH TABLE t7 USING INDEX t7_idx_00000061 (a=?) 
+  0|0|0|SEARCH TABLE t7 USING INDEX t7_idx_00000062 (b=?)
+}
+
 finish_test
+