]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
The right-hand side of an AS in a SELECT can be used within expressions of
authordrh <drh@noemail.net>
Tue, 22 Jan 2002 03:13:42 +0000 (03:13 +0000)
committerdrh <drh@noemail.net>
Tue, 22 Jan 2002 03:13:42 +0000 (03:13 +0000)
the WHERE, ORDER BY, GROUP BY, and/or HAVING clauses. (CVS 350)

FossilOrigin-Name: 3684beab0f8a71ebdf453871bbde7a9ab1f65385

13 files changed:
VERSION
manifest
manifest.uuid
src/build.c
src/delete.c
src/expr.c
src/select.c
src/sqliteInt.h
src/update.c
test/select1.test
test/select3.test
www/changes.tcl
www/faq.tcl

diff --git a/VERSION b/VERSION
index 585940699b5b99df6541c819a773ef738985a956..530cdd91a205aaea0795fccb77f9314290e441e6 100644 (file)
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-2.2.3
+2.2.4
index 695ac9947524f16d24d970433f66dc0781fbe41f..c3da224cff160579fd7a4a7940ae5976d1fc20fa 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,9 +1,9 @@
-C Version\s2.2.3\s(CVS\s450)
-D 2002-01-16T21:05:00
+C The\sright-hand\sside\sof\san\sAS\sin\sa\sSELECT\scan\sbe\sused\swithin\sexpressions\sof\nthe\sWHERE,\sORDER\sBY,\sGROUP\sBY,\sand/or\sHAVING\sclauses.\s(CVS\s350)
+D 2002-01-22T03:13:42
 F Makefile.in 9fa4277413bf1d9cf91365f07d4108d7d87ed2af
 F Makefile.template 3e26a3b9e7aee1b811deaf673e8d8973bdb3f22d
 F README a4c0ba11354ef6ba0776b400d057c59da47a4cc0
-F VERSION da55054c39447bab51e716c492a9fa987086fa17
+F VERSION 2af606990ed9af7308a6e04cd7c9efd550f4e7be
 F aclocal.m4 11faa843caa38fd451bc6aeb43e248d1723a269d
 F config.guess f38b1e93d1e0fa6f5a6913e9e7b12774b9232588
 F config.log 6a73d03433669b10a3f0c221198c3f26b9413914
@@ -21,9 +21,9 @@ F sqlite.1 2e2bb0529ef468ade9e4322bd609d0695fb9ded9
 F src/TODO af7f3cab0228e34149cf98e073aa83d45878e7e6
 F src/btree.c c796e387da340cb628dc1e41f684fc20253f561e
 F src/btree.h 9ead7f54c270d8a554e59352ca7318fdaf411390
-F src/build.c d44fbcfaf0eacd33a4686aa4dda8fc770b640421
-F src/delete.c f7690efc09ad6a2f1f3f0490e1b0cbb676bb95cf
-F src/expr.c 8169261ac56e96c860407a8773ca10b779e32328
+F src/build.c bf8456b56011bb3761f11ff4a14121cfbbbd78da
+F src/delete.c cc200609f927ee8fefdda5d11d3f3b2288493c0f
+F src/expr.c 3c4359f9a00791f73569547bb11ce0f0fa5da631
 F src/hash.c 8f7c740ef2eaaa8decfa8751f2be30680b123e46
 F src/hash.h a5f5b3ce2d086a172c5879b0b06a27a82eac9fac
 F src/insert.c 813c37719866c583e6ca7660f94f10230f4e385d
@@ -36,18 +36,18 @@ F src/pager.h f78d064c780855ff70beacbeba0e2324471b26fe
 F src/parse.y f3fc4fb5766393003577bd175eb611495f6efd9f
 F src/printf.c 300a90554345751f26e1fc0c0333b90a66110a1d
 F src/random.c f6b36bec5ebd3edb3440224bf5bf811fe4ac9a1b
-F src/select.c bddd8b5d07ffdae0d798c10b20dc7167469a3904
+F src/select.c f944a94d5004a1b87a5c6b1e41c29ac94488b42a
 F src/shell.c 539a41d4121ed371d438d57d829e53056a54471c
 F src/shell.tcl 27ecbd63dd88396ad16d81ab44f73e6c0ea9d20e
 F src/sqlite.h.in f57074c84a2c112a5093ba7a9d9636aa9cacc87c
-F src/sqliteInt.h 2382456c76bd66d0255d385820af1c72c961540c
+F src/sqliteInt.h 576b7b8165b2d78204412227e242cded54188bd5
 F src/table.c c89698bd5bb4b8d14722d6ee7e9be014c383d24a
 F src/tclsqlite.c b9cf346e95291cb4c4f1bf5ac1d77db6b8ad023d
 F src/test1.c 33efd350dca27c52c58c553c04fd3a6a51f13c1f
 F src/test2.c e9f99aa5ee73872819259d6612c11e55e1644321
 F src/test3.c d6775f95fd91f5b3cf0e2382a28e5aaeb68f745b
 F src/tokenize.c 830e9ef684334070a26583d94770bb869e2727bf
-F src/update.c 5cb326ed4bace89cbad7d919b828da6c2a9064e4
+F src/update.c f30a47928fb7e894221eab2a81c8fa2653f96fb0
 F src/util.c 3958a14a2dbfb13fa5f779976b4d0daf9ab49bb1
 F src/vdbe.c 158bab65e4eafceb75a83f616caafa2c58f00242
 F src/vdbe.h e5cc6fb13d1905a4339db4d6dba4ab393c0765fa
@@ -77,9 +77,9 @@ F test/printf.test 3cb415073754cb8ff076f26173143c3cd293a9da
 F test/quick.test 6f023c7a73fc413e6d65b7a1879c79764038dc05
 F test/quote.test 286db944717afa9a9bf829dd85e59185c65d5435
 F test/rowid.test cb023f2df36886e1fc4cdfd32eaba05cf7db4331
-F test/select1.test 7423a9dbb81b6d282b13cbe10be64d1216dec155
+F test/select1.test 391a1e1a0527391d1bfa2daab279bf6be21da011
 F test/select2.test ed2c1882857106b85478f54f67000e14966be4c4
-F test/select3.test 5e1fe8e5a4e63fb2827ab3b89527e0fd4ae35259
+F test/select3.test 3a053d8fd29e10b55f468644641098b5c9adbc06
 F test/select4.test 29a2ffb187f3d8b6ca42a0a6b619e9cabe12e228
 F test/select5.test c2a6c4a003316ee42cbbd689eebef8fdce0db2ac
 F test/sort.test 462c1161eee1abaa7cc93990e0b34d5fdb70ce19
@@ -105,11 +105,11 @@ F www/arch.fig d5f9752a4dbf242e9cfffffd3f5762b6c63b3bcf
 F www/arch.png 82ef36db1143828a7abc88b1e308a5f55d4336f4
 F www/arch.tcl 72a0c80e9054cc7025a50928d28d9c75c02c2b8b
 F www/c_interface.tcl 82a026b1681757f13b3f62e035f3a31407c1d353
-F www/changes.tcl 21116410e94d5f0852b49880ddf65f390423f24c
+F www/changes.tcl 0f1348ff7203706633953211c7b4bb73bd6a723f
 F www/crosscompile.tcl 3622ebbe518927a3854a12de51344673eb2dd060
 F www/download.tcl 1ea61f9d89a2a5a9b2cee36b0d5cf97321bdefe0
 F www/dynload.tcl 02eb8273aa78cfa9070dd4501dca937fb22b466c
-F www/faq.tcl 324ec51080e5c3d62ccce4fb22a8b839eaded694
+F www/faq.tcl 32cbc134879871604070d4cc3a32e73fb22a35f9
 F www/formatchng.tcl d96e5e937dcbbebd481720aa08745ca5a906a63f
 F www/index.tcl 571c585a5c0b577db2fe7cb88cf1f12cccd96ceb
 F www/lang.tcl 6843fd3f85cba95fd199a350533ce742c706603c
@@ -119,7 +119,7 @@ F www/speed.tcl 83457b2bf6bb430900bd48ca3dd98264d9a916a5
 F www/sqlite.tcl 8b5884354cb615049aed83039f8dfe1552a44279
 F www/tclsqlite.tcl 829b393d1ab187fd7a5e978631b3429318885c49
 F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218
-P f74d61aaf3fec06cde2c4a6f1465f86ac9058ad2
-R 0e682a68cf7bb91386b1d3da8599787d
+P a4fe893ce7cdec0d8a4f8cdc640b8967dce7763e
+R 42174a8584ff6b02199355782a39f765
 U drh
-Z d05a6c87487d5a9de2ff07f77b94d69d
+Z 43f0669b77399b52f2f84c6f1b77e1c1
index ae63754710475ac40e38fdd86e4d3587c4751997..6ed609124d73ff571fcc5a5dcbad470b076be46d 100644 (file)
@@ -1 +1 @@
-a4fe893ce7cdec0d8a4f8cdc640b8967dce7763e
\ No newline at end of file
+3684beab0f8a71ebdf453871bbde7a9ab1f65385
\ No newline at end of file
index 431854e117e84660cab4b9619e9654e66296ea57..1fbf6351d14bea69f77f460379c832d6e39188d1 100644 (file)
@@ -25,7 +25,7 @@
 **     ROLLBACK
 **     PRAGMA
 **
-** $Id: build.c,v 1.64 2002/01/10 14:31:49 drh Exp $
+** $Id: build.c,v 1.65 2002/01/22 03:13:42 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -127,18 +127,6 @@ Expr *sqliteExprFunction(ExprList *pList, Token *pToken){
   return pNew;
 }
 
-/*
-** Recursively delete an expression tree.
-*/
-void sqliteExprDelete(Expr *p){
-  if( p==0 ) return;
-  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);
-}
-
 /*
 ** Locate the in-memory structure that describes 
 ** a particular database table given the name
index 53e6e96000c4d5207dfffff664e7c9d6544c0d54..70638afbaf0c5165e04f2ee13d7cada06e98da34 100644 (file)
@@ -12,7 +12,7 @@
 ** This file contains C code routines that are called by the parser
 ** to handle DELETE FROM statements.
 **
-** $Id: delete.c,v 1.22 2001/12/21 14:30:43 drh Exp $
+** $Id: delete.c,v 1.23 2002/01/22 03:13:42 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -70,7 +70,7 @@ void sqliteDeleteFrom(
   */
   if( pWhere ){
     sqliteExprResolveInSelect(pParse, pWhere);
-    if( sqliteExprResolveIds(pParse, pTabList, pWhere) ){
+    if( sqliteExprResolveIds(pParse, pTabList, 0, pWhere) ){
       goto delete_from_cleanup;
     }
     if( sqliteExprCheck(pParse, pWhere, 0, 0) ){
index 6d2e3104b6998f77a0d2f81ddf2f26b572912461..0a0113886bdc34b129e9e0fd0cdb37007350d1f6 100644 (file)
 ** 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;
 }
index cc4a2d9813fbee787dca965551851f95f739ca6f..719f63d563fd78dd2f119d67e4104ca8cb62a286 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.53 2002/01/04 03:09:30 drh Exp $
+** $Id: select.c,v 1.54 2002/01/22 03:13:42 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -698,7 +698,7 @@ int sqliteSelect(
   WhereInfo *pWInfo;
   Vdbe *v;
   int isAgg = 0;         /* True for select lists like "count(*)" */
-  ExprList *pEList;      /* List of columns to extract.  NULL means "*" */
+  ExprList *pEList;      /* List of columns to extract. */
   IdList *pTabList;      /* List of tables to select from */
   Expr *pWhere;          /* The WHERE clause.  May be NULL */
   ExprList *pOrderBy;    /* The ORDER BY clause.  May be NULL */
@@ -798,7 +798,7 @@ int sqliteSelect(
   ** Resolve the column names and do a semantics check on all the expressions.
   */
   for(i=0; i<pEList->nExpr; i++){
-    if( sqliteExprResolveIds(pParse, pTabList, pEList->a[i].pExpr) ){
+    if( sqliteExprResolveIds(pParse, pTabList, 0, pEList->a[i].pExpr) ){
       return 1;
     }
     if( sqliteExprCheck(pParse, pEList->a[i].pExpr, 1, &isAgg) ){
@@ -806,7 +806,7 @@ int sqliteSelect(
     }
   }
   if( pWhere ){
-    if( sqliteExprResolveIds(pParse, pTabList, pWhere) ){
+    if( sqliteExprResolveIds(pParse, pTabList, pEList, pWhere) ){
       return 1;
     }
     if( sqliteExprCheck(pParse, pWhere, 0, 0) ){
@@ -816,7 +816,7 @@ int sqliteSelect(
   if( pOrderBy ){
     for(i=0; i<pOrderBy->nExpr; i++){
       Expr *pE = pOrderBy->a[i].pExpr;
-      if( sqliteExprResolveIds(pParse, pTabList, pE) ){
+      if( sqliteExprResolveIds(pParse, pTabList, pEList, pE) ){
         return 1;
       }
       if( sqliteExprCheck(pParse, pE, isAgg, 0) ){
@@ -827,7 +827,7 @@ int sqliteSelect(
   if( pGroupBy ){
     for(i=0; i<pGroupBy->nExpr; i++){
       Expr *pE = pGroupBy->a[i].pExpr;
-      if( sqliteExprResolveIds(pParse, pTabList, pE) ){
+      if( sqliteExprResolveIds(pParse, pTabList, pEList, pE) ){
         return 1;
       }
       if( sqliteExprCheck(pParse, pE, isAgg, 0) ){
@@ -842,7 +842,7 @@ int sqliteSelect(
       pParse->nErr++;
       return 1;
     }
-    if( sqliteExprResolveIds(pParse, pTabList, pHaving) ){
+    if( sqliteExprResolveIds(pParse, pTabList, pEList, pHaving) ){
       return 1;
     }
     if( sqliteExprCheck(pParse, pHaving, isAgg, 0) ){
index 11129c94281f862a2080fb1300c4632f867af0ba..88e7a56f86c718cd5a2190ed66efcc8876206cca 100644 (file)
@@ -11,7 +11,7 @@
 *************************************************************************
 ** Internal interface definitions for SQLite.
 **
-** @(#) $Id: sqliteInt.h,v 1.77 2002/01/16 21:00:27 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.78 2002/01/22 03:13:42 drh Exp $
 */
 #include "sqlite.h"
 #include "hash.h"
@@ -517,7 +517,7 @@ char *sqliteTableNameFromToken(Token*);
 int sqliteExprCheck(Parse*, Expr*, int, int*);
 int sqliteExprCompare(Expr*, Expr*);
 int sqliteFuncId(Token*);
-int sqliteExprResolveIds(Parse*, IdList*, Expr*);
+int sqliteExprResolveIds(Parse*, IdList*, ExprList*, Expr*);
 void sqliteExprResolveInSelect(Parse*, Expr*);
 int sqliteExprAnalyzeAggregates(Parse*, Expr*);
 void sqliteParseInfoReset(Parse*);
index ed760ff993ff931af070a9c88a63c29af76eca8c..016545aa9e3654c367b853f8183baf89ab971063 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.26 2002/01/14 02:56:25 drh Exp $
+** $Id: update.c,v 1.27 2002/01/22 03:13:42 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -84,7 +84,7 @@ void sqliteUpdate(
     sqliteExprResolveInSelect(pParse, pChanges->a[i].pExpr);
   }
   if( pWhere ){
-    if( sqliteExprResolveIds(pParse, pTabList, pWhere) ){
+    if( sqliteExprResolveIds(pParse, pTabList, 0, pWhere) ){
       goto update_cleanup;
     }
     if( sqliteExprCheck(pParse, pWhere, 0, 0) ){
@@ -93,7 +93,7 @@ void sqliteUpdate(
   }
   chngRecno = 0;
   for(i=0; i<pChanges->nExpr; i++){
-    if( sqliteExprResolveIds(pParse, pTabList, pChanges->a[i].pExpr) ){
+    if( sqliteExprResolveIds(pParse, pTabList, 0, pChanges->a[i].pExpr) ){
       goto update_cleanup;
     }
     if( sqliteExprCheck(pParse, pChanges->a[i].pExpr, 0, 0) ){
index 48f834d84df34a4efb8cd508eb1a62364e99d963..c321402baea1d0e7b31eac3c25391164f8fd72bf 100644 (file)
@@ -11,7 +11,7 @@
 # This file implements regression tests for SQLite library.  The
 # focus of this file is testing the SELECT statement.
 #
-# $Id: select1.test,v 1.16 2001/12/16 20:05:06 drh Exp $
+# $Id: select1.test,v 1.17 2002/01/22 03:13:43 drh Exp $
 
 set testdir [file dirname $argv0]
 source $testdir/tester.tcl
@@ -467,4 +467,38 @@ do_test select1-9.5 {
 } {f1 f2}
 unset r
 
+# Check for ORDER BY clauses that refer to an AS name in the column list
+#
+do_test select1-10.1 {
+  execsql {
+    SELECT f1 AS x FROM test1 ORDER BY x
+  }
+} {11 33}
+do_test select1-10.2 {
+  execsql {
+    SELECT f1 AS x FROM test1 ORDER BY -x
+  }
+} {33 11}
+do_test select1-10.3 {
+  execsql {
+    SELECT f1-23 AS x FROM test1 ORDER BY abs(x)
+  }
+} {10 -12}
+do_test select1-10.4 {
+  execsql {
+    SELECT f1-23 AS x FROM test1 ORDER BY -abs(x)
+  }
+} {-12 10}
+do_test select1-10.5 {
+  execsql {
+    SELECT f1-22 AS x, f2-22 as y FROM test1
+  }
+} {-11 0 11 22}
+do_test select1-10.6 {
+  execsql {
+    SELECT f1-22 AS x, f2-22 as y FROM test1 WHERE x>0 AND y<50
+  }
+} {11 22}
+
+
 finish_test
index 7052c392cbb77f41230e292584aef0e7e13136e9..d4ba8b9c848e6ab2d6fc3a85a63615c2ea1cc429 100644 (file)
@@ -12,7 +12,7 @@
 # focus of this file is testing aggregate functions and the
 # GROUP BY and HAVING clauses of SELECT statements.
 #
-# $Id: select3.test,v 1.3 2001/09/16 00:13:28 drh Exp $
+# $Id: select3.test,v 1.4 2002/01/22 03:13:43 drh Exp $
 
 set testdir [file dirname $argv0]
 source $testdir/tester.tcl
@@ -69,6 +69,21 @@ do_test select3-2.4 {
 do_test select3-2.5 {
   execsql {SELECT log*2+1, avg(n)-min(n) FROM t1 GROUP BY log ORDER BY log}
 } {1 0 3 0 5 0.5 7 1.5 9 3.5 11 7}
+do_test select3-2.6 {
+  execsql {
+    SELECT log*2+1 as x, count(*) FROM t1 GROUP BY x ORDER BY x
+  }
+} {1 1 3 1 5 2 7 4 9 8 11 15}
+do_test select3-2.7 {
+  execsql {
+    SELECT log*2+1 AS x, count(*) AS y FROM t1 GROUP BY x ORDER BY y
+  }
+} {1 1 3 1 5 2 7 4 9 8 11 15}
+do_test select3-2.8 {
+  execsql {
+    SELECT log*2+1 AS x, count(*) AS y FROM t1 GROUP BY x ORDER BY 10-(x+y)
+  }
+} {11 15 9 8 7 4 5 2 3 1 1 1}
 
 # Cannot have a HAVING without a GROUP BY
 #
@@ -98,6 +113,14 @@ do_test select3-4.3 {
     ORDER BY max(n)
   }
 } {3 4 4 8 5 15}
+do_test select3-4.4 {
+  execsql {
+    SELECT log AS x, count(*) AS y FROM t1 
+    GROUP BY x
+    HAVING y>=4 
+    ORDER BY max(n)
+  }
+} {3 4 4 8 5 15}
 
 do_test select3-5.1 {
   execsql {
index 0d6e7eb98e6d568050bb3ee5d5e9aa2e58463ce2..9e231ba360b6e8609f2eafa6c9980ec95b7aa0cf 100644 (file)
@@ -17,6 +17,12 @@ proc chng {date desc} {
   puts "<DD><P><UL>$desc</UL></P></DD>"
 }
 
+chng {2002 Jan ?? (2.2.4)} {
+<li>The label to the right of an AS in the column list of a SELECT can now
+    be used as part of an expression in the WHERE, ORDER BY, GROUP BY, and/or
+    HAVING clauses.</li>
+}
+
 chng {2002 Jan 16 (2.2.3)} {
 <li>Fix warning messages in VC++ 7.0.  (Patches from nicolas352001)</li>
 <li>Make the library thread-safe.  (The code is there and appears to work
index d8756421af7f8619418849965600bca31c1b30e2..af12e01ad505a8900cafcb0a22fcc4e24e233c46 100644 (file)
@@ -1,7 +1,7 @@
 #
 # Run this script to generated a faq.html output file
 #
-set rcsid {$Id: faq.tcl,v 1.6 2002/01/16 21:00:28 drh Exp $}
+set rcsid {$Id: faq.tcl,v 1.7 2002/01/22 03:13:43 drh Exp $}
 
 puts {<html>
 <head>
@@ -161,7 +161,7 @@ faq {
   on my SparcStation.
 } {
   <p>The x86 processor on your linux box is little-endian (meaning that
-  the least signification byte of integers comes first) but the Sparc is
+  the least significant byte of integers comes first) but the Sparc is
   big-endian (the most significant bytes comes first).  SQLite databases
   created on a little-endian architecture cannot be used on a big-endian
   machine and vice versa.</p>