1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-10 01:02:56 +03:00

Cleanup the processing of MEM_Agg elements. (CVS 2660)

FossilOrigin-Name: 7ecf3654aa9a275a4cf0c3ec5f63a8c1e0a11fc9
This commit is contained in:
drh
2005-09-06 20:36:48 +00:00
parent 1ec43c9a5a
commit abfcea25ea
8 changed files with 81 additions and 82 deletions

View File

@@ -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) C Cleanup\sthe\sprocessing\sof\sMEM_Agg\selements.\s(CVS\s2660)
D 2005-09-06T10:26:47 D 2005-09-06T20:36:49
F Makefile.in 12784cdce5ffc8dfb707300c34e4f1eb3b8a14f1 F Makefile.in 12784cdce5ffc8dfb707300c34e4f1eb3b8a14f1
F Makefile.linux-gcc 06be33b2a9ad4f005a5f42b22c4a19dab3cbb5c7 F Makefile.linux-gcc 06be33b2a9ad4f005a5f42b22c4a19dab3cbb5c7
F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028 F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
@@ -41,7 +41,7 @@ F src/date.c 7444b0900a28da77e57e3337a636873cff0ae940
F src/delete.c be1fc25c9e109cd8cbab42a43ee696263da7c04b F src/delete.c be1fc25c9e109cd8cbab42a43ee696263da7c04b
F src/experimental.c 50c1e3b34f752f4ac10c36f287db095c2b61766d F src/experimental.c 50c1e3b34f752f4ac10c36f287db095c2b61766d
F src/expr.c 8a72157fa6842e84819a8c80521be02ec471180c F src/expr.c 8a72157fa6842e84819a8c80521be02ec471180c
F src/func.c 9da04a6241309a612cf610715944c6a2aaf0f297 F src/func.c 713cf33a0ab8685d44ed31a9c753983a7ff9fd6e
F src/hash.c 2b1b13f7400e179631c83a1be0c664608c8f021f F src/hash.c 2b1b13f7400e179631c83a1be0c664608c8f021f
F src/hash.h 1b0c445e1c89ff2aaad9b4605ba61375af001e84 F src/hash.h 1b0c445e1c89ff2aaad9b4605ba61375af001e84
F src/insert.c 484c73bc1309f283a31baa0e114f3ee980536397 F src/insert.c 484c73bc1309f283a31baa0e114f3ee980536397
@@ -80,13 +80,13 @@ F src/update.c a9d2c5f504212d62da1b094476f1389c0e02f83f
F src/utf.c bda5eb85039ef16f2d17004c1e18c96e1ab0a80c F src/utf.c bda5eb85039ef16f2d17004c1e18c96e1ab0a80c
F src/util.c 5650f6fe5ee30e0678985ad7b94da91e3f85752b F src/util.c 5650f6fe5ee30e0678985ad7b94da91e3f85752b
F src/vacuum.c 829d9e1a6d7c094b80e0899686670932eafd768c F src/vacuum.c 829d9e1a6d7c094b80e0899686670932eafd768c
F src/vdbe.c efde23f8829b5902cfbc8cca3f3fab51a7e9c99a F src/vdbe.c 5f0ed87252912fa1d4c989b0c6d7e3d4d2bb337a
F src/vdbe.h 3b29a9af6c7a64ed692bef1fc5f61338f40d2f67 F src/vdbe.h 3b29a9af6c7a64ed692bef1fc5f61338f40d2f67
F src/vdbeInt.h 52811a5182c6f98a10d34a1d1d0188fe3582ae03 F src/vdbeInt.h 7a6b3c1adfa7b23c1f4f15ce0549b5b52a85a635
F src/vdbeapi.c f0d36ff0f06bb5315efac5645b62e99db2c175b8 F src/vdbeapi.c 46e2fd47e2ce3c1aea9bb48bbbac31a1dc75a6ff
F src/vdbeaux.c b23bb870ab88fb91a2dd15273922d93314d8a7a3 F src/vdbeaux.c 2cfc66b30be5e293bd72db8084f8cb5c865e8b01
F src/vdbefifo.c 9efb94c8c3f4c979ebd0028219483f88e57584f5 F src/vdbefifo.c 9efb94c8c3f4c979ebd0028219483f88e57584f5
F src/vdbemem.c 4732fd4d1a75dc38549493d7f9a81d02bf7c59b5 F src/vdbemem.c b6ae3ac842a6759bd8ec4eb1cd428520b5eafc57
F src/where.c 92ab208abe6bec15e81616b8c1a619be23ece506 F src/where.c 92ab208abe6bec15e81616b8c1a619be23ece506
F tclinstaller.tcl 046e3624671962dc50f0481d7c25b38ef803eb42 F tclinstaller.tcl 046e3624671962dc50f0481d7c25b38ef803eb42
F test/all.test 7f0988442ab811dfa41793b5b550f5828ce316f3 F test/all.test 7f0988442ab811dfa41793b5b550f5828ce316f3
@@ -306,7 +306,7 @@ F www/tclsqlite.tcl 3df553505b6efcad08f91e9b975deb2e6c9bb955
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
F www/version3.tcl a99cf5f6d8bd4d5537584a2b342f0fb9fa601d8b F www/version3.tcl a99cf5f6d8bd4d5537584a2b342f0fb9fa601d8b
F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513 F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513
P 449a7895995013720f5d4c7b3b7f5bd6a5413717 P bfdaef1224d741deefe211e1e607bac4c80f2d89
R 68bd3a3e3907990d3c3125f35717440b R 93135a9d31c9998d4b9c71aa574ff69f
U drh U drh
Z 24033ba2c6a1ea752cac6b534c09791f Z 6dd7706565f409f6810f70b1066b3664

View File

@@ -1 +1 @@
bfdaef1224d741deefe211e1e607bac4c80f2d89 7ecf3654aa9a275a4cf0c3ec5f63a8c1e0a11fc9

View File

@@ -16,7 +16,7 @@
** sqliteRegisterBuildinFunctions() found at the bottom of the file. ** sqliteRegisterBuildinFunctions() found at the bottom of the file.
** All other code has file scope. ** 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 "sqliteInt.h"
#include <ctype.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){ static void sumFinalize(sqlite3_context *context){
SumCtx *p; SumCtx *p;
p = sqlite3_aggregate_context(context, sizeof(*p)); p = sqlite3_aggregate_context(context, 0);
sqlite3_result_double(context, p ? p->sum : 0.0); sqlite3_result_double(context, p ? p->sum : 0.0);
} }
static void avgFinalize(sqlite3_context *context){ static void avgFinalize(sqlite3_context *context){
SumCtx *p; SumCtx *p;
p = sqlite3_aggregate_context(context, sizeof(*p)); p = sqlite3_aggregate_context(context, 0);
if( p && p->cnt>0 ){ if( p && p->cnt>0 ){
sqlite3_result_double(context, p->sum/(double)p->cnt); 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){ static void countFinalize(sqlite3_context *context){
CountCtx *p; CountCtx *p;
p = sqlite3_aggregate_context(context, sizeof(*p)); p = sqlite3_aggregate_context(context, 0);
sqlite3_result_int(context, p ? p->n : 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){ static void minMaxFinalize(sqlite3_context *context){
sqlite3_value *pRes; sqlite3_value *pRes;
pRes = (sqlite3_value *)sqlite3_aggregate_context(context, sizeof(Mem)); pRes = (sqlite3_value *)sqlite3_aggregate_context(context, 0);
if( pRes->flags ){ if( pRes ){
sqlite3_result_value(context, pRes); if( pRes->flags ){
sqlite3_result_value(context, pRes);
}
sqlite3VdbeMemRelease(pRes);
} }
sqlite3VdbeMemRelease(pRes);
} }

View File

@@ -43,7 +43,7 @@
** in this file for details. If in doubt, do not deviate from existing ** in this file for details. If in doubt, do not deviate from existing
** commenting and indentation practices when changing or adding code. ** 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 "sqliteInt.h"
#include "os.h" #include "os.h"
@@ -4278,10 +4278,8 @@ case OP_AggFunc: { /* no-push */
i = pTos->i; i = pTos->i;
assert( i>=0 && i<p->pAgg->nMem ); assert( i>=0 && i<p->pAgg->nMem );
ctx.pFunc = (FuncDef*)pOp->p3; ctx.pFunc = (FuncDef*)pOp->p3;
pMem = &p->pAgg->pCurrent->aMem[i]; ctx.pMem = pMem = &p->pAgg->pCurrent->aMem[i];
ctx.s.z = pMem->zShort; /* Space used for small aggregate contexts */ pMem->n++;
ctx.pAgg = pMem->z;
ctx.cnt = ++pMem->i;
ctx.isError = 0; ctx.isError = 0;
ctx.pColl = 0; ctx.pColl = 0;
if( ctx.pFunc->needCollSeq ){ if( ctx.pFunc->needCollSeq ){
@@ -4291,8 +4289,6 @@ case OP_AggFunc: { /* no-push */
ctx.pColl = (CollSeq *)pOp[-1].p3; ctx.pColl = (CollSeq *)pOp[-1].p3;
} }
(ctx.pFunc->xStep)(&ctx, n, apVal); (ctx.pFunc->xStep)(&ctx, n, apVal);
pMem->z = ctx.pAgg;
pMem->flags = MEM_AggCtx;
popStack(&pTos, n+1); popStack(&pTos, n+1);
if( ctx.isError ){ if( ctx.isError ){
rc = SQLITE_ERROR; rc = SQLITE_ERROR;
@@ -4436,7 +4432,6 @@ case OP_AggNext: { /* no-push */
pc = pOp->p2 - 1; pc = pOp->p2 - 1;
}else{ }else{
int i; int i;
sqlite3_context ctx;
Mem *aMem; Mem *aMem;
if( p->pAgg->pCsr ){ if( p->pAgg->pCsr ){
@@ -4448,21 +4443,7 @@ case OP_AggNext: { /* no-push */
for(i=0; i<p->pAgg->nMem; i++){ for(i=0; i<p->pAgg->nMem; i++){
FuncDef *pFunc = p->pAgg->apFunc[i]; FuncDef *pFunc = p->pAgg->apFunc[i];
Mem *pMem = &aMem[i]; Mem *pMem = &aMem[i];
if( pFunc==0 || pFunc->xFinalize==0 ) continue; sqlite3VdbeMemFinalize(pMem, pFunc);
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;
}
} }
} }
break; break;

View File

@@ -114,13 +114,13 @@ typedef struct Cursor Cursor;
** SQLITE_BLOB. ** SQLITE_BLOB.
*/ */
struct Mem { 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' */ int n; /* Number of characters in string value, including '\0' */
u16 flags; /* Some combination of MEM_Null, MEM_Str, MEM_Dyn, etc. */ u16 flags; /* Some combination of MEM_Null, MEM_Str, MEM_Dyn, etc. */
u8 type; /* One of MEM_Null, MEM_Str, etc. */ u8 type; /* One of MEM_Null, MEM_Str, etc. */
u8 enc; /* TEXT_Utf8, TEXT_Utf16le, or TEXT_Utf16be */ 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 */ void (*xDel)(void *); /* If not null, call this function to delete Mem.z */
char zShort[NBFS]; /* Space for short strings */ 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_Static 0x0080 /* Mem.z points to a static string */
#define MEM_Ephem 0x0100 /* Mem.z points to an ephemeral string */ #define MEM_Ephem 0x0100 /* Mem.z points to an ephemeral string */
#define MEM_Short 0x0200 /* Mem.z points to Mem.zShort */ #define MEM_Short 0x0200 /* Mem.z points to Mem.zShort */
#define MEM_Agg 0x0400 /* Mem.z points to an agg function context */
/* 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 */
/* A VdbeFunc is just a FuncDef (defined in sqliteInt.h) that contains /* 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 ** But this file is the only place where the internal details of this
** structure are known. ** 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. ** (Mem) which are only defined there.
*/ */
struct sqlite3_context { 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. */ VdbeFunc *pVdbeFunc; /* Auxilary data, if created. */
Mem s; /* The return value is stored here */ Mem s; /* The return value is stored here */
void *pAgg; /* Aggregate context */ Mem *pMem; /* Memory cell used to store aggregate context */
u8 isError; /* Set to true for an error */ u8 isError; /* Set to true for an error */
int cnt; /* Number of times that the step function has been called */ CollSeq *pColl; /* Collating sequence */
CollSeq *pColl;
}; };
/* /*
@@ -397,6 +391,7 @@ double sqlite3VdbeRealValue(Mem*);
int sqlite3VdbeMemRealify(Mem*); int sqlite3VdbeMemRealify(Mem*);
int sqlite3VdbeMemFromBtree(BtCursor*,int,int,int,Mem*); int sqlite3VdbeMemFromBtree(BtCursor*,int,int,int,Mem*);
void sqlite3VdbeMemRelease(Mem *p); void sqlite3VdbeMemRelease(Mem *p);
void sqlite3VdbeMemFinalize(Mem*, FuncDef*);
#ifndef NDEBUG #ifndef NDEBUG
void sqlite3VdbeMemSanity(Mem*, u8); void sqlite3VdbeMemSanity(Mem*, u8);
int sqlite3VdbeOpcodeNoPush(u8); int sqlite3VdbeOpcodeNoPush(u8);

View File

@@ -258,15 +258,18 @@ void *sqlite3_user_data(sqlite3_context *p){
*/ */
void *sqlite3_aggregate_context(sqlite3_context *p, int nByte){ void *sqlite3_aggregate_context(sqlite3_context *p, int nByte){
assert( p && p->pFunc && p->pFunc->xStep ); 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 ){ if( nByte<=NBFS ){
p->pAgg = (void*)p->s.z; pMem->z = pMem->zShort;
memset(p->pAgg, 0, nByte); memset(pMem->z, 0, nByte);
}else{ }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){ int sqlite3_aggregate_count(sqlite3_context *p){
assert( p && p->pFunc && p->pFunc->xStep ); assert( p && p->pFunc && p->pFunc->xStep );
return p->cnt; return p->pMem->n;
} }
/* /*

View File

@@ -776,22 +776,11 @@ static void freeAggElem(AggElem *pElem, Agg *pAgg){
int i; int i;
for(i=0; i<pAgg->nMem; i++){ for(i=0; i<pAgg->nMem; i++){
Mem *pMem = &pElem->aMem[i]; Mem *pMem = &pElem->aMem[i];
if( pAgg->apFunc && pAgg->apFunc[i] && (pMem->flags & MEM_AggCtx)!=0 ){ if( pAgg->apFunc && pAgg->apFunc[i] && (pMem->flags & MEM_Agg)!=0 ){
sqlite3_context ctx; sqlite3VdbeMemFinalize(pMem, pAgg->apFunc[i]);
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);
} }
sqlite3VdbeMemRelease(pMem);
} }
sqliteFree(pElem); sqliteFree(pElem);
} }

View File

@@ -187,15 +187,44 @@ int sqlite3VdbeMemStringify(Mem *pMem, int enc){
return rc; 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 ** Release any memory held by the Mem. This may leave the Mem in an
** inconsistent state, for example with (Mem.z==0) and ** inconsistent state, for example with (Mem.z==0) and
** (Mem.type==SQLITE_TEXT). ** (Mem.type==SQLITE_TEXT).
*/ */
void sqlite3VdbeMemRelease(Mem *p){ void sqlite3VdbeMemRelease(Mem *p){
if( p->flags & MEM_Dyn ){ if( p->flags & (MEM_Dyn|MEM_Agg) ){
if( p->xDel ){ 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{ }else{
sqliteFree(p->z); sqliteFree(p->z);
} }