]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Further foundation prep work prior to starting to flesh-out the
authordrh <>
Wed, 23 Nov 2022 14:13:39 +0000 (14:13 +0000)
committerdrh <>
Wed, 23 Nov 2022 14:13:39 +0000 (14:13 +0000)
optimizeAggregateUseOfIndexedExpr() routine.

FossilOrigin-Name: 23145fe999ff74d787a3999baedd4ffe755c5f1f1275082ed0338ba637ecc56e

manifest
manifest.uuid
src/select.c

index 768c50fa57b57c4d5638c24e083701ec9184f61c..1ffe8b4bb74db3470da6946e229695487832e44d 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Merge\senhancements\sand\sfixes\sfrom\strunk.
-D 2022-11-22T20:58:18.661
+C Further\sfoundation\sprep\swork\sprior\sto\sstarting\sto\sflesh-out\sthe\noptimizeAggregateUseOfIndexedExpr()\sroutine.
+D 2022-11-23T14:13:39.215
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -641,7 +641,7 @@ F src/printf.c e99ee9741e79ae3873458146f59644276657340385ade4e76a5f5d1c25793764
 F src/random.c 606b00941a1d7dd09c381d3279a058d771f406c5213c9932bbd93d5587be4b9c
 F src/resolve.c efea4e5fbecfd6d0a9071b0be0d952620991673391b6ffaaf4c277b0bb674633
 F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92
-F src/select.c 6f5403b8f1849d2a8ba152dd790ec189bba18242157904ddca77707e209265d4
+F src/select.c 1d3f8a5b510f8e2859c7f800babb5a63802789f93c9c29498312b37655dac1b8
 F src/shell.c.in 7d1705f139e6762e8c0fe254a8ebf3ab77aec6d8366f033cdd5f5ebadefbbb20
 F src/sqlite.h.in 100fc660c2f19961b8ed8437b9d53d687de2f8eb2b96437ec6da216adcb643ca
 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
@@ -2059,8 +2059,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P d85bb724fdd6fbad2b88ed7f60e4174e3f65182356f404d04620c5cf6b17f77e 9ec923b5dc24d6082da8d42bc0ee8ab1c418912625c0c56de9627be2c818ef98
-R 55f08c65335ec615b6caa516a7697c9d
+P f8932e04d4d18eb9d71edda15aa08af2eb139ff14d77ca147ea6e9b173e0f5e0
+R e49e6155bccbafba580b14baaea3db86
 U drh
-Z dbc39758acc6c225892e0cac1e391b2a
+Z b6500d1e8d8b2720badce4287d0e1594
 # Remove this line to create a well-formed Fossil manifest.
index 9c7d27e3fed72aa5d68f7e85bff8347025ba371a..f88bcea3d3677501e9b8f61767439e30d2ca056b 100644 (file)
@@ -1 +1 @@
-f8932e04d4d18eb9d71edda15aa08af2eb139ff14d77ca147ea6e9b173e0f5e0
\ No newline at end of file
+23145fe999ff74d787a3999baedd4ffe755c5f1f1275082ed0338ba637ecc56e
\ No newline at end of file
index f71fa3197e0889fb0e56299c6f3171d44773dc19..8f2517ad4f4a9b895be6d65afd8a3c987a69da43 100644 (file)
@@ -6204,9 +6204,106 @@ void sqlite3SelectPrep(
   sqlite3SelectAddTypeInfo(pParse, p);
 }
 
+#if TREETRACE_ENABLED
 /*
-** Assign register numbers to all pAggInfo->aCol[] and pAggInfo->aFunc[]
-** entries.
+** Display all information about an AggInfo object
+*/
+static void printAggInfo(AggInfo *pAggInfo){
+  int ii;
+  for(ii=0; ii<pAggInfo->nColumn; ii++){
+    struct AggInfo_col *pCol = &pAggInfo->aCol[ii];
+    sqlite3DebugPrintf(
+       "agg-column[%d] pTab=%s iTable=%d iColumn=%d iMem=%d"
+       " iSorterColumn=%d %s\n",
+       ii, pCol->pTab ? pCol->pTab->zName : "NULL", 
+       pCol->iTable, pCol->iColumn, AggInfoColumnReg(pAggInfo,ii),
+       pCol->iSorterColumn, 
+       ii>=pAggInfo->nAccumulator ? "" : " Accumulator");
+    sqlite3TreeViewExpr(0, pAggInfo->aCol[ii].pCExpr, 0);
+  }
+  for(ii=0; ii<pAggInfo->nFunc; ii++){
+    sqlite3DebugPrintf("agg-func[%d]: iMem=\n",
+        ii, AggInfoFuncReg(pAggInfo,ii));
+    sqlite3TreeViewExpr(0, pAggInfo->aFunc[ii].pFExpr, 0);
+  }
+}
+#endif /* TREETRACE_ENABLED */
+
+/*
+** Analyze the arguments to aggregate functions.  Create new pAggInfo->aCol[]
+** entries for columns that are arguments to aggregate functions but which
+** are not otherwise used.
+**
+** The aCol[] entries in AggInfo prior to nAccumulator are columns that
+** are referenced outside of aggregate functions.  These might be columns
+** that are part of the GROUP by clause, for example.  Other database engines
+** would throw an error if there is a column reference that is not in the
+** GROUP BY clause and that is not part of an aggregate function argument.
+** But SQLite allows this.
+**
+** The aCol[] entries beginning with the aCol[nAccumulator] and following
+** are column references that are used exclusively as arguments to
+** aggregate functions.  This routine is responsible for computing
+** (or recomputing) those aCol[] entries.
+*/
+static void analyzeAggFuncArgs(
+  Parse *pParse,
+  AggInfo *pAggInfo,
+  NameContext *pNC
+){
+  int i;
+  assert( pAggInfo!=0 );
+  pNC->ncFlags |= NC_InAggFunc;
+  for(i=0; i<pAggInfo->nFunc; i++){
+    Expr *pExpr = pAggInfo->aFunc[i].pFExpr;
+    assert( ExprUseXList(pExpr) );
+    sqlite3ExprAnalyzeAggList(pNC, pExpr->x.pList);
+#ifndef SQLITE_OMIT_WINDOWFUNC
+    assert( !IsWindowFunc(pExpr) );
+    if( ExprHasProperty(pExpr, EP_WinFunc) ){
+      sqlite3ExprAnalyzeAggregates(pNC, pExpr->y.pWin->pFilter);
+    }
+#endif
+  }
+  pNC->ncFlags &= ~NC_InAggFunc;
+}
+
+/*
+** An index on expressions is being used in the inner loop of an
+** aggregate query with a GROUP BY clause.  This routine attempts
+** to adjust the AggInfo object to take advantage of index and to
+** perhaps use the index as a covering index.
+**
+*/
+static void optimizeAggregateUseOfIndexedExpr(
+  Parse *pParse,          /* Parsing context */
+  Select *pSelect,        /* The SELECT statement being processed */
+  AggInfo *pAggInfo,      /* The aggregate info */
+  NameContext *pNC        /* Name context used to resolve agg-func args */
+){
+#if TREETRACE_ENABLED
+  if( sqlite3TreeTrace & 0x80000 ){
+    IndexedExpr *pIEpr;
+    TREETRACE(0x80000, pParse, pSelect,
+        ("Attempting to optimize AggInfo for Indexed Exprs\n"));
+    for(pIEpr=pParse->pIdxEpr; pIEpr; pIEpr=pIEpr->pIENext){
+      printf("data-cursor=%d index={%d,%d}\n",
+          pIEpr->iDataCur, pIEpr->iIdxCur, pIEpr->iIdxCol);
+      sqlite3TreeViewExpr(0, pIEpr->pExpr, 0);
+    }
+    printAggInfo(pAggInfo);
+  }
+#else
+  (void)pSelect;  /* Suppress unused-parameter warnings */
+#endif
+  pAggInfo->nColumn = pAggInfo->nAccumulator;
+  analyzeAggFuncArgs(pParse, pAggInfo, pNC);
+}
+
+/*
+** Allocate a block of registers so that there is one register for each
+** pAggInfo->aCol[] and pAggInfo->aFunc[] entry in pAggInfo.  The first
+** register in this block is stored in pAggInfo->iFirstReg.
 */
 static void assignAggregateRegisters(Parse *pParse, AggInfo *pAggInfo){
   assert( pAggInfo!=0 );
@@ -6630,60 +6727,6 @@ static int sameSrcAlias(SrcItem *p0, SrcList *pSrc){
   return 0;
 }
 
-#if TREETRACE_ENABLED
-/*
-** Display all information about an AggInfo object
-*/
-static void printAggInfo(AggInfo *pAggInfo){
-  int ii;
-  for(ii=0; ii<pAggInfo->nColumn; ii++){
-    struct AggInfo_col *pCol = &pAggInfo->aCol[ii];
-    sqlite3DebugPrintf(
-       "agg-column[%d] pTab=%s iTable=%d iColumn=%d iMem=%d"
-       " iSorterColumn=%d %s\n",
-       ii, pCol->pTab ? pCol->pTab->zName : "NULL", 
-       pCol->iTable, pCol->iColumn, AggInfoColumnReg(pAggInfo,ii),
-       pCol->iSorterColumn, 
-       ii>=pAggInfo->nAccumulator ? "" : " Accumulator");
-    sqlite3TreeViewExpr(0, pAggInfo->aCol[ii].pCExpr, 0);
-  }
-  for(ii=0; ii<pAggInfo->nFunc; ii++){
-    sqlite3DebugPrintf("agg-func[%d]: iMem=\n",
-        ii, AggInfoFuncReg(pAggInfo,ii));
-    sqlite3TreeViewExpr(0, pAggInfo->aFunc[ii].pFExpr, 0);
-  }
-}
-#endif /* TREETRACE_ENABLED */
-
-/*
-** An index on expressions is being used in the inner loop of an
-** aggregate query with a GROUP BY clause.  This routine attempts
-** to adjust the AggInfo object to take advantage of index and to
-** perhaps use the index as a covering index.
-**
-*/
-static int optimizeAggregateUsingIndexedExpr(
-  Parse *pParse,          /* Parsing context */
-  Select *pSelect,        /* The SELECT being coded */
-  AggInfo *pAggInfo       /* The aggregate info */
-){
-#if TREETRACE_ENABLED
-  if( sqlite3TreeTrace & 0x80000 ){
-    IndexedExpr *pIEpr;
-    TREETRACE(0x80000, pParse, pSelect,
-        ("Attempting to optimize AggInfo for Indexed Exprs\n"));
-    for(pIEpr=pParse->pIdxEpr; pIEpr; pIEpr=pIEpr->pIENext){
-      printf("data-cursor=%d index={%d,%d}\n",
-          pIEpr->iDataCur, pIEpr->iIdxCur, pIEpr->iIdxCol);
-      sqlite3TreeViewExpr(0, pIEpr->pExpr, 0);
-    }
-    printAggInfo(pAggInfo);
-  }
-#endif
-  return 0;
-}
-
-
 /*
 ** Generate code for the SELECT statement given in the p argument.  
 **
@@ -7465,19 +7508,7 @@ int sqlite3Select(
     }else{
       minMaxFlag = WHERE_ORDERBY_NORMAL;
     }
-    for(i=0; i<pAggInfo->nFunc; i++){
-      Expr *pExpr = pAggInfo->aFunc[i].pFExpr;
-      assert( ExprUseXList(pExpr) );
-      sNC.ncFlags |= NC_InAggFunc;
-      sqlite3ExprAnalyzeAggList(&sNC, pExpr->x.pList);
-#ifndef SQLITE_OMIT_WINDOWFUNC
-      assert( !IsWindowFunc(pExpr) );
-      if( ExprHasProperty(pExpr, EP_WinFunc) ){
-        sqlite3ExprAnalyzeAggregates(&sNC, pExpr->y.pWin->pFilter);
-      }
-#endif
-      sNC.ncFlags &= ~NC_InAggFunc;
-    }
+    analyzeAggFuncArgs(pParse, pAggInfo, &sNC);
     if( db->mallocFailed ) goto select_end;
 #if TREETRACE_ENABLED
     if( sqlite3TreeTrace & 0x20 ){
@@ -7566,7 +7597,7 @@ int sqlite3Select(
         goto select_end;
       }
       if( pParse->pIdxEpr ){
-        optimizeAggregateUsingIndexedExpr(pParse, p, pAggInfo);
+        optimizeAggregateUseOfIndexedExpr(pParse, p, pAggInfo, &sNC);
       }
       assignAggregateRegisters(pParse, pAggInfo);
       eDist = sqlite3WhereIsDistinct(pWInfo);