aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordrh <drh@noemail.net>2005-01-18 04:00:42 +0000
committerdrh <drh@noemail.net>2005-01-18 04:00:42 +0000
commit73b211abedb90d0012f5fce39563b2c135552c16 (patch)
tree47f21200def9715dd53a01ab87d223a8bc647775 /src
parent626a879a25f01431a1212c22b5a99bb768e44b32 (diff)
downloadsqlite-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.c4
-rw-r--r--src/delete.c4
-rw-r--r--src/expr.c72
-rw-r--r--src/insert.c4
-rw-r--r--src/select.c14
-rw-r--r--src/sqliteInt.h5
-rw-r--r--src/tokenize.c8
-rw-r--r--src/trigger.c2
-rw-r--r--src/update.c6
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;
}