Avoid reevaluating WHERE and ORDER BY expressions that alias terms in the
result set.  Ticket #3343.  Note that aliased GROUP BY expressions are still
evaluated twice. (CVS 5637)

FossilOrigin-Name: ab0292caa5887cc1bdc0e8c9d3f3502b83975440
diff --git a/src/delete.c b/src/delete.c
index 72c2ec1..4219b88 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.173 2008/08/22 12:30:52 drh Exp $
+** $Id: delete.c,v 1.174 2008/08/29 02:14:03 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -104,8 +104,8 @@
     Token viewName;
     
     pWhere = sqlite3ExprDup(db, pWhere);
-    viewName.z = pView->zName;
-    viewName.n = strlen(viewName.z);
+    viewName.z = (u8*)pView->zName;
+    viewName.n = (unsigned int)strlen((const char*)viewName.z);
     pFrom = sqlite3SrcListAppendFromTerm(pParse, 0, 0, 0, &viewName, pDup, 0,0);
     pDup = sqlite3SelectNew(pParse, 0, pFrom, pWhere, 0, 0, 0, 0, 0, 0);
   }
diff --git a/src/expr.c b/src/expr.c
index becc82a..8f2d13f 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.391 2008/08/22 17:34:45 drh Exp $
+** $Id: expr.c,v 1.392 2008/08/29 02:14:03 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -701,6 +701,7 @@
     pItem->sortOrder = pOldItem->sortOrder;
     pItem->done = 0;
     pItem->iCol = pOldItem->iCol;
+    pItem->iAlias = pOldItem->iAlias;
   }
   return pNew;
 }
@@ -829,6 +830,7 @@
     memset(pItem, 0, sizeof(*pItem));
     pItem->zName = sqlite3NameFromToken(db, pName);
     pItem->pExpr = pExpr;
+    pItem->iAlias = 0;
   }
   return pList;
 
@@ -1665,11 +1667,46 @@
 }
 
 /*
+** Generate code to store the value of the iAlias-th alias in register
+** target.  The first time this is called, pExpr is evaluated to compute
+** the value of the alias.  The value is stored in an auxiliary register
+** and the number of that register is returned.  On subsequent calls,
+** the register number is returned without generating any code.
+**
+** Note that in order for this to work, code must be generated in the
+** same order that it is executed.
+**
+** Aliases are numbered starting with 1.  So iAlias is in the range
+** of 1 to pParse->nAlias inclusive.  
+**
+** pParse->aAlias[iAlias-1] records the register number where the value
+** of the iAlias-th alias is stored.  If zero, that means that the
+** alias has not yet been computed.
+*/
+static int codeAlias(Parse *pParse, int iAlias, Expr *pExpr){
+  sqlite3 *db = pParse->db;
+  int iReg;
+  if( pParse->aAlias==0 ){
+    pParse->aAlias = sqlite3DbMallocZero(db, 
+                                 sizeof(pParse->aAlias[0])*pParse->nAlias );
+    if( db->mallocFailed ) return 0;
+  }
+  assert( iAlias>0 && iAlias<=pParse->nAlias );
+  iReg = pParse->aAlias[iAlias-1];
+  if( iReg==0 ){
+    iReg = ++pParse->nMem;
+    sqlite3ExprCode(pParse, pExpr, iReg);
+    pParse->aAlias[iAlias-1] = iReg;
+  }
+  return iReg;
+}
+
+/*
 ** Generate code into the current Vdbe to evaluate the given
 ** expression.  Attempt to store the results in register "target".
 ** Return the register where results are stored.
 **
-** With this routine, there is no guaranteed that results will
+** With this routine, there is no guarantee that results will
 ** be stored in target.  The result might be stored in some other
 ** register if it is convenient to do so.  The calling function
 ** must check the return code and move the results to the desired
@@ -1682,8 +1719,10 @@
   int regFree1 = 0;         /* If non-zero free this temporary register */
   int regFree2 = 0;         /* If non-zero free this temporary register */
   int r1, r2, r3, r4;       /* Various register numbers */
+  sqlite3 *db;
 
-  assert( v!=0 || pParse->db->mallocFailed );
+  db = pParse->db;
+  assert( v!=0 || db->mallocFailed );
   assert( target>0 && target<=pParse->nMem );
   if( v==0 ) return 0;
 
@@ -1729,7 +1768,7 @@
       break;
     }
     case TK_STRING: {
-      sqlite3DequoteExpr(pParse->db, pExpr);
+      sqlite3DequoteExpr(db, pExpr);
       sqlite3VdbeAddOp4(v,OP_String8, 0, target, 0,
                         (char*)pExpr->token.z, pExpr->token.n);
       break;
@@ -1765,6 +1804,10 @@
       inReg = pExpr->iTable;
       break;
     }
+    case TK_AS: {
+      inReg = codeAlias(pParse, pExpr->iTable, pExpr->pLeft);
+      break;
+    }
 #ifndef SQLITE_OMIT_CAST
     case TK_CAST: {
       /* Expressions of the form:   CAST(pLeft AS token) */
@@ -1921,7 +1964,6 @@
       const char *zId;
       int constMask = 0;
       int i;
-      sqlite3 *db = pParse->db;
       u8 enc = ENC(db);
       CollSeq *pColl = 0;
 
@@ -1929,7 +1971,7 @@
       testcase( op==TK_FUNCTION );
       zId = (char*)pExpr->token.z;
       nId = pExpr->token.n;
-      pDef = sqlite3FindFunction(pParse->db, zId, nId, nExpr, enc, 0);
+      pDef = sqlite3FindFunction(db, zId, nId, nExpr, enc, 0);
       assert( pDef!=0 );
       if( pList ){
         nExpr = pList->nExpr;
@@ -1966,7 +2008,7 @@
         }
       }
       if( pDef->needCollSeq ){
-        if( !pColl ) pColl = pParse->db->pDfltColl; 
+        if( !pColl ) pColl = db->pDfltColl; 
         sqlite3VdbeAddOp4(v, OP_CollSeq, 0, 0, 0, (char *)pColl, P4_COLLSEQ);
       }
       sqlite3VdbeAddOp4(v, OP_Function, constMask, r1, target,
@@ -2206,7 +2248,7 @@
          assert( pExpr->iColumn==OE_Rollback ||
                  pExpr->iColumn == OE_Abort ||
                  pExpr->iColumn == OE_Fail );
-         sqlite3DequoteExpr(pParse->db, pExpr);
+         sqlite3DequoteExpr(db, pExpr);
          sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CONSTRAINT, pExpr->iColumn, 0,
                         (char*)pExpr->token.z, pExpr->token.n);
       } else {
@@ -2422,7 +2464,13 @@
   assert( target>0 );
   n = pList->nExpr;
   for(pItem=pList->a, i=0; i<n; i++, pItem++){
-    sqlite3ExprCode(pParse, pItem->pExpr, target+i);
+    if( pItem->iAlias ){
+      int iReg = codeAlias(pParse, pItem->iAlias, pItem->pExpr);
+      Vdbe *v = sqlite3GetVdbe(pParse);
+      sqlite3VdbeAddOp2(v, OP_SCopy, iReg, target+i);
+    }else{
+      sqlite3ExprCode(pParse, pItem->pExpr, target+i);
+    }
     if( doHardCopy ) sqlite3ExprHardCopy(pParse, target, n);
   }
   return n;
@@ -2811,6 +2859,8 @@
   switch( pExpr->op ){
     case TK_AGG_COLUMN:
     case TK_COLUMN: {
+      testcase( pExpr->op==TK_AGG_COLUMN );
+      testcase( pExpr->op==TK_COLUMN );
       /* Check to see if the column is in one of the tables in the FROM
       ** clause of the aggregate query */
       if( pSrcList ){
diff --git a/src/resolve.c b/src/resolve.c
index 439fc74..dfbc3b1 100644
--- a/src/resolve.c
+++ b/src/resolve.c
@@ -14,13 +14,76 @@
 ** resolve all identifiers by associating them with a particular
 ** table and column.
 **
-** $Id: resolve.c,v 1.4 2008/08/25 17:23:29 drh Exp $
+** $Id: resolve.c,v 1.5 2008/08/29 02:14:03 drh Exp $
 */
 #include "sqliteInt.h"
 #include <stdlib.h>
 #include <string.h>
 
 /*
+** Turn the pExpr expression into an alias for the iCol-th column of the
+** result set in pEList.
+**
+** If the result set column is a simple column reference, then this routine
+** makes an exact copy.  But for any other kind of expression, this
+** routine make a copy of the result set column as the argument to the
+** TK_AS operator.  The TK_AS operator causes the expression to be
+** evaluated just once and then reused for each alias.
+**
+** The reason for suppressing the TK_AS term when the expression is a simple
+** column reference is so that the column reference will be recognized as
+** usable by indices within the WHERE clause processing logic. 
+**
+** Hack:  The TK_AS operator is inhibited if zType[0]=='G'.  This means
+** that in a GROUP BY clause, the expression is evaluated twice.  Hence:
+**
+**     SELECT random()%5 AS x, count(*) FROM tab GROUP BY x
+**
+** Is equivalent to:
+**
+**     SELECT random()%5 AS x, count(*) FROM tab GROUP BY random()%5
+**
+** The result of random()%5 in the GROUP BY clause is probably different
+** from the result in the result-set.  We might fix this someday.  Or
+** then again, we might not...
+*/
+static void resolveAlias(
+  Parse *pParse,         /* Parsing context */
+  ExprList *pEList,      /* A result set */
+  int iCol,              /* A column in the result set.  0..pEList->nExpr-1 */
+  Expr *pExpr,           /* Transform this into an alias to the result set */
+  const char *zType      /* "GROUP" or "ORDER" or "" */
+){
+  Expr *pOrig;           /* The iCol-th column of the result set */
+  Expr *pDup;            /* Copy of pOrig */
+  sqlite3 *db;           /* The database connection */
+
+  assert( iCol>=0 && iCol<pEList->nExpr );
+  pOrig = pEList->a[iCol].pExpr;
+  assert( pOrig!=0 );
+  assert( pOrig->flags & EP_Resolved );
+  db = pParse->db;
+  pDup = sqlite3ExprDup(db, pOrig);
+  if( pDup==0 ) return;
+  if( pDup->op!=TK_COLUMN && zType[0]!='G' ){
+    pDup = sqlite3PExpr(pParse, TK_AS, pDup, 0, 0);
+    if( pDup==0 ) return;
+    if( pEList->a[iCol].iAlias==0 ){
+      pEList->a[iCol].iAlias = ++pParse->nAlias;
+    }
+    pDup->iTable = pEList->a[iCol].iAlias;
+  }
+  if( pExpr->flags & EP_ExpCollate ){
+    pDup->pColl = pExpr->pColl;
+    pDup->flags |= EP_ExpCollate;
+  }
+  if( pExpr->span.dyn ) sqlite3DbFree(db, (char*)pExpr->span.z);
+  if( pExpr->token.dyn ) sqlite3DbFree(db, (char*)pExpr->token.z);
+  memcpy(pExpr, pDup, sizeof(*pExpr));
+  sqlite3DbFree(db, pDup);
+}
+
+/*
 ** Given the name of a column of the form X.Y.Z or Y.Z or just Z, look up
 ** that name in the set of source tables in pSrcList and make the pExpr 
 ** expression node refer back to that source column.  The following changes
@@ -218,7 +281,7 @@
       for(j=0; j<pEList->nExpr; j++){
         char *zAs = pEList->a[j].zName;
         if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){
-          Expr *pDup, *pOrig;
+          Expr *pOrig;
           assert( pExpr->pLeft==0 && pExpr->pRight==0 );
           assert( pExpr->pList==0 );
           assert( pExpr->pSelect==0 );
@@ -228,15 +291,7 @@
             sqlite3DbFree(db, zCol);
             return 2;
           }
-          pDup = sqlite3ExprDup(db, pOrig);
-          if( pExpr->flags & EP_ExpCollate ){
-            pDup->pColl = pExpr->pColl;
-            pDup->flags |= EP_ExpCollate;
-          }
-          if( pExpr->span.dyn ) sqlite3DbFree(db, (char*)pExpr->span.z);
-          if( pExpr->token.dyn ) sqlite3DbFree(db, (char*)pExpr->token.z);
-          memcpy(pExpr, pDup, sizeof(*pExpr));
-          sqlite3DbFree(db, pDup);
+          resolveAlias(pParse, pEList, j, pExpr, "");
           cnt = 1;
           pMatch = 0;
           assert( zTab==0 && zDb==0 );
@@ -731,24 +786,11 @@
   assert( pEList!=0 );  /* sqlite3SelectNew() guarantees this */
   for(i=0, pItem=pOrderBy->a; i<pOrderBy->nExpr; i++, pItem++){
     if( pItem->iCol ){
-      Expr *pE;
-      CollSeq *pColl;
-      int flags;
-
       if( pItem->iCol>pEList->nExpr ){
         resolveOutOfRangeError(pParse, zType, i+1, pEList->nExpr);
         return 1;
       }
-      pE = pItem->pExpr;
-      pColl = pE->pColl;
-      flags = pE->flags & EP_ExpCollate;
-      sqlite3ExprDelete(db, pE);
-      pE = sqlite3ExprDup(db, pEList->a[pItem->iCol-1].pExpr);
-      pItem->pExpr = pE;
-      if( pE && flags ){
-        pE->pColl = pColl;
-        pE->flags |= flags;
-      }
+      resolveAlias(pParse, pEList, pItem->iCol-1, pItem->pExpr, zType);
     }
   }
   return 0;
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index d66036b..b41104a 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -11,7 +11,7 @@
 *************************************************************************
 ** Internal interface definitions for SQLite.
 **
-** @(#) $Id: sqliteInt.h,v 1.761 2008/08/22 17:34:45 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.762 2008/08/29 02:14:03 drh Exp $
 */
 #ifndef _SQLITEINT_H_
 #define _SQLITEINT_H_
@@ -1345,6 +1345,7 @@
     u8 sortOrder;          /* 1 for DESC or 0 for ASC */
     u8 done;               /* A flag to indicate when processing is finished */
     u16 iCol;              /* For ORDER BY, column number in result set */
+    u16 iAlias;            /* Index into Parse.aAlias[] for zName */
   } *a;                  /* One entry for each expression */
 };
 
@@ -1681,6 +1682,8 @@
   int nVarExpr;        /* Number of used slots in apVarExpr[] */
   int nVarExprAlloc;   /* Number of allocated slots in apVarExpr[] */
   Expr **apVarExpr;    /* Pointers to :aaa and $aaaa wildcard expressions */
+  int nAlias;          /* Number of aliased result set columns */
+  int *aAlias;         /* Register used to hold aliased result */
   u8 explain;          /* True if the EXPLAIN flag is found on the query */
   Token sErrToken;     /* The token at which the error occurred */
   Token sNameToken;    /* Token with unqualified schema object name */
diff --git a/src/tokenize.c b/src/tokenize.c
index 3e5bd9d..802c163 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.150 2008/08/08 14:19:41 drh Exp $
+** $Id: tokenize.c,v 1.151 2008/08/29 02:14:03 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -503,6 +503,7 @@
 
   sqlite3DeleteTrigger(db, pParse->pNewTrigger);
   sqlite3DbFree(db, pParse->apVarExpr);
+  sqlite3DbFree(db, pParse->aAlias);
   if( nErr>0 && (pParse->rc==SQLITE_OK || pParse->rc==SQLITE_DONE) ){
     pParse->rc = SQLITE_ERROR;
   }