diff options
Diffstat (limited to 'ext/pdo_sqlite/sqlite/src/vdbemem.c')
-rw-r--r-- | ext/pdo_sqlite/sqlite/src/vdbemem.c | 37 |
1 files changed, 34 insertions, 3 deletions
diff --git a/ext/pdo_sqlite/sqlite/src/vdbemem.c b/ext/pdo_sqlite/sqlite/src/vdbemem.c index 416beb6c78..0b7e193bec 100644 --- a/ext/pdo_sqlite/sqlite/src/vdbemem.c +++ b/ext/pdo_sqlite/sqlite/src/vdbemem.c @@ -188,14 +188,44 @@ int sqlite3VdbeMemStringify(Mem *pMem, int enc){ } /* +** 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; + assert( (pMem->flags & MEM_Null)!=0 || pFunc==*(FuncDef**)&pMem->i ); + 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); } @@ -287,6 +317,7 @@ void sqlite3VdbeMemSetNull(Mem *pMem){ sqlite3VdbeMemRelease(pMem); pMem->flags = MEM_Null; pMem->type = SQLITE_NULL; + pMem->n = 0; } /* @@ -699,7 +730,7 @@ const void *sqlite3ValueText(sqlite3_value* pVal, u8 enc){ /* ** Create a new sqlite3_value object. */ -sqlite3_value* sqlite3ValueNew(){ +sqlite3_value* sqlite3ValueNew(void){ Mem *p = sqliteMalloc(sizeof(*p)); if( p ){ p->flags = MEM_Null; |