summaryrefslogtreecommitdiff
path: root/ext/pdo_sqlite/sqlite/src/expr.c
diff options
context:
space:
mode:
authorWez Furlong <wez@php.net>2005-02-27 05:20:19 +0000
committerWez Furlong <wez@php.net>2005-02-27 05:20:19 +0000
commitae5649598dcbb3b3b105344452c782bf0f289739 (patch)
treee03893cec670b02478808f8913d6b4148455ec2c /ext/pdo_sqlite/sqlite/src/expr.c
parent58f61a16eea562cfed04c19cc319a608b2e9f345 (diff)
downloadphp-git-ae5649598dcbb3b3b105344452c782bf0f289739.tar.gz
upgrade bundled sqlite to sqlite 3.1.3
Diffstat (limited to 'ext/pdo_sqlite/sqlite/src/expr.c')
-rw-r--r--ext/pdo_sqlite/sqlite/src/expr.c1086
1 files changed, 666 insertions, 420 deletions
diff --git a/ext/pdo_sqlite/sqlite/src/expr.c b/ext/pdo_sqlite/sqlite/src/expr.c
index 2da3645b9b..c4943b1f83 100644
--- a/ext/pdo_sqlite/sqlite/src/expr.c
+++ b/ext/pdo_sqlite/sqlite/src/expr.c
@@ -62,8 +62,8 @@ CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){
}
/*
-** pExpr is the left operand of a comparison operator. aff2 is the
-** type affinity of the right operand. This routine returns the
+** pExpr is an operand of a comparison operator. aff2 is the
+** type affinity of the other operand. This routine returns the
** type affinity that should be used for the comparison operator.
*/
char sqlite3CompareAffinity(Expr *pExpr, char aff2){
@@ -179,7 +179,7 @@ static int codeCompare(
** for this node is obtained from sqliteMalloc(). The calling function
** is responsible for making sure the node eventually gets freed.
*/
-Expr *sqlite3Expr(int op, Expr *pLeft, Expr *pRight, Token *pToken){
+Expr *sqlite3Expr(int op, Expr *pLeft, Expr *pRight, const Token *pToken){
Expr *pNew;
pNew = sqliteMalloc( sizeof(Expr) );
if( pNew==0 ){
@@ -189,6 +189,7 @@ Expr *sqlite3Expr(int op, Expr *pLeft, Expr *pRight, Token *pToken){
pNew->op = op;
pNew->pLeft = pLeft;
pNew->pRight = pRight;
+ pNew->iAgg = -1;
if( pToken ){
assert( pToken->dyn==0 );
pNew->span = pNew->token = *pToken;
@@ -199,6 +200,42 @@ Expr *sqlite3Expr(int op, Expr *pLeft, Expr *pRight, Token *pToken){
}
/*
+** 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.
+**
+** 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.
+** The returns an expression that will code to extract the value from
+** that memory location as needed.
+*/
+Expr *sqlite3RegisterExpr(Parse *pParse, Token *pToken){
+ 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;
+ }
+ 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;
+ }
+ return p;
+}
+
+/*
** Join two expressions using an AND operator. If either expression is
** NULL, then just return the other expression.
*/
@@ -356,7 +393,7 @@ Expr *sqlite3ExprDup(Expr *p){
if( pNew==0 ) return 0;
memcpy(pNew, p, sizeof(*pNew));
if( p->token.z!=0 ){
- pNew->token.z = sqliteStrDup(p->token.z);
+ pNew->token.z = sqliteStrNDup(p->token.z, p->token.n);
pNew->token.dyn = 1;
}else{
assert( pNew->token.z==0 );
@@ -410,6 +447,15 @@ ExprList *sqlite3ExprListDup(ExprList *p){
}
return pNew;
}
+
+/*
+** If cursors, triggers, views and subqueries are all omitted from
+** the build, then none of the following routines, except for
+** sqlite3SelectDup(), can be called. sqlite3SelectDup() is sometimes
+** called with a NULL argument.
+*/
+#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER) \
+ || !defined(SQLITE_OMIT_SUBQUERY)
SrcList *sqlite3SrcListDup(SrcList *p){
SrcList *pNew;
int i;
@@ -427,10 +473,14 @@ SrcList *sqlite3SrcListDup(SrcList *p){
pNewItem->zAlias = sqliteStrDup(pOldItem->zAlias);
pNewItem->jointype = pOldItem->jointype;
pNewItem->iCursor = pOldItem->iCursor;
- pNewItem->pTab = 0;
+ pNewItem->pTab = pOldItem->pTab;
+ if( pNewItem->pTab ){
+ pNewItem->pTab->isTransient = 0;
+ }
pNewItem->pSelect = sqlite3SelectDup(pOldItem->pSelect);
pNewItem->pOn = sqlite3ExprDup(pOldItem->pOn);
pNewItem->pUsing = sqlite3IdListDup(pOldItem->pUsing);
+ pNewItem->colUsed = pOldItem->colUsed;
}
return pNew;
}
@@ -465,14 +515,22 @@ Select *sqlite3SelectDup(Select *p){
pNew->pOrderBy = sqlite3ExprListDup(p->pOrderBy);
pNew->op = p->op;
pNew->pPrior = sqlite3SelectDup(p->pPrior);
- pNew->nLimit = p->nLimit;
- pNew->nOffset = p->nOffset;
- pNew->zSelect = 0;
+ pNew->pLimit = sqlite3ExprDup(p->pLimit);
+ pNew->pOffset = sqlite3ExprDup(p->pOffset);
pNew->iLimit = -1;
pNew->iOffset = -1;
pNew->ppOpenTemp = 0;
+ pNew->pFetch = 0;
+ pNew->isResolved = p->isResolved;
+ pNew->isAgg = p->isAgg;
return pNew;
}
+#else
+Select *sqlite3SelectDup(Select *p){
+ assert( p==0 );
+ return 0;
+}
+#endif
/*
@@ -525,44 +583,104 @@ void sqlite3ExprListDelete(ExprList *pList){
}
/*
-** Walk an expression tree. Return 1 if the expression is constant
-** and 0 if it involves variables.
+** Walk an expression tree. Call xFunc for each node visited.
**
-** 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.
+** The return value from xFunc determines whether the tree walk continues.
+** 0 means continue walking the tree. 1 means do not walk children
+** of the current node but continue with siblings. 2 means abandon
+** the tree walk completely.
+**
+** The return value from this routine is 1 to abandon the tree walk
+** and 0 to continue.
*/
-int sqlite3ExprIsConstant(Expr *p){
- switch( p->op ){
+static int walkExprList(ExprList *, int (*)(void *, Expr*), void *);
+static int walkExprTree(Expr *pExpr, int (*xFunc)(void*,Expr*), void *pArg){
+ int rc;
+ if( pExpr==0 ) return 0;
+ rc = (*xFunc)(pArg, pExpr);
+ if( rc==0 ){
+ if( walkExprTree(pExpr->pLeft, xFunc, pArg) ) return 1;
+ if( walkExprTree(pExpr->pRight, xFunc, pArg) ) return 1;
+ if( walkExprList(pExpr->pList, xFunc, pArg) ) return 1;
+ }
+ return rc>1;
+}
+
+/*
+** Call walkExprTree() for every expression in list p.
+*/
+static int walkExprList(ExprList *p, int (*xFunc)(void *, Expr*), void *pArg){
+ int i;
+ struct ExprList_item *pItem;
+ if( !p ) return 0;
+ for(i=p->nExpr, pItem=p->a; i>0; i--, pItem++){
+ if( walkExprTree(pItem->pExpr, xFunc, pArg) ) return 1;
+ }
+ return 0;
+}
+
+/*
+** Call walkExprTree() for every expression in Select p, not including
+** expressions that are part of sub-selects in any FROM clause or the LIMIT
+** or OFFSET expressions..
+*/
+static int walkSelectExpr(Select *p, int (*xFunc)(void *, Expr*), void *pArg){
+ walkExprList(p->pEList, xFunc, pArg);
+ walkExprTree(p->pWhere, xFunc, pArg);
+ walkExprList(p->pGroupBy, xFunc, pArg);
+ walkExprTree(p->pHaving, xFunc, pArg);
+ walkExprList(p->pOrderBy, xFunc, pArg);
+ return 0;
+}
+
+
+/*
+** This routine is designed as an xFunc for walkExprTree().
+**
+** pArg is really a pointer to an integer. If we can tell by looking
+** at pExpr that the expression that contains pExpr is not a constant
+** expression, then set *pArg to 0 and return 2 to abandon the tree walk.
+** If pExpr does does not disqualify the expression from being a constant
+** then do nothing.
+**
+** After walking the whole tree, if no nodes are found that disqualify
+** the expression as constant, then we assume the whole expression
+** is constant. See sqlite3ExprIsConstant() for additional information.
+*/
+static int exprNodeIsConstant(void *pArg, Expr *pExpr){
+ switch( pExpr->op ){
case TK_ID:
case TK_COLUMN:
case TK_DOT:
+ case TK_AGG_FUNCTION:
case TK_FUNCTION:
+#ifndef SQLITE_OMIT_SUBQUERY
+ case TK_SELECT:
+ case TK_EXISTS:
+#endif
+ *((int*)pArg) = 0;
+ return 2;
+ default:
return 0;
- case TK_NULL:
- case TK_STRING:
- case TK_BLOB:
- case TK_INTEGER:
- case TK_FLOAT:
- case TK_VARIABLE:
- return 1;
- default: {
- if( p->pLeft && !sqlite3ExprIsConstant(p->pLeft) ) return 0;
- if( p->pRight && !sqlite3ExprIsConstant(p->pRight) ) return 0;
- if( p->pList ){
- int i;
- for(i=0; i<p->pList->nExpr; i++){
- if( !sqlite3ExprIsConstant(p->pList->a[i].pExpr) ) return 0;
- }
- }
- return p->pLeft!=0 || p->pRight!=0 || (p->pList && p->pList->nExpr>0);
- }
}
- return 0;
}
/*
-** If the given expression codes a constant integer that is small enough
+** Walk an expression tree. Return 1 if the expression is constant
+** and 0 if it involves 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 sqlite3ExprIsConstant(Expr *p){
+ int isConst = 1;
+ walkExprTree(p, exprNodeIsConstant, &isConst);
+ return isConst;
+}
+
+/*
+** 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
** to fit in a signed 32-bit integer, return 0 and leave *pValue unchanged.
@@ -575,16 +693,6 @@ int sqlite3ExprIsInteger(Expr *p, int *pValue){
}
break;
}
- case TK_STRING: {
- const u8 *z = (u8*)p->token.z;
- int n = p->token.n;
- if( n>0 && z[0]=='-' ){ z++; n--; }
- while( n>0 && *z && isdigit(*z) ){ z++; n--; }
- if( n==0 && sqlite3GetInt32(p->token.z, pValue) ){
- return 1;
- }
- break;
- }
case TK_UPLUS: {
return sqlite3ExprIsInteger(p->pLeft, pValue);
}
@@ -641,8 +749,7 @@ static int lookupName(
Token *pDbToken, /* Name of the database containing table, or NULL */
Token *pTableToken, /* Name of table containing column, or NULL */
Token *pColumnToken, /* Name of the column. */
- SrcList *pSrcList, /* List of tables used to resolve column names */
- ExprList *pEList, /* List of expressions used to resolve "AS" */
+ NameContext *pNC, /* The name context used to resolve the name */
Expr *pExpr /* Make this EXPR node point to the selected column */
){
char *zDb = 0; /* Name of the database. The "X" in X.Y.Z */
@@ -652,6 +759,9 @@ static int lookupName(
int cnt = 0; /* Number of matching column names */
int cntTab = 0; /* Number of matching table names */
sqlite3 *db = pParse->db; /* The database */
+ struct SrcList_item *pItem; /* Use for looping over pSrcList items */
+ struct SrcList_item *pMatch = 0; /* The matching pSrcList item */
+ NameContext *pTopNC = pNC; /* First namecontext in the list */
assert( pColumnToken && pColumnToken->z ); /* The Z in X.Y.Z cannot be NULL */
zDb = sqlite3NameFromToken(pDbToken);
@@ -660,114 +770,132 @@ static int lookupName(
if( sqlite3_malloc_failed ){
return 1; /* Leak memory (zDb and zTab) if malloc fails */
}
- assert( zTab==0 || pEList==0 );
pExpr->iTable = -1;
- for(i=0; i<pSrcList->nSrc; i++){
- struct SrcList_item *pItem = &pSrcList->a[i];
- Table *pTab = pItem->pTab;
- Column *pCol;
-
- if( pTab==0 ) continue;
- assert( pTab->nCol>0 );
- if( zTab ){
- if( pItem->zAlias ){
- char *zTabName = pItem->zAlias;
- if( sqlite3StrICmp(zTabName, zTab)!=0 ) continue;
- }else{
- char *zTabName = pTab->zName;
- if( zTabName==0 || sqlite3StrICmp(zTabName, zTab)!=0 ) continue;
- if( zDb!=0 && sqlite3StrICmp(db->aDb[pTab->iDb].zName, zDb)!=0 ){
- continue;
+ while( pNC && cnt==0 ){
+ SrcList *pSrcList = pNC->pSrcList;
+ ExprList *pEList = pNC->pEList;
+
+ pNC->nRef++;
+ /* assert( zTab==0 || pEList==0 ); */
+ if( pSrcList ){
+ for(i=0, pItem=pSrcList->a; i<pSrcList->nSrc; i++, pItem++){
+ Table *pTab = pItem->pTab;
+ Column *pCol;
+
+ if( pTab==0 ) continue;
+ assert( pTab->nCol>0 );
+ if( zTab ){
+ if( pItem->zAlias ){
+ char *zTabName = pItem->zAlias;
+ if( sqlite3StrICmp(zTabName, zTab)!=0 ) continue;
+ }else{
+ char *zTabName = pTab->zName;
+ if( zTabName==0 || sqlite3StrICmp(zTabName, zTab)!=0 ) continue;
+ if( zDb!=0 && sqlite3StrICmp(db->aDb[pTab->iDb].zName, zDb)!=0 ){
+ continue;
+ }
+ }
+ }
+ if( 0==(cntTab++) ){
+ pExpr->iTable = pItem->iCursor;
+ pExpr->iDb = pTab->iDb;
+ pMatch = pItem;
+ }
+ for(j=0, pCol=pTab->aCol; j<pTab->nCol; j++, pCol++){
+ if( sqlite3StrICmp(pCol->zName, zCol)==0 ){
+ cnt++;
+ pExpr->iTable = pItem->iCursor;
+ pMatch = pItem;
+ pExpr->iDb = pTab->iDb;
+ /* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */
+ pExpr->iColumn = j==pTab->iPKey ? -1 : j;
+ pExpr->affinity = pTab->aCol[j].affinity;
+ pExpr->pColl = pTab->aCol[j].pColl;
+ break;
+ }
}
}
}
- if( 0==(cntTab++) ){
- pExpr->iTable = pItem->iCursor;
- pExpr->iDb = pTab->iDb;
- }
- for(j=0, pCol=pTab->aCol; j<pTab->nCol; j++, pCol++){
- if( sqlite3StrICmp(pCol->zName, zCol)==0 ){
- cnt++;
- pExpr->iTable = pItem->iCursor;
- pExpr->iDb = pTab->iDb;
- /* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */
- pExpr->iColumn = j==pTab->iPKey ? -1 : j;
- pExpr->affinity = pTab->aCol[j].affinity;
- pExpr->pColl = pTab->aCol[j].pColl;
- break;
+
+#ifndef SQLITE_OMIT_TRIGGER
+ /* If we have not already resolved the name, then maybe
+ ** it is a new.* or old.* trigger argument reference
+ */
+ if( zDb==0 && zTab!=0 && cnt==0 && pParse->trigStack!=0 ){
+ TriggerStack *pTriggerStack = pParse->trigStack;
+ Table *pTab = 0;
+ if( pTriggerStack->newIdx != -1 && sqlite3StrICmp("new", zTab) == 0 ){
+ pExpr->iTable = pTriggerStack->newIdx;
+ assert( pTriggerStack->pTab );
+ pTab = pTriggerStack->pTab;
+ }else if( pTriggerStack->oldIdx != -1 && sqlite3StrICmp("old", zTab)==0 ){
+ pExpr->iTable = pTriggerStack->oldIdx;
+ assert( pTriggerStack->pTab );
+ pTab = pTriggerStack->pTab;
}
- }
- }
- /* If we have not already resolved the name, then maybe
- ** it is a new.* or old.* trigger argument reference
- */
- if( zDb==0 && zTab!=0 && cnt==0 && pParse->trigStack!=0 ){
- TriggerStack *pTriggerStack = pParse->trigStack;
- Table *pTab = 0;
- if( pTriggerStack->newIdx != -1 && sqlite3StrICmp("new", zTab) == 0 ){
- pExpr->iTable = pTriggerStack->newIdx;
- assert( pTriggerStack->pTab );
- pTab = pTriggerStack->pTab;
- }else if( pTriggerStack->oldIdx != -1 && sqlite3StrICmp("old", zTab) == 0 ){
- pExpr->iTable = pTriggerStack->oldIdx;
- assert( pTriggerStack->pTab );
- pTab = pTriggerStack->pTab;
- }
-
- if( pTab ){
- int j;
- Column *pCol = pTab->aCol;
-
- pExpr->iDb = pTab->iDb;
- cntTab++;
- for(j=0; j < pTab->nCol; j++, pCol++) {
- if( sqlite3StrICmp(pCol->zName, zCol)==0 ){
- cnt++;
- pExpr->iColumn = j==pTab->iPKey ? -1 : j;
- pExpr->affinity = pTab->aCol[j].affinity;
- pExpr->pColl = pTab->aCol[j].pColl;
- break;
+ if( pTab ){
+ int j;
+ Column *pCol = pTab->aCol;
+
+ pExpr->iDb = pTab->iDb;
+ cntTab++;
+ for(j=0; j < pTab->nCol; j++, pCol++) {
+ if( sqlite3StrICmp(pCol->zName, zCol)==0 ){
+ cnt++;
+ pExpr->iColumn = j==pTab->iPKey ? -1 : j;
+ pExpr->affinity = pTab->aCol[j].affinity;
+ pExpr->pColl = pTab->aCol[j].pColl;
+ break;
+ }
}
}
}
- }
+#endif /* !defined(SQLITE_OMIT_TRIGGER) */
- /*
- ** Perhaps the name is a reference to the ROWID
- */
- if( cnt==0 && cntTab==1 && sqlite3IsRowid(zCol) ){
- cnt = 1;
- pExpr->iColumn = -1;
- pExpr->affinity = SQLITE_AFF_INTEGER;
- }
+ /*
+ ** Perhaps the name is a reference to the ROWID
+ */
+ if( cnt==0 && cntTab==1 && sqlite3IsRowid(zCol) ){
+ cnt = 1;
+ pExpr->iColumn = -1;
+ pExpr->affinity = SQLITE_AFF_INTEGER;
+ }
- /*
- ** If the input is of the form Z (not Y.Z or X.Y.Z) then the name Z
- ** might refer to an result-set alias. This happens, for example, when
- ** we are resolving names in the WHERE clause of the following command:
- **
- ** SELECT a+b AS x FROM table WHERE x<10;
- **
- ** In cases like this, replace pExpr with a copy of the expression that
- ** forms the result set entry ("a+b" in the example) and return immediately.
- ** Note that the expression in the result set should have already been
- ** resolved by the time the WHERE clause is resolved.
- */
- if( cnt==0 && pEList!=0 ){
- for(j=0; j<pEList->nExpr; j++){
- char *zAs = pEList->a[j].zName;
- if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){
- assert( pExpr->pLeft==0 && pExpr->pRight==0 );
- pExpr->op = TK_AS;
- pExpr->iColumn = j;
- pExpr->pLeft = sqlite3ExprDup(pEList->a[j].pExpr);
- sqliteFree(zCol);
- assert( zTab==0 && zDb==0 );
- return 0;
- }
- }
+ /*
+ ** If the input is of the form Z (not Y.Z or X.Y.Z) then the name Z
+ ** might refer to an result-set alias. This happens, for example, when
+ ** we are resolving names in the WHERE clause of the following command:
+ **
+ ** SELECT a+b AS x FROM table WHERE x<10;
+ **
+ ** In cases like this, replace pExpr with a copy of the expression that
+ ** forms the result set entry ("a+b" in the example) and return immediately.
+ ** Note that the expression in the result set should have already been
+ ** resolved by the time the WHERE clause is resolved.
+ */
+ if( cnt==0 && pEList!=0 && zTab==0 ){
+ for(j=0; j<pEList->nExpr; j++){
+ char *zAs = pEList->a[j].zName;
+ if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){
+ assert( pExpr->pLeft==0 && pExpr->pRight==0 );
+ pExpr->op = TK_AS;
+ pExpr->iColumn = j;
+ pExpr->pLeft = sqlite3ExprDup(pEList->a[j].pExpr);
+ sqliteFree(zCol);
+ assert( zTab==0 && zDb==0 );
+ return 0;
+ }
+ }
+ }
+
+ /* Advance to the next name context. The loop will exit when either
+ ** we have a match (cnt>0) or when we run out of name contexts.
+ */
+ if( cnt==0 ){
+ pNC = pNC->pNext;
+ }
}
/*
@@ -799,6 +927,22 @@ static int lookupName(
}
sqlite3ErrorMsg(pParse, zErr, z);
sqliteFree(z);
+ pTopNC->nErr++;
+ }
+
+ /* If a column from a table in pSrcList is referenced, then record
+ ** this fact in the pSrcList.a[].colUsed bitmask. Column 0 causes
+ ** bit 0 to be set. Column 1 sets bit 1. And so forth. If the
+ ** column number is greater than the number of bits in the bitmask
+ ** then set the high-order bit of the bitmask.
+ */
+ if( pExpr->iColumn>=0 && pMatch!=0 ){
+ int n = pExpr->iColumn;
+ if( n>=sizeof(Bitmask)*8 ){
+ n = sizeof(Bitmask)*8-1;
+ }
+ assert( pMatch->iCursor==pExpr->iTable );
+ pMatch->colUsed |= 1<<n;
}
/* Clean up and return
@@ -811,53 +955,87 @@ static int lookupName(
sqlite3ExprDelete(pExpr->pRight);
pExpr->pRight = 0;
pExpr->op = TK_COLUMN;
- sqlite3AuthRead(pParse, pExpr, pSrcList);
+ if( cnt==1 ){
+ assert( pNC!=0 );
+ sqlite3AuthRead(pParse, pExpr, pNC->pSrcList);
+ }
return cnt!=1;
}
/*
-** This routine walks an expression tree and resolves references to
-** table columns. Nodes of the form ID.ID or ID resolve into an
-** index to the table in the table list and a column offset. The
-** Expr.opcode for such nodes is changed to TK_COLUMN. The Expr.iTable
-** value is changed to the index of the referenced table in pTabList
-** plus the "base" value. The base value will ultimately become the
-** VDBE cursor number for a cursor that is pointing into the referenced
-** table. The Expr.iColumn value is changed to the index of the column
-** of the referenced table. The Expr.iColumn value for the special
-** ROWID column is -1. Any INTEGER PRIMARY KEY column is tried as an
-** alias for ROWID.
-**
-** We also check for instances of the IN operator. IN comes in two
-** forms:
-**
-** expr IN (exprlist)
-** and
-** expr IN (SELECT ...)
+** pExpr is a node that defines a function of some kind. It might
+** be a syntactic function like "count(x)" or it might be a function
+** that implements an operator, like "a LIKE b".
**
-** The first form is handled by creating a set holding the list
-** of allowed values. The second form causes the SELECT to generate
-** a temporary table.
+** This routine makes *pzName point to the name of the function and
+** *pnName hold the number of characters in the function name.
+*/
+static void getFunctionName(Expr *pExpr, const char **pzName, int *pnName){
+ switch( pExpr->op ){
+ case TK_FUNCTION: {
+ *pzName = pExpr->token.z;
+ *pnName = pExpr->token.n;
+ break;
+ }
+ case TK_LIKE: {
+ *pzName = "like";
+ *pnName = 4;
+ break;
+ }
+ case TK_GLOB: {
+ *pzName = "glob";
+ *pnName = 4;
+ break;
+ }
+ case TK_CTIME: {
+ *pzName = "current_time";
+ *pnName = 12;
+ break;
+ }
+ case TK_CDATE: {
+ *pzName = "current_date";
+ *pnName = 12;
+ break;
+ }
+ case TK_CTIMESTAMP: {
+ *pzName = "current_timestamp";
+ *pnName = 17;
+ break;
+ }
+ }
+}
+
+/*
+** This routine is designed as an xFunc for walkExprTree().
**
-** This routine also looks for scalar SELECTs that are part of an expression.
-** If it finds any, it generates code to write the value of that select
-** into a memory cell.
+** Resolve symbolic names into TK_COLUMN operators for the current
+** node in the expression tree. Return 0 to continue the search down
+** the tree or 2 to abort the tree walk.
**
-** Unknown columns or tables provoke an error. The function returns
-** the number of errors seen and leaves an error message on pParse->zErrMsg.
+** This routine also does error checking and name resolution for
+** function names. The operator for aggregate functions is changed
+** to TK_AGG_FUNCTION.
*/
-int sqlite3ExprResolveIds(
- Parse *pParse, /* The parser context */
- SrcList *pSrcList, /* List of tables used to resolve column names */
- ExprList *pEList, /* List of expressions used to resolve "AS" */
- Expr *pExpr /* The expression to be analyzed. */
-){
- int i;
-
- if( pExpr==0 || pSrcList==0 ) return 0;
- for(i=0; i<pSrcList->nSrc; i++){
- assert( pSrcList->a[i].iCursor>=0 && pSrcList->a[i].iCursor<pParse->nTab );
+static int nameResolverStep(void *pArg, Expr *pExpr){
+ NameContext *pNC = (NameContext*)pArg;
+ SrcList *pSrcList;
+ Parse *pParse;
+
+ if( pExpr==0 ) return 1;
+ assert( pNC!=0 );
+ pSrcList = pNC->pSrcList;
+ pParse = pNC->pParse;
+
+ if( ExprHasAnyProperty(pExpr, EP_Resolved) ) return 1;
+ ExprSetProperty(pExpr, EP_Resolved);
+#ifndef NDEBUG
+ if( pSrcList ){
+ int i;
+ for(i=0; i<pSrcList->nSrc; i++){
+ assert( pSrcList->a[i].iCursor>=0 && pSrcList->a[i].iCursor<pParse->nTab);
+ }
}
+#endif
switch( pExpr->op ){
/* Double-quoted strings (ex: "abc") are used as identifiers if
** possible. Otherwise they remain as strings. Single-quoted
@@ -867,13 +1045,11 @@ int sqlite3ExprResolveIds(
if( pExpr->token.z[0]=='\'' ) break;
/* Fall thru into the TK_ID case if this is a double-quoted string */
}
- /* A lone identifier is the name of a columnd.
+ /* A lone identifier is the name of a column.
*/
case TK_ID: {
- if( lookupName(pParse, 0, 0, &pExpr->token, pSrcList, pEList, pExpr) ){
- return 1;
- }
- break;
+ lookupName(pParse, 0, 0, &pExpr->token, pNC, pExpr);
+ return 1;
}
/* A table name and column name: ID.ID
@@ -885,6 +1061,7 @@ int sqlite3ExprResolveIds(
Token *pDb;
Expr *pRight;
+ /* if( pSrcList==0 ) break; */
pRight = pExpr->pRight;
if( pRight->op==TK_ID ){
pDb = 0;
@@ -896,22 +1073,171 @@ int sqlite3ExprResolveIds(
pTable = &pRight->pLeft->token;
pColumn = &pRight->pRight->token;
}
- if( lookupName(pParse, pDb, pTable, pColumn, pSrcList, 0, pExpr) ){
- return 1;
+ lookupName(pParse, pDb, pTable, pColumn, pNC, pExpr);
+ return 1;
+ }
+
+ /* Resolve function names
+ */
+ case TK_CTIME:
+ case TK_CTIMESTAMP:
+ case TK_CDATE:
+ case TK_GLOB:
+ case TK_LIKE:
+ case TK_FUNCTION: {
+ ExprList *pList = pExpr->pList; /* The argument list */
+ int n = pList ? pList->nExpr : 0; /* Number of arguments */
+ int no_such_func = 0; /* True if no such function exists */
+ int wrong_num_args = 0; /* True if wrong number of arguments */
+ int is_agg = 0; /* True if is an aggregate function */
+ int i;
+ int nId; /* Number of characters in function name */
+ const char *zId; /* The function name. */
+ FuncDef *pDef; /* Information about the function */
+ int enc = pParse->db->enc; /* The database encoding */
+
+ getFunctionName(pExpr, &zId, &nId);
+ pDef = sqlite3FindFunction(pParse->db, zId, nId, n, enc, 0);
+ if( pDef==0 ){
+ pDef = sqlite3FindFunction(pParse->db, zId, nId, -1, enc, 0);
+ if( pDef==0 ){
+ no_such_func = 1;
+ }else{
+ wrong_num_args = 1;
+ }
+ }else{
+ is_agg = pDef->xFunc==0;
+ }
+ if( is_agg && !pNC->allowAgg ){
+ sqlite3ErrorMsg(pParse, "misuse of aggregate function %.*s()", nId,zId);
+ pNC->nErr++;
+ is_agg = 0;
+ }else if( no_such_func ){
+ sqlite3ErrorMsg(pParse, "no such function: %.*s", nId, zId);
+ pNC->nErr++;
+ }else if( wrong_num_args ){
+ sqlite3ErrorMsg(pParse,"wrong number of arguments to function %.*s()",
+ nId, zId);
+ pNC->nErr++;
+ }
+ if( is_agg ){
+ pExpr->op = TK_AGG_FUNCTION;
+ pNC->hasAgg = 1;
+ }
+ if( is_agg ) pNC->allowAgg = 0;
+ for(i=0; pNC->nErr==0 && i<n; i++){
+ walkExprTree(pList->a[i].pExpr, nameResolverStep, pNC);
+ }
+ if( is_agg ) pNC->allowAgg = 1;
+ /* FIX ME: Compute pExpr->affinity based on the expected return
+ ** type of the function
+ */
+ return is_agg;
+ }
+#ifndef SQLITE_OMIT_SUBQUERY
+ case TK_SELECT:
+ case TK_EXISTS:
+#endif
+ case TK_IN: {
+ if( pExpr->pSelect ){
+ int nRef = pNC->nRef;
+ sqlite3SelectResolve(pParse, pExpr->pSelect, pNC);
+ assert( pNC->nRef>=nRef );
+ if( nRef!=pNC->nRef ){
+ ExprSetProperty(pExpr, EP_VarSelect);
+ }
}
- break;
}
+ }
+ return 0;
+}
+/*
+** This routine walks an expression tree and resolves references to
+** table columns. Nodes of the form ID.ID or ID resolve into an
+** index to the table in the table list and a column offset. The
+** Expr.opcode for such nodes is changed to TK_COLUMN. The Expr.iTable
+** value is changed to the index of the referenced table in pTabList
+** plus the "base" value. The base value will ultimately become the
+** VDBE cursor number for a cursor that is pointing into the referenced
+** table. The Expr.iColumn value is changed to the index of the column
+** of the referenced table. The Expr.iColumn value for the special
+** ROWID column is -1. Any INTEGER PRIMARY KEY column is tried as an
+** alias for ROWID.
+**
+** Also resolve function names and check the functions for proper
+** usage. Make sure all function names are recognized and all functions
+** have the correct number of arguments. Leave an error message
+** in pParse->zErrMsg if anything is amiss. Return the number of errors.
+**
+** If the expression contains aggregate functions then set the EP_Agg
+** property on the expression.
+*/
+int sqlite3ExprResolveNames(
+ NameContext *pNC, /* Namespace to resolve expressions in. */
+ Expr *pExpr /* The expression to be analyzed. */
+){
+ if( pExpr==0 ) return 0;
+ walkExprTree(pExpr, nameResolverStep, pNC);
+ if( pNC->nErr>0 ){
+ ExprSetProperty(pExpr, EP_Error);
+ }
+ return ExprHasProperty(pExpr, EP_Error);
+}
+
+/*
+** A pointer instance of this structure is used to pass information
+** through walkExprTree into codeSubqueryStep().
+*/
+typedef struct QueryCoder QueryCoder;
+struct QueryCoder {
+ Parse *pParse; /* The parsing context */
+ NameContext *pNC; /* Namespace of first enclosing query */
+};
+
+
+/*
+** Generate code for subqueries and IN operators.
+**
+** IN operators comes in two forms:
+**
+** expr IN (exprlist)
+** and
+** expr IN (SELECT ...)
+**
+** The first form is handled by creating a set holding the list
+** of allowed values. The second form causes the SELECT to generate
+** a temporary table.
+*/
+#ifndef SQLITE_OMIT_SUBQUERY
+void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
+ int label = 0; /* Address after sub-select code */
+ 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).
+ */
+ 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);
+ 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;
- Vdbe *v = sqlite3GetVdbe(pParse);
KeyInfo keyInfo;
int addr; /* Address of OP_OpenTemp instruction */
- if( v==0 ) return 1;
- if( sqlite3ExprResolveIds(pParse, pSrcList, pEList, pExpr->pLeft) ){
- return 1;
- }
affinity = sqlite3ExprAffinity(pExpr->pLeft);
/* Whether this is an 'x IN(SELECT...)' or an 'x IN(<exprlist>)'
@@ -970,10 +1296,7 @@ int sqlite3ExprResolveIds(
if( !sqlite3ExprIsConstant(pE2) ){
sqlite3ErrorMsg(pParse,
"right-hand side of IN operator must be constant");
- return 1;
- }
- if( sqlite3ExprCheck(pParse, pE2, 0, 0) ){
- return 1;
+ return;
}
/* Evaluate the expression and insert it into the temp table */
@@ -984,183 +1307,43 @@ int sqlite3ExprResolveIds(
}
}
sqlite3VdbeChangeP3(v, addr, (void *)&keyInfo, P3_KEYINFO);
-
break;
}
+ case TK_EXISTS:
case TK_SELECT: {
/* This has to be a scalar SELECT. Generate code to put the
** value of this select in a memory cell and record the number
** of the memory cell in iColumn.
*/
- pExpr->iColumn = pParse->nMem++;
- if(sqlite3Select(pParse, pExpr->pSelect, SRT_Mem,pExpr->iColumn,0,0,0,0)){
- return 1;
- }
- break;
- }
-
- /* For all else, just recursively walk the tree */
- default: {
- if( pExpr->pLeft
- && sqlite3ExprResolveIds(pParse, pSrcList, pEList, pExpr->pLeft) ){
- return 1;
- }
- if( pExpr->pRight
- && sqlite3ExprResolveIds(pParse, pSrcList, pEList, pExpr->pRight) ){
- return 1;
- }
- if( pExpr->pList ){
- int i;
- ExprList *pList = pExpr->pList;
- for(i=0; i<pList->nExpr; i++){
- Expr *pArg = pList->a[i].pExpr;
- if( sqlite3ExprResolveIds(pParse, pSrcList, pEList, pArg) ){
- return 1;
- }
- }
- }
- }
- }
- return 0;
-}
-
-/*
-** pExpr is a node that defines a function of some kind. It might
-** be a syntactic function like "count(x)" or it might be a function
-** that implements an operator, like "a LIKE b".
-**
-** This routine makes *pzName point to the name of the function and
-** *pnName hold the number of characters in the function name.
-*/
-static void getFunctionName(Expr *pExpr, const char **pzName, int *pnName){
- switch( pExpr->op ){
- case TK_FUNCTION: {
- *pzName = pExpr->token.z;
- *pnName = pExpr->token.n;
- break;
- }
- case TK_LIKE: {
- *pzName = "like";
- *pnName = 4;
- break;
- }
- case TK_GLOB: {
- *pzName = "glob";
- *pnName = 4;
- break;
- }
- default: {
- *pzName = "can't happen";
- *pnName = 12;
- break;
- }
- }
-}
-
-/*
-** Error check the functions in an expression. Make sure all
-** function names are recognized and all functions have the correct
-** number of arguments. Leave an error message in pParse->zErrMsg
-** if anything is amiss. Return the number of errors.
-**
-** if pIsAgg is not null and this expression is an aggregate function
-** (like count(*) or max(value)) then write a 1 into *pIsAgg.
-*/
-int sqlite3ExprCheck(Parse *pParse, Expr *pExpr, int allowAgg, int *pIsAgg){
- int nErr = 0;
- if( pExpr==0 ) return 0;
- switch( pExpr->op ){
- case TK_GLOB:
- case TK_LIKE:
- case TK_FUNCTION: {
- int n = pExpr->pList ? pExpr->pList->nExpr : 0; /* Number of arguments */
- int no_such_func = 0; /* True if no such function exists */
- int wrong_num_args = 0; /* True if wrong number of arguments */
- int is_agg = 0; /* True if is an aggregate function */
- int i;
- int nId; /* Number of characters in function name */
- const char *zId; /* The function name. */
- FuncDef *pDef;
- int enc = pParse->db->enc;
+ int sop;
+ Select *pSel;
- getFunctionName(pExpr, &zId, &nId);
- pDef = sqlite3FindFunction(pParse->db, zId, nId, n, enc, 0);
- if( pDef==0 ){
- pDef = sqlite3FindFunction(pParse->db, zId, nId, -1, enc, 0);
- if( pDef==0 ){
- no_such_func = 1;
- }else{
- wrong_num_args = 1;
- }
+ pExpr->iColumn = pParse->nMem++;
+ pSel = pExpr->pSelect;
+ if( pExpr->op==TK_SELECT ){
+ sop = SRT_Mem;
}else{
- is_agg = pDef->xFunc==0;
- }
- if( is_agg && !allowAgg ){
- sqlite3ErrorMsg(pParse, "misuse of aggregate function %.*s()", nId, zId);
- nErr++;
- is_agg = 0;
- }else if( no_such_func ){
- sqlite3ErrorMsg(pParse, "no such function: %.*s", nId, zId);
- nErr++;
- }else if( wrong_num_args ){
- sqlite3ErrorMsg(pParse,"wrong number of arguments to function %.*s()",
- nId, zId);
- nErr++;
- }
- if( is_agg ){
- pExpr->op = TK_AGG_FUNCTION;
- if( pIsAgg ) *pIsAgg = 1;
- }
- for(i=0; nErr==0 && i<n; i++){
- nErr = sqlite3ExprCheck(pParse, pExpr->pList->a[i].pExpr,
- allowAgg && !is_agg, pIsAgg);
- }
- /* FIX ME: Compute pExpr->affinity based on the expected return
- ** type of the function
- */
- }
- default: {
- if( pExpr->pLeft ){
- nErr = sqlite3ExprCheck(pParse, pExpr->pLeft, allowAgg, pIsAgg);
- }
- if( nErr==0 && pExpr->pRight ){
- nErr = sqlite3ExprCheck(pParse, pExpr->pRight, allowAgg, pIsAgg);
- }
- if( nErr==0 && pExpr->pList ){
- int n = pExpr->pList->nExpr;
- int i;
- for(i=0; nErr==0 && i<n; i++){
- Expr *pE2 = pExpr->pList->a[i].pExpr;
- nErr = sqlite3ExprCheck(pParse, pE2, allowAgg, pIsAgg);
- }
+ static const Token one = { "1", 0, 1 };
+ sop = SRT_Exists;
+ sqlite3ExprListDelete(pSel->pEList);
+ pSel->pEList = sqlite3ExprListAppend(0,
+ sqlite3Expr(TK_INTEGER, 0, 0, &one), 0);
}
+ sqlite3Select(pParse, pSel, sop, pExpr->iColumn, 0, 0, 0, 0);
break;
}
}
- return nErr;
-}
-/*
-** Call sqlite3ExprResolveIds() followed by sqlite3ExprCheck().
-**
-** This routine is provided as a convenience since it is very common
-** to call ResolveIds() and Check() back to back.
-*/
-int sqlite3ExprResolveAndCheck(
- Parse *pParse, /* The parser context */
- SrcList *pSrcList, /* List of tables used to resolve column names */
- ExprList *pEList, /* List of expressions used to resolve "AS" */
- Expr *pExpr, /* The expression to be analyzed. */
- int allowAgg, /* True to allow aggregate expressions */
- int *pIsAgg /* Set to TRUE if aggregates are found */
-){
- if( pExpr==0 ) return 0;
- if( sqlite3ExprResolveIds(pParse,pSrcList,pEList,pExpr) ){
- return 1;
+ if( pExpr->pSelect ){
+ sqlite3VdbeAddOp(v, OP_AggContextPop, 0, 0);
+ }
+ if( label<0 ){
+ sqlite3VdbeResolveLabel(v, label);
}
- return sqlite3ExprCheck(pParse, pExpr, allowAgg, pIsAgg);
+ return;
}
+#endif /* SQLITE_OMIT_SUBQUERY */
/*
** Generate an instruction that will put the integer describe by
@@ -1190,12 +1373,16 @@ static void codeInteger(Vdbe *v, const char *z, int n){
void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
Vdbe *v = pParse->pVdbe;
int op;
- if( v==0 || pExpr==0 ) return;
+ if( v==0 ) return;
+ if( pExpr==0 ){
+ sqlite3VdbeAddOp(v, OP_String8, 0, 0); /* Empty expression evals to NULL */
+ return;
+ }
op = pExpr->op;
switch( op ){
case TK_COLUMN: {
- if( pParse->useAgg ){
- sqlite3VdbeAddOp(v, OP_AggGet, 0, pExpr->iAgg);
+ if( !pParse->fillAgg && pExpr->iAgg>=0 ){
+ sqlite3VdbeAddOp(v, OP_AggGet, pExpr->iAggCtx, pExpr->iAgg);
}else if( pExpr->iColumn>=0 ){
sqlite3VdbeAddOp(v, OP_Column, pExpr->iTable, pExpr->iColumn);
#ifndef NDEBUG
@@ -1220,12 +1407,14 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
sqlite3VdbeDequoteP3(v, -1);
break;
}
+#ifndef SQLITE_OMIT_BLOB_LITERAL
case TK_BLOB: {
assert( TK_BLOB==OP_HexBlob );
sqlite3VdbeOp3(v, op, 0, 0, pExpr->token.z+1, pExpr->token.n-1);
sqlite3VdbeDequoteP3(v, -1);
break;
}
+#endif
case TK_NULL: {
sqlite3VdbeAddOp(v, OP_String8, 0, 0);
break;
@@ -1237,6 +1426,10 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
}
break;
}
+ case TK_REGISTER: {
+ sqlite3VdbeAddOp(v, OP_MemLoad, pExpr->iTable, 0);
+ break;
+ }
case TK_LT:
case TK_LE:
case TK_GT:
@@ -1323,6 +1516,9 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
sqlite3VdbeAddOp(v, OP_AggGet, 0, pExpr->iAgg);
break;
}
+ case TK_CDATE:
+ case TK_CTIME:
+ case TK_CTIMESTAMP:
case TK_GLOB:
case TK_LIKE:
case TK_FUNCTION: {
@@ -1354,7 +1550,10 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
sqlite3VdbeOp3(v, OP_Function, nExpr, p2, (char*)pDef, P3_FUNCDEF);
break;
}
+#ifndef SQLITE_OMIT_SUBQUERY
+ case TK_EXISTS:
case TK_SELECT: {
+ sqlite3CodeSubselect(pParse, pExpr);
sqlite3VdbeAddOp(v, OP_MemLoad, pExpr->iColumn, 0);
VdbeComment((v, "# load subquery result"));
break;
@@ -1362,6 +1561,7 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
case TK_IN: {
int addr;
char affinity;
+ sqlite3CodeSubselect(pParse, pExpr);
/* Figure out the affinity to use to create a key from the results
** of the expression. affinityStr stores a static string suitable for
@@ -1386,6 +1586,7 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
break;
}
+#endif
case TK_BETWEEN: {
Expr *pLeft = pExpr->pLeft;
struct ExprList_item *pLItem = pExpr->pList->a;
@@ -1452,6 +1653,7 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
sqlite3VdbeResolveLabel(v, expr_end_label);
break;
}
+#ifndef SQLITE_OMIT_TRIGGER
case TK_RAISE: {
if( !pParse->trigStack ){
sqlite3ErrorMsg(pParse,
@@ -1472,10 +1674,38 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr){
VdbeComment((v, "# raise(IGNORE)"));
}
}
+#endif
break;
}
}
+#ifndef SQLITE_OMIT_TRIGGER
+/*
+** Generate code that evalutes the given expression and leaves the result
+** on the stack. See also sqlite3ExprCode().
+**
+** This routine might also cache the result and modify the pExpr tree
+** so that it will make use of the cached result on subsequent evaluations
+** rather than evaluate the whole expression again. Trivial expressions are
+** not cached. If the expression is cached, its result is stored in a
+** memory location.
+*/
+void sqlite3ExprCodeAndCache(Parse *pParse, Expr *pExpr){
+ Vdbe *v = pParse->pVdbe;
+ int iMem;
+ int addr1, addr2;
+ if( v==0 ) return;
+ addr1 = sqlite3VdbeCurrentAddr(v);
+ sqlite3ExprCode(pParse, pExpr);
+ addr2 = sqlite3VdbeCurrentAddr(v);
+ if( addr2>addr1+1 || sqlite3VdbeGetOp(v, addr1)->opcode==OP_Function ){
+ iMem = pExpr->iTable = pParse->nMem++;
+ sqlite3VdbeAddOp(v, OP_MemStore, iMem, 0);
+ pExpr->op = TK_REGISTER;
+ }
+}
+#endif
+
/*
** Generate code that pushes the value of every element of the given
** expression list onto the stack.
@@ -1737,6 +1967,8 @@ int sqlite3ExprCompare(Expr *pA, Expr *pB){
/*
** 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.
*/
static int appendAggInfo(Parse *pParse){
if( (pParse->nAgg & 0x7)==0 ){
@@ -1752,80 +1984,91 @@ static int appendAggInfo(Parse *pParse){
}
/*
-** Analyze the given expression looking for aggregate functions and
-** for variables that need to be added to the pParse->aAgg[] array.
-** Make additional entries to the pParse->aAgg[] array as necessary.
+** This is an xFunc for walkExprTree() used to implement
+** sqlite3ExprAnalyzeAggregates(). See sqlite3ExprAnalyzeAggregates
+** for additional information.
**
-** This routine should only be called after the expression has been
-** analyzed by sqlite3ExprResolveIds() and sqlite3ExprCheck().
-**
-** If errors are seen, leave an error message in zErrMsg and return
-** the number of errors.
+** This routine analyzes the aggregate function at pExpr.
*/
-int sqlite3ExprAnalyzeAggregates(Parse *pParse, Expr *pExpr){
+static int analyzeAggregate(void *pArg, Expr *pExpr){
int i;
AggExpr *aAgg;
- int nErr = 0;
+ NameContext *pNC = (NameContext *)pArg;
+ Parse *pParse = pNC->pParse;
+ SrcList *pSrcList = pNC->pSrcList;
- if( pExpr==0 ) return 0;
switch( pExpr->op ){
case TK_COLUMN: {
- 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;
+ 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;
+ }
+ }
+ 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>=pParse->nAgg ){
- i = appendAggInfo(pParse);
- if( i<0 ) return 1;
- pParse->aAgg[i].isAgg = 0;
- pParse->aAgg[i].pExpr = pExpr;
- }
- pExpr->iAgg = i;
- break;
+ return 1;
}
case TK_AGG_FUNCTION: {
- aAgg = pParse->aAgg;
- for(i=0; i<pParse->nAgg; i++){
- if( !aAgg[i].isAgg ) continue;
- if( sqlite3ExprCompare(aAgg[i].pExpr, pExpr) ){
- break;
+ 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) ){
+ break;
+ }
}
- }
- if( i>=pParse->nAgg ){
- 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);
- }
- pExpr->iAgg = i;
- break;
- }
- default: {
- if( pExpr->pLeft ){
- nErr = sqlite3ExprAnalyzeAggregates(pParse, pExpr->pLeft);
- }
- if( nErr==0 && pExpr->pRight ){
- nErr = sqlite3ExprAnalyzeAggregates(pParse, pExpr->pRight);
- }
- if( nErr==0 && pExpr->pList ){
- int n = pExpr->pList->nExpr;
- int i;
- for(i=0; nErr==0 && i<n; i++){
- nErr = sqlite3ExprAnalyzeAggregates(pParse, pExpr->pList->a[i].pExpr);
+ if( i>=pParse->nAgg ){
+ 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);
}
+ pExpr->iAgg = i;
+ return 1;
}
- break;
}
}
- return nErr;
+ if( pExpr->pSelect ){
+ pNC->nDepth++;
+ walkSelectExpr(pExpr->pSelect, analyzeAggregate, pNC);
+ pNC->nDepth--;
+ }
+ return 0;
+}
+
+/*
+** Analyze the given expression looking for aggregate functions and
+** for variables that need to be added to the pParse->aAgg[] array.
+** Make additional entries to the pParse->aAgg[] array as necessary.
+**
+** This routine should only be called after the expression has been
+** analyzed by sqlite3ExprResolveNames().
+**
+** If errors are seen, leave an error message in zErrMsg and return
+** the number of errors.
+*/
+int sqlite3ExprAnalyzeAggregates(NameContext *pNC, Expr *pExpr){
+ int nErr = pNC->pParse->nErr;
+ walkExprTree(pExpr, analyzeAggregate, pNC);
+ return pNC->pParse->nErr - nErr;
}
/*
@@ -1917,7 +2160,10 @@ FuncDef *sqlite3FindFunction(
pBest->iPrefEnc = enc;
memcpy(pBest->zName, zName, nName);
pBest->zName[nName] = 0;
- sqlite3HashInsert(&db->aFunc, pBest->zName, nName, (void*)pBest);
+ if( pBest==sqlite3HashInsert(&db->aFunc,pBest->zName,nName,(void*)pBest) ){
+ sqliteFree(pBest);
+ return 0;
+ }
}
if( pBest && (pBest->xStep || pBest->xFunc || createFlag) ){