]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Attempt to disable inner loops of a join that do not generate output.
authordrh <drh@noemail.net>
Fri, 21 Jun 2013 02:05:06 +0000 (02:05 +0000)
committerdrh <drh@noemail.net>
Fri, 21 Jun 2013 02:05:06 +0000 (02:05 +0000)
This does not work, since the inner loops might run zero times and thus
inhibit all output.  Needs to be enhanced to work only for LEFT JOINs
or when we know that the inner loop will always run at least once.

FossilOrigin-Name: ca839723a21bb13d3e0666a672c15c6f3a267c2f

manifest
manifest.uuid
src/where.c
test/alter2.test

index ede3df57062df3cb4a615950616f39f4a088a071..2d7ec778f62243bb57fcf873bb30f1056de57358 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Modify\sthe\squery\splanner\sinterface\sso\sthat\sit\salways\spasses\sin\sthe\sresult\sset.\nThis\sis\sthe\sfirst\sstep\stoward\sadding\san\soptimization\sthat\swill\somit\stables\nfrom\sa\sjoin\sthat\sdo\snot\scontribute\sto\sthe\sresult.
-D 2013-06-21T00:35:37.456
+C Attempt\sto\sdisable\sinner\sloops\sof\sa\sjoin\sthat\sdo\snot\sgenerate\soutput.\nThis\sdoes\snot\swork,\ssince\sthe\sinner\sloops\smight\srun\szero\stimes\sand\sthus\ninhibit\sall\soutput.\s\sNeeds\sto\sbe\senhanced\sto\swork\sonly\sfor\sLEFT\sJOINs\nor\swhen\swe\sknow\sthat\sthe\sinner\sloop\swill\salways\srun\sat\sleast\sonce.
+D 2013-06-21T02:05:06.206
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in 5e41da95d92656a5004b03d3576e8b226858a28e
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -289,14 +289,14 @@ F src/vtab.c b05e5f1f4902461ba9f5fc49bb7eb7c3a0741a83
 F src/wal.c 436bfceb141b9423c45119e68e444358ee0ed35d
 F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
 F src/walker.c 4fa43583d0a84b48f93b1e88f11adf2065be4e73
-F src/where.c c950b131584a40121092d735804472f567beefbc
+F src/where.c fc5293b54a70474c2b46e9df26c9e2803b152e68
 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
 F test/aggnested.test 45c0201e28045ad38a530b5a144b73cd4aa2cfd6
 F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87
 F test/all.test 6ff7b43c2b4b905c74dc4a813d201d0fa64c5783
 F test/alter.test 57d96ec9b320bd07af77567034488dcb6642c748
-F test/alter2.test 40531b1f89d4fe43f9007b1bfc304e291ed000ae
+F test/alter2.test 7ea05c7d92ac99349a802ef7ada17294dd647060
 F test/alter3.test 49c9d9fba2b8fcdce2dedeca97bbf1f369cc548d
 F test/alter4.test b2debc14d8cbe4c1d12ccd6a41eef88a8c1f15d5
 F test/altermalloc.test e81ac9657ed25c6c5bb09bebfa5a047cd8e4acfc
@@ -1096,10 +1096,7 @@ F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
 F tool/wherecosttest.c f407dc4c79786982a475261866a161cd007947ae
 F tool/win/sqlite.vsix 97894c2790eda7b5bce3cc79cb2a8ec2fde9b3ac
-P 604c3c5de6fd8f8a569aa9ed981055a5b0123ba1
-R 54a7c9b08c105a408dfe2c4fd7fd4419
-T *branch * omit-join-table-opt
-T *sym-omit-join-table-opt *
-T -sym-nextgen-query-plan-exp *
+P 2c2577e69ccb47f1af674a755e71221e2ca0b322
+R b2263c66dd8a59884ee45351c335261a
 U drh
-Z d2a3072c8b463b513f8068b32a4cb830
+Z 6fd83e64fe937f64082b799e88969f81
index 169f9d22e6a7a4dd5d4db9dac0ba1105323f2ec9..b8cca3c3d89e588593dd141268b624b69d4abb0d 100644 (file)
@@ -1 +1 @@
-2c2577e69ccb47f1af674a755e71221e2ca0b322
\ No newline at end of file
+ca839723a21bb13d3e0666a672c15c6f3a267c2f
\ No newline at end of file
index ab4170fe6fe7c94ad9324cf3e057d20cc668056e..18b4a3782e68c83ecf2430676e902d594d8e8e1c 100644 (file)
@@ -392,10 +392,10 @@ struct WhereInfo {
   u8 okOnePass;             /* Ok to use one-pass algorithm for UPDATE/DELETE */
   u8 untestedTerms;         /* Not all WHERE terms resolved by outer loop */
   u8 eDistinct;             /* One of the WHERE_DISTINCT_* values below */
+  u8 nLevel;                /* Number of nested loop */
   int iTop;                 /* The very beginning of the WHERE loop */
   int iContinue;            /* Jump here to continue with next record */
   int iBreak;               /* Jump here to break out of the loop */
-  int nLevel;               /* Number of nested loop */
   int savedNQueryLoop;      /* pParse->nQueryLoop outside the WHERE loop */
   WhereMaskSet sMaskSet;    /* Map cursor numbers to bitmasks */
   WhereClause sWC;          /* Decomposition of the WHERE clause */
@@ -5370,8 +5370,9 @@ static int wherePathSolver(WhereInfo *pWInfo, WhereCost nRowEst){
     pLevel->iFrom = pWLoop->iTab;
     pLevel->iTabCur = pWInfo->pTabList->a[pLevel->iFrom].iCursor;
   }
-  if( (pWInfo->wctrlFlags & (WHERE_DISTINCTBY|WHERE_WANT_DISTINCT))
-                ==WHERE_WANT_DISTINCT
+  if( (pWInfo->wctrlFlags & WHERE_WANT_DISTINCT)!=0
+   && (pWInfo->wctrlFlags & WHERE_DISTINCTBY)==0
+   && pWInfo->eDistinct==WHERE_DISTINCT_NOOP
    && nRowEst
   ){
     Bitmask notUsed;
@@ -5571,15 +5572,23 @@ WhereInfo *sqlite3WhereBegin(
   WhereLoopBuilder sWLB;     /* The WhereLoop builder */
   WhereMaskSet *pMaskSet;    /* The expression mask set */
   WhereLevel *pLevel;        /* A single level in pWInfo->a[] */
+  WhereLoop *pLoop;          /* Pointer to a single WhereLoop object */
   int ii;                    /* Loop counter */
   sqlite3 *db;               /* Database connection */
   int rc;                    /* Return code */
 
 
   /* Variable initialization */
+  db = pParse->db;
   memset(&sWLB, 0, sizeof(sWLB));
   sWLB.pOrderBy = pOrderBy;
 
+  /* Disable the DISTINCT optimization if SQLITE_DistinctOpt is set via
+  ** sqlite3_test_ctrl(SQLITE_TESTCTRL_OPTIMIZATIONS,...) */
+  if( OptimizationDisabled(db, SQLITE_DistinctOpt) ){
+    wctrlFlags &= ~WHERE_WANT_DISTINCT;
+  }
+
   /* The number of tables in the FROM clause is limited by the number of
   ** bits in a Bitmask 
   */
@@ -5603,7 +5612,6 @@ WhereInfo *sqlite3WhereBegin(
   ** field (type Bitmask) it must be aligned on an 8-byte boundary on
   ** some architectures. Hence the ROUND8() below.
   */
-  db = pParse->db;
   nByteWInfo = ROUND8(sizeof(WhereInfo)+(nTabList-1)*sizeof(WhereLevel));
   pWInfo = sqlite3DbMallocZero(db, nByteWInfo + sizeof(WhereLoop));
   if( db->mallocFailed ){
@@ -5628,12 +5636,6 @@ WhereInfo *sqlite3WhereBegin(
   sWLB.pNew->cId = '*';
 #endif
 
-  /* Disable the DISTINCT optimization if SQLITE_DistinctOpt is set via
-  ** sqlite3_test_ctrl(SQLITE_TESTCTRL_OPTIMIZATIONS,...) */
-  if( OptimizationDisabled(db, SQLITE_DistinctOpt) ){
-    wctrlFlags &= ~WHERE_WANT_DISTINCT;
-  }
-
   /* Split the WHERE clause into separate subexpressions where each
   ** subexpression is separated by an AND operator.
   */
@@ -5718,7 +5720,6 @@ WhereInfo *sqlite3WhereBegin(
   if( wctrlFlags & WHERE_WANT_DISTINCT ){
     if( isDistinctRedundant(pParse, pTabList, &pWInfo->sWC, pResultSet) ){
       /* The DISTINCT marking is pointless.  Ignore it. */
-      wctrlFlags &= ~WHERE_WANT_DISTINCT;
       pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE;
     }else if( pOrderBy==0 ){
       /* Try to ORDER BY the result set to make distinct processing easier */
@@ -5737,11 +5738,11 @@ WhereInfo *sqlite3WhereBegin(
 #ifdef WHERETRACE_ENABLED
     if( sqlite3WhereTrace ){
       WhereLoop *p;
-      int i = 0;
+      int i;
       static char zLabel[] = "0123456789abcdefghijklmnopqrstuvwyxz"
                                        "ABCDEFGHIJKLMNOPQRSTUVWYXZ";
-      for(p=pWInfo->pLoops; p; p=p->pNextLoop){
-        p->cId = zLabel[(i++)%sizeof(zLabel)];
+      for(p=pWInfo->pLoops, i=0; p; p=p->pNextLoop, i++){
+        p->cId = zLabel[i%sizeof(zLabel)];
         whereLoopPrint(p, pTabList);
       }
     }
@@ -5782,11 +5783,29 @@ WhereInfo *sqlite3WhereBegin(
       }
     }
     sqlite3DebugPrintf("\n");
-    for(ii=0; ii<nTabList; ii++){
+    for(ii=0; ii<pWInfo->nLevel; ii++){
       whereLoopPrint(pWInfo->a[ii].pWLoop, pTabList);
     }
   }
 #endif
+  /* Attempt to omit tables from the join that do not effect the result */
+  if( pResultSet!=0 && pWInfo->nLevel>=2 ){
+    Bitmask tabUsed = exprListTableUsage(pMaskSet, pResultSet);
+    if( pOrderBy ) tabUsed |= exprListTableUsage(pMaskSet, pOrderBy);
+    while( pWInfo->nLevel>=2 ){
+      pLoop = pWInfo->a[pWInfo->nLevel-1].pWLoop;
+      if( ((wctrlFlags & WHERE_WANT_DISTINCT)!=0
+           || (pLoop->wsFlags & WHERE_ONEROW)!=0)
+       && (tabUsed & pLoop->maskSelf)==0
+      ){
+        WHERETRACE(0xffff, ("-> drop loop %c not used\n", pLoop->cId));
+        pWInfo->nLevel--;
+        nTabList--;
+      }else{
+        break;
+      }
+    }
+  }
   WHERETRACE(0xffff,("*** Optimizer Finished ***\n"));
   pWInfo->pParse->nQueryLoop += pWInfo->nRowOut;
 
@@ -5955,7 +5974,7 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
 
   /* Close all of the cursors that were opened by sqlite3WhereBegin.
   */
-  assert( pWInfo->nLevel==1 || pWInfo->nLevel==pTabList->nSrc );
+  assert( pWInfo->nLevel<=pTabList->nSrc );
   for(i=0, pLevel=pWInfo->a; i<pWInfo->nLevel; i++, pLevel++){
     Index *pIdx = 0;
     struct SrcList_item *pTabItem = &pTabList->a[pLevel->iFrom];
index db8a83bf9f935df8119c2badad9abbef55e5068d..14be637f970ffd3a6a6875420a2196faf3e05a71 100644 (file)
@@ -120,7 +120,6 @@ do_test alter2-1.5 {
   }
 } {}
 do_test alter2-1.6 {
-breakpoint
   execsql {
     SELECT c FROM abc ORDER BY c;
   }