]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Now generating OR-clause plans.
authordrh <drh@noemail.net>
Fri, 10 May 2013 20:26:22 +0000 (20:26 +0000)
committerdrh <drh@noemail.net>
Fri, 10 May 2013 20:26:22 +0000 (20:26 +0000)
FossilOrigin-Name: e17003fcfec0c0b524b1b9ff8e15e7ee83efa571

manifest
manifest.uuid
src/where.c

index 180d5b5b5125f9e15efc0a9d34aa5b90d58de5ee..5d695c8a7f8d5070e3643a73841ab4ec2ea0d5ab 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Update\sthe\sNGQP\sso\sthat\sit\scan\sproduce\splans\sthat\sinclude\sautomatic\sindices.
-D 2013-05-10T15:16:30.669
+C Now\sgenerating\sOR-clause\splans.
+D 2013-05-10T20:26:22.071
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in ce81671efd6223d19d4c8c6b88ac2c4134427111
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -264,7 +264,7 @@ F src/vtab.c b05e5f1f4902461ba9f5fc49bb7eb7c3a0741a83
 F src/wal.c 436bfceb141b9423c45119e68e444358ee0ed35d
 F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
 F src/walker.c 4fa43583d0a84b48f93b1e88f11adf2065be4e73
-F src/where.c f96b2602fd2da89873ed5a210608c58bf80d7c0e
+F src/where.c 374f50ced988b23addabd3c351f1c18d8652d394
 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
 F test/aggnested.test 45c0201e28045ad38a530b5a144b73cd4aa2cfd6
@@ -1062,7 +1062,7 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381
 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
 F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac
-P 0278e420614e02fb2d8474ed99b0904275882dfe
-R 69dec67361636bd352a6f82f3ef9f1cb
+P 586b55d8d7722de1c0530b3b832bae0511e6d05c
+R a9f14f7930497f93900a124a55885f20
 U drh
-Z ef95f556fc74affef6b6df28ead69ff3
+Z 9615c6567bc86000a51d8e76292d6ef0
index 0143fae8fc717fef4879a0061b202c0f7c34e2a8..250be9516250d3c4c8523f5a601c75d5a66c7e91 100644 (file)
@@ -1 +1 @@
-586b55d8d7722de1c0530b3b832bae0511e6d05c
\ No newline at end of file
+e17003fcfec0c0b524b1b9ff8e15e7ee83efa571
\ No newline at end of file
index 40653d7c5117607014f1108b413abc80079c4c2b..fdadc3e7387e7ceacb841abf77a8bf8265edb51e 100644 (file)
@@ -289,6 +289,7 @@ struct WhereLoopBuilder {
   SrcList *pTabList;        /* FROM clause */
   ExprList *pOrderBy;       /* ORDER BY clause */
   WhereLoop *pNew;          /* Template WhereLoop */
+  WhereLoop *pBest;         /* If non-NULL, store single best loop here */
   int mxTerm;               /* Maximum number of aTerm[] entries on pNew */
 };
 
@@ -5162,10 +5163,27 @@ static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){
 ** fewer dependencies than the template.  Otherwise a new WhereLoop is
 ** added based no the template.
 */
-static int whereLoopInsert(WhereInfo *pWInfo, WhereLoop *pTemplate){
+static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){
   WhereLoop **ppPrev, *p, *pNext = 0, *pToFree = 0;
   WhereTerm **paTerm = 0;
-  sqlite3 *db = pWInfo->pParse->db;
+  sqlite3 *db = pBuilder->db;
+  WhereInfo *pWInfo = pBuilder->pWInfo;
+
+  if( (p = pBuilder->pBest)!=0 ){
+    if( p->maskSelf!=0 ){
+      if( p->rRun+p->rSetup < pTemplate->rRun+pTemplate->rSetup ){
+        return SQLITE_OK;
+      }
+      if( p->rRun+p->rSetup == pTemplate->rRun+pTemplate->rSetup
+       && p->prereq <= pTemplate->prereq ){
+        return SQLITE_OK;
+      }
+    }
+    *p = *pTemplate;
+    p->aTerm = 0;
+    p->u.vtab.needFree = 0;
+    return SQLITE_OK;
+  }
 
   /* Search for an existing WhereLoop to overwrite, or which takes
   ** priority over pTemplate.
@@ -5210,11 +5228,13 @@ static int whereLoopInsert(WhereInfo *pWInfo, WhereLoop *pTemplate){
   p->pNextLoop = pNext;
   *ppPrev = p;
   p->aTerm = paTerm;
-  if( pTemplate->nTerm ){
-    memcpy(p->aTerm, pTemplate->aTerm, pTemplate->nTerm*sizeof(p->aTerm[0]));
+  if( p->nTerm ){
+    memcpy(p->aTerm, pTemplate->aTerm, p->nTerm*sizeof(p->aTerm[0]));
   }
   if( (p->wsFlags & WHERE_VIRTUALTABLE)==0 ){
-    if( p->u.btree.pIndex && p->u.btree.pIndex->tnum==0 ) p->u.btree.pIndex = 0;
+    if( p->u.btree.pIndex && p->u.btree.pIndex->tnum==0 ){
+      p->u.btree.pIndex = 0;
+    }
   }else{
     pTemplate->u.vtab.needFree = 0;
   }
@@ -5305,7 +5325,7 @@ static int whereLoopAddBtreeIndex(
     }
     /* TBD: Adjust nOut and rRun for STAT3 range values */
     /* TBD: Adjust nOut for additional constraints */
-    rc = whereLoopInsert(pBuilder->pWInfo, pNew);
+    rc = whereLoopInsert(pBuilder, pNew);
     if( (pNew->wsFlags & WHERE_TOP_LIMIT)==0
      && pNew->u.btree.nEq<pProbe->nColumn
     ){
@@ -5366,7 +5386,8 @@ static int whereLoopAddBtree(
   rLogSize = estLog(rSize);
 
   /* Automatic indexes */
-  if( (pBuilder->pParse->db->flags & SQLITE_AutoIndex)!=0 
+  if( !pBuilder->pBest
+   && (pBuilder->pParse->db->flags & SQLITE_AutoIndex)!=0 
    && !pSrc->viaCoroutine
    && !pSrc->notIndexed
    && !pSrc->isCorrelated
@@ -5385,7 +5406,7 @@ static int whereLoopAddBtree(
         pNew->rRun = rLogSize + pNew->nOut;
         pNew->wsFlags = WHERE_TEMP_INDEX;
         pNew->prereq = mExtra | pTerm->prereqRight;
-        rc = whereLoopInsert(pBuilder->pWInfo, pNew);
+        rc = whereLoopInsert(pBuilder, pNew);
       }
     }
   }
@@ -5400,7 +5421,7 @@ static int whereLoopAddBtree(
   pNew->nOut = rSize;
   pNew->rRun = rSize + rLogSize;
   /* TBD: Reduce nOut using constraints */
-  rc = whereLoopInsert(pBuilder->pWInfo, pNew);
+  rc = whereLoopInsert(pBuilder, pNew);
 
   /* Loop over all indices
   */
@@ -5565,7 +5586,7 @@ static int whereLoopAddVirtual(
       pNew->rSetup = (double)0;
       pNew->rRun = pIdxInfo->estimatedCost;
       pNew->nOut = (double)25;
-      whereLoopInsert(pBuilder->pWInfo, pNew);
+      whereLoopInsert(pBuilder, pNew);
       if( pNew->u.vtab.needFree ){
         sqlite3_free(pNew->u.vtab.idxStr);
         pNew->u.vtab.needFree = 0;
@@ -5579,6 +5600,84 @@ whereLoopAddVtab_exit:
   return rc;
 }
 
+/*
+** Add WhereLoop entries to handle OR terms.  This works for either
+** btrees or virtual tables.
+*/
+static int whereLoopAddOr(WhereLoopBuilder *pBuilder, Bitmask mExtra){
+  WhereClause *pWC;
+  WhereLoop *pNew;
+  WhereTerm *pTerm, *pWCEnd;
+  int rc = SQLITE_OK;
+  int iCur;
+  WhereClause tempWC;
+  WhereLoopBuilder sSubBuild;
+  WhereLoop sBest;
+  struct SrcList_item *pItem;
+  
+
+  pWC = pBuilder->pWC;
+  if( pWC->wctrlFlags & WHERE_AND_ONLY ) return SQLITE_OK;
+  pWCEnd = pWC->a + pWC->nTerm;
+  pNew = pBuilder->pNew;
+  pItem = pBuilder->pTabList->a + pNew->iTab;
+  iCur = pItem->iCursor;
+  sSubBuild = *pBuilder;
+  sSubBuild.pOrderBy = 0;
+  sSubBuild.pBest = &sBest;
+  tempWC.pParse = pWC->pParse;
+  tempWC.pMaskSet = pWC->pMaskSet;
+  tempWC.pOuter = pWC;
+  tempWC.op = TK_AND;
+  tempWC.wctrlFlags = 0;
+  tempWC.nTerm = 1;
+
+  for(pTerm=pWC->a; pTerm<pWCEnd && rc==SQLITE_OK; pTerm++){
+    if( (pTerm->eOperator & WO_OR)!=0
+     && (pTerm->u.pOrInfo->indexable & pNew->maskSelf)!=0 
+    ){
+      WhereClause * const pOrWC = &pTerm->u.pOrInfo->wc;
+      WhereTerm * const pOrWCEnd = &pOrWC->a[pOrWC->nTerm];
+      WhereTerm *pOrTerm;
+      double rTotal = 0;
+      double nRow = 0;
+      Bitmask prereq = mExtra;
+
+
+      for(pOrTerm=pOrWC->a; pOrTerm<pOrWCEnd; pOrTerm++){
+        if( (pOrTerm->eOperator& WO_AND)!=0 ){
+          sSubBuild.pWC = &pOrTerm->u.pAndInfo->wc;
+        }else if( pOrTerm->leftCursor==iCur ){
+          tempWC.a = pOrTerm;
+          sSubBuild.pWC = &tempWC;
+        }else{
+          continue;
+        }
+        sBest.maskSelf = 0;
+        if( IsVirtual(pItem->pTab) ){
+          rc = whereLoopAddVirtual(&sSubBuild, mExtra);
+        }else{
+          rc = whereLoopAddBtree(&sSubBuild, mExtra);
+        }
+        if( sBest.maskSelf==0 ) break;
+        assert( sBest.rSetup==(double)0 );
+        rTotal += sBest.rRun;
+        nRow += sBest.nOut;
+        prereq |= sBest.prereq;
+      }
+      pNew->nTerm = 1;
+      pNew->aTerm[0] = pTerm;
+      pNew->wsFlags = WHERE_MULTI_OR;
+      pNew->rSetup = (double)0;
+      pNew->rRun = rTotal;
+      pNew->nOut = nRow;
+      pNew->prereq = prereq;
+      rc = whereLoopInsert(pBuilder, pNew);
+    }
+  }
+  return rc;
+}
+
 /*
 ** Add all WhereLoop objects for all tables 
 */
@@ -5619,11 +5718,9 @@ static int whereLoopAddAll(WhereLoopBuilder *pBuilder){
     }else{
       rc = whereLoopAddBtree(pBuilder, mExtra);
     }
-#if 0
     if( rc==SQLITE_OK ){
       rc = whereLoopAddOr(pBuilder, mExtra);
     }
-#endif
     mPrior |= pNew->maskSelf;
     if( rc || db->mallocFailed ) break;
   }