]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Further modifications to do with ORDER BY and compound SELECT queries. Related to...
authordanielk1977 <danielk1977@noemail.net>
Mon, 10 Dec 2007 18:51:47 +0000 (18:51 +0000)
committerdanielk1977 <danielk1977@noemail.net>
Mon, 10 Dec 2007 18:51:47 +0000 (18:51 +0000)
FossilOrigin-Name: 0d9b0e6e3a8f8a66956878084085842e94c3cb2f

manifest
manifest.uuid
src/select.c
test/select4.test
test/tkt2822.test [new file with mode: 0644]

index 839693fd1b456ac71a55854bda9f6e3dd9b041a5..904cd28c25098f01d3f16da91c2340c2474d3918 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Fix\sa\smacro\sin\sfunc.c\sthat\scauses\sproblems\sfor\sthe\samalgamation.\s(CVS\s4605)
-D 2007-12-10T18:07:21
+C Further\smodifications\sto\sdo\swith\sORDER\sBY\sand\scompound\sSELECT\squeries.\sRelated\sto\sticket\s#2822.\s(CVS\s4606)
+D 2007-12-10T18:51:48
 F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7
 F Makefile.in 30789bf70614bad659351660d76b8e533f3340e9
 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@@ -131,7 +131,7 @@ F src/pragma.c 0246032dbe681dded8710ac43eaf654eead1434e
 F src/prepare.c f811fdb6fd4a82cca673a6e1d5b041d6caf567f1
 F src/printf.c c94a2571a828b927c64f5e3ed3584da8a91fcaec
 F src/random.c 4a22746501bf36b0a088c66e38dde5daba6a35da
-F src/select.c 2c08239b55cf93c03a79cbdedf1ac89967fd6acb
+F src/select.c b7408624b55f58e5aa8521edb177b26ad72f968b
 F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96
 F src/shell.c c97be281cfc3dcb14902f45e4b16f20038eb83ff
 F src/sqlite.h.in 544587c10005dde0ad8f132dd9b7816b132b2bea
@@ -414,7 +414,7 @@ F test/schema2.test 35e1c9696443d6694c8980c411497c2b5190d32e
 F test/select1.test 79784038f0e7df66bb420e149c6fb91e61e11fb7
 F test/select2.test f3c2678c3a9f3cf08ec4988a3845bda64be6d9e3
 F test/select3.test 47439f28862489626b483b0c718cfb0562e6f6d5
-F test/select4.test 4192e6c712194d53b4b77f094eb9d880b8d5ac0e
+F test/select4.test 2dd28cfea6f50281fb29cf136cf50df8ead6a5d2
 F test/select5.test 0b47058d3e916c1fc9fe81f44b438e02bade21ce
 F test/select6.test 399f14b9ba37b768afe5d2cd8c12e4f340a69db8
 F test/select7.test 7906735805cfbee4dddc0bed4c14e68d7f5f9c5f
@@ -478,6 +478,7 @@ F test/tkt2686.test 3022db0eee8ecf501f516557c77ef1c4039399cd
 F test/tkt2767.test 6b02308d553d194f329a469bf5c157fe724738d4
 F test/tkt2817.test 709a2201a5590bf56cb97f6fb168a62282203fd1
 F test/tkt2820.test 017fdee33aaef7abc092beab6088816f1942304b
+F test/tkt2822.test 782d6041b9ec10c74e28768f477cba722c43d88e
 F test/trace.test 75ffc1b992c780d054748a656e3e7fd674f18567
 F test/trans.test b73289992b46d38d9479ecc4fdc03d8edb2413dc
 F test/trigger1.test 7c13f39ca36f529bf856e05c7d004fc0531d48b4
@@ -597,7 +598,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130
 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
 F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
-P d384810a95c97b868a87d090f8dcb903cc82cbf7
-R 02ccd20331c3a0f99f895b6e82412309
-U drh
-Z f800f34be093e13e0ebe3d12e796a99d
+P 6adbe91efffc6b3f53dae87494430ede61d40ecc
+R c5664694f29e5838b66b78cd136777a8
+U danielk1977
+Z 0cfc5f38f552087a6f749e4e8561ad47
index cc805b2b9301387e1fbf31fd6af0a398c5b79bcd..28298be38fa228c2a125433df2ebff0a385c3444 100644 (file)
@@ -1 +1 @@
-6adbe91efffc6b3f53dae87494430ede61d40ecc
\ No newline at end of file
+0d9b0e6e3a8f8a66956878084085842e94c3cb2f
\ No newline at end of file
index 09074e2c327b5537676c8a777d2c4b109a768fe7..49273ed102e5f1d3907866a3bf9b508d37bc6969 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.364 2007/12/08 21:10:20 drh Exp $
+** $Id: select.c,v 1.365 2007/12/10 18:51:48 danielk1977 Exp $
 */
 #include "sqliteInt.h"
 
@@ -1412,15 +1412,6 @@ static int prepSelectStmt(Parse *pParse, Select *p){
   return rc;
 }
 
-/*
-** During the process of matching ORDER BY terms to columns of the 
-** result set, the Exprlist.a[].done flag can be set to one of the
-** following values:
-*/
-#define ORDERBY_MATCH_NONE     0   /* No match found */
-#define ORDERBY_MATCH_PARTIAL  1   /* A good match, but not perfect */
-#define ORDERBY_MATCH_EXACT    2   /* An exact match seen */
-
 #ifndef SQLITE_OMIT_COMPOUND_SELECT
 /*
 ** This routine associates entries in an ORDER BY expression list with
@@ -1429,9 +1420,6 @@ static int prepSelectStmt(Parse *pParse, Select *p){
 ** the top-level node is filled in with column number and the iTable
 ** value of the top-level node is filled with iTable parameter.
 **
-** If there are prior SELECT clauses, they are processed first.  A match
-** in an earlier SELECT takes precedence over a later SELECT.
-**
 ** Any entry that does not match is flagged as an error.  The number
 ** of errors is returned.
 */
@@ -1439,91 +1427,83 @@ static int matchOrderbyToColumn(
   Parse *pParse,          /* A place to leave error messages */
   Select *pSelect,        /* Match to result columns of this SELECT */
   ExprList *pOrderBy,     /* The ORDER BY values to match against columns */
-  int iTable,             /* Insert this value in iTable */
-  int rightMost           /* TRUE for outermost recursive invocation */
+  int iTable              /* Insert this value in iTable */
 ){
   int nErr = 0;
   int i, j;
-  ExprList *pEList;
   sqlite3 *db = pParse->db;
-  NameContext nc;
+  int nExpr;
 
   if( pSelect==0 || pOrderBy==0 ) return 1;
-  if( rightMost ){
-    assert( pSelect->pOrderBy==pOrderBy );
-    for(i=0; i<pOrderBy->nExpr; i++){
-      pOrderBy->a[i].done = ORDERBY_MATCH_NONE;
-    }
-  }
-  if( pSelect->pPrior
-      && matchOrderbyToColumn(pParse, pSelect->pPrior, pOrderBy, iTable, 0) ){
-    return 1;
-  }
   if( sqlite3SelectResolve(pParse, pSelect, 0) ){
     return 1;
   }
-  memset(&nc, 0, sizeof(nc));
-  nc.pParse = pParse;
-  nc.pSrcList = pSelect->pSrc;
-  nc.pEList = pEList = pSelect->pEList;
-  nc.allowAgg = 1;
+
+  nExpr = pSelect->pEList->nExpr;
   for(i=0; nErr==0 && i<pOrderBy->nExpr; i++){
-    struct ExprList_item *pItem;
     Expr *pE = pOrderBy->a[i].pExpr;
     int iCol = -1;
-    int match = ORDERBY_MATCH_NONE;
-    Expr *pDup;
 
-    if( pOrderBy->a[i].done==ORDERBY_MATCH_EXACT ){
-      continue;
-    }
     if( sqlite3ExprIsInteger(pE, &iCol) ){
-      if( iCol<=0 || iCol>pEList->nExpr ){
+      if( iCol<=0 || iCol>nExpr ){
         sqlite3ErrorMsg(pParse,
           "ORDER BY position %d should be between 1 and %d",
-          iCol, pEList->nExpr);
+          iCol, nExpr);
         nErr++;
         break;
       }
-      if( !rightMost ) continue;
       iCol--;
-      match = ORDERBY_MATCH_EXACT;
-    }
-    if( !match && pParse->nErr==0 && (pDup = sqlite3ExprDup(db, pE))!=0 ){
-      nc.nErr = 0;
-      assert( pParse->zErrMsg==0 );
-      if( sqlite3ExprResolveNames(&nc, pDup) ){
-        sqlite3ErrorClear(pParse);
-      }else{
-        for(j=0, pItem=pEList->a; j<pEList->nExpr; j++, pItem++){
-          if( sqlite3ExprCompare(pItem->pExpr, pDup) ){
-            iCol = j;
-            match = ORDERBY_MATCH_PARTIAL;
-            break;
+    }else{
+      Select *p;
+      for(p=pSelect; p; p=p->pPrior){
+        ExprList *pEList = p->pEList;
+        Expr *pDup = sqlite3ExprDup(db, pE);
+
+        NameContext nc;
+
+        memset(&nc, 0, sizeof(nc));
+        nc.pParse = pParse;
+        nc.pSrcList = p->pSrc;
+        nc.pEList = pEList;
+        nc.allowAgg = 1;
+        nc.nErr = 0;
+        if( sqlite3ExprResolveNames(&nc, pDup) ){
+          sqlite3ErrorClear(pParse);
+        }else{
+          struct ExprList_item *pItem;
+          for(j=0, pItem=pEList->a; j<pEList->nExpr; j++, pItem++){
+            if( sqlite3ExprCompare(pItem->pExpr, pDup) ){
+              if( iCol>=0 && iCol!=j ){
+                sqlite3ErrorMsg(
+                    pParse, "ORDER BY term number %d is ambiguous", i+1
+                );
+              }else{
+                iCol = j;
+              }
+            }
           }
         }
+        sqlite3ExprDelete(pDup);
       }
-      sqlite3ExprDelete(pDup);
     }
-    if( match ){
+
+    if( iCol<0 ){
+      sqlite3ErrorMsg(pParse,
+        "ORDER BY term number %d does not match any result column", i+1);
+    }else{
       pE->op = TK_COLUMN;
       pE->iTable = iTable;
       pE->iAgg = -1;
-      if( pOrderBy->a[i].done!=ORDERBY_MATCH_NONE && pE->iColumn!=iCol ){
-        sqlite3ErrorMsg(pParse,
-          "ORDER BY term number %d is ambiguous", i+1);
-        nErr++;
-      }
       pE->iColumn = iCol;
-      pOrderBy->a[i].done = match;
-    }else if( rightMost && pOrderBy->a[i].done==ORDERBY_MATCH_NONE ){
-      sqlite3ErrorMsg(pParse,
-        "ORDER BY term number %d does not match any result column", i+1);
-      nErr++;
-      break;
+      pOrderBy->a[i].done = 1;
+    }
+
+    if( pParse->nErr ){
+      return pParse->nErr;
     }
   }
-  return nErr;  
+
+  return SQLITE_OK;
 }
 #endif /* #ifndef SQLITE_OMIT_COMPOUND_SELECT */
 
@@ -1788,7 +1768,7 @@ static int multiSelect(
         ** intermediate results.
         */
         unionTab = pParse->nTab++;
-        if( pOrderBy && matchOrderbyToColumn(pParse, p, pOrderBy, unionTab,1) ){
+        if( pOrderBy && matchOrderbyToColumn(pParse, p, pOrderBy, unionTab) ){
           rc = 1;
           goto multi_select_end;
         }
@@ -1885,7 +1865,7 @@ static int multiSelect(
       */
       tab1 = pParse->nTab++;
       tab2 = pParse->nTab++;
-      if( pOrderBy && matchOrderbyToColumn(pParse,p,pOrderBy,tab1,1) ){
+      if( pOrderBy && matchOrderbyToColumn(pParse,p,pOrderBy,tab1) ){
         rc = 1;
         goto multi_select_end;
       }
index e26b89414f2b8260def8af9c465b9fcbe20dda11..713abe75566c15a77c5637398614f981937f077d 100644 (file)
@@ -12,7 +12,7 @@
 # focus of this file is testing UNION, INTERSECT and EXCEPT operators
 # in SELECT statements.
 #
-# $Id: select4.test,v 1.21 2007/12/08 21:10:20 drh Exp $
+# $Id: select4.test,v 1.22 2007/12/10 18:51:48 danielk1977 Exp $
 
 set testdir [file dirname $argv0]
 source $testdir/tester.tcl
@@ -572,13 +572,14 @@ do_test select4-9.7 {
 } ;# ifcapable subquery
 
 do_test select4-9.8 {
-  execsql2 {
+  catchsql {
     SELECT 0 AS x, 1 AS y
     UNION
     SELECT 2 AS y, -3 AS x
     ORDER BY x LIMIT 1;
   }
-} {x 0 y 1}
+} {1 {ORDER BY term number 1 is ambiguous}}
+
 do_test select4-9.9.1 {
   execsql2 {
     SELECT 1 AS a, 2 AS b UNION ALL SELECT 3 AS b, 4 AS a
diff --git a/test/tkt2822.test b/test/tkt2822.test
new file mode 100644 (file)
index 0000000..beff84c
--- /dev/null
@@ -0,0 +1,102 @@
+# 2007 Dec 4
+#
+# The author disclaims copyright to this source code. In place of
+# a legal notice, here is a blessing:
+#
+#    May you do good and not evil.
+#    May you find forgiveness for yourself and forgive others.
+#    May you share freely, never taking more than you give.
+#
+#***********************************************************************
+#
+# This file is to test that the issues surrounding expressions in
+# ORDER BY clauses on compound SELECT statements raised by ticket
+# #2822 have been dealt with.
+#
+# $Id: tkt2822.test,v 1.1 2007/12/10 18:51:48 danielk1977 Exp $
+#
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+# Test plan:
+#
+#   tkt2820-1.* - Simple identifier as ORDER BY expression.
+#   tkt2820-2.* - More complex ORDER BY expressions.
+
+do_test tkt2820-1.1 {
+  execsql {
+    CREATE TABLE t1(a, b, c);
+    CREATE TABLE t2(c, b, a);
+
+    INSERT INTO t1 VALUES(1, 2, 3);
+    INSERT INTO t2 VALUES(3, 2, 1);
+  }
+} {}
+
+# If an ORDER BY expression matches two different columns, it is an error.
+#
+do_test tkt2820-1.2 {
+  catchsql {
+    SELECT a, b FROM t1 UNION ALL SELECT b, a FROM t2 ORDER BY a;
+  }
+} {1 {ORDER BY term number 1 is ambiguous}}
+do_test tkt2820-1.3 {
+  catchsql {
+    SELECT a, b, c FROM t2 UNION ALL SELECT c, b, a FROM t1 ORDER BY a;
+  }
+} {1 {ORDER BY term number 1 is ambiguous}}
+
+# But not if it matches the same column in two or more of the
+# compounded SELECT statements.
+#
+do_test tkt2820-1.4 {
+  execsql {
+    SELECT a, b, c FROM t2 UNION ALL SELECT a, b, c FROM t1 ORDER BY a;
+  }
+} {1 2 3 1 2 3}
+
+do_test tkt2820-1.5 {
+  execsql {
+    SELECT a, b FROM t2 UNION ALL SELECT c, b FROM t1 ORDER BY c;
+  }
+} {1 2 3 2}
+
+# If a match cannot be found in any SELECT, return an error.
+#
+do_test tkt2820-1.6 {
+  catchsql {
+    SELECT * FROM t2 UNION ALL SELECT * FROM t1 ORDER BY d;
+  }
+} {1 {ORDER BY term number 1 does not match any result column}}
+
+
+do_test tkt2820-2.1 {
+  execsql {
+    SELECT a+1, b+1 FROM t1 UNION ALL SELECT a, c FROM t2 ORDER BY a+1;
+  }
+} {1 3 2 3}
+do_test tkt2820-2.2 {
+  catchsql {
+    SELECT a+1, b+1 FROM t1 UNION ALL SELECT a, c FROM t2 ORDER BY a+2;
+  }
+} {1 {ORDER BY term number 1 does not match any result column}}
+do_test tkt2820-2.3 {
+  catchsql {
+    SELECT a+1, b+1 FROM t1 UNION ALL SELECT c, a+1 FROM t2 ORDER BY a+1;
+  }
+} {1 {ORDER BY term number 1 is ambiguous}}
+
+do_test tkt2820-2.4 {
+  execsql {
+    SELECT t1.a, b+1 FROM t1 UNION ALL SELECT c, a+1 FROM t2 ORDER BY a;
+  }
+} {1 3 3 2}
+do_test tkt2820-2.5 {
+  execsql {
+    SELECT t1.a, b+1 FROM t1 UNION ALL SELECT c, a+1 FROM t2 ORDER BY t1.a;
+  }
+} {1 3 3 2}
+
+finish_test
+