]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Cleanup the processing of MEM_Agg elements. (CVS 2660)
authordrh <drh@noemail.net>
Tue, 6 Sep 2005 20:36:48 +0000 (20:36 +0000)
committerdrh <drh@noemail.net>
Tue, 6 Sep 2005 20:36:48 +0000 (20:36 +0000)
FossilOrigin-Name: 7ecf3654aa9a275a4cf0c3ec5f63a8c1e0a11fc9

manifest
manifest.uuid
src/func.c
src/vdbe.c
src/vdbeInt.h
src/vdbeapi.c
src/vdbeaux.c
src/vdbemem.c

index 0f35ab82801e4a47c97976ba333b42071540285e..359f999b6d3a0f52692cee7adbbfd85784bc9687 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Fix\sANALYZE\sso\sthat\sit\sworks\seven\sif\sthe\sempty_result_callbacks\spragma\sis\nenabled.\sTicket\s#1409.\s(CVS\s2659)
-D 2005-09-06T10:26:47
+C Cleanup\sthe\sprocessing\sof\sMEM_Agg\selements.\s(CVS\s2660)
+D 2005-09-06T20:36:49
 F Makefile.in 12784cdce5ffc8dfb707300c34e4f1eb3b8a14f1
 F Makefile.linux-gcc 06be33b2a9ad4f005a5f42b22c4a19dab3cbb5c7
 F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
@@ -41,7 +41,7 @@ F src/date.c 7444b0900a28da77e57e3337a636873cff0ae940
 F src/delete.c be1fc25c9e109cd8cbab42a43ee696263da7c04b
 F src/experimental.c 50c1e3b34f752f4ac10c36f287db095c2b61766d
 F src/expr.c 8a72157fa6842e84819a8c80521be02ec471180c
-F src/func.c 9da04a6241309a612cf610715944c6a2aaf0f297
+F src/func.c 713cf33a0ab8685d44ed31a9c753983a7ff9fd6e
 F src/hash.c 2b1b13f7400e179631c83a1be0c664608c8f021f
 F src/hash.h 1b0c445e1c89ff2aaad9b4605ba61375af001e84
 F src/insert.c 484c73bc1309f283a31baa0e114f3ee980536397
@@ -80,13 +80,13 @@ F src/update.c a9d2c5f504212d62da1b094476f1389c0e02f83f
 F src/utf.c bda5eb85039ef16f2d17004c1e18c96e1ab0a80c
 F src/util.c 5650f6fe5ee30e0678985ad7b94da91e3f85752b
 F src/vacuum.c 829d9e1a6d7c094b80e0899686670932eafd768c
-F src/vdbe.c efde23f8829b5902cfbc8cca3f3fab51a7e9c99a
+F src/vdbe.c 5f0ed87252912fa1d4c989b0c6d7e3d4d2bb337a
 F src/vdbe.h 3b29a9af6c7a64ed692bef1fc5f61338f40d2f67
-F src/vdbeInt.h 52811a5182c6f98a10d34a1d1d0188fe3582ae03
-F src/vdbeapi.c f0d36ff0f06bb5315efac5645b62e99db2c175b8
-F src/vdbeaux.c b23bb870ab88fb91a2dd15273922d93314d8a7a3
+F src/vdbeInt.h 7a6b3c1adfa7b23c1f4f15ce0549b5b52a85a635
+F src/vdbeapi.c 46e2fd47e2ce3c1aea9bb48bbbac31a1dc75a6ff
+F src/vdbeaux.c 2cfc66b30be5e293bd72db8084f8cb5c865e8b01
 F src/vdbefifo.c 9efb94c8c3f4c979ebd0028219483f88e57584f5
-F src/vdbemem.c 4732fd4d1a75dc38549493d7f9a81d02bf7c59b5
+F src/vdbemem.c b6ae3ac842a6759bd8ec4eb1cd428520b5eafc57
 F src/where.c 92ab208abe6bec15e81616b8c1a619be23ece506
 F tclinstaller.tcl 046e3624671962dc50f0481d7c25b38ef803eb42
 F test/all.test 7f0988442ab811dfa41793b5b550f5828ce316f3
@@ -306,7 +306,7 @@ F www/tclsqlite.tcl 3df553505b6efcad08f91e9b975deb2e6c9bb955
 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
 F www/version3.tcl a99cf5f6d8bd4d5537584a2b342f0fb9fa601d8b
 F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513
-P 449a7895995013720f5d4c7b3b7f5bd6a5413717
-R 68bd3a3e3907990d3c3125f35717440b
+P bfdaef1224d741deefe211e1e607bac4c80f2d89
+R 93135a9d31c9998d4b9c71aa574ff69f
 U drh
-Z 24033ba2c6a1ea752cac6b534c09791f
+Z 6dd7706565f409f6810f70b1066b3664
index d8314356c076bdd5555672f276758ed23b02e96b..bd220c2122f2adcb3eba4e2c8d89ee41b5816ebc 100644 (file)
@@ -1 +1 @@
-bfdaef1224d741deefe211e1e607bac4c80f2d89
\ No newline at end of file
+7ecf3654aa9a275a4cf0c3ec5f63a8c1e0a11fc9
\ No newline at end of file
index 919b3a83a41f64aac4dfe046b4fa96bc8b061122..ceb5c8c399403c95d4d0e0fd8eccfd344d7d4016 100644 (file)
@@ -16,7 +16,7 @@
 ** sqliteRegisterBuildinFunctions() found at the bottom of the file.
 ** All other code has file scope.
 **
-** $Id: func.c,v 1.106 2005/08/28 17:00:23 drh Exp $
+** $Id: func.c,v 1.107 2005/09/06 20:36:49 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -835,12 +835,12 @@ static void sumStep(sqlite3_context *context, int argc, sqlite3_value **argv){
 }
 static void sumFinalize(sqlite3_context *context){
   SumCtx *p;
-  p = sqlite3_aggregate_context(context, sizeof(*p));
+  p = sqlite3_aggregate_context(context, 0);
   sqlite3_result_double(context, p ? p->sum : 0.0);
 }
 static void avgFinalize(sqlite3_context *context){
   SumCtx *p;
-  p = sqlite3_aggregate_context(context, sizeof(*p));
+  p = sqlite3_aggregate_context(context, 0);
   if( p && p->cnt>0 ){
     sqlite3_result_double(context, p->sum/(double)p->cnt);
   }
@@ -878,7 +878,7 @@ static void countStep(sqlite3_context *context, int argc, sqlite3_value **argv){
 }   
 static void countFinalize(sqlite3_context *context){
   CountCtx *p;
-  p = sqlite3_aggregate_context(context, sizeof(*p));
+  p = sqlite3_aggregate_context(context, 0);
   sqlite3_result_int(context, p ? p->n : 0);
 }
 
@@ -916,11 +916,13 @@ static void minmaxStep(sqlite3_context *context, int argc, sqlite3_value **argv)
 }
 static void minMaxFinalize(sqlite3_context *context){
   sqlite3_value *pRes;
-  pRes = (sqlite3_value *)sqlite3_aggregate_context(context, sizeof(Mem));
-  if( pRes->flags ){
-    sqlite3_result_value(context, pRes);
+  pRes = (sqlite3_value *)sqlite3_aggregate_context(context, 0);
+  if( pRes ){
+    if( pRes->flags ){
+      sqlite3_result_value(context, pRes);
+    }
+    sqlite3VdbeMemRelease(pRes);
   }
-  sqlite3VdbeMemRelease(pRes);
 }
 
 
index 62898ec9d214235a648ac476d260abe46a114a1f..2de08559470ee24d6356d1475885c097f0666d77 100644 (file)
@@ -43,7 +43,7 @@
 ** in this file for details.  If in doubt, do not deviate from existing
 ** commenting and indentation practices when changing or adding code.
 **
-** $Id: vdbe.c,v 1.480 2005/09/01 12:16:29 drh Exp $
+** $Id: vdbe.c,v 1.481 2005/09/06 20:36:49 drh Exp $
 */
 #include "sqliteInt.h"
 #include "os.h"
@@ -4278,10 +4278,8 @@ case OP_AggFunc: {        /* no-push */
   i = pTos->i;
   assert( i>=0 && i<p->pAgg->nMem );
   ctx.pFunc = (FuncDef*)pOp->p3;
-  pMem = &p->pAgg->pCurrent->aMem[i];
-  ctx.s.z = pMem->zShort;  /* Space used for small aggregate contexts */
-  ctx.pAgg = pMem->z;
-  ctx.cnt = ++pMem->i;
+  ctx.pMem = pMem = &p->pAgg->pCurrent->aMem[i];
+  pMem->n++;
   ctx.isError = 0;
   ctx.pColl = 0;
   if( ctx.pFunc->needCollSeq ){
@@ -4291,8 +4289,6 @@ case OP_AggFunc: {        /* no-push */
     ctx.pColl = (CollSeq *)pOp[-1].p3;
   }
   (ctx.pFunc->xStep)(&ctx, n, apVal);
-  pMem->z = ctx.pAgg;
-  pMem->flags = MEM_AggCtx;
   popStack(&pTos, n+1);
   if( ctx.isError ){
     rc = SQLITE_ERROR;
@@ -4436,7 +4432,6 @@ case OP_AggNext: {        /* no-push */
     pc = pOp->p2 - 1;
   }else{
     int i;
-    sqlite3_context ctx;
     Mem *aMem;
 
     if( p->pAgg->pCsr ){
@@ -4448,21 +4443,7 @@ case OP_AggNext: {        /* no-push */
     for(i=0; i<p->pAgg->nMem; i++){
       FuncDef *pFunc = p->pAgg->apFunc[i];
       Mem *pMem = &aMem[i];
-      if( pFunc==0 || pFunc->xFinalize==0 ) continue;
-      ctx.s.flags = MEM_Null;
-      ctx.s.z = pMem->zShort;
-      ctx.pAgg = (void*)pMem->z;
-      ctx.cnt = pMem->i;
-      ctx.pFunc = pFunc;
-      pFunc->xFinalize(&ctx);
-      pMem->z = ctx.pAgg;
-      if( pMem->z && pMem->z!=pMem->zShort ){
-        sqliteFree( pMem->z );
-      }
-      *pMem = ctx.s;
-      if( pMem->flags & MEM_Short ){
-        pMem->z = pMem->zShort;
-      }
+      sqlite3VdbeMemFinalize(pMem, pFunc);
     }
   }
   break;
index 36b711487fb8935c32a6bf8e9333947f419dcda6..0ab61ec18e45a48173e28084941d81c324a3ec97 100644 (file)
@@ -114,13 +114,13 @@ typedef struct Cursor Cursor;
 ** SQLITE_BLOB.
 */
 struct Mem {
-  i64 i;              /* Integer value */
+  i64 i;              /* Integer value. Or FuncDef* when flags==MEM_Agg */
+  double r;           /* Real value */
+  char *z;            /* String or BLOB value */
   int n;              /* Number of characters in string value, including '\0' */
   u16 flags;          /* Some combination of MEM_Null, MEM_Str, MEM_Dyn, etc. */
   u8  type;           /* One of MEM_Null, MEM_Str, etc. */
   u8  enc;            /* TEXT_Utf8, TEXT_Utf16le, or TEXT_Utf16be */
-  double r;           /* Real value */
-  char *z;            /* String or BLOB value */
   void (*xDel)(void *);  /* If not null, call this function to delete Mem.z */
   char zShort[NBFS];  /* Space for short strings */
 };
@@ -157,12 +157,7 @@ typedef struct Mem Mem;
 #define MEM_Static    0x0080   /* Mem.z points to a static string */
 #define MEM_Ephem     0x0100   /* Mem.z points to an ephemeral string */
 #define MEM_Short     0x0200   /* Mem.z points to Mem.zShort */
-
-/* The following MEM_ value appears only in AggElem.aMem.s.flag fields.
-** It indicates that the corresponding AggElem.aMem.z points to a
-** aggregate function context that needs to be finalized.
-*/
-#define MEM_AggCtx    0x0400  /* Mem.z points to an agg function context */
+#define MEM_Agg       0x0400   /* Mem.z points to an agg function context */
 
 
 /* A VdbeFunc is just a FuncDef (defined in sqliteInt.h) that contains
@@ -194,17 +189,16 @@ typedef struct VdbeFunc VdbeFunc;
 ** But this file is the only place where the internal details of this
 ** structure are known.
 **
-** This structure is defined inside of vdbe.c because it uses substructures
+** This structure is defined inside of vdbeInt.h because it uses substructures
 ** (Mem) which are only defined there.
 */
 struct sqlite3_context {
-  FuncDef *pFunc;   /* Pointer to function information.  MUST BE FIRST */
+  FuncDef *pFunc;       /* Pointer to function information.  MUST BE FIRST */
   VdbeFunc *pVdbeFunc;  /* Auxilary data, if created. */
-  Mem s;            /* The return value is stored here */
-  void *pAgg;       /* Aggregate context */
-  u8 isError;       /* Set to true for an error */
-  int cnt;          /* Number of times that the step function has been called */
-  CollSeq *pColl;
+  Mem s;                /* The return value is stored here */
+  Mem *pMem;            /* Memory cell used to store aggregate context */
+  u8 isError;           /* Set to true for an error */
+  CollSeq *pColl;       /* Collating sequence */
 };
 
 /*
@@ -397,6 +391,7 @@ double sqlite3VdbeRealValue(Mem*);
 int sqlite3VdbeMemRealify(Mem*);
 int sqlite3VdbeMemFromBtree(BtCursor*,int,int,int,Mem*);
 void sqlite3VdbeMemRelease(Mem *p);
+void sqlite3VdbeMemFinalize(Mem*, FuncDef*);
 #ifndef NDEBUG
 void sqlite3VdbeMemSanity(Mem*, u8);
 int sqlite3VdbeOpcodeNoPush(u8);
index 75af8a9b65d0c575b7da9046a772dcb3ede34ba1..6c786f1dcee9a5142a9fedc1f88be4c2f8575e60 100644 (file)
@@ -258,15 +258,18 @@ void *sqlite3_user_data(sqlite3_context *p){
 */
 void *sqlite3_aggregate_context(sqlite3_context *p, int nByte){
   assert( p && p->pFunc && p->pFunc->xStep );
-  if( p->pAgg==0 ){
+  Mem *pMem = p->pMem;
+  if( (pMem->flags & MEM_Agg)==0 && nByte>0 ){
+    pMem->flags = MEM_Agg;
+    *(FuncDef**)&pMem->i = p->pFunc;
     if( nByte<=NBFS ){
-      p->pAgg = (void*)p->s.z;
-      memset(p->pAgg, 0, nByte);
+      pMem->z = pMem->zShort;
+      memset(pMem->z, 0, nByte);
     }else{
-      p->pAgg = sqliteMalloc( nByte );
+      pMem->z = sqliteMalloc( nByte );
     }
   }
-  return p->pAgg;
+  return (void*)pMem->z;
 }
 
 /*
@@ -325,7 +328,7 @@ void sqlite3_set_auxdata(
 */
 int sqlite3_aggregate_count(sqlite3_context *p){
   assert( p && p->pFunc && p->pFunc->xStep );
-  return p->cnt;
+  return p->pMem->n;
 }
 
 /*
index 917716ef45f8d322fb86704a81bb6138874bf094..0109f0bc2203e14e20f0d840b009442a869c9547 100644 (file)
@@ -776,22 +776,11 @@ static void freeAggElem(AggElem *pElem, Agg *pAgg){
   int i;
   for(i=0; i<pAgg->nMem; i++){
     Mem *pMem = &pElem->aMem[i];
-    if( pAgg->apFunc && pAgg->apFunc[i] && (pMem->flags & MEM_AggCtx)!=0 ){
-      sqlite3_context ctx;
-      ctx.pFunc = pAgg->apFunc[i];
-      ctx.s.flags = MEM_Null;
-      ctx.pAgg = pMem->z;
-      ctx.cnt = pMem->i;
-      ctx.isError = 0;
-      (*ctx.pFunc->xFinalize)(&ctx);
-      pMem->z = ctx.pAgg;
-      if( pMem->z!=0 && pMem->z!=pMem->zShort ){
-        sqliteFree(pMem->z);
-      }
-      sqlite3VdbeMemRelease(&ctx.s);
-    }else{
-      sqlite3VdbeMemRelease(pMem);
+    if( pAgg->apFunc && pAgg->apFunc[i] && (pMem->flags & MEM_Agg)!=0 ){
+      sqlite3VdbeMemFinalize(pMem, pAgg->apFunc[i]);
     }
+    sqlite3VdbeMemRelease(pMem);
+
   }
   sqliteFree(pElem);
 }
index 416beb6c785c15b7558983b497eb13d04821ab4e..a6c850029f41ce78118be149d68e0e1f23002265 100644 (file)
@@ -187,15 +187,44 @@ int sqlite3VdbeMemStringify(Mem *pMem, int enc){
   return rc;
 }
 
+/*
+** Memory cell pMem contains the context of an aggregate function.
+** This routine calls the finalize method for that function.  The
+** result of the aggregate is stored back into pMem.
+*/
+void sqlite3VdbeMemFinalize(Mem *pMem, FuncDef *pFunc){
+  if( pFunc && pFunc->xFinalize ){
+    sqlite3_context ctx;
+    ctx.s.flags = MEM_Null;
+    ctx.s.z = pMem->zShort;
+    ctx.pMem = pMem;
+    ctx.pFunc = pFunc;
+    pFunc->xFinalize(&ctx);
+    if( pMem->z && pMem->z!=pMem->zShort ){
+      sqliteFree( pMem->z );
+    }
+    *pMem = ctx.s;
+    if( pMem->flags & MEM_Short ){
+      pMem->z = pMem->zShort;
+    }
+  }
+}
+
 /*
 ** Release any memory held by the Mem. This may leave the Mem in an
 ** inconsistent state, for example with (Mem.z==0) and
 ** (Mem.type==SQLITE_TEXT).
 */
 void sqlite3VdbeMemRelease(Mem *p){
-  if( p->flags & MEM_Dyn ){
+  if( p->flags & (MEM_Dyn|MEM_Agg) ){
     if( p->xDel ){
-      p->xDel((void *)p->z);
+      if( p->flags & MEM_Agg ){
+        sqlite3VdbeMemFinalize(p, (FuncDef*)&p->i);
+        assert( (p->flags & MEM_Agg)==0 );
+        sqlite3VdbeMemRelease(p);
+      }else{
+        p->xDel((void *)p->z);
+      }
     }else{
       sqliteFree(p->z);
     }