1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-11-14 00:22:38 +03:00

Bug fixes in aggregate processing. Fewer tests fail. (CVS 2663)

FossilOrigin-Name: c3ac58592f5e6305640868cdf42c129f1a25255d
This commit is contained in:
drh
2005-09-07 22:09:48 +00:00
parent 13449892ef
commit a10a34b88f
7 changed files with 55 additions and 42 deletions

View File

@@ -12,7 +12,7 @@
** This file contains C code routines that are called by the parser
** to handle SELECT statements in SQLite.
**
** $Id: select.c,v 1.261 2005/09/07 21:22:47 drh Exp $
** $Id: select.c,v 1.262 2005/09/07 22:09:48 drh Exp $
*/
#include "sqliteInt.h"
@@ -2431,7 +2431,9 @@ static void finalizeAggFunctions(Parse *pParse, AggInfo *pAggInfo){
int i;
struct AggInfo_func *pF;
for(i=0, pF=pAggInfo->aFunc; i<pAggInfo->nFunc; i++, pF++){
sqlite3VdbeAddOp(v, OP_AggFinal, pF->iMem, 0);
ExprList *pList = pF->pExpr->pList;
sqlite3VdbeOp3(v, OP_AggFinal, pF->iMem, pList ? pList->nExpr : 0,
(void*)pF->pFunc, P3_FUNCDEF);
}
}

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.482 2005/09/07 21:22:47 drh Exp $
** $Id: vdbe.c,v 1.483 2005/09/07 22:09:48 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
@@ -4186,16 +4186,24 @@ case OP_AggStep: { /* no-push */
break;
}
/* Opcode: AggFinal P1 * *
/* Opcode: AggFinal P1 P2 P3
**
** Execute the finalizer function for an aggregate. P1 is
** the memory location that is the accumulator for the aggregate.
**
** P2 is the number of arguments that the step function takes and
** P3 is a pointer to the FuncDef for this function. The P2
** argument is not used by this opcode. It is only there to disambiguate
** functions that can take varying numbers of arguments. The
** P3 argument is only needed for the degenerate case where
** the step function was not previously called.
*/
case OP_AggFinal: { /* no-push */
Mem *pMem;
assert( pOp->p1>=0 && pOp->p1<p->nMem );
pMem = &p->aMem[pOp->p1];
sqlite3VdbeMemFinalize(pMem);
assert( (pMem->flags & ~(MEM_Null|MEM_Agg))==0 );
sqlite3VdbeMemFinalize(pMem, (FuncDef*)pOp->p3);
break;
}

View File

@@ -363,7 +363,7 @@ double sqlite3VdbeRealValue(Mem*);
int sqlite3VdbeMemRealify(Mem*);
int sqlite3VdbeMemFromBtree(BtCursor*,int,int,int,Mem*);
void sqlite3VdbeMemRelease(Mem *p);
void sqlite3VdbeMemFinalize(Mem*);
void sqlite3VdbeMemFinalize(Mem*, FuncDef*);
#ifndef NDEBUG
void sqlite3VdbeMemSanity(Mem*, u8);
int sqlite3VdbeOpcodeNoPush(u8);

View File

@@ -259,14 +259,19 @@ void *sqlite3_user_data(sqlite3_context *p){
void *sqlite3_aggregate_context(sqlite3_context *p, int nByte){
assert( p && p->pFunc && p->pFunc->xStep );
Mem *pMem = p->pMem;
if( (pMem->flags & MEM_Agg)==0 && nByte>0 ){
pMem->flags = MEM_Agg;
*(FuncDef**)&pMem->i = p->pFunc;
if( nByte<=NBFS ){
pMem->z = pMem->zShort;
memset(pMem->z, 0, nByte);
if( (pMem->flags & MEM_Agg)==0 ){
if( nByte==0 ){
assert( pMem->flags==MEM_Null );
pMem->z = 0;
}else{
pMem->z = sqliteMalloc( nByte );
pMem->flags = MEM_Agg;
*(FuncDef**)&pMem->i = p->pFunc;
if( nByte<=NBFS ){
pMem->z = pMem->zShort;
memset(pMem->z, 0, nByte);
}else{
pMem->z = sqliteMalloc( nByte );
}
}
}
return (void*)pMem->z;

View File

@@ -192,23 +192,21 @@ int sqlite3VdbeMemStringify(Mem *pMem, int enc){
** This routine calls the finalize method for that function. The
** result of the aggregate is stored back into pMem.
*/
void sqlite3VdbeMemFinalize(Mem *pMem){
if( pMem->flags & MEM_Agg ){
FuncDef *pFunc = *(FuncDef**)&pMem->i;
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;
}
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;
}
}
}
@@ -222,7 +220,7 @@ void sqlite3VdbeMemRelease(Mem *p){
if( p->flags & (MEM_Dyn|MEM_Agg) ){
if( p->xDel ){
if( p->flags & MEM_Agg ){
sqlite3VdbeMemFinalize(p);
sqlite3VdbeMemFinalize(p, *(FuncDef**)&p->i);
assert( (p->flags & MEM_Agg)==0 );
sqlite3VdbeMemRelease(p);
}else{