The unified diff between revisions [83b5270b..] and [5587f68e..] is displayed below. It can also be downloaded as a raw diff.
This diff has been restricted to the following files: 'sqlite/expr.c'
#
#
# patch "sqlite/expr.c"
# from [6d7058944c5f4b7e4304be3fe63ada91dac221a1]
# to [b8dbd5a30e80b83b0c1e137dcfcd687bd5d2b76c]
#
============================================================
--- sqlite/expr.c 6d7058944c5f4b7e4304be3fe63ada91dac221a1
+++ sqlite/expr.c b8dbd5a30e80b83b0c1e137dcfcd687bd5d2b76c
@@ -12,7 +12,7 @@
** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions in SQLite.
**
-** $Id: expr.c,v 1.206 2005/06/12 21:35:52 drh Exp $
+** $Id: expr.c,v 1.228 2005/09/16 02:38:10 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@@ -34,12 +34,18 @@ char sqlite3ExprAffinity(Expr *pExpr){
** SELECT * FROM t1 WHERE (select a from t1);
*/
char sqlite3ExprAffinity(Expr *pExpr){
- if( pExpr->op==TK_AS ){
+ int op = pExpr->op;
+ if( op==TK_AS ){
return sqlite3ExprAffinity(pExpr->pLeft);
}
- if( pExpr->op==TK_SELECT ){
+ if( op==TK_SELECT ){
return sqlite3ExprAffinity(pExpr->pSelect->pEList->a[0].pExpr);
}
+#ifndef SQLITE_OMIT_CAST
+ if( op==TK_CAST ){
+ return sqlite3AffinityType(&pExpr->token);
+ }
+#endif
return pExpr->affinity;
}
@@ -51,7 +57,7 @@ CollSeq *sqlite3ExprCollSeq(Parse *pPars
CollSeq *pColl = 0;
if( pExpr ){
pColl = pExpr->pColl;
- if( pExpr->op==TK_AS && !pColl ){
+ if( (pExpr->op==TK_AS || pExpr->op==TK_CAST) && !pColl ){
return sqlite3ExprCollSeq(pParse, pExpr->pLeft);
}
}
@@ -87,6 +93,7 @@ char sqlite3CompareAffinity(Expr *pExpr,
return SQLITE_AFF_NONE;
}else{
/* One side is a column, the other is not. Use the columns affinity. */
+ assert( aff1==0 || aff2==0 );
return (aff1 + aff2);
}
}
@@ -207,9 +214,8 @@ Expr *sqlite3Expr(int op, Expr *pLeft, E
/*
** When doing a nested parse, you can include terms in an expression
** that look like this: #0 #1 #2 ... These terms refer to elements
-** on the stack. "#0" (or just "#") means the top of the stack.
-** "#1" means the next down on the stack. And so forth. #-1 means
-** memory location 0. #-2 means memory location 1. And so forth.
+** on the stack. "#0" means the top of the stack.
+** "#1" means the next down on the stack. And so forth.
**
** This routine is called by the parser to deal with on of those terms.
** It immediately generates code to store the value in a memory location.
@@ -220,23 +226,19 @@ Expr *sqlite3RegisterExpr(Parse *pParse,
Vdbe *v = pParse->pVdbe;
Expr *p;
int depth;
- if( v==0 ) return 0;
if( pParse->nested==0 ){
sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", pToken);
return 0;
}
+ if( v==0 ) return 0;
p = sqlite3Expr(TK_REGISTER, 0, 0, pToken);
if( p==0 ){
return 0; /* Malloc failed */
}
depth = atoi(&pToken->z[1]);
- if( depth>=0 ){
- p->iTable = pParse->nMem++;
- sqlite3VdbeAddOp(v, OP_Dup, depth, 0);
- sqlite3VdbeAddOp(v, OP_MemStore, p->iTable, 1);
- }else{
- p->iTable = -1-depth;
- }
+ p->iTable = pParse->nMem++;
+ sqlite3VdbeAddOp(v, OP_Dup, depth, 0);
+ sqlite3VdbeAddOp(v, OP_MemStore, p->iTable, 1);
return p;
}
@@ -353,7 +355,7 @@ void sqlite3ExprAssignVarNumber(Parse *p
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 ){
@@ -378,7 +380,22 @@ void sqlite3ExprDelete(Expr *p){
sqliteFree(p);
}
+/*
+** The Expr.token field might be a string literal that is quoted.
+** If so, remove the quotation marks.
+*/
+void sqlite3DequoteExpr(Expr *p){
+ if( ExprHasAnyProperty(p, EP_Dequoted) ){
+ return;
+ }
+ ExprSetProperty(p, EP_Dequoted);
+ if( p->token.dyn==0 ){
+ sqlite3TokenCopy(&p->token, &p->token);
+ }
+ sqlite3Dequote((char*)p->token.z);
+}
+
/*
** The following group of routines make deep copies of expressions,
** expression lists, ID lists, and select statements. The copies can
@@ -529,9 +546,12 @@ Select *sqlite3SelectDup(Select *p){
pNew->pOffset = sqlite3ExprDup(p->pOffset);
pNew->iLimit = -1;
pNew->iOffset = -1;
- pNew->ppOpenTemp = 0;
pNew->isResolved = p->isResolved;
pNew->isAgg = p->isAgg;
+ pNew->pRightmost = 0;
+ pNew->addrOpenVirt[0] = -1;
+ pNew->addrOpenVirt[1] = -1;
+ pNew->addrOpenVirt[2] = -1;
return pNew;
}
#else
@@ -607,6 +627,8 @@ void sqlite3ExprListDelete(ExprList *pLi
**
** The return value from this routine is 1 to abandon the tree walk
** and 0 to continue.
+**
+** NOTICE: This routine does *not* descend into subqueries.
*/
static int walkExprList(ExprList *, int (*)(void *, Expr*), void *);
static int walkExprTree(Expr *pExpr, int (*xFunc)(void*,Expr*), void *pArg){
@@ -664,17 +686,27 @@ static int exprNodeIsConstant(void *pArg
*/
static int exprNodeIsConstant(void *pArg, Expr *pExpr){
switch( pExpr->op ){
+ /* Consider functions to be constant if all their arguments are constant
+ ** and *pArg==2 */
+ case TK_FUNCTION:
+ if( *((int*)pArg)==2 ) return 0;
+ /* Fall through */
case TK_ID:
case TK_COLUMN:
case TK_DOT:
case TK_AGG_FUNCTION:
- case TK_FUNCTION:
+ case TK_AGG_COLUMN:
#ifndef SQLITE_OMIT_SUBQUERY
case TK_SELECT:
case TK_EXISTS:
#endif
*((int*)pArg) = 0;
return 2;
+ case TK_IN:
+ if( pExpr->pSelect ){
+ *((int*)pArg) = 0;
+ return 2;
+ }
default:
return 0;
}
@@ -682,7 +714,7 @@ static int exprNodeIsConstant(void *pArg
/*
** Walk an expression tree. Return 1 if the expression is constant
-** and 0 if it involves variables.
+** and 0 if it involves variables or function calls.
**
** For the purposes of this function, a double-quoted string (ex: "abc")
** is considered a variable but a single-quoted string (ex: 'abc') is
@@ -695,6 +727,21 @@ int sqlite3ExprIsConstant(Expr *p){
}
/*
+** Walk an expression tree. Return 1 if the expression is constant
+** or a function call with constant arguments. Return and 0 if there
+** are any variables.
+**
+** For the purposes of this function, a double-quoted string (ex: "abc")
+** is considered a variable but a single-quoted string (ex: 'abc') is
+** a constant.
+*/
+int sqlite3ExprIsConstantOrFunction(Expr *p){
+ int isConst = 2;
+ walkExprTree(p, exprNodeIsConstant, &isConst);
+ return isConst!=0;
+}
+
+/*
** If the expression p codes a constant integer that is small enough
** to fit in a 32-bit integer, return 1 and put the value of the integer
** in *pValue. If the expression is not an integer or if it is too big
@@ -1184,11 +1231,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);
}
@@ -1218,37 +1273,39 @@ void sqlite3CodeSubselect(Parse *pParse,
*/
#ifndef SQLITE_OMIT_SUBQUERY
void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
- int label = 0; /* Address after sub-select code */
+ int testAddr = 0; /* One-time test address */
Vdbe *v = sqlite3GetVdbe(pParse);
if( v==0 ) return;
- /* If this is not a variable (correlated) select, then execute
- ** it only once. Unless this is part of a trigger program. In
- ** that case re-execute every time (this could be optimized).
+ /* This code must be run in its entirety every time it is encountered
+ ** if any of the following is true:
+ **
+ ** * The right-hand side is a correlated subquery
+ ** * The right-hand side is an expression list containing variables
+ ** * We are inside a trigger
+ **
+ ** If all of the above are false, then we can run this code just once
+ ** save the results, and reuse the same result on subsequent invocations.
*/
if( !ExprHasAnyProperty(pExpr, EP_VarSelect) && !pParse->trigStack ){
int mem = pParse->nMem++;
sqlite3VdbeAddOp(v, OP_MemLoad, mem, 0);
- label = sqlite3VdbeMakeLabel(v);
- sqlite3VdbeAddOp(v, OP_If, 0, label);
+ testAddr = sqlite3VdbeAddOp(v, OP_If, 0, 0);
+ assert( testAddr>0 || sqlite3_malloc_failed );
sqlite3VdbeAddOp(v, OP_Integer, 1, 0);
sqlite3VdbeAddOp(v, OP_MemStore, mem, 1);
}
- if( pExpr->pSelect ){
- sqlite3VdbeAddOp(v, OP_AggContextPush, 0, 0);
- }
-
switch( pExpr->op ){
case TK_IN: {
char affinity;
KeyInfo keyInfo;
- int addr; /* Address of OP_OpenTemp instruction */
+ int addr; /* Address of OP_OpenVirtual instruction */
affinity = sqlite3ExprAffinity(pExpr->pLeft);
/* Whether this is an 'x IN(SELECT...)' or an 'x IN(<exprlist>)'
- ** expression it is handled the same way. A temporary table is
+ ** expression it is handled the same way. A virtual table is
** filled with single-field index keys representing the results
** from the SELECT or the <exprlist>.
**
@@ -1261,7 +1318,7 @@ void sqlite3CodeSubselect(Parse *pParse,
** is used.
*/
pExpr->iTable = pParse->nTab++;
- addr = sqlite3VdbeAddOp(v, OP_OpenTemp, pExpr->iTable, 0);
+ addr = sqlite3VdbeAddOp(v, OP_OpenVirtual, pExpr->iTable, 0);
memset(&keyInfo, 0, sizeof(keyInfo));
keyInfo.nField = 1;
sqlite3VdbeAddOp(v, OP_SetNumColumns, pExpr->iTable, 1);
@@ -1290,20 +1347,30 @@ void sqlite3CodeSubselect(Parse *pParse,
** a column, use numeric affinity.
*/
int i;
+ ExprList *pList = pExpr->pList;
+ struct ExprList_item *pItem;
+
if( !affinity ){
affinity = SQLITE_AFF_NUMERIC;
}
keyInfo.aColl[0] = pExpr->pLeft->pColl;
/* Loop through each expression in <exprlist>. */
- for(i=0; i<pExpr->pList->nExpr; i++){
- Expr *pE2 = pExpr->pList->a[i].pExpr;
+ for(i=pList->nExpr, pItem=pList->a; i>0; i--, pItem++){
+ Expr *pE2 = pItem->pExpr;
- /* Check that the expression is constant and valid. */
- if( !sqlite3ExprIsConstant(pE2) ){
- sqlite3ErrorMsg(pParse,
- "right-hand side of IN operator must be constant");
- return;
+ /* If the expression is not constant then we will need to
+ ** disable the test that was generated above that makes sure
+ ** this code only executes once. Because for a non-constant
+ ** expression we need to rerun this code each time.
+ */
+ if( testAddr>0 && !sqlite3ExprIsConstant(pE2) ){
+ VdbeOp *aOp = sqlite3VdbeGetOp(v, testAddr-1);
+ int i;
+ for(i=0; i<4; i++){
+ aOp[i].opcode = OP_Noop;
+ }
+ testAddr = 0;
}
/* Evaluate the expression and insert it into the temp table */
@@ -1341,12 +1408,9 @@ void sqlite3CodeSubselect(Parse *pParse,
}
}
- if( pExpr->pSelect ){
- sqlite3VdbeAddOp(v, OP_AggContextPop, 0, 0);
+ if( testAddr ){
+ sqlite3VdbeChangeP2(v, testAddr, sqlite3VdbeCurrentAddr(v));
}
- if( label<0 ){
- sqlite3VdbeResolveLabel(v, label);
- }
return;
}
#endif /* SQLITE_OMIT_SUBQUERY */
@@ -1360,7 +1424,7 @@ static void codeInteger(Vdbe *v, const c
if( sqlite3GetInt32(z, &i) ){
sqlite3VdbeAddOp(v, OP_Integer, i, 0);
}else if( sqlite3FitsIn64Bits(z) ){
- sqlite3VdbeOp3(v, OP_Integer, 0, 0, z, n);
+ sqlite3VdbeOp3(v, OP_Int64, 0, 0, z, n);
}else{
sqlite3VdbeOp3(v, OP_Real, 0, 0, z, n);
}
@@ -1386,10 +1450,21 @@ void sqlite3ExprCode(Parse *pParse, Expr
}
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{
@@ -1405,8 +1480,8 @@ void sqlite3ExprCode(Parse *pParse, Expr
case TK_STRING: {
assert( TK_FLOAT==OP_Real );
assert( TK_STRING==OP_String8 );
+ sqlite3DequoteExpr(pExpr);
sqlite3VdbeOp3(v, op, 0, 0, pExpr->token.z, pExpr->token.n);
- sqlite3VdbeDequoteP3(v, -1);
break;
}
case TK_NULL: {
@@ -1415,9 +1490,16 @@ void sqlite3ExprCode(Parse *pParse, Expr
}
#ifndef SQLITE_OMIT_BLOB_LITERAL
case TK_BLOB: {
+ int n;
+ const char *z;
assert( TK_BLOB==OP_HexBlob );
- sqlite3VdbeOp3(v, op, 0, 0, pExpr->token.z+1, pExpr->token.n-1);
- sqlite3VdbeDequoteP3(v, -1);
+ n = pExpr->token.n - 3;
+ z = pExpr->token.z + 2;
+ assert( n>=0 );
+ if( n==0 ){
+ z = "";
+ }
+ sqlite3VdbeOp3(v, op, 0, 0, z, n);
break;
}
#endif
@@ -1432,6 +1514,22 @@ void sqlite3ExprCode(Parse *pParse, Expr
sqlite3VdbeAddOp(v, OP_MemLoad, pExpr->iTable, 0);
break;
}
+#ifndef SQLITE_OMIT_CAST
+ case TK_CAST: {
+ /* Expressions of the form: CAST(pLeft AS token) */
+ int aff, op;
+ sqlite3ExprCode(pParse, pExpr->pLeft);
+ aff = sqlite3AffinityType(&pExpr->token);
+ switch( aff ){
+ case SQLITE_AFF_INTEGER: op = OP_ToInt; break;
+ case SQLITE_AFF_NUMERIC: op = OP_ToNumeric; break;
+ case SQLITE_AFF_TEXT: op = OP_ToText; break;
+ case SQLITE_AFF_NONE: op = OP_ToBlob; break;
+ }
+ sqlite3VdbeAddOp(v, op, 0, 0);
+ break;
+ }
+#endif /* SQLITE_OMIT_CAST */
case TK_LT:
case TK_LE:
case TK_GT:
@@ -1515,7 +1613,8 @@ void sqlite3ExprCode(Parse *pParse, Expr
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:
@@ -1525,7 +1624,7 @@ void sqlite3ExprCode(Parse *pParse, Expr
FuncDef *pDef;
int nId;
const char *zId;
- int p2 = 0;
+ int constMask = 0;
int i;
u8 enc = pParse->db->enc;
CollSeq *pColl = 0;
@@ -1536,7 +1635,7 @@ void sqlite3ExprCode(Parse *pParse, Expr
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);
@@ -1546,7 +1645,7 @@ void sqlite3ExprCode(Parse *pParse, Expr
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
@@ -1663,9 +1762,9 @@ void sqlite3ExprCode(Parse *pParse, Expr
assert( pExpr->iColumn==OE_Rollback ||
pExpr->iColumn == OE_Abort ||
pExpr->iColumn == OE_Fail );
+ sqlite3DequoteExpr(pExpr);
sqlite3VdbeOp3(v, OP_Halt, SQLITE_CONSTRAINT, pExpr->iColumn,
pExpr->token.z, pExpr->token.n);
- sqlite3VdbeDequoteP3(v, -1);
} else {
assert( pExpr->iColumn == OE_Ignore );
sqlite3VdbeAddOp(v, OP_ContextPop, 0, 0);
@@ -1717,11 +1816,9 @@ int sqlite3ExprCodeExprList(
){
struct ExprList_item *pItem;
int i, n;
- Vdbe *v;
if( pList==0 ) return 0;
- v = sqlite3GetVdbe(pParse);
n = pList->nExpr;
- for(pItem=pList->a, i=0; i<n; i++, pItem++){
+ for(pItem=pList->a, i=n; i>0; i--, pItem++){
sqlite3ExprCode(pParse, pItem->pExpr);
}
return n;
@@ -1941,6 +2038,7 @@ int sqlite3ExprCompare(Expr *pA, Expr *p
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 ){
@@ -1964,25 +2062,34 @@ int sqlite3ExprCompare(Expr *pA, Expr *p
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
** sqlite3ExprAnalyzeAggregates(). See sqlite3ExprAnalyzeAggregates
** for additional information.
@@ -1991,60 +2098,118 @@ static int analyzeAggregate(void *pArg,
*/
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);
@@ -2069,3 +2234,21 @@ int sqlite3ExprAnalyzeAggregates(NameCon
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;
+}