diff options
Diffstat (limited to 'ext/pdo_sqlite/sqlite/src/expr.c')
| -rw-r--r-- | ext/pdo_sqlite/sqlite/src/expr.c | 244 | 
1 files changed, 173 insertions, 71 deletions
| diff --git a/ext/pdo_sqlite/sqlite/src/expr.c b/ext/pdo_sqlite/sqlite/src/expr.c index a83b9d78cf..1276fe9f6a 100644 --- a/ext/pdo_sqlite/sqlite/src/expr.c +++ b/ext/pdo_sqlite/sqlite/src/expr.c @@ -355,7 +355,7 @@ void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){        pExpr->iTable = ++pParse->nVar;        if( pParse->nVarExpr>=pParse->nVarExprAlloc-1 ){          pParse->nVarExprAlloc += pParse->nVarExprAlloc + 10; -        pParse->apVarExpr = sqliteRealloc(pParse->apVarExpr, +        sqlite3ReallocOrFree((void**)&pParse->apVarExpr,                         pParse->nVarExprAlloc*sizeof(pParse->apVarExpr[0]) );        }        if( !sqlite3_malloc_failed ){ @@ -546,9 +546,14 @@ Select *sqlite3SelectDup(Select *p){    pNew->pOffset = sqlite3ExprDup(p->pOffset);    pNew->iLimit = -1;    pNew->iOffset = -1; -  pNew->ppOpenVirtual = 0;    pNew->isResolved = p->isResolved;    pNew->isAgg = p->isAgg; +  pNew->usesVirt = 0; +  pNew->disallowOrderBy = 0; +  pNew->pRightmost = 0; +  pNew->addrOpenVirt[0] = -1; +  pNew->addrOpenVirt[1] = -1; +  pNew->addrOpenVirt[2] = -1;    return pNew;  }  #else @@ -692,6 +697,7 @@ static int exprNodeIsConstant(void *pArg, Expr *pExpr){      case TK_COLUMN:      case TK_DOT:      case TK_AGG_FUNCTION: +    case TK_AGG_COLUMN:  #ifndef SQLITE_OMIT_SUBQUERY      case TK_SELECT:      case TK_EXISTS: @@ -1227,11 +1233,19 @@ int sqlite3ExprResolveNames(    NameContext *pNC,       /* Namespace to resolve expressions in. */    Expr *pExpr             /* The expression to be analyzed. */  ){ +  int savedHasAgg;    if( pExpr==0 ) return 0; +  savedHasAgg = pNC->hasAgg; +  pNC->hasAgg = 0;    walkExprTree(pExpr, nameResolverStep, pNC);    if( pNC->nErr>0 ){      ExprSetProperty(pExpr, EP_Error);    } +  if( pNC->hasAgg ){ +    ExprSetProperty(pExpr, EP_Agg); +  }else if( savedHasAgg ){ +    pNC->hasAgg = 1; +  }    return ExprHasProperty(pExpr, EP_Error);  } @@ -1279,13 +1293,8 @@ void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){      int mem = pParse->nMem++;      sqlite3VdbeAddOp(v, OP_MemLoad, mem, 0);      testAddr = sqlite3VdbeAddOp(v, OP_If, 0, 0); -    assert( testAddr>0 ); -    sqlite3VdbeAddOp(v, OP_Integer, 1, 0); -    sqlite3VdbeAddOp(v, OP_MemStore, mem, 1); -  } - -  if( pExpr->pSelect ){ -    sqlite3VdbeAddOp(v, OP_AggContextPush, 0, 0); +    assert( testAddr>0 || sqlite3_malloc_failed ); +    sqlite3VdbeAddOp(v, OP_MemInt, 1, mem);    }    switch( pExpr->op ){ @@ -1359,7 +1368,7 @@ void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){            if( testAddr>0 && !sqlite3ExprIsConstant(pE2) ){              VdbeOp *aOp = sqlite3VdbeGetOp(v, testAddr-1);              int i; -            for(i=0; i<4; i++){ +            for(i=0; i<3; i++){                aOp[i].opcode = OP_Noop;              }              testAddr = 0; @@ -1400,11 +1409,8 @@ void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){      }    } -  if( pExpr->pSelect ){ -    sqlite3VdbeAddOp(v, OP_AggContextPop, 0, 0); -  }    if( testAddr ){ -    sqlite3VdbeChangeP2(v, testAddr, sqlite3VdbeCurrentAddr(v)); +    sqlite3VdbeJumpHere(v, testAddr);    }    return;  } @@ -1445,10 +1451,21 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){    }    op = pExpr->op;    switch( op ){ +    case TK_AGG_COLUMN: { +      AggInfo *pAggInfo = pExpr->pAggInfo; +      struct AggInfo_col *pCol = &pAggInfo->aCol[pExpr->iAgg]; +      if( !pAggInfo->directMode ){ +        sqlite3VdbeAddOp(v, OP_MemLoad, pCol->iMem, 0); +        break; +      }else if( pAggInfo->useSortingIdx ){ +        sqlite3VdbeAddOp(v, OP_Column, pAggInfo->sortingIdx, +                              pCol->iSorterColumn); +        break; +      } +      /* Otherwise, fall thru into the TK_COLUMN case */ +    }      case TK_COLUMN: { -      if( !pParse->fillAgg && pExpr->iAgg>=0 ){ -        sqlite3VdbeAddOp(v, OP_AggGet, pExpr->iAggCtx, pExpr->iAgg); -      }else if( pExpr->iColumn>=0 ){ +      if( pExpr->iColumn>=0 ){          sqlite3VdbeAddOp(v, OP_Column, pExpr->iTable, pExpr->iColumn);          sqlite3ColumnDefault(v, pExpr->pTab, pExpr->iColumn);        }else{ @@ -1597,7 +1614,8 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){        break;      }      case TK_AGG_FUNCTION: { -      sqlite3VdbeAddOp(v, OP_AggGet, 0, pExpr->iAgg); +      AggInfo *pInfo = pExpr->pAggInfo; +      sqlite3VdbeAddOp(v, OP_MemLoad, pInfo->aFunc[pExpr->iAgg].iMem, 0);        break;      }      case TK_CONST_FUNC: @@ -1607,7 +1625,7 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){        FuncDef *pDef;        int nId;        const char *zId; -      int p2 = 0; +      int constMask = 0;        int i;        u8 enc = pParse->db->enc;        CollSeq *pColl = 0; @@ -1618,7 +1636,7 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){        nExpr = sqlite3ExprCodeExprList(pParse, pList);        for(i=0; i<nExpr && i<32; i++){          if( sqlite3ExprIsConstant(pList->a[i].pExpr) ){ -          p2 |= (1<<i); +          constMask |= (1<<i);          }          if( pDef->needCollSeq && !pColl ){            pColl = sqlite3ExprCollSeq(pParse, pList->a[i].pExpr); @@ -1628,7 +1646,7 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){          if( !pColl ) pColl = pParse->db->pDfltColl;           sqlite3VdbeOp3(v, OP_CollSeq, 0, 0, (char *)pColl, P3_COLLSEQ);        } -      sqlite3VdbeOp3(v, OP_Function, nExpr, p2, (char*)pDef, P3_FUNCDEF); +      sqlite3VdbeOp3(v, OP_Function, constMask, nExpr, (char*)pDef, P3_FUNCDEF);        break;      }  #ifndef SQLITE_OMIT_SUBQUERY @@ -1692,7 +1710,6 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){      case TK_CASE: {        int expr_end_label;        int jumpInst; -      int addr;        int nExpr;        int i;        ExprList *pEList; @@ -1720,8 +1737,7 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){          }          sqlite3ExprCode(pParse, aListelem[i+1].pExpr);          sqlite3VdbeAddOp(v, OP_Goto, 0, expr_end_label); -        addr = sqlite3VdbeCurrentAddr(v); -        sqlite3VdbeChangeP2(v, jumpInst, addr); +        sqlite3VdbeJumpHere(v, jumpInst);        }        if( pExpr->pLeft ){          sqlite3VdbeAddOp(v, OP_Pop, 1, 0); @@ -1888,7 +1904,7 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){        codeCompare(pParse, pLeft, pRight, OP_Le, dest, jumpIfNull);        sqlite3VdbeAddOp(v, OP_Integer, 0, 0); -      sqlite3VdbeChangeP2(v, addr, sqlite3VdbeCurrentAddr(v)); +      sqlite3VdbeJumpHere(v, addr);        sqlite3VdbeAddOp(v, OP_Pop, 1, 0);        break;      } @@ -2021,6 +2037,7 @@ int sqlite3ExprCompare(Expr *pA, Expr *pB){      return 0;    }    if( pA->op!=pB->op ) return 0; +  if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 0;    if( !sqlite3ExprCompare(pA->pLeft, pB->pLeft) ) return 0;    if( !sqlite3ExprCompare(pA->pRight, pB->pRight) ) return 0;    if( pA->pList ){ @@ -2044,23 +2061,32 @@ int sqlite3ExprCompare(Expr *pA, Expr *pB){    return 1;  } +  /* -** Add a new element to the pParse->aAgg[] array and return its index. -** The new element is initialized to zero.  The calling function is -** expected to fill it in. +** Add a new element to the pAggInfo->aCol[] array.  Return the index of +** the new element.  Return a negative number if malloc fails.  */ -static int appendAggInfo(Parse *pParse){ -  if( (pParse->nAgg & 0x7)==0 ){ -    int amt = pParse->nAgg + 8; -    AggExpr *aAgg = sqliteRealloc(pParse->aAgg, amt*sizeof(pParse->aAgg[0])); -    if( aAgg==0 ){ -      return -1; -    } -    pParse->aAgg = aAgg; +static int addAggInfoColumn(AggInfo *pInfo){ +  int i; +  i = sqlite3ArrayAllocate((void**)&pInfo->aCol, sizeof(pInfo->aCol[0]), 3); +  if( i<0 ){ +    return -1;    } -  memset(&pParse->aAgg[pParse->nAgg], 0, sizeof(pParse->aAgg[0])); -  return pParse->nAgg++; -} +  return i; +}     + +/* +** Add a new element to the pAggInfo->aFunc[] array.  Return the index of +** the new element.  Return a negative number if malloc fails. +*/ +static int addAggInfoFunc(AggInfo *pInfo){ +  int i; +  i = sqlite3ArrayAllocate((void**)&pInfo->aFunc, sizeof(pInfo->aFunc[0]), 2); +  if( i<0 ){ +    return -1; +  } +  return i; +}      /*  ** This is an xFunc for walkExprTree() used to implement  @@ -2071,60 +2097,118 @@ static int appendAggInfo(Parse *pParse){  */  static int analyzeAggregate(void *pArg, Expr *pExpr){    int i; -  AggExpr *aAgg;    NameContext *pNC = (NameContext *)pArg;    Parse *pParse = pNC->pParse;    SrcList *pSrcList = pNC->pSrcList; +  AggInfo *pAggInfo = pNC->pAggInfo; +      switch( pExpr->op ){      case TK_COLUMN: { -      for(i=0; pSrcList && i<pSrcList->nSrc; i++){ -        if( pExpr->iTable==pSrcList->a[i].iCursor ){ -          aAgg = pParse->aAgg; -          for(i=0; i<pParse->nAgg; i++){ -            if( aAgg[i].isAgg ) continue; -            if( aAgg[i].pExpr->iTable==pExpr->iTable -             && aAgg[i].pExpr->iColumn==pExpr->iColumn ){ -              break; +      /* Check to see if the column is in one of the tables in the FROM +      ** clause of the aggregate query */ +      if( pSrcList ){ +        struct SrcList_item *pItem = pSrcList->a; +        for(i=0; i<pSrcList->nSrc; i++, pItem++){ +          struct AggInfo_col *pCol; +          if( pExpr->iTable==pItem->iCursor ){ +            /* If we reach this point, it means that pExpr refers to a table +            ** that is in the FROM clause of the aggregate query.   +            ** +            ** Make an entry for the column in pAggInfo->aCol[] if there +            ** is not an entry there already. +            */ +            pCol = pAggInfo->aCol; +            for(i=0; i<pAggInfo->nColumn; i++, pCol++){ +              if( pCol->iTable==pExpr->iTable && +                  pCol->iColumn==pExpr->iColumn ){ +                break; +              }              } -          } -          if( i>=pParse->nAgg ){ -            i = appendAggInfo(pParse); -            if( i<0 ) return 1; -            pParse->aAgg[i].isAgg = 0; -            pParse->aAgg[i].pExpr = pExpr; -          } -          pExpr->iAgg = i; -          pExpr->iAggCtx = pNC->nDepth; -          return 1; -        } +            if( i>=pAggInfo->nColumn && (i = addAggInfoColumn(pAggInfo))>=0 ){ +              pCol = &pAggInfo->aCol[i]; +              pCol->iTable = pExpr->iTable; +              pCol->iColumn = pExpr->iColumn; +              pCol->iMem = pParse->nMem++; +              pCol->iSorterColumn = -1; +              pCol->pExpr = pExpr; +              if( pAggInfo->pGroupBy ){ +                int j, n; +                ExprList *pGB = pAggInfo->pGroupBy; +                struct ExprList_item *pTerm = pGB->a; +                n = pGB->nExpr; +                for(j=0; j<n; j++, pTerm++){ +                  Expr *pE = pTerm->pExpr; +                  if( pE->op==TK_COLUMN && pE->iTable==pExpr->iTable && +                      pE->iColumn==pExpr->iColumn ){ +                    pCol->iSorterColumn = j; +                    break; +                  } +                } +              } +              if( pCol->iSorterColumn<0 ){ +                pCol->iSorterColumn = pAggInfo->nSortingColumn++; +              } +            } +            /* There is now an entry for pExpr in pAggInfo->aCol[] (either +            ** because it was there before or because we just created it). +            ** Convert the pExpr to be a TK_AGG_COLUMN referring to that +            ** pAggInfo->aCol[] entry. +            */ +            pExpr->pAggInfo = pAggInfo; +            pExpr->op = TK_AGG_COLUMN; +            pExpr->iAgg = i; +            break; +          } /* endif pExpr->iTable==pItem->iCursor */ +        } /* end loop over pSrcList */        }        return 1;      }      case TK_AGG_FUNCTION: { +      /* The pNC->nDepth==0 test causes aggregate functions in subqueries +      ** to be ignored */        if( pNC->nDepth==0 ){ -        aAgg = pParse->aAgg; -        for(i=0; i<pParse->nAgg; i++){ -          if( !aAgg[i].isAgg ) continue; -          if( sqlite3ExprCompare(aAgg[i].pExpr, pExpr) ){ +        /* Check to see if pExpr is a duplicate of another aggregate  +        ** function that is already in the pAggInfo structure +        */ +        struct AggInfo_func *pItem = pAggInfo->aFunc; +        for(i=0; i<pAggInfo->nFunc; i++, pItem++){ +          if( sqlite3ExprCompare(pItem->pExpr, pExpr) ){              break;            }          } -        if( i>=pParse->nAgg ){ +        if( i>=pAggInfo->nFunc ){ +          /* pExpr is original.  Make a new entry in pAggInfo->aFunc[] +          */            u8 enc = pParse->db->enc; -          i = appendAggInfo(pParse); -          if( i<0 ) return 1; -          pParse->aAgg[i].isAgg = 1; -          pParse->aAgg[i].pExpr = pExpr; -          pParse->aAgg[i].pFunc = sqlite3FindFunction(pParse->db, -               pExpr->token.z, pExpr->token.n, -               pExpr->pList ? pExpr->pList->nExpr : 0, enc, 0); +          i = addAggInfoFunc(pAggInfo); +          if( i>=0 ){ +            pItem = &pAggInfo->aFunc[i]; +            pItem->pExpr = pExpr; +            pItem->iMem = pParse->nMem++; +            pItem->pFunc = sqlite3FindFunction(pParse->db, +                   pExpr->token.z, pExpr->token.n, +                   pExpr->pList ? pExpr->pList->nExpr : 0, enc, 0); +            if( pExpr->flags & EP_Distinct ){ +              pItem->iDistinct = pParse->nTab++; +            }else{ +              pItem->iDistinct = -1; +            } +          }          } +        /* Make pExpr point to the appropriate pAggInfo->aFunc[] entry +        */          pExpr->iAgg = i; +        pExpr->pAggInfo = pAggInfo;          return 1;        }      }    } + +  /* Recursively walk subqueries looking for TK_COLUMN nodes that need +  ** to be changed to TK_AGG_COLUMN.  But increment nDepth so that +  ** TK_AGG_FUNCTION nodes in subqueries will be unchanged. +  */    if( pExpr->pSelect ){      pNC->nDepth++;      walkSelectExpr(pExpr->pSelect, analyzeAggregate, pNC); @@ -2149,3 +2233,21 @@ int sqlite3ExprAnalyzeAggregates(NameContext *pNC, Expr *pExpr){    walkExprTree(pExpr, analyzeAggregate, pNC);    return pNC->pParse->nErr - nErr;  } + +/* +** Call sqlite3ExprAnalyzeAggregates() for every expression in an +** expression list.  Return the number of errors. +** +** If an error is found, the analysis is cut short. +*/ +int sqlite3ExprAnalyzeAggList(NameContext *pNC, ExprList *pList){ +  struct ExprList_item *pItem; +  int i; +  int nErr = 0; +  if( pList ){ +    for(pItem=pList->a, i=0; nErr==0 && i<pList->nExpr; i++, pItem++){ +      nErr += sqlite3ExprAnalyzeAggregates(pNC, pItem->pExpr); +    } +  } +  return nErr; +} | 
