diff options
Diffstat (limited to 'ext/pdo_sqlite/sqlite/src/select.c')
| -rw-r--r-- | ext/pdo_sqlite/sqlite/src/select.c | 1086 | 
1 files changed, 677 insertions, 409 deletions
| diff --git a/ext/pdo_sqlite/sqlite/src/select.c b/ext/pdo_sqlite/sqlite/src/select.c index a4eb3fca4a..8a51208d79 100644 --- a/ext/pdo_sqlite/sqlite/src/select.c +++ b/ext/pdo_sqlite/sqlite/src/select.c @@ -60,6 +60,9 @@ Select *sqlite3SelectNew(      pNew->pOffset = pOffset;      pNew->iLimit = -1;      pNew->iOffset = -1; +    pNew->addrOpenVirt[0] = -1; +    pNew->addrOpenVirt[1] = -1; +    pNew->addrOpenVirt[2] = -1;    }    return pNew;  } @@ -70,6 +73,7 @@ Select *sqlite3SelectNew(  ** in terms of the following bit values:  **  **     JT_INNER +**     JT_CROSS  **     JT_OUTER  **     JT_NATURAL  **     JT_LEFT @@ -95,7 +99,7 @@ int sqlite3JoinType(Parse *pParse, Token *pA, Token *pB, Token *pC){      { "full",    4, JT_LEFT|JT_RIGHT|JT_OUTER },      { "outer",   5, JT_OUTER },      { "inner",   5, JT_INNER }, -    { "cross",   5, JT_INNER }, +    { "cross",   5, JT_INNER|JT_CROSS },    };    int i, j;    apAll[0] = pA; @@ -175,6 +179,7 @@ static void addWhereTerm(    const char *zAlias1,     /* Alias for first table.  May be NULL */    const Table *pTab2,      /* Second table */    const char *zAlias2,     /* Alias for second table.  May be NULL */ +  int iRightJoinTable,     /* VDBE cursor for the right table */    Expr **ppExpr            /* Add the equality term to this expression */  ){    Expr *pE1a, *pE1b, *pE1c; @@ -195,11 +200,14 @@ static void addWhereTerm(    pE2c = sqlite3Expr(TK_DOT, pE2b, pE2a, 0);    pE = sqlite3Expr(TK_EQ, pE1c, pE2c, 0);    ExprSetProperty(pE, EP_FromJoin); +  pE->iRightJoinTable = iRightJoinTable;    *ppExpr = sqlite3ExprAnd(*ppExpr, pE);  }  /*  ** Set the EP_FromJoin property on all terms of the given expression. +** And set the Expr.iRightJoinTable to iTable for every term in the +** expression.  **  ** The EP_FromJoin property is used on terms of an expression to tell  ** the LEFT OUTER JOIN processing logic that this term is part of the @@ -207,11 +215,26 @@ static void addWhereTerm(  ** of the more general WHERE clause.  These terms are moved over to the  ** WHERE clause during join processing but we need to remember that they  ** originated in the ON or USING clause. +** +** The Expr.iRightJoinTable tells the WHERE clause processing that the +** expression depends on table iRightJoinTable even if that table is not +** explicitly mentioned in the expression.  That information is needed +** for cases like this: +** +**    SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.b AND t1.x=5 +** +** The where clause needs to defer the handling of the t1.x=5 +** term until after the t2 loop of the join.  In that way, a +** NULL t2 row will be inserted whenever t1.x!=5.  If we do not +** defer the handling of t1.x=5, it will be processed immediately +** after the t1 loop and rows with t1.x!=5 will never appear in +** the output, which is incorrect.  */ -static void setJoinExpr(Expr *p){ +static void setJoinExpr(Expr *p, int iTable){    while( p ){      ExprSetProperty(p, EP_FromJoin); -    setJoinExpr(p->pLeft); +    p->iRightJoinTable = iTable; +    setJoinExpr(p->pLeft, iTable);      p = p->pRight;    }   } @@ -258,7 +281,9 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){          char *zName = pLeftTab->aCol[j].zName;          if( columnIndex(pRightTab, zName)>=0 ){            addWhereTerm(zName, pLeftTab, pLeft->zAlias,  -                              pRightTab, pRight->zAlias, &p->pWhere); +                              pRightTab, pRight->zAlias, +                              pRight->iCursor, &p->pWhere); +                    }        }      } @@ -275,7 +300,7 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){      ** an AND operator.      */      if( pLeft->pOn ){ -      setJoinExpr(pLeft->pOn); +      setJoinExpr(pLeft->pOn, pRight->iCursor);        p->pWhere = sqlite3ExprAnd(p->pWhere, pLeft->pOn);        pLeft->pOn = 0;      } @@ -297,7 +322,8 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){            return 1;          }          addWhereTerm(zName, pLeftTab, pLeft->zAlias,  -                            pRightTab, pRight->zAlias, &p->pWhere); +                            pRightTab, pRight->zAlias, +                            pRight->iCursor, &p->pWhere);        }      }    } @@ -327,8 +353,10 @@ void sqlite3SelectDelete(Select *p){  */  static void pushOntoSorter(Parse *pParse, Vdbe *v, ExprList *pOrderBy){    sqlite3ExprCodeExprList(pParse, pOrderBy); -  sqlite3VdbeAddOp(v, OP_MakeRecord, pOrderBy->nExpr, 0); -  sqlite3VdbeAddOp(v, OP_SortInsert, 0, 0); +  sqlite3VdbeAddOp(v, OP_Sequence, pOrderBy->iECursor, 0); +  sqlite3VdbeAddOp(v, OP_Pull, pOrderBy->nExpr + 1, 0); +  sqlite3VdbeAddOp(v, OP_MakeRecord, pOrderBy->nExpr + 2, 0); +  sqlite3VdbeAddOp(v, OP_IdxInsert, pOrderBy->iECursor, 0);  }  /* @@ -341,7 +369,7 @@ static void codeLimiter(    int iBreak,       /* Jump here to end the loop */    int nPop          /* Number of times to pop stack when jumping */  ){ -  if( p->iOffset>=0 ){ +  if( p->iOffset>=0 && iContinue!=0 ){      int addr = sqlite3VdbeCurrentAddr(v) + 3;      if( nPop>0 ) addr++;      sqlite3VdbeAddOp(v, OP_MemIncr, p->iOffset, 0); @@ -352,13 +380,41 @@ static void codeLimiter(      sqlite3VdbeAddOp(v, OP_Goto, 0, iContinue);      VdbeComment((v, "# skip OFFSET records"));    } -  if( p->iLimit>=0 ){ +  if( p->iLimit>=0 && iBreak!=0 ){      sqlite3VdbeAddOp(v, OP_MemIncr, p->iLimit, iBreak);      VdbeComment((v, "# exit when LIMIT reached"));    }  }  /* +** Add code that will check to make sure the top N elements of the +** stack are distinct.  iTab is a sorting index that holds previously +** seen combinations of the N values.  A new entry is made in iTab +** if the current N values are new. +** +** A jump to addrRepeat is made and the K values are popped from the +** stack if the top N elements are not distinct. +*/ +static void codeDistinct( +  Vdbe *v,           /* Generate code into this VM */ +  int iTab,          /* A sorting index used to test for distinctness */ +  int addrRepeat,    /* Jump to here if not distinct */ +  int N,             /* The top N elements of the stack must be distinct */ +  int K              /* Pop K elements from the stack if indistinct */ +){ +#if NULL_ALWAYS_DISTINCT +  sqlite3VdbeAddOp(v, OP_IsNull, -N, sqlite3VdbeCurrentAddr(v)+6); +#endif +  sqlite3VdbeAddOp(v, OP_MakeRecord, -N, 0); +  sqlite3VdbeAddOp(v, OP_Distinct, iTab, sqlite3VdbeCurrentAddr(v)+3); +  sqlite3VdbeAddOp(v, OP_Pop, K, 0); +  sqlite3VdbeAddOp(v, OP_Goto, 0, addrRepeat); +  VdbeComment((v, "# skip indistinct records")); +  sqlite3VdbeAddOp(v, OP_IdxInsert, iTab, 0); +} + + +/*  ** This routine generates the code for the inside of the inner loop  ** of a SELECT.  ** @@ -413,30 +469,22 @@ static int selectInnerLoop(    */    if( hasDistinct ){      int n = pEList->nExpr; -#if NULL_ALWAYS_DISTINCT -    sqlite3VdbeAddOp(v, OP_IsNull, -pEList->nExpr, sqlite3VdbeCurrentAddr(v)+7); -#endif -    /* Deliberately leave the affinity string off of the following -    ** OP_MakeRecord */ -    sqlite3VdbeAddOp(v, OP_MakeRecord, -n, 0); -    sqlite3VdbeAddOp(v, OP_Distinct, distinct, sqlite3VdbeCurrentAddr(v)+3); -    sqlite3VdbeAddOp(v, OP_Pop, n+1, 0); -    sqlite3VdbeAddOp(v, OP_Goto, 0, iContinue); -    VdbeComment((v, "# skip indistinct records")); -    sqlite3VdbeAddOp(v, OP_IdxInsert, distinct, 0); +    codeDistinct(v, distinct, iContinue, n, n+1);      if( pOrderBy==0 ){        codeLimiter(v, p, iContinue, iBreak, nColumn);      }    }    switch( eDest ){ -#ifndef SQLITE_OMIT_COMPOUND_SELECT      /* In this mode, write each query result to the key of the temporary      ** table iParm.      */ +#ifndef SQLITE_OMIT_COMPOUND_SELECT      case SRT_Union: {        sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, NULL_ALWAYS_DISTINCT); -      sqlite3VdbeChangeP3(v, -1, aff, P3_STATIC); +      if( aff ){ +        sqlite3VdbeChangeP3(v, -1, aff, P3_STATIC); +      }        sqlite3VdbeAddOp(v, OP_IdxInsert, iParm, 0);        break;      } @@ -458,7 +506,7 @@ static int selectInnerLoop(      /* Store the result as data using a unique key.      */      case SRT_Table: -    case SRT_TempTable: { +    case SRT_VirtualTab: {        sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, 0);        if( pOrderBy ){          pushOntoSorter(pParse, v, pOrderBy); @@ -484,6 +532,10 @@ static int selectInnerLoop(        sqlite3VdbeAddOp(v, OP_Pop, 1, 0);        addr2 = sqlite3VdbeAddOp(v, OP_Goto, 0, 0);        if( pOrderBy ){ +        /* At first glance you would think we could optimize out the +        ** ORDER BY in this case since the order of entries in the set +        ** does not matter.  But there might be a LIMIT clause, in which +        ** case the order does matter */          pushOntoSorter(pParse, v, pOrderBy);        }else{          char aff = (iParm>>16)&0xFF; @@ -491,7 +543,7 @@ static int selectInnerLoop(          sqlite3VdbeOp3(v, OP_MakeRecord, 1, 0, &aff, 1);          sqlite3VdbeAddOp(v, OP_IdxInsert, (iParm&0x0000FFFF), 0);        } -      sqlite3VdbeChangeP2(v, addr2, sqlite3VdbeCurrentAddr(v)); +      sqlite3VdbeJumpHere(v, addr2);        break;      } @@ -517,15 +569,13 @@ static int selectInnerLoop(      ** popping the data from the stack.      */      case SRT_Subroutine: -    case SRT_Callback: -    case SRT_Sorter: { +    case SRT_Callback: {        if( pOrderBy ){          sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, 0);          pushOntoSorter(pParse, v, pOrderBy);        }else if( eDest==SRT_Subroutine ){          sqlite3VdbeAddOp(v, OP_Gosub, 0, iParm);        }else{ -        assert( eDest!=SRT_Sorter );          sqlite3VdbeAddOp(v, OP_Callback, nColumn, 0);        }        break; @@ -548,6 +598,48 @@ static int selectInnerLoop(  }  /* +** Given an expression list, generate a KeyInfo structure that records +** the collating sequence for each expression in that expression list. +** +** If the ExprList is an ORDER BY or GROUP BY clause then the resulting +** KeyInfo structure is appropriate for initializing a virtual index to +** implement that clause.  If the ExprList is the result set of a SELECT +** then the KeyInfo structure is appropriate for initializing a virtual +** index to implement a DISTINCT test. +** +** Space to hold the KeyInfo structure is obtain from malloc.  The calling +** function is responsible for seeing that this structure is eventually +** freed.  Add the KeyInfo structure to the P3 field of an opcode using +** P3_KEYINFO_HANDOFF is the usual way of dealing with this. +*/ +static KeyInfo *keyInfoFromExprList(Parse *pParse, ExprList *pList){ +  sqlite3 *db = pParse->db; +  int nExpr; +  KeyInfo *pInfo; +  struct ExprList_item *pItem; +  int i; + +  nExpr = pList->nExpr; +  pInfo = sqliteMalloc( sizeof(*pInfo) + nExpr*(sizeof(CollSeq*)+1) ); +  if( pInfo ){ +    pInfo->aSortOrder = (char*)&pInfo->aColl[nExpr]; +    pInfo->nField = nExpr; +    pInfo->enc = db->enc; +    for(i=0, pItem=pList->a; i<nExpr; i++, pItem++){ +      CollSeq *pColl; +      pColl = sqlite3ExprCollSeq(pParse, pItem->pExpr); +      if( !pColl ){ +        pColl = db->pDfltColl; +      } +      pInfo->aColl[i] = pColl; +      pInfo->aSortOrder[i] = pItem->sortOrder; +    } +  } +  return pInfo; +} + + +/*  ** If the inner loop was generated using a non-null pOrderBy argument,  ** then the results were placed in a sorter.  After the loop is terminated  ** we need to run the sorter and output the results.  The following @@ -561,38 +653,19 @@ static void generateSortTail(    int eDest,       /* Write the sorted results here */    int iParm        /* Optional parameter associated with eDest */  ){ -  int end1 = sqlite3VdbeMakeLabel(v); -  int end2 = sqlite3VdbeMakeLabel(v); +  int brk = sqlite3VdbeMakeLabel(v); +  int cont = sqlite3VdbeMakeLabel(v);    int addr; -  KeyInfo *pInfo; -  ExprList *pOrderBy; -  int nCol, i; -  sqlite3 *db = pParse->db; +  int iTab; +  ExprList *pOrderBy = p->pOrderBy; -  if( eDest==SRT_Sorter ) return; -  pOrderBy = p->pOrderBy; -  nCol = pOrderBy->nExpr; -  pInfo = sqliteMalloc( sizeof(*pInfo) + nCol*(sizeof(CollSeq*)+1) ); -  if( pInfo==0 ) return; -  pInfo->aSortOrder = (char*)&pInfo->aColl[nCol]; -  pInfo->nField = nCol; -  for(i=0; i<nCol; i++){ -    /* If a collation sequence was specified explicity, then it -    ** is stored in pOrderBy->a[i].zName. Otherwise, use the default -    ** collation type for the expression. -    */ -    pInfo->aColl[i] = sqlite3ExprCollSeq(pParse, pOrderBy->a[i].pExpr); -    if( !pInfo->aColl[i] ){ -      pInfo->aColl[i] = db->pDfltColl; -    } -    pInfo->aSortOrder[i] = pOrderBy->a[i].sortOrder; -  } -  sqlite3VdbeOp3(v, OP_Sort, 0, 0, (char*)pInfo, P3_KEYINFO_HANDOFF); -  addr = sqlite3VdbeAddOp(v, OP_SortNext, 0, end1); -  codeLimiter(v, p, addr, end2, 1); +  iTab = pOrderBy->iECursor; +  addr = 1 + sqlite3VdbeAddOp(v, OP_Sort, iTab, brk); +  codeLimiter(v, p, cont, brk, 0); +  sqlite3VdbeAddOp(v, OP_Column, iTab, pOrderBy->nExpr + 1);    switch( eDest ){      case SRT_Table: -    case SRT_TempTable: { +    case SRT_VirtualTab: {        sqlite3VdbeAddOp(v, OP_NewRowid, iParm, 0);        sqlite3VdbeAddOp(v, OP_Pull, 1, 0);        sqlite3VdbeAddOp(v, OP_Insert, iParm, 0); @@ -612,7 +685,7 @@ static void generateSortTail(      case SRT_Mem: {        assert( nColumn==1 );        sqlite3VdbeAddOp(v, OP_MemStore, iParm, 1); -      sqlite3VdbeAddOp(v, OP_Goto, 0, end1); +      sqlite3VdbeAddOp(v, OP_Goto, 0, brk);        break;      }  #endif @@ -637,11 +710,9 @@ static void generateSortTail(        break;      }    } -  sqlite3VdbeAddOp(v, OP_Goto, 0, addr); -  sqlite3VdbeResolveLabel(v, end2); -  sqlite3VdbeAddOp(v, OP_Pop, 1, 0); -  sqlite3VdbeResolveLabel(v, end1); -  sqlite3VdbeAddOp(v, OP_SortReset, 0, 0); +  sqlite3VdbeResolveLabel(v, cont); +  sqlite3VdbeAddOp(v, OP_Next, iTab, addr); +  sqlite3VdbeResolveLabel(v, brk);  }  /* @@ -1305,59 +1376,33 @@ static void computeLimitRegisters(Parse *pParse, Select *p){  }  /* -** Generate VDBE instructions that will open a transient table that -** will be used for an index or to store keyed results for a compound -** select.  In other words, open a transient table that needs a -** KeyInfo structure.  The number of columns in the KeyInfo is determined -** by the result set of the SELECT statement in the second argument. -** -** Specifically, this routine is called to open an index table for -** DISTINCT, UNION, INTERSECT and EXCEPT select statements (but not  -** UNION ALL). -** -** The value returned is the address of the OP_OpenVirtual instruction. +** Allocate a virtual index to use for sorting.  */ -static int openVirtualIndex(Parse *pParse, Select *p, int iTab){ -  KeyInfo *pKeyInfo; -  int nColumn; -  sqlite3 *db = pParse->db; -  int i; -  Vdbe *v = pParse->pVdbe; -  int addr; - -  if( prepSelectStmt(pParse, p) ){ -    return 0; -  } -  nColumn = p->pEList->nExpr; -  pKeyInfo = sqliteMalloc( sizeof(*pKeyInfo)+nColumn*sizeof(CollSeq*) ); -  if( pKeyInfo==0 ) return 0; -  pKeyInfo->enc = db->enc; -  pKeyInfo->nField = nColumn; -  for(i=0; i<nColumn; i++){ -    pKeyInfo->aColl[i] = sqlite3ExprCollSeq(pParse, p->pEList->a[i].pExpr); -    if( !pKeyInfo->aColl[i] ){ -      pKeyInfo->aColl[i] = db->pDfltColl; -    } +static void createSortingIndex(Parse *pParse, Select *p, ExprList *pOrderBy){ +  if( pOrderBy ){ +    int addr; +    assert( pOrderBy->iECursor==0 ); +    pOrderBy->iECursor = pParse->nTab++; +    addr = sqlite3VdbeAddOp(pParse->pVdbe, OP_OpenVirtual, +                            pOrderBy->iECursor, pOrderBy->nExpr+1); +    assert( p->addrOpenVirt[2] == -1 ); +    p->addrOpenVirt[2] = addr;    } -  addr = sqlite3VdbeOp3(v, OP_OpenVirtual, iTab, 0,  -      (char*)pKeyInfo, P3_KEYINFO_HANDOFF); -  return addr;  } -#ifndef SQLITE_OMIT_COMPOUND_SELECT  /* -** Add the address "addr" to the set of all OpenVirtual opcode addresses -** that are being accumulated in p->ppOpenVirtual. +** The opcode at addr is an OP_OpenVirtual that created a sorting +** index tha we ended up not needing.  This routine changes that +** opcode to OP_Noop.  */ -static int multiSelectOpenVirtualAddr(Select *p, int addr){ -  IdList *pList = *p->ppOpenVirtual = sqlite3IdListAppend(*p->ppOpenVirtual, 0); -  if( pList==0 ){ -    return SQLITE_NOMEM; -  } -  pList->a[pList->nId-1].idx = addr; -  return SQLITE_OK; +static void uncreateSortingIndex(Parse *pParse, int addr){ +  Vdbe *v = pParse->pVdbe; +  VdbeOp *pOp = sqlite3VdbeGetOp(v, addr); +  sqlite3VdbeChangeP3(v, addr, 0, 0); +  pOp->opcode = OP_Noop; +  pOp->p1 = 0; +  pOp->p2 = 0;  } -#endif /* SQLITE_OMIT_COMPOUND_SELECT */  #ifndef SQLITE_OMIT_COMPOUND_SELECT  /* @@ -1423,10 +1468,10 @@ static int multiSelect(    int rc = SQLITE_OK;   /* Success code from a subroutine */    Select *pPrior;       /* Another SELECT immediately to our left */    Vdbe *v;              /* Generate code to this VDBE */ -  IdList *pOpenVirtual = 0;/* OP_OpenVirtual opcodes that need a KeyInfo */ -  int aAddr[5];         /* Addresses of SetNumColumns operators */ -  int nAddr = 0;        /* Number used */    int nCol;             /* Number of columns in the result set */ +  ExprList *pOrderBy;   /* The ORDER BY clause on p */ +  int aSetP2[2];        /* Set P2 value of these op to number of columns */ +  int nSetP2 = 0;       /* Number of slots in aSetP2[] used */    /* Make sure there is no ORDER BY or LIMIT clause on prior SELECTs.  Only    ** the last (right-most) SELECT in the series may have an ORDER BY or LIMIT. @@ -1436,6 +1481,8 @@ static int multiSelect(      goto multi_select_end;    }    pPrior = p->pPrior; +  assert( pPrior->pRightmost!=pPrior ); +  assert( pPrior->pRightmost==p->pRightmost );    if( pPrior->pOrderBy ){      sqlite3ErrorMsg(pParse,"ORDER BY clause should come after %s not before",        selectOpName(p->op)); @@ -1457,32 +1504,21 @@ static int multiSelect(      goto multi_select_end;    } -  /* If *p this is the right-most select statement, then initialize -  ** p->ppOpenVirtual to point to pOpenVirtual.  If *p is not the right most -  ** statement then p->ppOpenVirtual will have already been initialized -  ** by a prior call to this same procedure.  Pass along the pOpenVirtual -  ** pointer to pPrior, the next statement to our left. -  */ -  if( p->ppOpenVirtual==0 ){ -    p->ppOpenVirtual = &pOpenVirtual; -  } -  pPrior->ppOpenVirtual = p->ppOpenVirtual; -    /* Create the destination temporary table if necessary    */ -  if( eDest==SRT_TempTable ){ +  if( eDest==SRT_VirtualTab ){      assert( p->pEList ); -    sqlite3VdbeAddOp(v, OP_OpenVirtual, iParm, 0); -    assert( nAddr==0 ); -    aAddr[nAddr++] = sqlite3VdbeAddOp(v, OP_SetNumColumns, iParm, 0); +    assert( nSetP2<sizeof(aSetP2)/sizeof(aSetP2[0]) ); +    aSetP2[nSetP2++] = sqlite3VdbeAddOp(v, OP_OpenVirtual, iParm, 0);      eDest = SRT_Table;    }    /* Generate code for the left and right SELECT statements.    */ +  pOrderBy = p->pOrderBy;    switch( p->op ){      case TK_ALL: { -      if( p->pOrderBy==0 ){ +      if( pOrderBy==0 ){          assert( !pPrior->pLimit );          pPrior->pLimit = p->pLimit;          pPrior->pOffset = p->pOffset; @@ -1510,11 +1546,10 @@ static int multiSelect(        int op = 0;      /* One of the SRT_ operations to apply to self */        int priorOp;     /* The SRT_ operation to apply to prior selects */        Expr *pLimit, *pOffset; /* Saved values of p->nLimit and p->nOffset */ -      ExprList *pOrderBy;     /* The ORDER BY clause for the right SELECT */        int addr;        priorOp = p->op==TK_ALL ? SRT_Table : SRT_Union; -      if( eDest==priorOp && p->pOrderBy==0 && !p->pLimit && !p->pOffset ){ +      if( eDest==priorOp && pOrderBy==0 && !p->pLimit && !p->pOffset ){          /* We can reuse a temporary table generated by a SELECT to our          ** right.          */ @@ -1524,20 +1559,20 @@ static int multiSelect(          ** intermediate results.          */          unionTab = pParse->nTab++; -        if( p->pOrderBy  -        && matchOrderbyToColumn(pParse, p, p->pOrderBy, unionTab, 1) ){ +        if( pOrderBy && matchOrderbyToColumn(pParse, p, pOrderBy, unionTab,1) ){            rc = 1;            goto multi_select_end;          }          addr = sqlite3VdbeAddOp(v, OP_OpenVirtual, unionTab, 0); -        if( p->op!=TK_ALL ){ -          rc = multiSelectOpenVirtualAddr(p, addr); -          if( rc!=SQLITE_OK ){ -            goto multi_select_end; -          } +        if( priorOp==SRT_Table ){ +          assert( nSetP2<sizeof(aSetP2)/sizeof(aSetP2[0]) ); +          aSetP2[nSetP2++] = addr; +        }else{ +          assert( p->addrOpenVirt[0] == -1 ); +          p->addrOpenVirt[0] = addr; +          p->pRightmost->usesVirt = 1;          } -	assert( nAddr<sizeof(aAddr)/sizeof(aAddr[0]) ); -        aAddr[nAddr++] = sqlite3VdbeAddOp(v, OP_SetNumColumns, unionTab, 0); +        createSortingIndex(pParse, p, pOrderBy);          assert( p->pEList );        } @@ -1557,8 +1592,8 @@ static int multiSelect(           case TK_ALL:     op = SRT_Table;    break;        }        p->pPrior = 0; -      pOrderBy = p->pOrderBy;        p->pOrderBy = 0; +      p->disallowOrderBy = pOrderBy!=0;        pLimit = p->pLimit;        p->pLimit = 0;        pOffset = p->pOffset; @@ -1591,7 +1626,7 @@ static int multiSelect(          computeLimitRegisters(pParse, p);          iStart = sqlite3VdbeCurrentAddr(v);          rc = selectInnerLoop(pParse, p, p->pEList, unionTab, p->pEList->nExpr, -                             p->pOrderBy, -1, eDest, iParm,  +                             pOrderBy, -1, eDest, iParm,                                iCont, iBreak, 0);          if( rc ){            rc = 1; @@ -1616,18 +1651,16 @@ static int multiSelect(        */        tab1 = pParse->nTab++;        tab2 = pParse->nTab++; -      if( p->pOrderBy && matchOrderbyToColumn(pParse,p,p->pOrderBy,tab1,1) ){ +      if( pOrderBy && matchOrderbyToColumn(pParse,p,pOrderBy,tab1,1) ){          rc = 1;          goto multi_select_end;        } +      createSortingIndex(pParse, p, pOrderBy);        addr = sqlite3VdbeAddOp(v, OP_OpenVirtual, tab1, 0); -      rc = multiSelectOpenVirtualAddr(p, addr); -      if( rc!=SQLITE_OK ){ -        goto multi_select_end; -      } -      assert( nAddr<sizeof(aAddr)/sizeof(aAddr[0]) ); -      aAddr[nAddr++] = sqlite3VdbeAddOp(v, OP_SetNumColumns, tab1, 0); +      assert( p->addrOpenVirt[0] == -1 ); +      p->addrOpenVirt[0] = addr; +      p->pRightmost->usesVirt = 1;        assert( p->pEList );        /* Code the SELECTs to our left into temporary table "tab1". @@ -1640,12 +1673,8 @@ static int multiSelect(        /* Code the current SELECT into temporary table "tab2"        */        addr = sqlite3VdbeAddOp(v, OP_OpenVirtual, tab2, 0); -      rc = multiSelectOpenVirtualAddr(p, addr); -      if( rc!=SQLITE_OK ){ -        goto multi_select_end; -      } -      assert( nAddr<sizeof(aAddr)/sizeof(aAddr[0]) ); -      aAddr[nAddr++] = sqlite3VdbeAddOp(v, OP_SetNumColumns, tab2, 0); +      assert( p->addrOpenVirt[1] == -1 ); +      p->addrOpenVirt[1] = addr;        p->pPrior = 0;        pLimit = p->pLimit;        p->pLimit = 0; @@ -1674,7 +1703,7 @@ static int multiSelect(        iStart = sqlite3VdbeAddOp(v, OP_RowKey, tab1, 0);        sqlite3VdbeAddOp(v, OP_NotFound, tab2, iCont);        rc = selectInnerLoop(pParse, p, p->pEList, tab1, p->pEList->nExpr, -                             p->pOrderBy, -1, eDest, iParm,  +                             pOrderBy, -1, eDest, iParm,                                iCont, iBreak, 0);        if( rc ){          rc = 1; @@ -1703,9 +1732,8 @@ static int multiSelect(    /* Set the number of columns in temporary tables    */    nCol = p->pEList->nExpr; -  while( nAddr>0 ){ -    nAddr--; -    sqlite3VdbeChangeP2(v, aAddr[nAddr], nCol); +  while( nSetP2 ){ +    sqlite3VdbeChangeP2(v, aSetP2[--nSetP2], nCol);    }    /* Compute collating sequences used by either the ORDER BY clause or @@ -1718,12 +1746,15 @@ static int multiSelect(    ** SELECT might also skip this part if it has no ORDER BY clause and    ** no temp tables are required.    */ -  if( p->pOrderBy || (pOpenVirtual && pOpenVirtual->nId>0) ){ +  if( pOrderBy || p->usesVirt ){      int i;                        /* Loop counter */      KeyInfo *pKeyInfo;            /* Collating sequence for the result set */ +    Select *pLoop;                /* For looping through SELECT statements */ +    CollSeq **apColl; +    CollSeq **aCopy; -    assert( p->ppOpenVirtual == &pOpenVirtual ); -    pKeyInfo = sqliteMalloc(sizeof(*pKeyInfo)+nCol*sizeof(CollSeq*)); +    assert( p->pRightmost==p ); +    pKeyInfo = sqliteMalloc(sizeof(*pKeyInfo)+nCol*2*sizeof(CollSeq*) + nCol);      if( !pKeyInfo ){        rc = SQLITE_NOMEM;        goto multi_select_end; @@ -1732,46 +1763,62 @@ static int multiSelect(      pKeyInfo->enc = pParse->db->enc;      pKeyInfo->nField = nCol; -    for(i=0; i<nCol; i++){ -      pKeyInfo->aColl[i] = multiSelectCollSeq(pParse, p, i); -      if( !pKeyInfo->aColl[i] ){ -        pKeyInfo->aColl[i] = pParse->db->pDfltColl; +    for(i=0, apColl=pKeyInfo->aColl; i<nCol; i++, apColl++){ +      *apColl = multiSelectCollSeq(pParse, p, i); +      if( 0==*apColl ){ +        *apColl = pParse->db->pDfltColl;        }      } -    for(i=0; pOpenVirtual && i<pOpenVirtual->nId; i++){ -      int p3type = (i==0?P3_KEYINFO_HANDOFF:P3_KEYINFO); -      int addr = pOpenVirtual->a[i].idx; -      sqlite3VdbeChangeP3(v, addr, (char *)pKeyInfo, p3type); +    for(pLoop=p; pLoop; pLoop=pLoop->pPrior){ +      for(i=0; i<2; i++){ +        int addr = pLoop->addrOpenVirt[i]; +        if( addr<0 ){ +          /* If [0] is unused then [1] is also unused.  So we can +          ** always safely abort as soon as the first unused slot is found */ +          assert( pLoop->addrOpenVirt[1]<0 ); +          break; +        } +        sqlite3VdbeChangeP2(v, addr, nCol); +        sqlite3VdbeChangeP3(v, addr, (char*)pKeyInfo, P3_KEYINFO); +      }      } -    if( p->pOrderBy ){ -      struct ExprList_item *pOrderByTerm = p->pOrderBy->a; -      for(i=0; i<p->pOrderBy->nExpr; i++, pOrderByTerm++){ -        Expr *pExpr = pOrderByTerm->pExpr; -        char *zName = pOrderByTerm->zName; +    if( pOrderBy ){ +      struct ExprList_item *pOTerm = pOrderBy->a; +      int nExpr = pOrderBy->nExpr; +      int addr; +      u8 *pSortOrder; + +      aCopy = (CollSeq**)&pKeyInfo[1]; +      pSortOrder = pKeyInfo->aSortOrder = (u8*)&aCopy[nExpr]; +      memcpy(aCopy, pKeyInfo->aColl, nCol*sizeof(CollSeq*)); +      apColl = pKeyInfo->aColl; +      for(i=0; i<pOrderBy->nExpr; i++, pOTerm++, apColl++, pSortOrder++){ +        Expr *pExpr = pOTerm->pExpr; +        char *zName = pOTerm->zName;          assert( pExpr->op==TK_COLUMN && pExpr->iColumn<nCol ); -        /* assert( !pExpr->pColl ); */          if( zName ){ -          pExpr->pColl = sqlite3LocateCollSeq(pParse, zName, -1); +          *apColl = sqlite3LocateCollSeq(pParse, zName, -1);          }else{ -          pExpr->pColl = pKeyInfo->aColl[pExpr->iColumn]; +          *apColl = aCopy[pExpr->iColumn];          } +        *pSortOrder = pOTerm->sortOrder;        } +      assert( p->pRightmost==p ); +      assert( p->addrOpenVirt[2]>=0 ); +      addr = p->addrOpenVirt[2]; +      sqlite3VdbeChangeP2(v, addr, p->pEList->nExpr+2); +      pKeyInfo->nField = pOrderBy->nExpr; +      sqlite3VdbeChangeP3(v, addr, (char*)pKeyInfo, P3_KEYINFO_HANDOFF); +      pKeyInfo = 0;        generateSortTail(pParse, p, v, p->pEList->nExpr, eDest, iParm);      } -    if( !pOpenVirtual ){ -      /* This happens for UNION ALL ... ORDER BY */ -      sqliteFree(pKeyInfo); -    } +    sqliteFree(pKeyInfo);    }  multi_select_end: -  if( pOpenVirtual ){ -    sqlite3IdListDelete(pOpenVirtual); -  } -  p->ppOpenVirtual = 0;    return rc;  }  #endif /* SQLITE_OMIT_COMPOUND_SELECT */ @@ -1947,7 +1994,7 @@ static int flattenSubquery(       return 0;    }    if( p->isDistinct && subqueryIsAgg ) return 0; -  if( p->pOrderBy && pSub->pOrderBy ) return 0; +  if( (p->disallowOrderBy || p->pOrderBy) && pSub->pOrderBy ) return 0;    /* Restriction 3:  If the subquery is a join, make sure the subquery is     ** not used as the right operand of an outer join.  Examples of why this @@ -2175,9 +2222,8 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){    /* If the output is destined for a temporary table, open that table.    */ -  if( eDest==SRT_TempTable ){ -    sqlite3VdbeAddOp(v, OP_OpenVirtual, iParm, 0); -    sqlite3VdbeAddOp(v, OP_SetNumColumns, iParm, 1); +  if( eDest==SRT_VirtualTab ){ +    sqlite3VdbeAddOp(v, OP_OpenVirtual, iParm, 1);    }    /* Generating code to find the min or the max.  Basically all we have @@ -2286,6 +2332,7 @@ int sqlite3SelectResolve(    ExprList *pEList;          /* Result set. */    int i;                     /* For-loop variable used in multiple places */    NameContext sNC;           /* Local name-context */ +  ExprList *pGroupBy;        /* The group by clause */    /* If this routine has run before, return immediately. */    if( p->isResolved ){ @@ -2329,18 +2376,6 @@ int sqlite3SelectResolve(    sNC.pSrcList = p->pSrc;    sNC.pNext = pOuterNC; -  /* NameContext.nDepth stores the depth of recursion for this query. For -  ** an outer query (e.g. SELECT * FROM sqlite_master) this is 1. For -  ** a subquery it is 2. For a subquery of a subquery, 3. And so on.  -  ** Parse.nMaxDepth is the maximum depth for any subquery resolved so -  ** far. This is used to determine the number of aggregate contexts -  ** required at runtime. -  */ -  sNC.nDepth = (pOuterNC?pOuterNC->nDepth+1:1); -  if( sNC.nDepth>pParse->nMaxDepth ){ -    pParse->nMaxDepth = sNC.nDepth; -  } -    /* Resolve names in the result set. */    pEList = p->pEList;    if( !pEList ) return SQLITE_ERROR; @@ -2355,7 +2390,8 @@ int sqlite3SelectResolve(    ** expression, do not allow aggregates in any of the other expressions.    */    assert( !p->isAgg ); -  if( p->pGroupBy || sNC.hasAgg ){ +  pGroupBy = p->pGroupBy; +  if( pGroupBy || sNC.hasAgg ){      p->isAgg = 1;    }else{      sNC.allowAgg = 0; @@ -2363,7 +2399,7 @@ int sqlite3SelectResolve(    /* If a HAVING clause is present, then there must be a GROUP BY clause.    */ -  if( p->pHaving && !p->pGroupBy ){ +  if( p->pHaving && !pGroupBy ){      sqlite3ErrorMsg(pParse, "a GROUP BY clause is required before HAVING");      return SQLITE_ERROR;    } @@ -2380,49 +2416,128 @@ int sqlite3SelectResolve(    if( sqlite3ExprResolveNames(&sNC, p->pWhere) ||        sqlite3ExprResolveNames(&sNC, p->pHaving) ||        processOrderGroupBy(&sNC, p->pOrderBy, "ORDER") || -      processOrderGroupBy(&sNC, p->pGroupBy, "GROUP") +      processOrderGroupBy(&sNC, pGroupBy, "GROUP")    ){      return SQLITE_ERROR;    } +  /* Make sure the GROUP BY clause does not contain aggregate functions. +  */ +  if( pGroupBy ){ +    struct ExprList_item *pItem; +   +    for(i=0, pItem=pGroupBy->a; i<pGroupBy->nExpr; i++, pItem++){ +      if( ExprHasProperty(pItem->pExpr, EP_Agg) ){ +        sqlite3ErrorMsg(pParse, "aggregate functions are not allowed in " +            "the GROUP BY clause"); +        return SQLITE_ERROR; +      } +    } +  } +    return SQLITE_OK;  }  /* -** An instance of the following struct is used by sqlite3Select() -** to save aggregate related information from the Parse object -** at the start of each call and to restore it at the end. See -** saveAggregateInfo() and restoreAggregateInfo(). -*/  -struct AggregateInfo { -  int nAgg; -  AggExpr *aAgg; -}; -typedef struct AggregateInfo AggregateInfo; - -/*  -** Copy aggregate related information from the Parse structure -** into the AggregateInfo structure. Zero the aggregate related -** values in the Parse struct. +** Reset the aggregate accumulator. +** +** The aggregate accumulator is a set of memory cells that hold +** intermediate results while calculating an aggregate.  This +** routine simply stores NULLs in all of those memory cells. +*/ +static void resetAccumulator(Parse *pParse, AggInfo *pAggInfo){ +  Vdbe *v = pParse->pVdbe; +  int i; +  struct AggInfo_func *pFunc; +  if( pAggInfo->nFunc+pAggInfo->nColumn==0 ){ +    return; +  } +  for(i=0; i<pAggInfo->nColumn; i++){ +    sqlite3VdbeAddOp(v, OP_MemNull, pAggInfo->aCol[i].iMem, 0); +  } +  for(pFunc=pAggInfo->aFunc, i=0; i<pAggInfo->nFunc; i++, pFunc++){ +    sqlite3VdbeAddOp(v, OP_MemNull, pFunc->iMem, 0); +    if( pFunc->iDistinct>=0 ){ +      Expr *pE = pFunc->pExpr; +      if( pE->pList==0 || pE->pList->nExpr!=1 ){ +        sqlite3ErrorMsg(pParse, "DISTINCT in aggregate must be followed " +           "by an expression"); +        pFunc->iDistinct = -1; +      }else{ +        KeyInfo *pKeyInfo = keyInfoFromExprList(pParse, pE->pList); +        sqlite3VdbeOp3(v, OP_OpenVirtual, pFunc->iDistinct, 0,  +                          (char*)pKeyInfo, P3_KEYINFO_HANDOFF); +      } +    } +  } +} + +/* +** Invoke the OP_AggFinalize opcode for every aggregate function +** in the AggInfo structure.  */ -static void saveAggregateInfo(Parse *pParse, AggregateInfo *pInfo){ -  pInfo->aAgg = pParse->aAgg; -  pInfo->nAgg = pParse->nAgg; -  pParse->aAgg = 0; -  pParse->nAgg = 0; +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); +  }  }  /* -** Copy aggregate related information from the AggregateInfo struct -** back into the Parse structure. The aggregate related information -** currently stored in the Parse structure is deleted. +** Update the accumulator memory cells for an aggregate based on +** the current cursor position.  */ -static void restoreAggregateInfo(Parse *pParse, AggregateInfo *pInfo){ -  sqliteFree(pParse->aAgg); -  pParse->aAgg = pInfo->aAgg; -  pParse->nAgg = pInfo->nAgg; +static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){ +  Vdbe *v = pParse->pVdbe; +  int i; +  struct AggInfo_func *pF; +  struct AggInfo_col *pC; + +  pAggInfo->directMode = 1; +  for(i=0, pF=pAggInfo->aFunc; i<pAggInfo->nFunc; i++, pF++){ +    int nArg; +    int addrNext = 0; +    ExprList *pList = pF->pExpr->pList; +    if( pList ){ +      nArg = pList->nExpr; +      sqlite3ExprCodeExprList(pParse, pList); +    }else{ +      nArg = 0; +    } +    if( pF->iDistinct>=0 ){ +      addrNext = sqlite3VdbeMakeLabel(v); +      assert( nArg==1 ); +      codeDistinct(v, pF->iDistinct, addrNext, 1, 2); +    } +    if( pF->pFunc->needCollSeq ){ +      CollSeq *pColl = 0; +      struct ExprList_item *pItem; +      int j; +      for(j=0, pItem=pList->a; !pColl && j<pList->nExpr; j++, pItem++){ +        pColl = sqlite3ExprCollSeq(pParse, pItem->pExpr); +      } +      if( !pColl ){ +        pColl = pParse->db->pDfltColl; +      } +      sqlite3VdbeOp3(v, OP_CollSeq, 0, 0, (char *)pColl, P3_COLLSEQ); +    } +    sqlite3VdbeOp3(v, OP_AggStep, pF->iMem, nArg, (void*)pF->pFunc, P3_FUNCDEF); +    if( addrNext ){ +      sqlite3VdbeResolveLabel(v, addrNext); +    } +  } +  for(i=0, pC=pAggInfo->aCol; i<pAggInfo->nAccumulator; i++, pC++){ +    sqlite3ExprCode(pParse, pC->pExpr); +    sqlite3VdbeAddOp(v, OP_MemStore, pC->iMem, 1); +  } +  pAggInfo->directMode = 0;  } -   + +  /*  ** Generate code for the given SELECT statement.  ** @@ -2485,9 +2600,9 @@ int sqlite3Select(    int *pParentAgg,       /* True if pParent uses aggregate functions */    char *aff              /* If eDest is SRT_Union, the affinity string */  ){ -  int i; -  WhereInfo *pWInfo; -  Vdbe *v; +  int i, j;              /* Loop counters */ +  WhereInfo *pWInfo;     /* Return from sqlite3WhereBegin() */ +  Vdbe *v;               /* The virtual machine under construction */    int isAgg;             /* True for select lists like "count(*)" */    ExprList *pEList;      /* List of columns to extract. */    SrcList *pTabList;     /* List of tables to select from */ @@ -2498,22 +2613,29 @@ int sqlite3Select(    int isDistinct;        /* True if the DISTINCT keyword is present */    int distinct;          /* Table to use for the distinct set */    int rc = 1;            /* Value to return from this function */ -  AggregateInfo sAggInfo; +  int addrSortIndex;     /* Address of an OP_OpenVirtual instruction */ +  AggInfo sAggInfo;      /* Information used by aggregate queries */    if( sqlite3_malloc_failed || pParse->nErr || p==0 ) return 1;    if( sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 1; +  memset(&sAggInfo, 0, sizeof(sAggInfo));  #ifndef SQLITE_OMIT_COMPOUND_SELECT    /* If there is are a sequence of queries, do the earlier ones first.    */    if( p->pPrior ){ +    if( p->pRightmost==0 ){ +      Select *pLoop; +      for(pLoop=p; pLoop; pLoop=pLoop->pPrior){ +        pLoop->pRightmost = p; +      } +    }      return multiSelect(pParse, p, eDest, iParm, aff);    }  #endif -  saveAggregateInfo(pParse, &sAggInfo);    pOrderBy = p->pOrderBy; -  if( eDest==SRT_Union || eDest==SRT_Except || eDest==SRT_Discard ){ +  if( IgnorableOrderby(eDest) ){      p->pOrderBy = 0;    }    if( sqlite3SelectResolve(pParse, p, 0) ){ @@ -2552,14 +2674,8 @@ int sqlite3Select(    /* ORDER BY is ignored for some destinations.    */ -  switch( eDest ){ -    case SRT_Union: -    case SRT_Except: -    case SRT_Discard: -      pOrderBy = 0; -      break; -    default: -      break; +  if( IgnorableOrderby(eDest) ){ +    pOrderBy = 0;    }    /* Begin generating code. @@ -2580,23 +2696,24 @@ int sqlite3Select(    for(i=0; i<pTabList->nSrc; i++){      const char *zSavedAuthContext = 0;      int needRestoreContext; +    struct SrcList_item *pItem = &pTabList->a[i]; -    if( pTabList->a[i].pSelect==0 ) continue; -    if( pTabList->a[i].zName!=0 ){ +    if( pItem->pSelect==0 ) continue; +    if( pItem->zName!=0 ){        zSavedAuthContext = pParse->zAuthContext; -      pParse->zAuthContext = pTabList->a[i].zName; +      pParse->zAuthContext = pItem->zName;        needRestoreContext = 1;      }else{        needRestoreContext = 0;      } -    sqlite3Select(pParse, pTabList->a[i].pSelect, SRT_TempTable,  -                 pTabList->a[i].iCursor, p, i, &isAgg, 0); +    sqlite3Select(pParse, pItem->pSelect, SRT_VirtualTab,  +                 pItem->iCursor, p, i, &isAgg, 0);      if( needRestoreContext ){        pParse->zAuthContext = zSavedAuthContext;      }      pTabList = p->pSrc;      pWhere = p->pWhere; -    if( eDest!=SRT_Union && eDest!=SRT_Except && eDest!=SRT_Discard ){ +    if( !IgnorableOrderby(eDest) ){        pOrderBy = p->pOrderBy;      }      pGroupBy = p->pGroupBy; @@ -2625,18 +2742,32 @@ int sqlite3Select(  #endif    /* If there is an ORDER BY clause, resolve any collation sequences -  ** names that have been explicitly specified. +  ** names that have been explicitly specified and create a sorting index. +  ** +  ** This sorting index might end up being unused if the data can be  +  ** extracted in pre-sorted order.  If that is the case, then the +  ** OP_OpenVirtual instruction will be changed to an OP_Noop once +  ** we figure out that the sorting index is not needed.  The addrSortIndex +  ** variable is used to facilitate that change.    */    if( pOrderBy ){ -    for(i=0; i<pOrderBy->nExpr; i++){ -      if( pOrderBy->a[i].zName ){ -        pOrderBy->a[i].pExpr->pColl =  -            sqlite3LocateCollSeq(pParse, pOrderBy->a[i].zName, -1); +    struct ExprList_item *pTerm; +    KeyInfo *pKeyInfo; +    for(i=0, pTerm=pOrderBy->a; i<pOrderBy->nExpr; i++, pTerm++){ +      if( pTerm->zName ){ +        pTerm->pExpr->pColl = sqlite3LocateCollSeq(pParse, pTerm->zName, -1);        }      }      if( pParse->nErr ){        goto select_end;      } +    pKeyInfo = keyInfoFromExprList(pParse, pOrderBy); +    pOrderBy->iECursor = pParse->nTab++; +    p->addrOpenVirt[2] = addrSortIndex = +       sqlite3VdbeOp3(v, OP_OpenVirtual, pOrderBy->iECursor, pOrderBy->nExpr+2,  +                        (char*)pKeyInfo, P3_KEYINFO_HANDOFF); +  }else{ +    addrSortIndex = -1;    }    /* Set the limiter. @@ -2645,184 +2776,320 @@ int sqlite3Select(    /* If the output is destined for a temporary table, open that table.    */ -  if( eDest==SRT_TempTable ){ -    sqlite3VdbeAddOp(v, OP_OpenVirtual, iParm, 0); -    sqlite3VdbeAddOp(v, OP_SetNumColumns, iParm, pEList->nExpr); +  if( eDest==SRT_VirtualTab ){ +    sqlite3VdbeAddOp(v, OP_OpenVirtual, iParm, pEList->nExpr);    } -  /* Do an analysis of aggregate expressions. -  */ -  if( isAgg || pGroupBy ){ -    NameContext sNC; -    memset(&sNC, 0, sizeof(sNC)); -    sNC.pParse = pParse; -    sNC.pSrcList = pTabList; - -    assert( pParse->nAgg==0 ); -    isAgg = 1; -    for(i=0; i<pEList->nExpr; i++){ -      if( sqlite3ExprAnalyzeAggregates(&sNC, pEList->a[i].pExpr) ){ -        goto select_end; -      } -    } -    if( pGroupBy ){ -      for(i=0; i<pGroupBy->nExpr; i++){ -        if( sqlite3ExprAnalyzeAggregates(&sNC, pGroupBy->a[i].pExpr) ){ -          goto select_end; -        } -      } -    } -    if( pHaving && sqlite3ExprAnalyzeAggregates(&sNC, pHaving) ){ -      goto select_end; -    } -    if( pOrderBy ){ -      for(i=0; i<pOrderBy->nExpr; i++){ -        if( sqlite3ExprAnalyzeAggregates(&sNC, pOrderBy->a[i].pExpr) ){ -          goto select_end; -        } -      } -    } -  } - -  /* Reset the aggregator -  */ -  if( isAgg ){ -    int addr = sqlite3VdbeAddOp(v, OP_AggReset, (pGroupBy?0:1), pParse->nAgg); -    for(i=0; i<pParse->nAgg; i++){ -      FuncDef *pFunc; -      if( (pFunc = pParse->aAgg[i].pFunc)!=0 && pFunc->xFinalize!=0 ){ -        int nExpr = 0; -#ifdef SQLITE_SSE -        Expr *pAggExpr = pParse->aAgg[i].pExpr; -        if( pAggExpr && pAggExpr->pList ){ -          nExpr = pAggExpr->pList->nExpr; -        } -#endif -        sqlite3VdbeOp3(v, OP_AggInit, nExpr, i, (char*)pFunc, P3_FUNCDEF); -      } -    } -    if( pGroupBy ){ -      int sz = sizeof(KeyInfo) + pGroupBy->nExpr*sizeof(CollSeq*); -      KeyInfo *pKey = (KeyInfo *)sqliteMalloc(sz); -      if( 0==pKey ){ -        goto select_end; -      } -      pKey->enc = pParse->db->enc; -      pKey->nField = pGroupBy->nExpr; -      for(i=0; i<pGroupBy->nExpr; i++){ -        pKey->aColl[i] = sqlite3ExprCollSeq(pParse, pGroupBy->a[i].pExpr); -        if( !pKey->aColl[i] ){ -          pKey->aColl[i] = pParse->db->pDfltColl; -        } -      } -      sqlite3VdbeChangeP3(v, addr, (char *)pKey, P3_KEYINFO_HANDOFF); -    } -  }    /* Initialize the memory cell to NULL for SRT_Mem or 0 for SRT_Exists    */ -  if( eDest==SRT_Mem || eDest==SRT_Exists ){ -    sqlite3VdbeAddOp(v, eDest==SRT_Mem ? OP_Null : OP_Integer, 0, 0); -    sqlite3VdbeAddOp(v, OP_MemStore, iParm, 1); +  if( eDest==SRT_Mem ){ +    sqlite3VdbeAddOp(v, OP_MemNull, iParm, 0); +  }else if( eDest==SRT_Exists ){ +    sqlite3VdbeAddOp(v, OP_MemInt, 0, iParm);    } -  /* Open a temporary table to use for the distinct set. +  /* Open a virtual index to use for the distinct set.    */    if( isDistinct ){ +    KeyInfo *pKeyInfo;      distinct = pParse->nTab++; -    openVirtualIndex(pParse, p, distinct); +    pKeyInfo = keyInfoFromExprList(pParse, p->pEList); +    sqlite3VdbeOp3(v, OP_OpenVirtual, distinct, 0,  +                        (char*)pKeyInfo, P3_KEYINFO_HANDOFF);    }else{      distinct = -1;    } -  /* Begin the database scan -  */ -  pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, -                             pGroupBy ? 0 : &pOrderBy); -  if( pWInfo==0 ) goto select_end; +  /* Aggregate and non-aggregate queries are handled differently */ +  if( !isAgg && pGroupBy==0 ){ +    /* This case is for non-aggregate queries +    ** Begin the database scan +    */ +    pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pOrderBy); +    if( pWInfo==0 ) goto select_end; -  /* Use the standard inner loop if we are not dealing with -  ** aggregates -  */ -  if( !isAgg ){ +    /* If sorting index that was created by a prior OP_OpenVirtual  +    ** instruction ended up not being needed, then change the OP_OpenVirtual +    ** into an OP_Noop. +    */ +    if( addrSortIndex>=0 && pOrderBy==0 ){ +      uncreateSortingIndex(pParse, addrSortIndex); +      p->addrOpenVirt[2] = -1; +    } + +    /* Use the standard inner loop +    */      if( selectInnerLoop(pParse, p, pEList, 0, 0, pOrderBy, distinct, eDest,                      iParm, pWInfo->iContinue, pWInfo->iBreak, aff) ){         goto select_end;      } -  } -  /* If we are dealing with aggregates, then do the special aggregate -  ** processing.   -  */ -  else{ -    AggExpr *pAgg; -    int lbl1 = 0; -    pParse->fillAgg = 1; +    /* End the database scan loop. +    */ +    sqlite3WhereEnd(pWInfo); +  }else{ +    /* This is the processing for aggregate queries */ +    NameContext sNC;    /* Name context for processing aggregate information */ +    int iAMem;          /* First Mem address for storing current GROUP BY */ +    int iBMem;          /* First Mem address for previous GROUP BY */ +    int iUseFlag;       /* Mem address holding flag indicating that at least +                        ** one row of the input to the aggregator has been +                        ** processed */ +    int iAbortFlag;     /* Mem address which causes query abort if positive */ +    int groupBySort;    /* Rows come from source in GROUP BY order */ + + +    /* The following variables hold addresses or labels for parts of the +    ** virtual machine program we are putting together */ +    int addrOutputRow;      /* Start of subroutine that outputs a result row */ +    int addrSetAbort;       /* Set the abort flag and return */ +    int addrInitializeLoop; /* Start of code that initializes the input loop */ +    int addrTopOfLoop;      /* Top of the input loop */ +    int addrGroupByChange;  /* Code that runs when any GROUP BY term changes */ +    int addrProcessRow;     /* Code to process a single input row */ +    int addrEnd;            /* End of all processing */ +    int addrSortingIdx;     /* The OP_OpenVirtual for the sorting index */ +    int addrReset;          /* Subroutine for resetting the accumulator */ + +    addrEnd = sqlite3VdbeMakeLabel(v); + +    /* Convert TK_COLUMN nodes into TK_AGG_COLUMN and make entries in +    ** sAggInfo for all TK_AGG_FUNCTION nodes in expressions of the +    ** SELECT statement. +    */ +    memset(&sNC, 0, sizeof(sNC)); +    sNC.pParse = pParse; +    sNC.pSrcList = pTabList; +    sNC.pAggInfo = &sAggInfo; +    sAggInfo.nSortingColumn = pGroupBy ? pGroupBy->nExpr+1 : 0; +    sAggInfo.pGroupBy = pGroupBy; +    if( sqlite3ExprAnalyzeAggList(&sNC, pEList) ){ +      goto select_end; +    } +    if( sqlite3ExprAnalyzeAggList(&sNC, pOrderBy) ){ +      goto select_end; +    } +    if( pHaving && sqlite3ExprAnalyzeAggregates(&sNC, pHaving) ){ +      goto select_end; +    } +    sAggInfo.nAccumulator = sAggInfo.nColumn; +    for(i=0; i<sAggInfo.nFunc; i++){ +      if( sqlite3ExprAnalyzeAggList(&sNC, sAggInfo.aFunc[i].pExpr->pList) ){ +        goto select_end; +      } +    } +    if( sqlite3_malloc_failed ) goto select_end; + +    /* Processing for aggregates with GROUP BY is very different and +    ** much more complex tha aggregates without a GROUP BY. +    */      if( pGroupBy ){ -      sqlite3ExprCodeExprList(pParse, pGroupBy); -      /* No affinity string is attached to the following OP_MakeRecord  -      ** because we do not need to do any coercion of datatypes. */ -      sqlite3VdbeAddOp(v, OP_MakeRecord, pGroupBy->nExpr, 0); -      lbl1 = sqlite3VdbeMakeLabel(v); -      sqlite3VdbeAddOp(v, OP_AggFocus, 0, lbl1); -    } -    for(i=0, pAgg=pParse->aAgg; i<pParse->nAgg; i++, pAgg++){ -      if( pAgg->isAgg ) continue; -      sqlite3ExprCode(pParse, pAgg->pExpr); -      sqlite3VdbeAddOp(v, OP_AggSet, 0, i); -    } -    pParse->fillAgg = 0; -    if( lbl1<0 ){ -      sqlite3VdbeResolveLabel(v, lbl1); -    } -    for(i=0, pAgg=pParse->aAgg; i<pParse->nAgg; i++, pAgg++){ -      Expr *pE; -      int nExpr; -      FuncDef *pDef; -      if( !pAgg->isAgg ) continue; -      assert( pAgg->pFunc!=0 ); -      assert( pAgg->pFunc->xStep!=0 ); -      pDef = pAgg->pFunc; -      pE = pAgg->pExpr; -      assert( pE!=0 ); -      assert( pE->op==TK_AGG_FUNCTION ); -      nExpr = sqlite3ExprCodeExprList(pParse, pE->pList); -      sqlite3VdbeAddOp(v, OP_Integer, i, 0); -      if( pDef->needCollSeq ){ -        CollSeq *pColl = 0; -        int j; -        for(j=0; !pColl && j<nExpr; j++){ -          pColl = sqlite3ExprCollSeq(pParse, pE->pList->a[j].pExpr); +      KeyInfo *pKeyInfo;  /* Keying information for the group by clause */ + +      /* Create labels that we will be needing +      */ +      +      addrInitializeLoop = sqlite3VdbeMakeLabel(v); +      addrGroupByChange = sqlite3VdbeMakeLabel(v); +      addrProcessRow = sqlite3VdbeMakeLabel(v); + +      /* If there is a GROUP BY clause we might need a sorting index to +      ** implement it.  Allocate that sorting index now.  If it turns out +      ** that we do not need it after all, the OpenVirtual instruction +      ** will be converted into a Noop.   +      */ +      sAggInfo.sortingIdx = pParse->nTab++; +      pKeyInfo = keyInfoFromExprList(pParse, pGroupBy); +      addrSortingIdx = +          sqlite3VdbeOp3(v, OP_OpenVirtual, sAggInfo.sortingIdx, +                         sAggInfo.nSortingColumn, +                         (char*)pKeyInfo, P3_KEYINFO_HANDOFF); + +      /* Initialize memory locations used by GROUP BY aggregate processing +      */ +      iUseFlag = pParse->nMem++; +      iAbortFlag = pParse->nMem++; +      iAMem = pParse->nMem; +      pParse->nMem += pGroupBy->nExpr; +      iBMem = pParse->nMem; +      pParse->nMem += pGroupBy->nExpr; +      sqlite3VdbeAddOp(v, OP_MemInt, 0, iAbortFlag); +      VdbeComment((v, "# clear abort flag")); +      sqlite3VdbeAddOp(v, OP_MemInt, 0, iUseFlag); +      VdbeComment((v, "# indicate accumulator empty")); +      sqlite3VdbeAddOp(v, OP_Goto, 0, addrInitializeLoop); + +      /* Generate a subroutine that outputs a single row of the result +      ** set.  This subroutine first looks at the iUseFlag.  If iUseFlag +      ** is less than or equal to zero, the subroutine is a no-op.  If +      ** the processing calls for the query to abort, this subroutine +      ** increments the iAbortFlag memory location before returning in +      ** order to signal the caller to abort. +      */ +      addrSetAbort = sqlite3VdbeCurrentAddr(v); +      sqlite3VdbeAddOp(v, OP_MemInt, 1, iAbortFlag); +      VdbeComment((v, "# set abort flag")); +      sqlite3VdbeAddOp(v, OP_Return, 0, 0); +      addrOutputRow = sqlite3VdbeCurrentAddr(v); +      sqlite3VdbeAddOp(v, OP_IfMemPos, iUseFlag, addrOutputRow+2); +      VdbeComment((v, "# Groupby result generator entry point")); +      sqlite3VdbeAddOp(v, OP_Return, 0, 0); +      finalizeAggFunctions(pParse, &sAggInfo); +      if( pHaving ){ +        sqlite3ExprIfFalse(pParse, pHaving, addrOutputRow+1, 1); +      } +      rc = selectInnerLoop(pParse, p, p->pEList, 0, 0, pOrderBy, +                           distinct, eDest, iParm,  +                           addrOutputRow+1, addrSetAbort, aff); +      if( rc ){ +        goto select_end; +      } +      sqlite3VdbeAddOp(v, OP_Return, 0, 0); +      VdbeComment((v, "# end groupby result generator")); + +      /* Generate a subroutine that will reset the group-by accumulator +      */ +      addrReset = sqlite3VdbeCurrentAddr(v); +      resetAccumulator(pParse, &sAggInfo); +      sqlite3VdbeAddOp(v, OP_Return, 0, 0); + +      /* Begin a loop that will extract all source rows in GROUP BY order. +      ** This might involve two separate loops with an OP_Sort in between, or +      ** it might be a single loop that uses an index to extract information +      ** in the right order to begin with. +      */ +      sqlite3VdbeResolveLabel(v, addrInitializeLoop); +      sqlite3VdbeAddOp(v, OP_Gosub, 0, addrReset); +      pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pGroupBy); +      if( pWInfo==0 ) goto select_end; +      if( pGroupBy==0 ){ +        /* The optimizer is able to deliver rows in group by order so +        ** we do not have to sort.  The OP_OpenVirtual table will be +        ** cancelled later because we still need to use the pKeyInfo +        */ +        pGroupBy = p->pGroupBy; +        groupBySort = 0; +      }else{ +        /* Rows are coming out in undetermined order.  We have to push +        ** each row into a sorting index, terminate the first loop, +        ** then loop over the sorting index in order to get the output +        ** in sorted order +        */ +        groupBySort = 1; +        sqlite3ExprCodeExprList(pParse, pGroupBy); +        sqlite3VdbeAddOp(v, OP_Sequence, sAggInfo.sortingIdx, 0); +        j = pGroupBy->nExpr+1; +        for(i=0; i<sAggInfo.nColumn; i++){ +          struct AggInfo_col *pCol = &sAggInfo.aCol[i]; +          if( pCol->iSorterColumn<j ) continue; +          if( pCol->iColumn<0 ){ +            sqlite3VdbeAddOp(v, OP_Rowid, pCol->iTable, 0); +          }else{ +            sqlite3VdbeAddOp(v, OP_Column, pCol->iTable, pCol->iColumn); +          } +          j++;          } -        if( !pColl ) pColl = pParse->db->pDfltColl; -        sqlite3VdbeOp3(v, OP_CollSeq, 0, 0, (char *)pColl, P3_COLLSEQ); +        sqlite3VdbeAddOp(v, OP_MakeRecord, j, 0); +        sqlite3VdbeAddOp(v, OP_IdxInsert, sAggInfo.sortingIdx, 0); +        sqlite3WhereEnd(pWInfo); +        sqlite3VdbeAddOp(v, OP_Sort, sAggInfo.sortingIdx, addrEnd); +        VdbeComment((v, "# GROUP BY sort")); +        sAggInfo.useSortingIdx = 1;        } -      sqlite3VdbeOp3(v, OP_AggFunc, 0, nExpr, (char*)pDef, P3_FUNCDEF); -    } -  } -  /* End the database scan loop. -  */ -  sqlite3WhereEnd(pWInfo); +      /* Evaluate the current GROUP BY terms and store in b0, b1, b2... +      ** (b0 is memory location iBMem+0, b1 is iBMem+1, and so forth) +      ** Then compare the current GROUP BY terms against the GROUP BY terms +      ** from the previous row currently stored in a0, a1, a2... +      */ +      addrTopOfLoop = sqlite3VdbeCurrentAddr(v); +      for(j=0; j<pGroupBy->nExpr; j++){ +        if( groupBySort ){ +          sqlite3VdbeAddOp(v, OP_Column, sAggInfo.sortingIdx, j); +        }else{ +          sAggInfo.directMode = 1; +          sqlite3ExprCode(pParse, pGroupBy->a[j].pExpr); +        } +        sqlite3VdbeAddOp(v, OP_MemStore, iBMem+j, j<pGroupBy->nExpr-1); +      } +      for(j=pGroupBy->nExpr-1; j>=0; j--){ +        if( j<pGroupBy->nExpr-1 ){ +          sqlite3VdbeAddOp(v, OP_MemLoad, iBMem+j, 0); +        } +        sqlite3VdbeAddOp(v, OP_MemLoad, iAMem+j, 0); +        if( j==0 ){ +          sqlite3VdbeAddOp(v, OP_Eq, 0x200, addrProcessRow); +        }else{ +          sqlite3VdbeAddOp(v, OP_Ne, 0x200, addrGroupByChange); +        } +        sqlite3VdbeChangeP3(v, -1, (void*)pKeyInfo->aColl[j], P3_COLLSEQ); +      } -  /* If we are processing aggregates, we need to set up a second loop -  ** over all of the aggregate values and process them. -  */ -  if( isAgg ){ -    int endagg = sqlite3VdbeMakeLabel(v); -    int startagg; -    startagg = sqlite3VdbeAddOp(v, OP_AggNext, 0, endagg); -    if( pHaving ){ -      sqlite3ExprIfFalse(pParse, pHaving, startagg, 1); -    } -    if( selectInnerLoop(pParse, p, pEList, 0, 0, pOrderBy, distinct, eDest, -                    iParm, startagg, endagg, aff) ){ -      goto select_end; +      /* Generate code that runs whenever the GROUP BY changes. +      ** Change in the GROUP BY are detected by the previous code +      ** block.  If there were no changes, this block is skipped. +      ** +      ** This code copies current group by terms in b0,b1,b2,... +      ** over to a0,a1,a2.  It then calls the output subroutine +      ** and resets the aggregate accumulator registers in preparation +      ** for the next GROUP BY batch. +      */ +      sqlite3VdbeResolveLabel(v, addrGroupByChange); +      for(j=0; j<pGroupBy->nExpr; j++){ +        sqlite3VdbeAddOp(v, OP_MemMove, iAMem+j, iBMem+j); +      } +      sqlite3VdbeAddOp(v, OP_Gosub, 0, addrOutputRow); +      VdbeComment((v, "# output one row")); +      sqlite3VdbeAddOp(v, OP_IfMemPos, iAbortFlag, addrEnd); +      VdbeComment((v, "# check abort flag")); +      sqlite3VdbeAddOp(v, OP_Gosub, 0, addrReset); +      VdbeComment((v, "# reset accumulator")); + +      /* Update the aggregate accumulators based on the content of +      ** the current row +      */ +      sqlite3VdbeResolveLabel(v, addrProcessRow); +      updateAccumulator(pParse, &sAggInfo); +      sqlite3VdbeAddOp(v, OP_MemInt, 1, iUseFlag); +      VdbeComment((v, "# indicate data in accumulator")); + +      /* End of the loop +      */ +      if( groupBySort ){ +        sqlite3VdbeAddOp(v, OP_Next, sAggInfo.sortingIdx, addrTopOfLoop); +      }else{ +        sqlite3WhereEnd(pWInfo); +        uncreateSortingIndex(pParse, addrSortingIdx); +      } + +      /* Output the final row of result +      */ +      sqlite3VdbeAddOp(v, OP_Gosub, 0, addrOutputRow); +      VdbeComment((v, "# output final row")); +       +    } /* endif pGroupBy */ +    else { +      /* This case runs if the aggregate has no GROUP BY clause.  The +      ** processing is much simpler since there is only a single row +      ** of output. +      */ +      resetAccumulator(pParse, &sAggInfo); +      pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0); +      if( pWInfo==0 ) goto select_end; +      updateAccumulator(pParse, &sAggInfo); +      sqlite3WhereEnd(pWInfo); +      finalizeAggFunctions(pParse, &sAggInfo); +      pOrderBy = 0; +      if( pHaving ){ +        sqlite3ExprIfFalse(pParse, pHaving, addrEnd, 1); +      } +      selectInnerLoop(pParse, p, p->pEList, 0, 0, 0, -1,  +                      eDest, iParm, addrEnd, addrEnd, aff);      } -    sqlite3VdbeAddOp(v, OP_Goto, 0, startagg); -    sqlite3VdbeResolveLabel(v, endagg); -    sqlite3VdbeAddOp(v, OP_Noop, 0, 0); -  } +    sqlite3VdbeResolveLabel(v, addrEnd); +     +  } /* endif aggregate query */    /* If there is an ORDER BY clause, then we need to sort the results    ** and send them to the callback one by one. @@ -2854,6 +3121,7 @@ int sqlite3Select(    ** successful coding of the SELECT.    */  select_end: -  restoreAggregateInfo(pParse, &sAggInfo); +  sqliteFree(sAggInfo.aCol); +  sqliteFree(sAggInfo.aFunc);    return rc;  } | 
