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:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
14
src/vdbe.c
14
src/vdbe.c
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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{
|
||||
|
||||
Reference in New Issue
Block a user