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:
22
manifest
22
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)
|
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
|
||||||
|
@@ -1 +1 @@
|
|||||||
bfdaef1224d741deefe211e1e607bac4c80f2d89
|
7ecf3654aa9a275a4cf0c3ec5f63a8c1e0a11fc9
|
18
src/func.c
18
src/func.c
@@ -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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
27
src/vdbe.c
27
src/vdbe.c
@@ -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;
|
||||||
|
@@ -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);
|
||||||
|
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -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);
|
||||||
}
|
}
|
||||||
|
@@ -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);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user