/ Check-in [8d56118f]
Login

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

Overview
Comment:Have the vdbe aggregator use a btree table instead of a hash table. (CVS 1569)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 8d56118f64dbaf8c8006266fa7026f900a4a16bd
User & Date: danielk1977 2004-06-11 13:19:21
Context
2004-06-11
17:48
Documentation of the new pager locking mechanism. (CVS 1570) check-in: 13cf1ba8 user: drh tags: trunk
13:19
Have the vdbe aggregator use a btree table instead of a hash table. (CVS 1569) check-in: 8d56118f user: danielk1977 tags: trunk
10:51
Fix various collation sequence issues. (CVS 1568) check-in: 66835ee6 user: danielk1977 tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/select.c.

     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** This file contains C code routines that are called by the parser
    13     13   ** to handle SELECT statements in SQLite.
    14     14   **
    15         -** $Id: select.c,v 1.187 2004/06/11 10:51:35 danielk1977 Exp $
           15  +** $Id: select.c,v 1.188 2004/06/11 13:19:21 danielk1977 Exp $
    16     16   */
    17     17   #include "sqliteInt.h"
    18     18   
    19     19   
    20     20   /*
    21     21   ** Allocate a new Select structure and return a pointer to that
    22     22   ** structure.
................................................................................
  2437   2437         }
  2438   2438       }
  2439   2439     }
  2440   2440   
  2441   2441     /* Reset the aggregator
  2442   2442     */
  2443   2443     if( isAgg ){
  2444         -    sqlite3VdbeAddOp(v, OP_AggReset, 0, pParse->nAgg);
         2444  +    int addr = sqlite3VdbeAddOp(v, OP_AggReset, 0, pParse->nAgg);
  2445   2445       for(i=0; i<pParse->nAgg; i++){
  2446   2446         FuncDef *pFunc;
  2447   2447         if( (pFunc = pParse->aAgg[i].pFunc)!=0 && pFunc->xFinalize!=0 ){
  2448   2448           sqlite3VdbeOp3(v, OP_AggInit, 0, i, (char*)pFunc, P3_FUNCDEF);
  2449   2449         }
  2450   2450       }
  2451   2451       if( pGroupBy==0 ){
  2452   2452         sqlite3VdbeAddOp(v, OP_String8, 0, 0);
  2453   2453         sqlite3VdbeAddOp(v, OP_AggFocus, 0, 0);
         2454  +    }else{
         2455  +      int sz = sizeof(KeyInfo) + pGroupBy->nExpr*sizeof(CollSeq*);
         2456  +      KeyInfo *pKey = (KeyInfo *)sqliteMalloc(sz);
         2457  +      if( 0==pKey ){
         2458  +        goto select_end;
         2459  +      }
         2460  +      pKey->enc = pParse->db->enc;
         2461  +      pKey->nField = pGroupBy->nExpr;
         2462  +      for(i=0; i<pGroupBy->nExpr; i++){
         2463  +        pKey->aColl[i] = sqlite3ExprCollSeq(pParse, pGroupBy->a[i].pExpr);
         2464  +        if( !pKey->aColl[i] ){
         2465  +          pKey->aColl[i] = pParse->db->pDfltColl;
         2466  +        }
         2467  +      }
         2468  +      sqlite3VdbeChangeP3(v, addr, (char *)pKey, P3_KEYINFO_HANDOFF);
  2454   2469       }
  2455   2470     }
  2456   2471   
  2457   2472     /* Initialize the memory cell to NULL
  2458   2473     */
  2459   2474     if( eDest==SRT_Mem ){
  2460   2475       sqlite3VdbeAddOp(v, OP_String8, 0, 0);

Changes to src/vdbe.c.

    39     39   **
    40     40   ** Various scripts scan this source file in order to generate HTML
    41     41   ** documentation, headers files, or other derived files.  The formatting
    42     42   ** of the code in this file is, therefore, important.  See other comments
    43     43   ** in this file for details.  If in doubt, do not deviate from existing
    44     44   ** commenting and indentation practices when changing or adding code.
    45     45   **
    46         -** $Id: vdbe.c,v 1.364 2004/06/11 10:51:37 danielk1977 Exp $
           46  +** $Id: vdbe.c,v 1.365 2004/06/11 13:19:21 danielk1977 Exp $
    47     47   */
    48     48   #include "sqliteInt.h"
    49     49   #include "os.h"
    50     50   #include <ctype.h>
    51     51   #include "vdbeInt.h"
    52     52   
    53     53   /*
................................................................................
   156    156   /*
   157    157   ** Insert a new aggregate element and make it the element that
   158    158   ** has focus.
   159    159   **
   160    160   ** Return 0 on success and 1 if memory is exhausted.
   161    161   */
   162    162   static int AggInsert(Agg *p, char *zKey, int nKey){
   163         -  AggElem *pElem, *pOld;
          163  +  AggElem *pElem;
   164    164     int i;
   165         -  Mem *pMem;
          165  +  int rc;
   166    166     pElem = sqliteMalloc( sizeof(AggElem) + nKey +
   167    167                           (p->nMem-1)*sizeof(pElem->aMem[0]) );
   168         -  if( pElem==0 ) return 1;
          168  +  if( pElem==0 ) return SQLITE_NOMEM;
   169    169     pElem->zKey = (char*)&pElem->aMem[p->nMem];
   170    170     memcpy(pElem->zKey, zKey, nKey);
   171    171     pElem->nKey = nKey;
   172         -  pOld = sqlite3HashInsert(&p->hash, pElem->zKey, pElem->nKey, pElem);
   173         -  if( pOld!=0 ){
   174         -    assert( pOld==pElem );  /* Malloc failed on insert */
   175         -    sqliteFree(pOld);
   176         -    return 0;
          172  +
          173  +  assert( p->pCsr );
          174  +  rc = sqlite3BtreeInsert(p->pCsr, zKey, nKey, &pElem, sizeof(AggElem*));
          175  +  if( rc!=SQLITE_OK ){
          176  +    sqliteFree(pElem);
          177  +    return rc;
   177    178     }
   178         -  for(i=0, pMem=pElem->aMem; i<p->nMem; i++, pMem++){
   179         -    pMem->flags = MEM_Null;
          179  +
          180  +  for(i=0; i<p->nMem; i++){
          181  +    pElem->aMem[i].flags = MEM_Null;
   180    182     }
   181    183     p->pCurrent = pElem;
   182    184     return 0;
   183    185   }
   184    186   
   185    187   /*
   186    188   ** Get the AggElem currently in focus
   187    189   */
          190  +#if 0
   188    191   #define AggInFocus(P)   ((P).pCurrent ? (P).pCurrent : _AggInFocus(&(P)))
   189    192   static AggElem *_AggInFocus(Agg *p){
   190    193     HashElem *pElem = sqliteHashFirst(&p->hash);
   191    194     if( pElem==0 ){
   192    195       AggInsert(p,"",1);
   193    196       pElem = sqliteHashFirst(&p->hash);
   194    197     }
   195    198     return pElem ? sqliteHashData(pElem) : 0;
   196    199   }
          200  +#endif
          201  +/*
          202  +** Store a pointer to the AggElem currently in focus in *ppElem. Return
          203  +** SQLITE_OK if successful, otherwise an error-code.
          204  +*/
          205  +static int AggInFocus(Agg *p, AggElem **ppElem){
          206  +  int rc;
          207  +  int res;
          208  +
          209  +  if( p->pCurrent ){
          210  +    *ppElem = p->pCurrent;
          211  +    return SQLITE_OK;
          212  +  }
          213  +
          214  +  rc = sqlite3BtreeFirst(p->pCsr, &res);
          215  +  if( rc!=SQLITE_OK ){
          216  +    return rc;
          217  +  }
          218  +  if( res!=0 ){
          219  +    rc = AggInsert(p,"",1);
          220  +    *ppElem = p->pCurrent;
          221  +  }else{
          222  +    rc = sqlite3BtreeData(p->pCsr, 0, 4, (char *)ppElem);
          223  +  }
          224  +  return rc;
          225  +}
   197    226   
   198    227   /*
   199    228   ** Pop the stack N times.
   200    229   */
   201    230   static void popStack(Mem **ppTos, int N){
   202    231     Mem *pTos = *ppTos;
   203    232     while( N>0 ){
................................................................................
  1294   1323     ** immediately call the destructor for any non-static values.
  1295   1324     */
  1296   1325     if( ctx.pVdbeFunc ){
  1297   1326       int mask = pOp->p2;
  1298   1327       for(i=0; i<ctx.pVdbeFunc->nAux; i++){
  1299   1328         struct AuxData *pAux = &ctx.pVdbeFunc->apAux[i];
  1300   1329         if( (i>31 || !(mask&(1<<i))) && pAux->pAux ){
  1301         -        pAux->xDelete(pAux->pAux);
         1330  +        if( pAux->xDelete ){
         1331  +          pAux->xDelete(pAux->pAux);
         1332  +        }
  1302   1333           pAux->pAux = 0;
  1303   1334         }
  1304   1335       }
  1305   1336       pOp->p3 = (char *)ctx.pVdbeFunc;
  1306   1337       pOp->p3type = P3_VDBEFUNC;
  1307   1338     }
  1308   1339   
................................................................................
  4255   4286     pMem->i++;
  4256   4287     if( pOp->p2>0 && pMem->i>0 ){
  4257   4288        pc = pOp->p2 - 1;
  4258   4289     }
  4259   4290     break;
  4260   4291   }
  4261   4292   
  4262         -/* Opcode: AggReset * P2 *
         4293  +/* Opcode: AggReset * P2 P3
  4263   4294   **
  4264   4295   ** Reset the aggregator so that it no longer contains any data.
  4265         -** Future aggregator elements will contain P2 values each.
         4296  +** Future aggregator elements will contain P2 values each and be sorted
         4297  +** using the KeyInfo structure pointed to by P3.
  4266   4298   */
  4267   4299   case OP_AggReset: {
  4268         -  sqlite3VdbeAggReset(&p->agg);
         4300  +  assert( !pOp->p3 || pOp->p3type==P3_KEYINFO );
         4301  +  rc = sqlite3VdbeAggReset(db, &p->agg, (KeyInfo *)pOp->p3);
         4302  +  if( rc!=SQLITE_OK ){
         4303  +    goto abort_due_to_error;
         4304  +  }
  4269   4305     p->agg.nMem = pOp->p2;
  4270   4306     p->agg.apFunc = sqliteMalloc( p->agg.nMem*sizeof(p->agg.apFunc[0]) );
  4271   4307     if( p->agg.apFunc==0 ) goto no_mem;
  4272   4308     break;
  4273   4309   }
  4274   4310   
  4275   4311   /* Opcode: AggInit * P2 P3
................................................................................
  4352   4388   ** The order of aggregator opcodes is important.  The order is:
  4353   4389   ** AggReset AggFocus AggNext.  In other words, you must execute
  4354   4390   ** AggReset first, then zero or more AggFocus operations, then
  4355   4391   ** zero or more AggNext operations.  You must not execute an AggFocus
  4356   4392   ** in between an AggNext and an AggReset.
  4357   4393   */
  4358   4394   case OP_AggFocus: {
  4359         -  AggElem *pElem;
  4360   4395     char *zKey;
  4361   4396     int nKey;
  4362         -
         4397  +  int res;
  4363   4398     assert( pTos>=p->aStack );
  4364   4399     Stringify(pTos, db->enc);
  4365   4400     zKey = pTos->z;
  4366   4401     nKey = pTos->n;
  4367         -  pElem = sqlite3HashFind(&p->agg.hash, zKey, nKey);
  4368         -  if( pElem ){
  4369         -    p->agg.pCurrent = pElem;
         4402  +  rc = sqlite3BtreeMoveto(p->agg.pCsr, zKey, nKey, &res);
         4403  +  if( rc!=SQLITE_OK ){
         4404  +    goto abort_due_to_error;
         4405  +  }
         4406  +  if( res==0 ){
         4407  +    rc = sqlite3BtreeData(p->agg.pCsr, 0, sizeof(AggElem*),
         4408  +        (char *)&p->agg.pCurrent);
         4409  +    if( rc!=SQLITE_OK ){
         4410  +      goto abort_due_to_error;
         4411  +    }
  4370   4412       pc = pOp->p2 - 1;
  4371   4413     }else{
  4372         -    AggInsert(&p->agg, zKey, nKey);
  4373         -    if( sqlite3_malloc_failed ) goto no_mem;
         4414  +    rc = AggInsert(&p->agg, zKey, nKey);
         4415  +    if( rc!=SQLITE_OK ){
         4416  +      goto abort_due_to_error;
         4417  +    }
  4374   4418     }
  4375   4419     Release(pTos);
  4376   4420     pTos--;
  4377   4421     break; 
  4378   4422   }
  4379   4423   
  4380   4424   /* Opcode: AggSet * P2 *
  4381   4425   **
  4382   4426   ** Move the top of the stack into the P2-th field of the current
  4383   4427   ** aggregate.  String values are duplicated into new memory.
  4384   4428   */
  4385   4429   case OP_AggSet: {
  4386         -  AggElem *pFocus = AggInFocus(p->agg);
         4430  +  AggElem *pFocus;
         4431  +  int i = pOp->p2;
  4387   4432     Mem *pMem;
  4388         -  int i = pOp->p2;
         4433  +  rc = AggInFocus(&p->agg, &pFocus);
         4434  +  if( rc!=SQLITE_OK ) goto abort_due_to_error;
  4389   4435     assert( pTos>=p->aStack );
  4390   4436     if( pFocus==0 ) goto no_mem;
  4391   4437     assert( i>=0 && i<p->agg.nMem );
  4392   4438     Deephemeralize(pTos);
  4393   4439     pMem = &pFocus->aMem[i];
  4394   4440     Release(pMem);
  4395   4441     *pMem = *pTos;
................................................................................
  4405   4451   /* Opcode: AggGet * P2 *
  4406   4452   **
  4407   4453   ** Push a new entry onto the stack which is a copy of the P2-th field
  4408   4454   ** of the current aggregate.  Strings are not duplicated so
  4409   4455   ** string values will be ephemeral.
  4410   4456   */
  4411   4457   case OP_AggGet: {
  4412         -  AggElem *pFocus = AggInFocus(p->agg);
         4458  +  AggElem *pFocus;
  4413   4459     Mem *pMem;
  4414   4460     int i = pOp->p2;
         4461  +  rc = AggInFocus(&p->agg, &pFocus);
         4462  +  if( rc!=SQLITE_OK ) goto abort_due_to_error;
  4415   4463     if( pFocus==0 ) goto no_mem;
  4416   4464     assert( i>=0 && i<p->agg.nMem );
  4417   4465     pTos++;
  4418   4466     pMem = &pFocus->aMem[i];
  4419   4467     *pTos = *pMem;
  4420   4468     if( pTos->flags & (MEM_Str|MEM_Blob) ){
  4421   4469       pTos->flags &= ~(MEM_Dyn|MEM_Static|MEM_Short);
................................................................................
  4436   4484   ** The order of aggregator opcodes is important.  The order is:
  4437   4485   ** AggReset AggFocus AggNext.  In other words, you must execute
  4438   4486   ** AggReset first, then zero or more AggFocus operations, then
  4439   4487   ** zero or more AggNext operations.  You must not execute an AggFocus
  4440   4488   ** in between an AggNext and an AggReset.
  4441   4489   */
  4442   4490   case OP_AggNext: {
         4491  +  int res;
  4443   4492     CHECK_FOR_INTERRUPT;
  4444         -  if( p->agg.pSearch==0 ){
  4445         -    p->agg.pSearch = sqliteHashFirst(&p->agg.hash);
         4493  +  if( p->agg.searching==0 ){
         4494  +    p->agg.searching = 1;
         4495  +    rc = sqlite3BtreeFirst(p->agg.pCsr, &res);
         4496  +    if( rc!=SQLITE_OK ) goto abort_due_to_error;
  4446   4497     }else{
  4447         -    p->agg.pSearch = sqliteHashNext(p->agg.pSearch);
         4498  +    rc = sqlite3BtreeNext(p->agg.pCsr, &res);
         4499  +    if( rc!=SQLITE_OK ) goto abort_due_to_error;
  4448   4500     }
  4449         -  if( p->agg.pSearch==0 ){
         4501  +  if( res!=0 ){
  4450   4502       pc = pOp->p2 - 1;
  4451         -  } else {
         4503  +  }else{
  4452   4504       int i;
  4453   4505       sqlite3_context ctx;
  4454   4506       Mem *aMem;
  4455         -    p->agg.pCurrent = sqliteHashData(p->agg.pSearch);
         4507  +
         4508  +    rc = sqlite3BtreeData(p->agg.pCsr, 0, sizeof(AggElem*),
         4509  +        (char *)&p->agg.pCurrent);
         4510  +    if( rc!=SQLITE_OK ){
         4511  +      goto abort_due_to_error;
         4512  +    }
  4456   4513       aMem = p->agg.pCurrent->aMem;
  4457   4514       for(i=0; i<p->agg.nMem; i++){
  4458   4515         int freeCtx;
  4459   4516         if( p->agg.apFunc[i]==0 ) continue;
  4460   4517         if( p->agg.apFunc[i]->xFinalize==0 ) continue;
  4461   4518         ctx.s.flags = MEM_Null;
  4462   4519         ctx.s.z = aMem[i].zShort;

Changes to src/vdbeInt.h.

   219    219   ** the GROUP BY clause of a select.
   220    220   */
   221    221   typedef struct Agg Agg;
   222    222   typedef struct AggElem AggElem;
   223    223   struct Agg {
   224    224     int nMem;            /* Number of values stored in each AggElem */
   225    225     AggElem *pCurrent;   /* The AggElem currently in focus */
          226  +  FuncDef **apFunc;    /* Information about aggregate functions */
          227  +#if 0
   226    228     HashElem *pSearch;   /* The hash element for pCurrent */
   227    229     Hash hash;           /* Hash table of all aggregate elements */
   228         -  FuncDef **apFunc;    /* Information about aggregate functions */
          230  +#endif
          231  +  Btree *pBtree;       /* The temporary btree used to group elements */
          232  +  BtCursor *pCsr;      /* Read/write cursor to the table in pBtree */
          233  +  int nTab;            /* Root page of the table in pBtree */
          234  +  u8 searching;        /* True between the first AggNext and AggReset */
   229    235   };
   230    236   struct AggElem {
   231    237     char *zKey;          /* The key to this AggElem */
   232    238     int nKey;            /* Number of bytes in the key, including '\0' at end */
   233    239     Mem aMem[1];         /* The values for this AggElem */
   234    240   };
   235    241   
................................................................................
   340    346   #define VDBE_MAGIC_DEAD     0xb606c3c8    /* The VDBE has been deallocated */
   341    347   
   342    348   /*
   343    349   ** Function prototypes
   344    350   */
   345    351   void sqlite3VdbeCleanupCursor(Cursor*);
   346    352   void sqlite3VdbeSorterReset(Vdbe*);
   347         -void sqlite3VdbeAggReset(Agg*);
          353  +int sqlite3VdbeAggReset(sqlite *, Agg *, KeyInfo *);
   348    354   void sqlite3VdbeKeylistFree(Keylist*);
   349    355   void sqliteVdbePopStack(Vdbe*,int);
   350    356   int sqlite3VdbeCursorMoveto(Cursor*);
   351    357   #if !defined(NDEBUG) || defined(VDBE_PROFILE)
   352    358   void sqlite3VdbePrintOp(FILE*, int, Op*);
   353    359   #endif
   354    360   int sqlite3VdbeSerialTypeLen(u32);

Changes to src/vdbeaux.c.

   647    647       p->azColName = (char**)&p->apArg[n];
   648    648       p->apVar = (Mem *)&p->azColName[n];
   649    649       for(n=0; n<p->nVar; n++){
   650    650         p->apVar[n].flags = MEM_Null;
   651    651       }
   652    652     }
   653    653   
   654         -  sqlite3HashInit(&p->agg.hash, SQLITE_HASH_BINARY, 0);
   655         -  p->agg.pSearch = 0;
   656    654   #ifdef SQLITE_DEBUG
   657    655     if( (p->db->flags & SQLITE_VdbeListing)!=0
   658    656       || sqlite3OsFileExists("vdbe_explain")
   659    657     ){
   660    658       int i;
   661    659       printf("VDBE Program Listing:\n");
   662    660       for(i=0; i<p->nOp; i++){
................................................................................
   707    705   **
   708    706   ** For installable aggregate functions, if the step function has been
   709    707   ** called, make sure the finalizer function has also been called.  The
   710    708   ** finalizer might need to free memory that was allocated as part of its
   711    709   ** private context.  If the finalizer has not been called yet, call it
   712    710   ** now.
   713    711   */
          712  +#if 0
   714    713   void sqlite3VdbeAggReset(Agg *pAgg){
   715    714     int i;
   716    715     HashElem *p;
   717    716     for(p = sqliteHashFirst(&pAgg->hash); p; p = sqliteHashNext(p)){
   718    717       AggElem *pElem = sqliteHashData(p);
   719    718       assert( pAgg->apFunc!=0 );
   720    719       for(i=0; i<pAgg->nMem; i++){
................................................................................
   743    742     sqlite3HashClear(&pAgg->hash);
   744    743     sqliteFree(pAgg->apFunc);
   745    744     pAgg->apFunc = 0;
   746    745     pAgg->pCurrent = 0;
   747    746     pAgg->pSearch = 0;
   748    747     pAgg->nMem = 0;
   749    748   }
          749  +#endif
          750  +
          751  +/*
          752  +** Reset an Agg structure.  Delete all its contents.
          753  +**
          754  +** For installable aggregate functions, if the step function has been
          755  +** called, make sure the finalizer function has also been called.  The
          756  +** finalizer might need to free memory that was allocated as part of its
          757  +** private context.  If the finalizer has not been called yet, call it
          758  +** now.
          759  +**
          760  +** If db is NULL, then this is being called from sqliteVdbeReset(). In
          761  +** this case clean up all references to the temp-table used for
          762  +** aggregates (if it was ever opened).
          763  +**
          764  +** If db is not NULL, then this is being called from with an OP_AggReset
          765  +** opcode. Open the temp-table, if it has not already been opened and
          766  +** delete the contents of the table used for aggregate information, ready
          767  +** for the next round of aggregate processing.
          768  +*/
          769  +int sqlite3VdbeAggReset(sqlite *db, Agg *pAgg, KeyInfo *pKeyInfo){
          770  +  int i;
          771  +  int rc = 0;
          772  +  BtCursor *pCsr = pAgg->pCsr;
          773  +
          774  +  assert( (pCsr && pAgg->nTab>0) || (!pCsr && pAgg->nTab==0)
          775  +         || sqlite3_malloc_failed );
          776  +
          777  +  /* If pCsr is not NULL, then the table used for aggregate information
          778  +  ** is open. Loop through it and free the AggElem* structure pointed at
          779  +  ** by each entry. If the finalizer has not been called for an AggElem,
          780  +  ** do that too. Finally, clear the btree table itself.
          781  +  */
          782  +  if( pCsr ){
          783  +    int res;
          784  +    assert( pAgg->pBtree );
          785  +    assert( pAgg->nTab>0 );
          786  +
          787  +    rc=sqlite3BtreeFirst(pCsr, &res);
          788  +    while( res==0 && rc==SQLITE_OK ){
          789  +      AggElem *pElem;
          790  +      rc = sqlite3BtreeData(pCsr, 0, sizeof(AggElem*), (char *)&pElem);
          791  +      if( res!=SQLITE_OK ){
          792  +        return rc;
          793  +      }
          794  +      assert( pAgg->apFunc!=0 );
          795  +      for(i=0; i<pAgg->nMem; i++){
          796  +        Mem *pMem = &pElem->aMem[i];
          797  +        if( pAgg->apFunc[i] && (pMem->flags & MEM_AggCtx)!=0 ){
          798  +          sqlite3_context ctx;
          799  +          ctx.pFunc = pAgg->apFunc[i];
          800  +          ctx.s.flags = MEM_Null;
          801  +          ctx.pAgg = pMem->z;
          802  +          ctx.cnt = pMem->i;
          803  +          ctx.isStep = 0;
          804  +          ctx.isError = 0;
          805  +          (*pAgg->apFunc[i]->xFinalize)(&ctx);
          806  +          if( pMem->z!=0 && pMem->z!=pMem->z ){
          807  +            sqliteFree(pMem->z);
          808  +          }
          809  +        }else if( pMem->flags&MEM_Dyn ){
          810  +          sqliteFree(pMem->z);
          811  +        }
          812  +      }
          813  +      sqliteFree(pElem);
          814  +      rc=sqlite3BtreeNext(pCsr, &res);
          815  +    }
          816  +    if( rc!=SQLITE_OK ){
          817  +      return rc;
          818  +    }
          819  +
          820  +    sqlite3BtreeCloseCursor(pCsr);
          821  +    sqlite3BtreeClearTable(pAgg->pBtree, pAgg->nTab);
          822  +  }
          823  +
          824  +  /* If db is not NULL and we have not yet and we have not yet opened
          825  +  ** the temporary btree then do so and create the table to store aggregate
          826  +  ** information.
          827  +  **
          828  +  ** If db is NULL, then close the temporary btree if it is open.
          829  +  */
          830  +  if( db ){
          831  +    if( !pAgg->pBtree ){
          832  +      assert( pAgg->nTab==0 );
          833  +      rc = sqlite3BtreeFactory(db, 0, 0, TEMP_PAGES, &pAgg->pBtree);
          834  +      if( rc!=SQLITE_OK ) return rc;
          835  +      sqlite3BtreeBeginTrans(pAgg->pBtree, 1, 0);
          836  +      rc = sqlite3BtreeCreateTable(pAgg->pBtree, &pAgg->nTab, 0);
          837  +      if( rc!=SQLITE_OK ) return rc;
          838  +    }
          839  +    assert( pAgg->nTab!=0 );
          840  +
          841  +    rc = sqlite3BtreeCursor(pAgg->pBtree, pAgg->nTab, 1,
          842  +        sqlite3VdbeRecordCompare, pKeyInfo, &pAgg->pCsr);
          843  +    if( rc!=SQLITE_OK ) return rc;
          844  +  }else{
          845  +    if( pAgg->pBtree ){
          846  +      sqlite3BtreeClose(pAgg->pBtree);
          847  +      pAgg->pBtree = 0;
          848  +      pAgg->nTab = 0;
          849  +    }
          850  +    pAgg->pCsr = 0;
          851  +  }
          852  +
          853  +  if( pAgg->apFunc ){ 
          854  +    sqliteFree(pAgg->apFunc);
          855  +    pAgg->apFunc = 0;
          856  +  }
          857  +  pAgg->pCurrent = 0;
          858  +  pAgg->nMem = 0;
          859  +  pAgg->searching = 0;
          860  +  return SQLITE_OK;
          861  +}
          862  +
   750    863   
   751    864   /*
   752    865   ** Delete a keylist
   753    866   */
   754    867   void sqlite3VdbeKeylistFree(Keylist *p){
   755    868     while( p ){
   756    869       Keylist *pNext = p->pNext;
................................................................................
   835    948     }
   836    949     p->nField = 0;
   837    950     if( p->zLine ){
   838    951       sqliteFree(p->zLine);
   839    952       p->zLine = 0;
   840    953     }
   841    954     p->nLineAlloc = 0;
   842         -  sqlite3VdbeAggReset(&p->agg);
          955  +  sqlite3VdbeAggReset(0, &p->agg, 0);
   843    956     if( p->keylistStack ){
   844    957       int ii;
   845    958       for(ii = 0; ii < p->keylistStackDepth; ii++){
   846    959         sqlite3VdbeKeylistFree(p->keylistStack[ii]);
   847    960       }
   848    961       sqliteFree(p->keylistStack);
   849    962       p->keylistStackDepth = 0;

Changes to src/vdbemem.c.

    45     45       /* If the current encoding does not match the desired encoding, then
    46     46       ** we will need to do some translation between encodings.
    47     47       */
    48     48       char *z;
    49     49       int n;
    50     50       int rc;
    51     51   
    52         -    rc = sqlite3utfTranslate(pMem->z, pMem->n, pMem->enc, &z, &n, desiredEnc);
           52  +    rc = sqlite3utfTranslate(pMem->z, pMem->n, pMem->enc, (void **)&z, 
           53  +        &n, desiredEnc);
    53     54       if( rc!=SQLITE_OK ){
    54     55         return rc;
    55     56       }
    56     57       if( pMem->flags&MEM_Dyn ){
    57     58         sqliteFree(pMem->z);
    58     59       }
    59     60       /* Result of sqlite3utfTranslate is currently always dynamically

Changes to test/select3.test.

     8      8   #    May you share freely, never taking more than you give.
     9      9   #
    10     10   #***********************************************************************
    11     11   # This file implements regression tests for SQLite library.  The
    12     12   # focus of this file is testing aggregate functions and the
    13     13   # GROUP BY and HAVING clauses of SELECT statements.
    14     14   #
    15         -# $Id: select3.test,v 1.10 2004/05/27 17:22:56 drh Exp $
           15  +# $Id: select3.test,v 1.11 2004/06/11 13:19:22 danielk1977 Exp $
    16     16   
    17     17   set testdir [file dirname $argv0]
    18     18   source $testdir/tester.tcl
    19     19   
    20     20   # Build some test data
    21     21   #
    22     22   do_test select3-1.0 {
................................................................................
    74     74       SELECT log*2+1 as x, count(*) FROM t1 GROUP BY x ORDER BY x
    75     75     }
    76     76   } {1 1 3 1 5 2 7 4 9 8 11 15}
    77     77   do_test select3-2.7 {
    78     78     execsql {
    79     79       SELECT log*2+1 AS x, count(*) AS y FROM t1 GROUP BY x ORDER BY y
    80     80     }
    81         -} {1 1 3 1 5 2 7 4 9 8 11 15}
           81  +} {3 1 1 1 5 2 7 4 9 8 11 15}
    82     82   do_test select3-2.8 {
    83     83     execsql {
    84     84       SELECT log*2+1 AS x, count(*) AS y FROM t1 GROUP BY x ORDER BY 10-(x+y)
    85     85     }
    86     86   } {11 15 9 8 7 4 5 2 3 1 1 1}
    87     87   do_test select3-2.9 {
    88     88     catchsql {