]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Crazy experimental change to refcount the AggInfo objects. refcount-agginfo
authordrh <drh@noemail.net>
Tue, 9 Jun 2020 14:56:01 +0000 (14:56 +0000)
committerdrh <drh@noemail.net>
Tue, 9 Jun 2020 14:56:01 +0000 (14:56 +0000)
FossilOrigin-Name: 9a4cc1dbf2a605ccda495ceb8e33cdc95f3436dbc11a1fa8aee4918b125fae90

manifest
manifest.uuid
src/expr.c
src/prepare.c
src/select.c
src/sqliteInt.h
src/window.c

index 330b564652b07edc28d2b8623570affe4a5c9b3f..5bc941daacbc4987338527c4f4e07cc29c5f7ad8 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Give\sthe\sexpression\spointer\sfields\sof\sAggInfo\sdistinctive\snames\sin\sorder\sto\nsimplify\stracking\sof\sall\stheir\suses.
-D 2020-06-09T13:38:12.505
+C Crazy\sexperimental\schange\sto\srefcount\sthe\sAggInfo\sobjects.
+D 2020-06-09T14:56:01.543
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -485,7 +485,7 @@ F src/date.c b29b349d277e3d579dcc295b24c0a2caed83fd8f090a9f7cbe6070c0fd662384
 F src/dbpage.c 8a01e865bf8bc6d7b1844b4314443a6436c07c3efe1d488ed89e81719047833a
 F src/dbstat.c 793deaf88a0904f88285d93d6713c636d55ede0ffd9f08d10f4ea825531d367f
 F src/delete.c 88047c8e59878c920fce14582bc1dde4d81157d1ca5ffdf36c2907e6d41996c4
-F src/expr.c 5afb8dd59d5617e0eb25f91143ed042b6cd99c006352bdbd441cb9638d2602d8
+F src/expr.c 87f1d6b0b25dd3ffb980c6a4119ca745220a2dc6b32a3625cdaeb8788b6975f0
 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
 F src/fkey.c 4b575423b0a5d4898b1a7868ce985cf1a8ad91c741c9abbb108ff02536d20f41
 F src/func.c 2333eb4277f55a5efdc12ef754e7d7ec9105d257b2fd00301d23ce1e8fa67dc0
@@ -528,17 +528,17 @@ F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586
 F src/pcache1.c 6596e10baf3d8f84cc1585d226cf1ab26564a5f5caf85a15757a281ff977d51a
 F src/pragma.c 1b0db48177e52b256c003b8dc6ac708b1079a82cded944a23820574586a4731f
 F src/pragma.h 8168e588536bffd95319451f34e9a754dc37d205ebe433031a7813c5b286beae
-F src/prepare.c bb996921a85590418f951f27566216646fad2d6856ba131b21594862055b1bd7
+F src/prepare.c aeb3ba661e2666dab15c4b5c55f6eb816f01d20e35fa860bb807e4a3b36e1e27
 F src/printf.c 94b5419ad0a17269f76a9e968ca19cf9fa37617abed2e246fc48844e511b6bc6
 F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
 F src/resolve.c c2008519a0654f1e7490e9281ed0397d0f14bb840d81f0b96946248afcbdb25d
 F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92
-F src/select.c a1f5efdbbfae1f73746242b43daedc974a4ae702d62c305219da650ec10fb08f
+F src/select.c 0944abec9afc89dfb89f366a021070af9d676e089edb4e529fdd0225fa23a50d
 F src/shell.c.in c6e26593f2738eefded08a39204bf6b48db135cdfaa458c26ffe57055b4fe365
 F src/sqlite.h.in 74342b41e9d68ff9e56b192009046f8dd0aa2bd76ce1a588f330de614ba61de7
 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
 F src/sqlite3ext.h 2d1af80082edffd71c6f96f70ad1ce6a4fb46615ad10291fc77fe0dea9ff0197
-F src/sqliteInt.h 8fddd3ff00bb5983c45fbe891c9c4134b5d4799d8816a1e97cba38dc66aca4c2
+F src/sqliteInt.h 6c523dc65a4886d2fe943ae0e9a78b1e2c31e1e3689f247ea194737f49aadc13
 F src/sqliteLimit.h 95cb8479ca459496d9c1c6a9f76b38aee12203a56ce1092fe13e50ae2454c032
 F src/status.c 9ff2210207c6c3b4d9631a8241a7d45ab1b26a0e9c84cb07a9b5ce2de9a3b278
 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
@@ -624,7 +624,7 @@ F src/where.c 7bcc07ff56d03d73308245135d96de46d2faeaee628bd4badf0bae60ae6a31fe
 F src/whereInt.h 6b874aa15f94e43a2cec1080be64d955b04deeafeac90ffb5d6975c0d511be3c
 F src/wherecode.c 7b939de85d65cc4b4bfa197513136b9e0ae03167e3b82842ca5a0ba1055ba65d
 F src/whereexpr.c 264d58971eaf8256eb5b0917bcd7fc7a1f1109fdda183a8382308a1b18a2dce7
-F src/window.c 7d19c08b62b70d5dc2ef4c098cc5ba611fac246a111fa36ebb39505415124b90
+F src/window.c ce5e05bb8fab2fafe5b10da8960a71257a6ce876e0e5e90a18712d5831e76745
 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
 F test/affinity2.test ce1aafc86e110685b324e9a763eab4f2a73f737842ec3b687bd965867de90627
 F test/affinity3.test 6a101af2fc945ce2912f6fe54dd646018551710d
@@ -1867,7 +1867,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P b5711b4eead10ef4b0b61f2e2c54768d215a4105f6d47d2ea78991b6e53a6831
-R 45115571336eb976de1e3114a0d3911d
+P a53bdd311c4154fd5e1131efbb9665362f79db5a35ce9f7b1547f74b8ee2d8ba
+R 3ee13eb60634ef4149de2b3557feb11d
+T *branch * refcount-agginfo
+T *sym-refcount-agginfo *
+T -sym-trunk *
 U drh
-Z b9fb75855deff6080f9952a1c1c95794
+Z 3bf31ff6e0ee54933573322b2a2bdccc
index 2406f422d17544b3f1594d9e283959d0089f6074..134277863d03ca6ccb1d8751acbad578da8597cd 100644 (file)
@@ -1 +1 @@
-a53bdd311c4154fd5e1131efbb9665362f79db5a35ce9f7b1547f74b8ee2d8ba
\ No newline at end of file
+9a4cc1dbf2a605ccda495ceb8e33cdc95f3436dbc11a1fa8aee4918b125fae90
\ No newline at end of file
index 555b2a8d82782622c80f4924757280315fa2acf3..eca92ef2110e4a7c82ca792f21fcf1d7373e2e54 100644 (file)
@@ -1135,8 +1135,17 @@ static SQLITE_NOINLINE void sqlite3ExprDeleteNN(sqlite3 *db, Expr *p){
 #endif
     }
   }
-  if( ExprHasProperty(p, EP_MemToken) ) sqlite3DbFree(db, p->u.zToken);
-  if( !ExprHasProperty(p, EP_Static) ){
+  if( ExprHasProperty(p, EP_MemToken|EP_AggInfo|EP_Static) ){
+    if( ExprHasProperty(p, EP_MemToken) ){
+      sqlite3DbFree(db, p->u.zToken);
+    }
+    if( ExprHasProperty(p, EP_AggInfo) ){
+      sqlite3AggInfoUnref(db, p->pAggInfo, p);
+    }
+    if( !ExprHasProperty(p, EP_Static) ){
+      sqlite3DbFreeNN(db, p);
+    }
+  }else{
     sqlite3DbFreeNN(db, p);
   }
 }
@@ -1371,6 +1380,11 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int dupFlags, u8 **pzBuffer){
         pNew->pRight = sqlite3ExprDup(db, p->pRight, 0);
       }
     }
+    if( ExprHasProperty(p, EP_AggInfo) ){
+      p->pAggInfo->nAggRef++;
+//printf("AggInfo (%d/%p) up to %d on dup\n", p->pAggInfo->selId, p->pAggInfo, p->pAggInfo->nAggRef); fflush(stdout);
+
+    }
   }
   return pNew;
 }
@@ -5715,61 +5729,34 @@ int sqlite3FunctionUsesThisSrc(Expr *pExpr, SrcList *pSrcList){
 }
 
 /*
-** This is a Walker expression node callback.
-**
-** For Expr nodes that contain pAggInfo pointers, make sure the AggInfo
-** object that is referenced does not refer directly to the Expr.  If
-** it does, make a copy.  This is done because the pExpr argument is
-** subject to change.
+** Decrement the reference count on pAggInfo.  Delete it when the
+** reference count reaches zero.
 **
-** The copy is stored on pParse->pConstExpr with a register number of 0.
-** This will cause the expression to be deleted automatically when the
-** Parse object is destroyed, but the zero register number means that it
-** will not generate any code in the preamble.
+** If pExpr is not NULL, that means that the reference count is being
+** decremented because pExpr is being deleted.  Break the reference
+** in pAggInfo to pExpr because pExpr is going away.
 */
-static int agginfoPersistExprCb(Walker *pWalker, Expr *pExpr){
-  if( ALWAYS(!ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced))
-   && pExpr->pAggInfo!=0
-  ){
-    AggInfo *pAggInfo = pExpr->pAggInfo;
-    int iAgg = pExpr->iAgg;
-    Parse *pParse = pWalker->pParse;
-    sqlite3 *db = pParse->db;
-    assert( pExpr->op==TK_AGG_COLUMN || pExpr->op==TK_AGG_FUNCTION );
-    if( pExpr->op==TK_AGG_COLUMN ){
-      assert( iAgg>=0 && iAgg<pAggInfo->nColumn );
-      if( pAggInfo->aCol[iAgg].pCExpr==pExpr ){
-        pExpr = sqlite3ExprDup(db, pExpr, 0);
-        if( pExpr ){
-          pAggInfo->aCol[iAgg].pCExpr = pExpr;
-          pParse->pConstExpr = 
-             sqlite3ExprListAppend(pParse, pParse->pConstExpr, pExpr);
-        }
-      }
-    }else{
-      assert( iAgg>=0 && iAgg<pAggInfo->nFunc );
-      if( pAggInfo->aFunc[iAgg].pFExpr==pExpr ){
-        pExpr = sqlite3ExprDup(db, pExpr, 0);
-        if( pExpr ){
-          pAggInfo->aFunc[iAgg].pFExpr = pExpr;
-          pParse->pConstExpr = 
-             sqlite3ExprListAppend(pParse, pParse->pConstExpr, pExpr);
-        }
-      }
-    }
+void sqlite3AggInfoUnref(sqlite3 *db, AggInfo *pAggInfo, Expr *pExpr){
+  int iAgg;
+  static Expr nullExpr = { TK_NULL };
+  if( pAggInfo==0 ) return;
+//printf("AggInfo (%d/%p) nRef down to %d\n", pAggInfo->selId, pAggInfo, pAggInfo->nAggRef-1); fflush(stdout);
+  if( pAggInfo->nAggRef==1 ){
+    sqlite3DbFree(db, pAggInfo->aCol);
+    sqlite3DbFree(db, pAggInfo->aFunc);
+    sqlite3DbFree(db, pAggInfo);
+    return;
+  }
+  pAggInfo->nAggRef--;
+  if( pExpr==0 ) return;
+  iAgg = pExpr->iAgg;
+  assert( iAgg>=0 );
+  if( iAgg<pAggInfo->nColumn && pAggInfo->aCol[iAgg].pCExpr==pExpr ){
+    pAggInfo->aCol[iAgg].pCExpr = &nullExpr;
+  }
+  if( iAgg<pAggInfo->nFunc && pAggInfo->aFunc[iAgg].pFExpr==pExpr ){
+    pAggInfo->aFunc[iAgg].pFExpr = &nullExpr;
   }
-  return WRC_Continue;
-}
-
-/*
-** Initialize a Walker object so that will persist AggInfo entries referenced
-** by the tree that is walked.
-*/
-void sqlite3AggInfoPersistWalkerInit(Walker *pWalker, Parse *pParse){
-  memset(pWalker, 0, sizeof(*pWalker));
-  pWalker->pParse = pParse;
-  pWalker->xExprCallback = agginfoPersistExprCb;
-  pWalker->xSelectCallback = sqlite3SelectWalkNoop;
 }
 
 /*
@@ -5879,8 +5866,12 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
             */
             ExprSetVVAProperty(pExpr, EP_NoReduce);
             pExpr->pAggInfo = pAggInfo;
+            pAggInfo->nAggRef++;
+//printf("AggInfo (%d/%p) nRef up to %d on col %d\n", pAggInfo->selId, pAggInfo, pAggInfo->nAggRef, k); fflush(stdout);
+
             pExpr->op = TK_AGG_COLUMN;
             pExpr->iAgg = (i16)k;
+            ExprSetProperty(pExpr, EP_AggInfo);
             break;
           } /* endif pExpr->iTable==pItem->iCursor */
         } /* end loop over pSrcList */
@@ -5927,6 +5918,10 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
         ExprSetVVAProperty(pExpr, EP_NoReduce);
         pExpr->iAgg = (i16)i;
         pExpr->pAggInfo = pAggInfo;
+        pAggInfo->nAggRef++;
+//printf("AggInfo (%d/%p) nRef up to %d on func %d\n", pAggInfo->selId, pAggInfo, pAggInfo->nAggRef, i); fflush(stdout);
+
+        ExprSetProperty(pExpr, EP_AggInfo);
         return WRC_Prune;
       }else{
         return WRC_Continue;
index c63c0a8353c9786d888756deff571b7d268d95f6..2599546760a3176b109022123f0beb1780ba3389 100644 (file)
@@ -530,26 +530,11 @@ int sqlite3SchemaToIndex(sqlite3 *db, Schema *pSchema){
   return i;
 }
 
-/*
-** Deallocate a single AggInfo object
-*/
-static void agginfoFree(sqlite3 *db, AggInfo *p){
-  sqlite3DbFree(db, p->aCol);
-  sqlite3DbFree(db, p->aFunc);
-  sqlite3DbFree(db, p);
-}
-
 /*
 ** Free all memory allocations in the pParse object
 */
 void sqlite3ParserReset(Parse *pParse){
   sqlite3 *db = pParse->db;
-  AggInfo *pThis = pParse->pAggList;
-  while( pThis ){
-    AggInfo *pNext = pThis->pNext;
-    agginfoFree(db, pThis);
-    pThis = pNext;
-  }
   sqlite3DbFree(db, pParse->aLabel);
   sqlite3ExprListDelete(db, pParse->pConstExpr);
   if( db ){
index cd242bb1fde6e5d4c7ad45bcbe8e295d89d1aa58..3de41893f13d097614037113d98d075aa9024718 100644 (file)
@@ -3791,7 +3791,6 @@ static int flattenSubquery(
   Expr *pWhere;                    /* The WHERE clause */
   struct SrcList_item *pSubitem;   /* The subquery */
   sqlite3 *db = pParse->db;
-  Walker w;                        /* Walker to persist agginfo data */
 
   /* Check to see if flattening is permitted.  Return 0 if not.
   */
@@ -4166,8 +4165,6 @@ static int flattenSubquery(
   /* Finially, delete what is left of the subquery and return
   ** success.
   */
-  sqlite3AggInfoPersistWalkerInit(&w, pParse);
-  sqlite3WalkSelect(&w,pSub1);
   sqlite3SelectDelete(db, pSub1);
 
 #if SELECTTRACE_ENABLED
@@ -6360,8 +6357,7 @@ int sqlite3Select(
     if( pAggInfo==0 ){
       goto select_end;
     }
-    pAggInfo->pNext = pParse->pAggList;
-    pParse->pAggList = pAggInfo;
+    pAggInfo->nAggRef = 1;
     pAggInfo->selId = p->selId;
     memset(&sNC, 0, sizeof(sNC));
     sNC.pParse = pParse;
@@ -6598,7 +6594,7 @@ int sqlite3Select(
       /* End of the loop
       */
       if( groupBySort ){
-        sqlite3VdbeAddOp2(v, OP_SorterNext, pAggInfo->sortingIdx, addrTopOfLoop);
+        sqlite3VdbeAddOp2(v, OP_SorterNext, pAggInfo->sortingIdx,addrTopOfLoop);
         VdbeCoverage(v);
       }else{
         sqlite3WhereEnd(pWInfo);
@@ -6806,21 +6802,20 @@ select_end:
 #ifdef SQLITE_DEBUG
   if( pAggInfo ){
     for(i=0; i<pAggInfo->nColumn; i++){
-      Expr *pExpr = pAggInfo->aCol[i].pCExpr;
-      assert( pExpr!=0 || db->mallocFailed );
-      if( pExpr==0 ) continue;
-      assert( pExpr->pAggInfo==pAggInfo );
-      assert( pExpr->iAgg==i );
+      Expr *pE = pAggInfo->aCol[i].pCExpr;
+      assert( pE!=0 || db->mallocFailed );
+      if( pE==0  ) continue;
+      assert( pE->pAggInfo==0 || (pE->pAggInfo==pAggInfo && pE->iAgg==i) );
     }
     for(i=0; i<pAggInfo->nFunc; i++){
-      Expr *pExpr = pAggInfo->aFunc[i].pFExpr;
-      assert( pExpr!=0 || db->mallocFailed );
-      if( pExpr==0 ) continue;
-      assert( pExpr->pAggInfo==pAggInfo );
-      assert( pExpr->iAgg==i );
+      Expr *pE = pAggInfo->aFunc[i].pFExpr;
+      assert( pE!=0 || db->mallocFailed );
+      if( pE==0  ) continue;
+      assert( pE->pAggInfo==0 || (pE->pAggInfo==pAggInfo && pE->iAgg==i) );
     }
   }
 #endif
+  sqlite3AggInfoUnref(db, pAggInfo, 0);
 
 #if SELECTTRACE_ENABLED
   SELECTTRACE(0x1,pParse,p,("end processing\n"));
index 723185642340ba808faa2f4c63960ed0b9e3d06f..16cd1a85ab5b327e67b0060902d71d9f6343eaae 100644 (file)
@@ -2524,7 +2524,7 @@ struct AggInfo {
   } *aFunc;
   int nFunc;              /* Number of entries in aFunc[] */
   u32 selId;              /* Select to which this AggInfo belongs */
-  AggInfo *pNext;         /* Next in list of them all */
+  u32 nAggRef;            /* Ref counter.  Delete when it reaches zero */
 };
 
 /*
@@ -2695,7 +2695,7 @@ struct Expr {
 #define EP_TokenOnly  0x004000 /* Expr struct EXPR_TOKENONLYSIZE bytes only */
 #define EP_Win        0x008000 /* Contains window functions */
 #define EP_MemToken   0x010000 /* Need to sqlite3DbFree() Expr.zToken */
-                  /*  0x020000 // available for reuse */
+#define EP_AggInfo    0x020000 /* Use the pAggInfo field */
 #define EP_Unlikely   0x040000 /* unlikely() or likelihood() function */
 #define EP_ConstFunc  0x080000 /* A SQLITE_FUNC_CONSTANT or _SLOCHNG function */
 #define EP_CanBeNull  0x100000 /* Can be null despite NOT NULL constraint */
@@ -3328,7 +3328,6 @@ struct Parse {
   Parse *pToplevel;    /* Parse structure for main program (or NULL) */
   Table *pTriggerTab;  /* Table triggers are being coded for */
   Parse *pParentParse; /* Parent parser if this parser is nested */
-  AggInfo *pAggList;   /* List of all AggInfo objects */
   int addrCrTab;       /* Address of OP_CreateBtree opcode on CREATE TABLE */
   u32 nQueryLoop;      /* Est number of iterations of a query (10*log2(N)) */
   u32 oldmask;         /* Mask of old.* columns referenced */
@@ -4295,7 +4294,7 @@ int sqlite3ExprCompareSkip(Expr*, Expr*, int);
 int sqlite3ExprListCompare(ExprList*, ExprList*, int);
 int sqlite3ExprImpliesExpr(Parse*,Expr*, Expr*, int);
 int sqlite3ExprImpliesNonNullRow(Expr*,int);
-void sqlite3AggInfoPersistWalkerInit(Walker*,Parse*);
+void sqlite3AggInfoUnref(sqlite3*, AggInfo*, Expr*);
 void sqlite3ExprAnalyzeAggregates(NameContext*, Expr*);
 void sqlite3ExprAnalyzeAggList(NameContext*,ExprList*);
 int sqlite3ExprCoveredByIndex(Expr*, int iCur, Index *pIdx);
index 8046e46274ccae99764e3bd23ea4db2e48b1e51d..cb1e2d324df22293f061bec61c65af199b78e2ec 100644 (file)
@@ -964,8 +964,6 @@ int sqlite3WindowRewrite(Parse *pParse, Select *p){
     if( pTab==0 ){
       return sqlite3ErrorToParser(db, SQLITE_NOMEM);
     }
-    sqlite3AggInfoPersistWalkerInit(&w, pParse);
-    sqlite3WalkSelect(&w, p);
 
     p->pSrc = 0;
     p->pWhere = 0;