From: drh Date: Tue, 6 Sep 2005 20:36:48 +0000 (+0000) Subject: Cleanup the processing of MEM_Agg elements. (CVS 2660) X-Git-Tag: version-3.6.10~3499 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=abfcea25eae1177103d38e973ab950efbd91d010;p=thirdparty%2Fsqlite.git Cleanup the processing of MEM_Agg elements. (CVS 2660) FossilOrigin-Name: 7ecf3654aa9a275a4cf0c3ec5f63a8c1e0a11fc9 --- diff --git a/manifest b/manifest index 0f35ab8280..359f999b6d 100644 --- 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 diff --git a/manifest.uuid b/manifest.uuid index d8314356c0..bd220c2122 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -bfdaef1224d741deefe211e1e607bac4c80f2d89 \ No newline at end of file +7ecf3654aa9a275a4cf0c3ec5f63a8c1e0a11fc9 \ No newline at end of file diff --git a/src/func.c b/src/func.c index 919b3a83a4..ceb5c8c399 100644 --- a/src/func.c +++ b/src/func.c @@ -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 @@ -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); } diff --git a/src/vdbe.c b/src/vdbe.c index 62898ec9d2..2de0855947 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -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 && ipAgg->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; ipAgg->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; diff --git a/src/vdbeInt.h b/src/vdbeInt.h index 36b711487f..0ab61ec18e 100644 --- a/src/vdbeInt.h +++ b/src/vdbeInt.h @@ -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); diff --git a/src/vdbeapi.c b/src/vdbeapi.c index 75af8a9b65..6c786f1dce 100644 --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@ -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; } /* diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 917716ef45..0109f0bc22 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -776,22 +776,11 @@ static void freeAggElem(AggElem *pElem, Agg *pAgg){ int i; for(i=0; inMem; 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); } diff --git a/src/vdbemem.c b/src/vdbemem.c index 416beb6c78..a6c850029f 100644 --- a/src/vdbemem.c +++ b/src/vdbemem.c @@ -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); }