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)
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

View File

@@ -1 +1 @@
bfdaef1224d741deefe211e1e607bac4c80f2d89
7ecf3654aa9a275a4cf0c3ec5f63a8c1e0a11fc9

View 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);
}

View 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;

View 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);

View 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;
}
/*

View 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);
}

View 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);
}