]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Infrastructure changes to handle name resolution differently. This is needed
authordrh <drh@noemail.net>
Mon, 17 Jan 2005 22:08:19 +0000 (22:08 +0000)
committerdrh <drh@noemail.net>
Mon, 17 Jan 2005 22:08:19 +0000 (22:08 +0000)
to fix various long-standing problems with column names in joins.  It will
also make the implementation of correlated subqueries easier. (CVS 2228)

FossilOrigin-Name: 4a7534396a72ccb300303df28798bb2c50293782

manifest
manifest.uuid
src/build.c
src/delete.c
src/expr.c
src/insert.c
src/select.c
src/sqliteInt.h
src/trigger.c
src/update.c
src/where.c

index be2a887962eb2f555afe186f07b3ee87dfcbbe32..59180f7b344f2c7980e3b1737d003e48ca22f211 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Fix\sa\sbug\sreported\son\sthe\smailing\slist\sconcerning\sa\sconflict\sbetween\s"INSERT\sINTO\s...\sSELECT"\sstatements\sand\sthe\s"SELECT\smax(x)\sFROM\stbl"\soptimization.\s(CVS\s2227)
-D 2005-01-17T08:57:09
+C Infrastructure\schanges\sto\shandle\sname\sresolution\sdifferently.\s\sThis\sis\sneeded\nto\sfix\svarious\slong-standing\sproblems\swith\scolumn\snames\sin\sjoins.\s\sIt\swill\nalso\smake\sthe\simplementation\sof\scorrelated\ssubqueries\seasier.\s(CVS\s2228)
+D 2005-01-17T22:08:19
 F Makefile.in 78d6d0af3725aef32468ac9923444d7645d21a28
 F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457
 F README a01693e454a00cc117967e3f9fdab2d4d52e9bc1
@@ -31,15 +31,15 @@ F src/attach.c e49d09dad9f5f9fb10b4b0c1be5a70ae4c45e689
 F src/auth.c 3b81f2a42f48a62c2c9c9b0eda31a157c681edea
 F src/btree.c 97101cce85304edbaedafc5f39ab12e2dc78b076
 F src/btree.h 74d19cf40ab49fd69abe9e4e12a6c321ad86c497
-F src/build.c 07d50fe1b167c77f183aedd59362d55e1f579163
+F src/build.c 4638b87f5e797e364ff995f8338b281b61dd8be1
 F src/cursor.c f883813759742068890b1f699335872bfa8fdf41
 F src/date.c f3d1f5cd1503dabf426a198f3ebef5afbc122a7f
-F src/delete.c 32277d2834e36c7538c047f14d643751c256c73b
-F src/expr.c 22bc51e18b2e686f3c831d33b2c38b5a3e6733f9
+F src/delete.c 5872f452031f31c6941ef70e9f4e1823e9fecefc
+F src/expr.c 2a9485be4ec44eea0f3eada89f415f2172fc5c2e
 F src/func.c dc188d862d7276ea897655b248e2cb17022686e3
 F src/hash.c a97721a55440b7bea31ffe471bb2f6b4123cddd5
 F src/hash.h 1b0c445e1c89ff2aaad9b4605ba61375af001e84
-F src/insert.c 2a8fadfd7494881632fcae453f115d42a7a58dee
+F src/insert.c 0acf8a8cd21d60c60432c0004586d2aee0ad8d8e
 F src/legacy.c d58ea507bce885298a2c8c3cbb0f4bff5d47830b
 F src/main.c cbe5a05baabad9fabb733065d0fb00c0b36f6ef1
 F src/md5.c 7ae1c39044b95de2f62e066f47bb1deb880a1070
@@ -57,10 +57,10 @@ F src/parse.y ceba179b9703657180963568f54b0e75f33e36e1
 F src/pragma.c ac594f74c90ffec043c43e49358719ffeb491eec
 F src/printf.c 3d20b21cfecadacecac3fb7274e746cb81d3d357
 F src/random.c eff68e3f257e05e81eae6c4d50a51eb88beb4ff3
-F src/select.c f74bdde6e77e7c351084646edbc859b08e0a3414
+F src/select.c cfd5f30611967ebd7c39d4bd448a1b1e263e9fb8
 F src/shell.c 591364a0e9ca4ce53873e21e0294476c0c2b4770
 F src/sqlite.h.in 0d5e48e506845b74a845c9470e01d3f472b59611
-F src/sqliteInt.h 641b348a109a080262d9f3603f2e94143d4383f2
+F src/sqliteInt.h f7ed4e6e112df9af7c85600bfb3b0af02e7b7577
 F src/table.c 25b3ff2b39b7d87e8d4a5da0713d68dfc06cbee9
 F src/tclsqlite.c fd27457b228118be96524dae285146c76efe032b
 F src/test1.c 2e27b110ba5aa16977bad1cc2388553479d73793
@@ -69,8 +69,8 @@ F src/test3.c a72f20066cccd5a7b9f20b7b78fa9b05b47b3020
 F src/test4.c 7c6b9fc33dd1f3f93c7f1ee6e5e6d016afa6c1df
 F src/test5.c 64f08b2a50ef371a1bd68ff206829e7b1b9997f5
 F src/tokenize.c c1d124ec41422c9ec14360ea3a1f98ca4acf7cf1
-F src/trigger.c 98f3b07c08ba01b34cff139ef9687883d325ae8e
-F src/update.c 0979397c41ac29c54fe0cc687a356d8629a633af
+F src/trigger.c 210fe50d4b3c01d3e5f8ef8a7a820117416a992b
+F src/update.c 79a1511104963df3368d9235f9393cfe7f38c027
 F src/utf.c 9bece2c7b94d9002ab1bb900a7658c6f826b0f74
 F src/util.c 63e8d77659df88b292ac2a9dbd4766419b0ea158
 F src/vacuum.c 1a9db113a027461daaf44724c71dd1ebbd064203
@@ -80,7 +80,7 @@ F src/vdbeInt.h f2b5f54d9881bbc89fff02d95f3f825ade68bce2
 F src/vdbeapi.c 0cf3bdc1072616bedc8eec7fc22e3f5a169d33fd
 F src/vdbeaux.c 6c294f7390880a7bb4795c9e0bc605b1a416579a
 F src/vdbemem.c 62fe89471b656a922e9879be005abf690509ead3
-F src/where.c 3a0d08505e298242f6f151f019a05129a4f8704c
+F src/where.c 09defb7d1efb150d323fc253c6534d23e8a73ce6
 F tclinstaller.tcl 36478c3bbfc5b93ceac42d94e3c736937b808432
 F test/all.test 7f0988442ab811dfa41793b5b550f5828ce316f3
 F test/alter.test 95c57a4f461fa81293e0dccef7f83889aadb169a
@@ -269,7 +269,7 @@ F www/tclsqlite.tcl e73f8f8e5f20e8277619433f7970060ab01088fc
 F www/vdbe.tcl 095f106d93875c94b47367384ebc870517431618
 F www/version3.tcl 092a01f5ef430d2c4acc0ae558d74c4bb89638a0
 F www/whentouse.tcl c3b50d3ac31c54be2a1af9b488a89d22f1e6e746
-P 6244252915fa312a6c4d192464023d95aaef4661
-R 8fdfbf5efd695da44259ce4a14c6dc0d
-U danielk1977
-Z f3732671f0bcdc732596f3a051a6bbad
+P 5a9da62ae303800ded99942aed30eadeb3863da3
+R 27952fc035e1cac4b0d3a414cfc9fe27
+U drh
+Z 916e3799f439fba92eda7a2a24dc2de5
index c6146e2d9d0c15865bb4b1784fa6688f7f9e6a8f..2c09d63b5dd70136e828330fdfee8fdbb88d4938 100644 (file)
@@ -1 +1 @@
-5a9da62ae303800ded99942aed30eadeb3863da3
\ No newline at end of file
+4a7534396a72ccb300303df28798bb2c50293782
\ No newline at end of file
index 928926a4b4909d4f8d7eb1d1580e4ef20f0d8e03..ee505d2efa24fdf0f621bac6be5571fb4311dda3 100644 (file)
@@ -22,7 +22,7 @@
 **     COMMIT
 **     ROLLBACK
 **
-** $Id: build.c,v 1.291 2005/01/17 07:53:44 danielk1977 Exp $
+** $Id: build.c,v 1.292 2005/01/17 22:08:19 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);
-    sqlite3ExprCheck(pParse, pExpr, 0, 0);
+    sqlite3ExprResolveNames(pParse,0,0,pExpr,0,0,0);
   }
   sqlite3ExprDelete(pExpr);
 }
index f29d665d3a647964c3e6b1a064082753c59c98f3..0bc24577ba29ad82b1f37e8645271b914587ad9a 100644 (file)
@@ -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.95 2005/01/10 02:48:49 danielk1977 Exp $
+** $Id: delete.c,v 1.96 2005/01/17 22:08:19 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -150,7 +150,7 @@ void sqlite3DeleteFrom(
   */
   assert( pTabList->nSrc==1 );
   iCur = pTabList->a[0].iCursor = pParse->nTab++;
-  if( sqlite3ExprResolveAndCheck(pParse, pTabList, 0, pWhere, 0, 0) ){
+  if( sqlite3ExprResolveNames(pParse, pTabList, 0, pWhere, 0, 0, 1) ){
     goto delete_from_cleanup;
   }
 
index 8e125624af92894e7d6e55dd00a8355374f6a7d9..7c0fb70cbb3284d3c081d8295283d8c4d296a7a1 100644 (file)
@@ -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.178 2005/01/15 01:52:32 drh Exp $
+** $Id: expr.c,v 1.179 2005/01/17 22:08:19 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -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){
@@ -561,43 +561,70 @@ 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.
+** 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.
 **
-** 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 this routine is 1 to abandon the tree walk
+** and 0 to continue.
 */
-int sqlite3ExprIsConstant(Expr *p){
-  switch( p->op ){
+static int walkExprTree(Expr *pExpr, int (*xFunc)(void*,Expr*), void *pArg){
+  ExprList *pList;
+  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;
+    pList = pExpr->pList;
+    if( pList ){
+      int i;
+      struct ExprList_item *pItem;
+      for(i=pList->nExpr, pItem=pList->a; i>0; i--, pItem++){
+        if( walkExprTree(pItem->pExpr, xFunc, pArg) ) return 1;
+      }
+    }
+  }
+  return rc>1;
+}
+
+/*
+** 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.
+*/
+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:
+      *((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:
-    case TK_CTIME:
-    case TK_CTIMESTAMP:
-    case TK_CDATE:
-      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;
+}
+
+/*
+** 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;
 }
 
 /*
@@ -670,8 +697,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 */
@@ -680,7 +706,7 @@ static int lookupName(
   int i, j;            /* Loop counters */
   int cnt = 0;         /* Number of matching column names */
   int cntTab = 0;      /* Number of matching table names */
-  sqlite3 *db = pParse->db;         /* The database */
+  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 */
 
@@ -691,73 +717,44 @@ 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, 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;
+  while( pNC && cnt==0 ){
+    SrcList *pSrcList = pNC->pSrcList;
+    ExprList *pEList = pNC->pEList;
+
+    pNC->nRef++;
+    /* assert( zTab==0 || pEList==0 ); */
+    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++;
+      if( 0==(cntTab++) ){
         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;
+        pMatch = pItem;
       }
-    }
-  }
-
-#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( pTab ){ 
-      int j;
-      Column *pCol = pTab->aCol;
-      
-      pExpr->iDb = pTab->iDb;
-      cntTab++;
-      for(j=0; j < pTab->nCol; j++, pCol++) {
+      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;
@@ -765,43 +762,85 @@ static int lookupName(
         }
       }
     }
-  }
-#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;
-  }
+#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 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( 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;
+    }
+
+    /*
+    ** 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;
+        }
+      } 
+    }
+
+    /* 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;
+    }
   }
 
   /*
@@ -860,53 +899,87 @@ static int lookupName(
   sqlite3ExprDelete(pExpr->pRight);
   pExpr->pRight = 0;
   pExpr->op = TK_COLUMN;
-  sqlite3AuthRead(pParse, pExpr, pSrcList);
+  if( cnt==1 ){
+    assert( pNC!=0 && pNC->pSrcList!=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 ...)
-**
-** 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.
+** 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 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 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;
+    }
+    default: {
+      *pzName = "can't happen";
+      *pnName = 12;
+      break;
+    }
+  }
+}
+
+/*
+** This routine is designed as an xFunc for walkExprTree().
 **
-** Unknown columns or tables provoke an error.  The function returns
-** the number of errors seen and leaves an error message on pParse->zErrMsg.
+** Resolve symbolic names into TK_COLUMN operands for the current
+** node in the expression tree.  Return 0 to continue the search down
+** the tree or 1 to abort the tree walk.
 */
-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. */
-){
+static int nameResolverStep(void *pArg, Expr *pExpr){
+  NameContext *pNC = (NameContext*)pArg;
+  SrcList *pSrcList;
+  Parse *pParse;
   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 );
+  assert( pNC!=0 );
+  pSrcList = pNC->pSrcList;
+  pParse = pNC->pParse;
+  if( pExpr==0 ) return 1;
+  if( ExprHasAnyProperty(pExpr, EP_Resolved) ) return 1;
+  ExprSetProperty(pExpr, EP_Resolved);
+#ifndef NDEBUG
+  if( pSrcList ){
+    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
@@ -916,13 +989,12 @@ 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; 
+      if( pSrcList==0 ) break;
+      lookupName(pParse, 0, 0, &pExpr->token, pNC, pExpr);
+      return 1;
     }
   
     /* A table name and column name:     ID.ID
@@ -934,6 +1006,7 @@ int sqlite3ExprResolveIds(
       Token *pDb;
       Expr *pRight;
 
+      if( pSrcList==0 ) break;
       pRight = pExpr->pRight;
       if( pRight->op==TK_ID ){
         pDb = 0;
@@ -945,22 +1018,150 @@ 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:
+    /* Note: The above three were a seperate case in sqlmoto. Reason? */
+    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;
+      int enc = pParse->db->enc;
+      NameContext ncParam;        /* Name context for parameters */
+
+      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;
       }
-      break;
+      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;
+      }
+      ncParam = *pNC;
+      if( is_agg ) ncParam.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;
+      }
+      if( pNC->nErr ) return 2;
+      /* FIX ME:  Compute pExpr->affinity based on the expected return
+      ** type of the function 
+      */
+      return is_agg;
     }
+  }
+  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 pIsAgg is not null and this expression is an aggregate function
+** (like count(*) or max(value)) then write a 1 into *pIsAgg.
+*/
+int sqlite3ExprResolveNames(
+  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 */
+  int codeSubquery   /* If true, then generate code for subqueries too */
+){
+  NameContext sNC;
+
+  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);
+  }
+  return sNC.nErr + pParse->nErr;
+}
 
+
+/*
+** Generate code for subqueries and IN operators.
+**
+** IN 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.
+**
+** 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.
+*/
+static int codeSubqueryStep(void *pArg, Expr *pExpr){
+  Parse *pParse = (Parse*)pArg;
+
+  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;
-      }
+      if( v==0 ) return 2;
       affinity = sqlite3ExprAffinity(pExpr->pLeft);
 
       /* Whether this is an 'x IN(SELECT...)' or an 'x IN(<exprlist>)'
@@ -1019,10 +1220,10 @@ int sqlite3ExprResolveIds(
           if( !sqlite3ExprIsConstant(pE2) ){
             sqlite3ErrorMsg(pParse,
               "right-hand side of IN operator must be constant");
-            return 1;
+            return 2;
           }
-          if( sqlite3ExprCheck(pParse, pE2, 0, 0) ){
-            return 1;
+          if( sqlite3ExprResolveNames(pParse, 0, 0, pE2, 0, 0, 0) ){
+            return 2;
           }
 
           /* Evaluate the expression and insert it into the temp table */
@@ -1033,8 +1234,7 @@ int sqlite3ExprResolveIds(
         }
       }
       sqlite3VdbeChangeP3(v, addr, (void *)&keyInfo, P3_KEYINFO);
-
-      break;
+      return 1;
     }
 
     case TK_SELECT: {
@@ -1043,191 +1243,19 @@ int sqlite3ExprResolveIds(
       ** 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;
-          }
-        }
-      }
+      sqlite3Select(pParse, pExpr->pSelect, SRT_Mem,pExpr->iColumn,0,0,0,0);
+      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;
-    }
-    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;
-    }
-    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.
+** Generate code to evaluate subqueries and IN operators.
 */
-int sqlite3ExprCheck(Parse *pParse, Expr *pExpr, int allowAgg, int *pIsAgg){
-  int nErr = 0;
-  if( pExpr==0 ) return 0;
-  switch( pExpr->op ){
-    case TK_CTIME:
-    case TK_CTIMESTAMP:
-    case TK_CDATE:
-    /* Note: The above three were a seperate case in sqlmoto. Reason? */
-    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;
-
-      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 && !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);
-        }
-      }
-      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;
-  }
-  return sqlite3ExprCheck(pParse, pExpr, allowAgg, pIsAgg);
+int sqlite3ExprCodeSubquery(Parse *pParse, Expr *pExpr){
+  walkExprTree(pExpr, codeSubqueryStep, pParse);
+  return 0;
 }
 
 /*
@@ -1856,22 +1884,17 @@ 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;
+  Parse *pParse = (Parse*)pArg;
 
-  if( pExpr==0 ) return 0;
   switch( pExpr->op ){
     case TK_COLUMN: {
       aAgg = pParse->aAgg;
@@ -1889,7 +1912,7 @@ int sqlite3ExprAnalyzeAggregates(Parse *pParse, Expr *pExpr){
         pParse->aAgg[i].pExpr = pExpr;
       }
       pExpr->iAgg = i;
-      break;
+      return 1;
     }
     case TK_AGG_FUNCTION: {
       aAgg = pParse->aAgg;
@@ -1910,26 +1933,27 @@ int sqlite3ExprAnalyzeAggregates(Parse *pParse, Expr *pExpr){
              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);
-        }
-      }
-      break;
+      return 1;
     }
   }
-  return nErr;
+  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(Parse *pParse, Expr *pExpr){
+  int nErr = pParse->nErr;
+  walkExprTree(pExpr, analyzeAggregate, pParse);
+  return pParse->nErr - nErr;
 }
 
 /*
index 156973162e5b6f43ef6c7e5aba1749c952256dbf..17b5cf8eee7277f7b57f694dea1e004ffd81e2c8 100644 (file)
@@ -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.130 2005/01/14 01:22:01 drh Exp $
+** $Id: insert.c,v 1.131 2005/01/17 22:08:19 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -380,7 +380,7 @@ void sqlite3Insert(
     nColumn = pList->nExpr;
     dummy.nSrc = 0;
     for(i=0; i<nColumn; i++){
-      if( sqlite3ExprResolveAndCheck(pParse,&dummy,0,pList->a[i].pExpr,0,0) ){
+      if( sqlite3ExprResolveNames(pParse,&dummy,0,pList->a[i].pExpr,0,0,1) ){
         goto insert_cleanup;
       }
     }
index be8c57893210b9cb1a1a3096d74187d4b2487e99..dce52c402206b98e22e12070924cb0863a88d417 100644 (file)
@@ -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.222 2005/01/17 08:57:09 danielk1977 Exp $
+** $Id: select.c,v 1.223 2005/01/17 22:08:19 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( sqlite3ExprResolveAndCheck(pParse, pTabList, pEList, pE, isAgg, 0) ){
+    if( sqlite3ExprResolveNames(pParse, pTabList, pEList, pE, isAgg, 0, 1) ){
       return 1;
     }
     if( sqlite3ExprIsConstant(pE) ){
@@ -2355,12 +2355,12 @@ int sqlite3Select(
   ** Resolve the column names and do a semantics check on all the expressions.
   */
   for(i=0; i<pEList->nExpr; i++){
-    if( sqlite3ExprResolveAndCheck(pParse, pTabList, 0, pEList->a[i].pExpr,
-                                    1, &isAgg) ){
+    if( sqlite3ExprResolveNames(pParse, pTabList, 0, pEList->a[i].pExpr,
+                                    1, &isAgg, 1) ){
       goto select_end;
     }
   }
-  if( sqlite3ExprResolveAndCheck(pParse, pTabList, pEList, pWhere, 0, 0) ){
+  if( sqlite3ExprResolveNames(pParse, pTabList, pEList, pWhere, 0, 0, 1) ){
     goto select_end;
   }
   if( pHaving ){
@@ -2368,7 +2368,7 @@ int sqlite3Select(
       sqlite3ErrorMsg(pParse, "a GROUP BY clause is required before HAVING");
       goto select_end;
     }
-    if( sqlite3ExprResolveAndCheck(pParse, pTabList, pEList,pHaving,1,&isAgg) ){
+    if( sqlite3ExprResolveNames(pParse, pTabList, pEList,pHaving,1,&isAgg,1) ){
       goto select_end;
     }
   }
index de6cf04761a8a60214d3375d41f29dc6b418bd9c..39393ea8666980815ab8eddf0c2bc54bc21cdc63 100644 (file)
@@ -11,7 +11,7 @@
 *************************************************************************
 ** Internal interface definitions for SQLite.
 **
-** @(#) $Id: sqliteInt.h,v 1.353 2005/01/13 02:14:25 danielk1977 Exp $
+** @(#) $Id: sqliteInt.h,v 1.354 2005/01/17 22:08:19 drh Exp $
 */
 #ifndef _SQLITEINT_H_
 #define _SQLITEINT_H_
@@ -316,6 +316,7 @@ typedef struct KeyClass KeyClass;
 typedef struct CollSeq CollSeq;
 typedef struct KeyInfo KeyInfo;
 typedef struct SqlCursor SqlCursor;
+typedef struct NameContext NameContext;
 typedef struct Fetch Fetch;
 typedef struct CursorSubst CursorSubst;
 
@@ -814,6 +815,8 @@ struct Expr {
 ** The following are the meanings of bits in the Expr.flags field.
 */
 #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 */
 
 /*
 ** These macros can be used to test, set, or clear bits in the 
@@ -973,6 +976,8 @@ struct Select {
   ExprList *pEList;      /* The fields of the result */
   u8 op;                 /* One of: TK_UNION TK_ALL TK_INTERSECT TK_EXCEPT */
   u8 isDistinct;         /* True if the DISTINCT keyword is present */
+  u8 isAgg;              /* True if uses aggregate functions */
+  u8 namesResolved;      /* True if processed by sqlite3ExprResolve() */
   SrcList *pSrc;         /* The FROM clause */
   Expr *pWhere;          /* The WHERE clause */
   ExprList *pGroupBy;    /* The GROUP BY clause */
@@ -1250,6 +1255,38 @@ typedef struct {
   char **pzErrMsg;    /* Error message stored here */
 } InitData;
 
+/*
+** A NameContext defines a context in which to resolve table and column
+** names.  The context consists of a list of tables (the pSrcList) field and
+** a list of named expression (pEList).  The named expression list may
+** be NULL.  The pSrc corresponds to the FROM clause of a SELECT or
+** to the table being operated on by INSERT, UPDATE, or DELETE.  The
+** pEList corresponds to the result set of a SELECT and is NULL for
+** other statements.
+**
+** NameContexts can be nested.  When resolving names, the inner-most 
+** context is searched first.  If no match is found, the next outer
+** context is checked.  If there is still no match, the next context
+** is checked.  This process continues until either a match is found
+** or all contexts are check.  When a match is found, the nRef member of
+** the context containing the match is incremented. 
+**
+** Each subquery gets a new NameContext.  The pNext field points to the
+** NameContext in the parent query.  Thus the process of scanning the
+** NameContext list corresponds to searching through successively outer
+** subqueries looking for a match.
+*/
+struct NameContext {
+  Parse *pParse;       /* The parser */
+  SrcList *pSrcList;   /* One or more tables used to resolve names */
+  ExprList *pEList;    /* Optional list of named expressions */
+  int nRef;            /* Number of names resolved by this context */
+  int nErr;            /* Number of errors encountered while resolving names */
+  u8 allowAgg;         /* Aggregate functions allowed here */
+  u8 hasAgg;           /* Expression actually contains aggregate functions */
+  NameContext *pNext;  /* Next outer name context.  NULL for outermost */
+};
+
 /*
 ** Each SQL cursor (a cursor created by the DECLARE ... CURSOR syntax)
 ** is represented by an instance of the following structure.
@@ -1386,8 +1423,8 @@ char *sqlite3NameFromToken(Token*);
 int sqlite3ExprCheck(Parse*, Expr*, int, int*);
 int sqlite3ExprCompare(Expr*, Expr*);
 int sqliteFuncId(Token*);
-int sqlite3ExprResolveIds(Parse*, SrcList*, ExprList*, Expr*);
-int sqlite3ExprResolveAndCheck(Parse*,SrcList*,ExprList*,Expr*,int,int*);
+int sqlite3ExprResolveNames(Parse*, SrcList*, ExprList*, Expr*, int, int*, int);
+int sqlite3ExprCodeSubquery(Parse*, Expr*);
 int sqlite3ExprAnalyzeAggregates(Parse*, Expr*);
 Vdbe *sqlite3GetVdbe(Parse*);
 void sqlite3Randomness(int, void*);
index d4469bf1ad13cda32a98e9d3cbab358a14bbac0c..0fe636971db4be39dc0b25d76305b4380b7518b3 100644 (file)
@@ -766,7 +766,7 @@ int sqlite3CodeRowTrigger(
       /* code the WHEN clause */
       endTrigger = sqlite3VdbeMakeLabel(pParse->pVdbe);
       whenExpr = sqlite3ExprDup(pTrigger->pWhen);
-      if( sqlite3ExprResolveIds(pParse, &dummyTablist, 0, whenExpr) ){
+      if( sqlite3ExprResolveNames(pParse, &dummyTablist, 0, whenExpr, 0, 0, 1)){
         pParse->trigStack = trigStackEntry.pNext;
         sqlite3ExprDelete(whenExpr);
         return 1;
index d3929984e95008d44f981d3ec7d68c29a6b4787d..38223ebae969124d4bcb82a277ad059556ba0be4 100644 (file)
@@ -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.100 2004/12/25 01:03:14 drh Exp $
+** $Id: update.c,v 1.101 2005/01/17 22:08:19 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -121,8 +121,8 @@ void sqlite3Update(
   */
   chngRecno = 0;
   for(i=0; i<pChanges->nExpr; i++){
-    if( sqlite3ExprResolveAndCheck(pParse, pTabList, 0,
-             pChanges->a[i].pExpr, 0, 0) ){
+    if( sqlite3ExprResolveNames(pParse, pTabList, 0,
+          pChanges->a[i].pExpr, 0, 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( sqlite3ExprResolveAndCheck(pParse, pTabList, 0, pWhere, 0, 0) ){
+  if( sqlite3ExprResolveNames(pParse, pTabList, 0, pWhere, 0, 0, 1) ){
     goto update_cleanup;
   }
 
index e035c06b0148d3e8679534e69ea4b42128765e46..118c8e90e96735549dd35ded9ac083d04375d0b1 100644 (file)
@@ -16,7 +16,7 @@
 ** so is applicable.  Because this module is responsible for selecting
 ** indices, you might also think of this module as the "query optimizer".
 **
-** $Id: where.c,v 1.128 2005/01/11 18:13:56 drh Exp $
+** $Id: where.c,v 1.129 2005/01/17 22:08:19 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -181,9 +181,9 @@ static Bitmask getMask(ExprMaskSet *pMaskSet, int iCursor){
 ** tree.
 **
 ** In order for this routine to work, the calling function must have
-** previously invoked sqlite3ExprResolveIds() on the expression.  See
+** previously invoked sqlite3ExprResolveNames() on the expression.  See
 ** the header comment on that routine for additional information.
-** The sqlite3ExprResolveIds() routines looks for column names and
+** The sqlite3ExprResolveNames() routines looks for column names and
 ** sets their opcodes to TK_COLUMN and their Expr.iTable fields to
 ** the VDBE cursor number of the table.
 */