/ Check-in [c3ac5859]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Bug fixes in aggregate processing. Fewer tests fail. (CVS 2663)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:c3ac58592f5e6305640868cdf42c129f1a25255d
User & Date: drh 2005-09-07 22:09:48
Context
2005-09-07
22:48
More bug fixes. But there are still tests that fail. (CVS 2664) check-in: 7e85a162 user: drh tags: trunk
22:09
Bug fixes in aggregate processing. Fewer tests fail. (CVS 2663) check-in: c3ac5859 user: drh tags: trunk
21:22
Rewrite the aggregate handling logic so that it runs in O(1) space. This is the first cut at the code. Many regression tests fail. (CVS 2662) check-in: 17039ec3 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/select.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
....
2427
2428
2429
2430
2431
2432
2433

2434

2435
2436
2437
2438
2439
2440
2441
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** 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 $
*/
#include "sqliteInt.h"


/*
** Allocate a new Select structure and return a pointer to that
** structure.
................................................................................
** in the AggInfo structure.
*/
static void finalizeAggFunctions(Parse *pParse, AggInfo *pAggInfo){
  Vdbe *v = pParse->pVdbe;
  int i;
  struct AggInfo_func *pF;
  for(i=0, pF=pAggInfo->aFunc; i<pAggInfo->nFunc; i++, pF++){

    sqlite3VdbeAddOp(v, OP_AggFinal, pF->iMem, 0);

  }
}

/*
** Update the accumulator memory cells for an aggregate based on
** the current cursor position.
*/







|







 







>
|
>







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
....
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle SELECT statements in SQLite.
**
** $Id: select.c,v 1.262 2005/09/07 22:09:48 drh Exp $
*/
#include "sqliteInt.h"


/*
** Allocate a new Select structure and return a pointer to that
** structure.
................................................................................
** in the AggInfo structure.
*/
static void finalizeAggFunctions(Parse *pParse, AggInfo *pAggInfo){
  Vdbe *v = pParse->pVdbe;
  int i;
  struct AggInfo_func *pF;
  for(i=0, pF=pAggInfo->aFunc; i<pAggInfo->nFunc; i++, pF++){
    ExprList *pList = pF->pExpr->pList;
    sqlite3VdbeOp3(v, OP_AggFinal, pF->iMem, pList ? pList->nExpr : 0,
                      (void*)pF->pFunc, P3_FUNCDEF);
  }
}

/*
** Update the accumulator memory cells for an aggregate based on
** the current cursor position.
*/

Changes to src/vdbe.c.

39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
....
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192







4193
4194
4195
4196
4197

4198
4199
4200
4201
4202
4203
4204
4205
**
** Various scripts scan this source file in order to generate HTML
** documentation, headers files, or other derived files.  The formatting
** of the code in this file is, therefore, important.  See other comments
** 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 $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>
#include "vdbeInt.h"

/*
................................................................................
  popStack(&pTos, n);
  if( ctx.isError ){
    rc = SQLITE_ERROR;
  }
  break;
}

/* Opcode: AggFinal P1 * *
**
** Execute the finalizer function for an aggregate.  P1 is
** the memory location that is the accumulator for the aggregate.







*/
case OP_AggFinal: {        /* no-push */
  Mem *pMem;
  assert( pOp->p1>=0 && pOp->p1<p->nMem );
  pMem = &p->aMem[pOp->p1];

  sqlite3VdbeMemFinalize(pMem);
  break;
}


/* Opcode: Vacuum * * *
**
** Vacuum the entire database.  This opcode will cause other virtual







|







 







|



>
>
>
>
>
>
>





>
|







39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
....
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
4208
4209
4210
4211
4212
4213
**
** Various scripts scan this source file in order to generate HTML
** documentation, headers files, or other derived files.  The formatting
** of the code in this file is, therefore, important.  See other comments
** 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.483 2005/09/07 22:09:48 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>
#include "vdbeInt.h"

/*
................................................................................
  popStack(&pTos, n);
  if( ctx.isError ){
    rc = SQLITE_ERROR;
  }
  break;
}

/* 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];
  assert( (pMem->flags & ~(MEM_Null|MEM_Agg))==0 );
  sqlite3VdbeMemFinalize(pMem, (FuncDef*)pOp->p3);
  break;
}


/* Opcode: Vacuum * * *
**
** Vacuum the entire database.  This opcode will cause other virtual

Changes to src/vdbeInt.h.

359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
int sqlite3VdbeMemStringify(Mem*, int);
i64 sqlite3VdbeIntValue(Mem*);
int sqlite3VdbeMemIntegerify(Mem*);
double sqlite3VdbeRealValue(Mem*);
int sqlite3VdbeMemRealify(Mem*);
int sqlite3VdbeMemFromBtree(BtCursor*,int,int,int,Mem*);
void sqlite3VdbeMemRelease(Mem *p);
void sqlite3VdbeMemFinalize(Mem*);
#ifndef NDEBUG
void sqlite3VdbeMemSanity(Mem*, u8);
int sqlite3VdbeOpcodeNoPush(u8);
#endif
int sqlite3VdbeMemTranslate(Mem*, u8);
void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf, int nBuf);
int sqlite3VdbeMemHandleBom(Mem *pMem);
void sqlite3VdbeFifoInit(Fifo*);
int sqlite3VdbeFifoPush(Fifo*, i64);
int sqlite3VdbeFifoPop(Fifo*, i64*);
void sqlite3VdbeFifoClear(Fifo*);







|











359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
int sqlite3VdbeMemStringify(Mem*, int);
i64 sqlite3VdbeIntValue(Mem*);
int sqlite3VdbeMemIntegerify(Mem*);
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);
#endif
int sqlite3VdbeMemTranslate(Mem*, u8);
void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf, int nBuf);
int sqlite3VdbeMemHandleBom(Mem *pMem);
void sqlite3VdbeFifoInit(Fifo*);
int sqlite3VdbeFifoPush(Fifo*, i64);
int sqlite3VdbeFifoPop(Fifo*, i64*);
void sqlite3VdbeFifoClear(Fifo*);

Changes to src/vdbeapi.c.

255
256
257
258
259
260
261
262




263
264
265
266
267
268
269

270
271
272
273
274
275
276
** Allocate or return the aggregate context for a user function.  A new
** context is allocated on the first call.  Subsequent calls return the
** same context that was returned on prior calls.
*/
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);
    }else{
      pMem->z = sqliteMalloc( nByte );

    }
  }
  return (void*)pMem->z;
}

/*
** Return the auxilary data pointer, if any, for the iArg'th argument to







|
>
>
>
>
|
|
|
|
|
|
|
>







255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
** Allocate or return the aggregate context for a user function.  A new
** context is allocated on the first call.  Subsequent calls return the
** same context that was returned on prior calls.
*/
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 ){
    if( nByte==0 ){
      assert( pMem->flags==MEM_Null );
      pMem->z = 0;
    }else{
      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;
}

/*
** Return the auxilary data pointer, if any, for the iArg'th argument to

Changes to src/vdbemem.c.

188
189
190
191
192
193
194
195
196
197
198
199

200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
}

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

/*
** 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|MEM_Agg) ){
    if( p->xDel ){
      if( p->flags & MEM_Agg ){
        sqlite3VdbeMemFinalize(p);
        assert( (p->flags & MEM_Agg)==0 );
        sqlite3VdbeMemRelease(p);
      }else{
        p->xDel((void *)p->z);
      }
    }else{
      sqliteFree(p->z);







|
<
<
|
|
>
|
|
|
|
|
|
|
|
|
|
|
<













|







188
189
190
191
192
193
194
195


196
197
198
199
200
201
202
203
204
205
206
207
208
209

210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
}

/*
** 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|MEM_Agg) ){
    if( p->xDel ){
      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);