diff options
author | drh <drh@noemail.net> | 2005-01-18 04:00:42 +0000 |
---|---|---|
committer | drh <drh@noemail.net> | 2005-01-18 04:00:42 +0000 |
commit | 73b211abedb90d0012f5fce39563b2c135552c16 (patch) | |
tree | 47f21200def9715dd53a01ab87d223a8bc647775 /src | |
parent | 626a879a25f01431a1212c22b5a99bb768e44b32 (diff) | |
download | sqlite-73b211abedb90d0012f5fce39563b2c135552c16.tar.gz sqlite-73b211abedb90d0012f5fce39563b2c135552c16.zip |
Refinements to the name resolution logic. Change the name of the
keywordhash.c file to keywordhash.h. (CVS 2229)
FossilOrigin-Name: 0142ae6f0004bf18a1c2d8e49c09d2a9a27d6369
Diffstat (limited to 'src')
-rw-r--r-- | src/build.c | 4 | ||||
-rw-r--r-- | src/delete.c | 4 | ||||
-rw-r--r-- | src/expr.c | 72 | ||||
-rw-r--r-- | src/insert.c | 4 | ||||
-rw-r--r-- | src/select.c | 14 | ||||
-rw-r--r-- | src/sqliteInt.h | 5 | ||||
-rw-r--r-- | src/tokenize.c | 8 | ||||
-rw-r--r-- | src/trigger.c | 2 | ||||
-rw-r--r-- | src/update.c | 6 |
9 files changed, 70 insertions, 49 deletions
diff --git a/src/build.c b/src/build.c index ee505d2ef..7e304ef64 100644 --- a/src/build.c +++ b/src/build.c @@ -22,7 +22,7 @@ ** COMMIT ** ROLLBACK ** -** $Id: build.c,v 1.292 2005/01/17 22:08:19 drh Exp $ +** $Id: build.c,v 1.293 2005/01/18 04:00:44 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> @@ -884,7 +884,7 @@ void sqlite3AddDefaultValue(Parse *pParse, Expr *pExpr){ }else{ sqlite3ExprDelete(pCol->pDflt); pCol->pDflt = sqlite3ExprDup(pExpr); - sqlite3ExprResolveNames(pParse,0,0,pExpr,0,0,0); + sqlite3ExprResolveNames(pParse,0,0,pExpr,0,0); } sqlite3ExprDelete(pExpr); } diff --git a/src/delete.c b/src/delete.c index 0bc24577b..f81ec3f7a 100644 --- a/src/delete.c +++ b/src/delete.c @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** in order to generate code for DELETE FROM statements. ** -** $Id: delete.c,v 1.96 2005/01/17 22:08:19 drh Exp $ +** $Id: delete.c,v 1.97 2005/01/18 04:00:44 drh Exp $ */ #include "sqliteInt.h" @@ -150,7 +150,7 @@ void sqlite3DeleteFrom( */ assert( pTabList->nSrc==1 ); iCur = pTabList->a[0].iCursor = pParse->nTab++; - if( sqlite3ExprResolveNames(pParse, pTabList, 0, pWhere, 0, 0, 1) ){ + if( sqlite3ExprResolveNames(pParse, pTabList, 0, pWhere, 0, 1) ){ goto delete_from_cleanup; } diff --git a/src/expr.c b/src/expr.c index 7c0fb70cb..36cfa2821 100644 --- a/src/expr.c +++ b/src/expr.c @@ -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.179 2005/01/17 22:08:19 drh Exp $ +** $Id: expr.c,v 1.180 2005/01/18 04:00:44 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> @@ -562,6 +562,7 @@ void sqlite3ExprListDelete(ExprList *pList){ /* ** Walk an expression tree. Call xFunc for each node visited. +** ** 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 @@ -594,10 +595,14 @@ static int walkExprTree(Expr *pExpr, int (*xFunc)(void*,Expr*), void *pArg){ ** This routine is designed as an xFunc for walkExprTree(). ** ** pArg is really a pointer to an integer. If we can tell by looking -** at just pExpr and none of its children that the expression is a -** constant, then set *pArg to 1 and return 0. If we can tell that -** the expression is not a constant, then set *pArg to 0 and return 0. -** If we need to look at child nodes, return 1. +** 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 ){ @@ -628,7 +633,7 @@ int sqlite3ExprIsConstant(Expr *p){ } /* -** If the given expression codes a constant integer that is small enough +** 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. @@ -709,6 +714,7 @@ static int lookupName( 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); @@ -872,6 +878,7 @@ static int lookupName( } sqlite3ErrorMsg(pParse, zErr, z); sqliteFree(z); + pTopNC->nErr++; } /* If a column from a table in pSrcList is referenced, then record @@ -957,9 +964,13 @@ static void getFunctionName(Expr *pExpr, const char **pzName, int *pnName){ /* ** This routine is designed as an xFunc for walkExprTree(). ** -** Resolve symbolic names into TK_COLUMN operands for the current +** 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 1 to abort the tree walk. +** the tree or 2 to abort the tree walk. +** +** This routine also does error checking and name resolution for +** function names. The operator for aggregate functions is changed +** to TK_AGG_FUNCTION. */ static int nameResolverStep(void *pArg, Expr *pExpr){ NameContext *pNC = (NameContext*)pArg; @@ -1039,9 +1050,8 @@ static int nameResolverStep(void *pArg, Expr *pExpr){ int i; int nId; /* Number of characters in function name */ const char *zId; /* The function name. */ - FuncDef *pDef; - int enc = pParse->db->enc; - NameContext ncParam; /* Name context for parameters */ + 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); @@ -1071,14 +1081,11 @@ static int nameResolverStep(void *pArg, Expr *pExpr){ pExpr->op = TK_AGG_FUNCTION; pNC->hasAgg = 1; } - ncParam = *pNC; - if( is_agg ) ncParam.allowAgg = 0; + if( is_agg ) pNC->allowAgg = 0; for(i=0; pNC->nErr==0 && i<n; i++){ - walkExprTree(pList->a[i].pExpr, nameResolverStep, &ncParam); - pNC->nErr += ncParam.nErr; - if( ncParam.hasAgg ) pNC->hasAgg = 1; + walkExprTree(pList->a[i].pExpr, nameResolverStep, pNC); } - if( pNC->nErr ) return 2; + if( is_agg ) pNC->allowAgg = 1; /* FIX ME: Compute pExpr->affinity based on the expected return ** type of the function */ @@ -1106,8 +1113,8 @@ static int nameResolverStep(void *pArg, Expr *pExpr){ ** 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. +** If the expression contains aggregate functions then set the EP_Agg +** property on the expression. */ int sqlite3ExprResolveNames( Parse *pParse, /* The parser context */ @@ -1115,29 +1122,33 @@ int sqlite3ExprResolveNames( 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 */ int codeSubquery /* If true, then generate code for subqueries too */ ){ NameContext sNC; + if( pExpr==0 ) return 0; memset(&sNC, 0, sizeof(sNC)); sNC.pSrcList = pSrcList; sNC.pParse = pParse; sNC.pEList = pEList; sNC.allowAgg = allowAgg; walkExprTree(pExpr, nameResolverStep, &sNC); - if( pIsAgg && sNC.hasAgg ) *pIsAgg = 1; - if( sNC.nErr==0 && codeSubquery ){ - sNC.nErr += sqlite3ExprCodeSubquery(pParse, pExpr); + if( sNC.hasAgg ){ + ExprSetProperty(pExpr, EP_Agg); + } + if( sNC.nErr>0 ){ + ExprSetProperty(pExpr, EP_Error); + }else if( codeSubquery && sqlite3ExprCodeSubquery(pParse, pExpr) ){ + return 1; } - return sNC.nErr + pParse->nErr; + return ExprHasProperty(pExpr, EP_Error); } /* ** Generate code for subqueries and IN operators. ** -** IN comes in two forms: +** IN operators comes in two forms: ** ** expr IN (exprlist) ** and @@ -1150,6 +1161,10 @@ int sqlite3ExprResolveNames( ** 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. +** +** This routine is a callback for wallExprTree() used to implement +** sqlite3ExprCodeSubquery(). See comments on those routines for +** additional information. */ static int codeSubqueryStep(void *pArg, Expr *pExpr){ Parse *pParse = (Parse*)pArg; @@ -1222,7 +1237,7 @@ static int codeSubqueryStep(void *pArg, Expr *pExpr){ "right-hand side of IN operator must be constant"); return 2; } - if( sqlite3ExprResolveNames(pParse, 0, 0, pE2, 0, 0, 0) ){ + if( sqlite3ExprResolveNames(pParse, 0, 0, pE2, 0, 0) ){ return 2; } @@ -1251,7 +1266,8 @@ static int codeSubqueryStep(void *pArg, Expr *pExpr){ } /* -** Generate code to evaluate subqueries and IN operators. +** Generate code to evaluate subqueries and IN operators contained +** in expression pExpr. */ int sqlite3ExprCodeSubquery(Parse *pParse, Expr *pExpr){ walkExprTree(pExpr, codeSubqueryStep, pParse); @@ -1869,6 +1885,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 ){ diff --git a/src/insert.c b/src/insert.c index 17b5cf8ee..11b27de2c 100644 --- a/src/insert.c +++ b/src/insert.c @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** to handle INSERT statements in SQLite. ** -** $Id: insert.c,v 1.131 2005/01/17 22:08:19 drh Exp $ +** $Id: insert.c,v 1.132 2005/01/18 04:00:44 drh Exp $ */ #include "sqliteInt.h" @@ -380,7 +380,7 @@ void sqlite3Insert( nColumn = pList->nExpr; dummy.nSrc = 0; for(i=0; i<nColumn; i++){ - if( sqlite3ExprResolveNames(pParse,&dummy,0,pList->a[i].pExpr,0,0,1) ){ + if( sqlite3ExprResolveNames(pParse,&dummy,0,pList->a[i].pExpr,0,1) ){ goto insert_cleanup; } } diff --git a/src/select.c b/src/select.c index dce52c402..c1d2dc9b4 100644 --- a/src/select.c +++ b/src/select.c @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** to handle SELECT statements in SQLite. ** -** $Id: select.c,v 1.223 2005/01/17 22:08:19 drh Exp $ +** $Id: select.c,v 1.224 2005/01/18 04:00:44 drh Exp $ */ #include "sqliteInt.h" @@ -2186,7 +2186,7 @@ static int processOrderGroupBy( sqlite3ExprDelete(pE); pE = pOrderBy->a[i].pExpr = sqlite3ExprDup(pEList->a[iCol-1].pExpr); } - if( sqlite3ExprResolveNames(pParse, pTabList, pEList, pE, isAgg, 0, 1) ){ + if( sqlite3ExprResolveNames(pParse, pTabList, pEList, pE, isAgg, 1) ){ return 1; } if( sqlite3ExprIsConstant(pE) ){ @@ -2355,12 +2355,13 @@ int sqlite3Select( ** Resolve the column names and do a semantics check on all the expressions. */ for(i=0; i<pEList->nExpr; i++){ - if( sqlite3ExprResolveNames(pParse, pTabList, 0, pEList->a[i].pExpr, - 1, &isAgg, 1) ){ + Expr *pX = pEList->a[i].pExpr; + if( sqlite3ExprResolveNames(pParse, pTabList, 0, pX, 1, 1) ){ goto select_end; } + if( ExprHasProperty(pX, EP_Agg) ) isAgg = 1; } - if( sqlite3ExprResolveNames(pParse, pTabList, pEList, pWhere, 0, 0, 1) ){ + if( sqlite3ExprResolveNames(pParse, pTabList, pEList, pWhere, 0, 1) ){ goto select_end; } if( pHaving ){ @@ -2368,9 +2369,10 @@ int sqlite3Select( sqlite3ErrorMsg(pParse, "a GROUP BY clause is required before HAVING"); goto select_end; } - if( sqlite3ExprResolveNames(pParse, pTabList, pEList,pHaving,1,&isAgg,1) ){ + if( sqlite3ExprResolveNames(pParse, pTabList, pEList, pHaving, 1, 1) ){ goto select_end; } + if( ExprHasProperty(pHaving, EP_Agg) ) isAgg = 1; } if( pGroupBy && !isAgg ){ sqlite3ErrorMsg(pParse, "GROUP BY may only be used on aggregate queries"); diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 39393ea86..b85b28d71 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -11,7 +11,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.354 2005/01/17 22:08:19 drh Exp $ +** @(#) $Id: sqliteInt.h,v 1.355 2005/01/18 04:00:44 drh Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ @@ -817,6 +817,7 @@ struct Expr { #define EP_FromJoin 0x0001 /* Originated in ON or USING clause of a join */ #define EP_Agg 0x0002 /* Contains one or more aggregate functions */ #define EP_Resolved 0x0004 /* IDs have been resolved to COLUMNs */ +#define EP_Error 0x0008 /* Expression contains one or more errors */ /* ** These macros can be used to test, set, or clear bits in the @@ -1423,7 +1424,7 @@ char *sqlite3NameFromToken(Token*); int sqlite3ExprCheck(Parse*, Expr*, int, int*); int sqlite3ExprCompare(Expr*, Expr*); int sqliteFuncId(Token*); -int sqlite3ExprResolveNames(Parse*, SrcList*, ExprList*, Expr*, int, int*, int); +int sqlite3ExprResolveNames(Parse*, SrcList*, ExprList*, Expr*, int, int); int sqlite3ExprCodeSubquery(Parse*, Expr*); int sqlite3ExprAnalyzeAggregates(Parse*, Expr*); Vdbe *sqlite3GetVdbe(Parse*); diff --git a/src/tokenize.c b/src/tokenize.c index 725223cef..43490cbeb 100644 --- a/src/tokenize.c +++ b/src/tokenize.c @@ -15,7 +15,7 @@ ** individual tokens and sends those tokens one-by-one over to the ** parser for analysis. ** -** $Id: tokenize.c,v 1.98 2005/01/11 17:59:48 drh Exp $ +** $Id: tokenize.c,v 1.99 2005/01/18 04:00:44 drh Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -28,12 +28,12 @@ ** returned. If the input is not a keyword, TK_ID is returned. ** ** The implementation of this routine was generated by a program, -** mkkeywordhash.c, located in the tool subdirectory of the distribution. +** mkkeywordhash.h, located in the tool subdirectory of the distribution. ** The output of the mkkeywordhash.c program is written into a file -** named keywordhash.c and then included into this source file by +** named keywordhash.h and then included into this source file by ** the #include below. */ -#include "keywordhash.c" +#include "keywordhash.h" /* diff --git a/src/trigger.c b/src/trigger.c index 0fe636971..f63c7c991 100644 --- a/src/trigger.c +++ b/src/trigger.c @@ -766,7 +766,7 @@ int sqlite3CodeRowTrigger( /* code the WHEN clause */ endTrigger = sqlite3VdbeMakeLabel(pParse->pVdbe); whenExpr = sqlite3ExprDup(pTrigger->pWhen); - if( sqlite3ExprResolveNames(pParse, &dummyTablist, 0, whenExpr, 0, 0, 1)){ + if( sqlite3ExprResolveNames(pParse, &dummyTablist, 0, whenExpr, 0, 1) ){ pParse->trigStack = trigStackEntry.pNext; sqlite3ExprDelete(whenExpr); return 1; diff --git a/src/update.c b/src/update.c index 38223ebae..27b9c2458 100644 --- a/src/update.c +++ b/src/update.c @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** to handle UPDATE statements. ** -** $Id: update.c,v 1.101 2005/01/17 22:08:19 drh Exp $ +** $Id: update.c,v 1.102 2005/01/18 04:00:44 drh Exp $ */ #include "sqliteInt.h" @@ -122,7 +122,7 @@ void sqlite3Update( chngRecno = 0; for(i=0; i<pChanges->nExpr; i++){ if( sqlite3ExprResolveNames(pParse, pTabList, 0, - pChanges->a[i].pExpr, 0, 0, 1) ){ + pChanges->a[i].pExpr, 0, 1) ){ goto update_cleanup; } for(j=0; j<pTab->nCol; j++){ @@ -198,7 +198,7 @@ void sqlite3Update( /* Resolve the column names in all the expressions in the ** WHERE clause. */ - if( sqlite3ExprResolveNames(pParse, pTabList, 0, pWhere, 0, 0, 1) ){ + if( sqlite3ExprResolveNames(pParse, pTabList, 0, pWhere, 0, 1) ){ goto update_cleanup; } |