aboutsummaryrefslogtreecommitdiff
path: root/src/expr.c
diff options
context:
space:
mode:
authordrh <drh@noemail.net>2002-01-22 03:13:42 +0000
committerdrh <drh@noemail.net>2002-01-22 03:13:42 +0000
commita2e00042a10c1ad3f75827ff0545f3af8d02f9e3 (patch)
tree0dc62b86634098137ac44f7cdbd0a08be8d16b53 /src/expr.c
parent555fcb489bcdf5b8386be0ea661eae02a52ce1eb (diff)
downloadsqlite-a2e00042a10c1ad3f75827ff0545f3af8d02f9e3.tar.gz
sqlite-a2e00042a10c1ad3f75827ff0545f3af8d02f9e3.zip
The right-hand side of an AS in a SELECT can be used within expressions of
the WHERE, ORDER BY, GROUP BY, and/or HAVING clauses. (CVS 350) FossilOrigin-Name: 3684beab0f8a71ebdf453871bbde7a9ab1f65385
Diffstat (limited to 'src/expr.c')
-rw-r--r--src/expr.c63
1 files changed, 55 insertions, 8 deletions
diff --git a/src/expr.c b/src/expr.c
index 6d2e3104b..0a0113886 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -12,10 +12,25 @@
** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions in SQLite.
**
-** $Id: expr.c,v 1.37 2002/01/06 17:07:40 drh Exp $
+** $Id: expr.c,v 1.38 2002/01/22 03:13:42 drh Exp $
*/
#include "sqliteInt.h"
+
+/*
+** Recursively delete an expression tree.
+*/
+void sqliteExprDelete(Expr *p){
+ if( p==0 ) return;
+ if( p->op!=TK_AS ){
+ if( p->pLeft ) sqliteExprDelete(p->pLeft);
+ if( p->pRight ) sqliteExprDelete(p->pRight);
+ }
+ if( p->pList ) sqliteExprListDelete(p->pList);
+ if( p->pSelect ) sqliteSelectDelete(p->pSelect);
+ sqliteFree(p);
+}
+
/*
** Walk an expression tree. Return 1 if the expression is constant
** and 0 if it involves variables.
@@ -116,10 +131,24 @@ static int sqliteIsRowid(const char *z){
** Unknown columns or tables provoke an error. The function returns
** the number of errors seen and leaves an error message on pParse->zErrMsg.
*/
-int sqliteExprResolveIds(Parse *pParse, IdList *pTabList, Expr *pExpr){
+int sqliteExprResolveIds(
+ Parse *pParse, /* The parser context */
+ IdList *pTabList, /* List of tables used to resolve column names */
+ ExprList *pEList, /* List of expressions used to resolve "AS" */
+ Expr *pExpr /* The expression to be analyzed. */
+){
if( pExpr==0 || pTabList==0 ) return 0;
switch( pExpr->op ){
- /* A lone identifier */
+ /* A lone identifier. Try and match it as follows:
+ **
+ ** 1. To the name of a column of one of the tables in pTabList
+ **
+ ** 2. To the right side of an AS keyword in the column list of
+ ** a SELECT statement. (For example, match against 'x' in
+ ** "SELECT a+b AS 'x' FROM t1".)
+ **
+ ** 3. One of the special names "ROWID", "OID", or "_ROWID_".
+ */
case TK_ID: {
int cnt = 0; /* Number of matches */
int i; /* Loop counter */
@@ -139,13 +168,28 @@ int sqliteExprResolveIds(Parse *pParse, IdList *pTabList, Expr *pExpr){
}else{
pExpr->iColumn = j;
}
+ pExpr->op = TK_COLUMN;
}
}
}
+ if( cnt==0 && pEList!=0 ){
+ int j;
+ for(j=0; j<pEList->nExpr; j++){
+ char *zAs = pEList->a[j].zName;
+ if( zAs!=0 && sqliteStrICmp(zAs, z)==0 ){
+ cnt++;
+ assert( pExpr->pLeft==0 && pExpr->pRight==0 );
+ pExpr->op = TK_AS;
+ pExpr->iColumn = j;
+ pExpr->pLeft = pEList->a[j].pExpr;
+ }
+ }
+ }
if( cnt==0 && sqliteIsRowid(z) ){
pExpr->iColumn = -1;
pExpr->iTable = pParse->nTab;
cnt = 1 + (pTabList->nId>1);
+ pExpr->op = TK_COLUMN;
}
sqliteFree(z);
if( cnt==0 ){
@@ -159,7 +203,6 @@ int sqliteExprResolveIds(Parse *pParse, IdList *pTabList, Expr *pExpr){
pParse->nErr++;
return 1;
}
- pExpr->op = TK_COLUMN;
break;
}
@@ -240,7 +283,7 @@ int sqliteExprResolveIds(Parse *pParse, IdList *pTabList, Expr *pExpr){
case TK_IN: {
Vdbe *v = sqliteGetVdbe(pParse);
if( v==0 ) return 1;
- if( sqliteExprResolveIds(pParse, pTabList, pExpr->pLeft) ){
+ if( sqliteExprResolveIds(pParse, pTabList, pEList, pExpr->pLeft) ){
return 1;
}
if( pExpr->pSelect ){
@@ -309,18 +352,18 @@ int sqliteExprResolveIds(Parse *pParse, IdList *pTabList, Expr *pExpr){
/* For all else, just recursively walk the tree */
default: {
if( pExpr->pLeft
- && sqliteExprResolveIds(pParse, pTabList, pExpr->pLeft) ){
+ && sqliteExprResolveIds(pParse, pTabList, pEList, pExpr->pLeft) ){
return 1;
}
if( pExpr->pRight
- && sqliteExprResolveIds(pParse, pTabList, pExpr->pRight) ){
+ && sqliteExprResolveIds(pParse, pTabList, pEList, pExpr->pRight) ){
return 1;
}
if( pExpr->pList ){
int i;
ExprList *pList = pExpr->pList;
for(i=0; i<pList->nExpr; i++){
- if( sqliteExprResolveIds(pParse, pTabList, pList->a[i].pExpr) ){
+ if( sqliteExprResolveIds(pParse,pTabList,pEList,pList->a[i].pExpr) ){
return 1;
}
}
@@ -704,6 +747,10 @@ void sqliteExprCode(Parse *pParse, Expr *pExpr){
sqliteVdbeResolveLabel(v, lbl);
break;
}
+ case TK_AS: {
+ sqliteExprCode(pParse, pExpr->pLeft);
+ break;
+ }
}
return;
}