-C Towards\sgetting\sORDER\sBY\sto\smatch\sagainst\sthe\scorrectin\scolumns.\nThis\sversion\sonly\slooks\sat\sthe\sleft-most\scolumn\sin\sa\scompound\sSELECT.\nThat\sis\sthe\scorrect\sthing\sto\sdo,\sbut\snot\swhat\sSQLite\shas\shistorically\sdone.\s(CVS\s4620)
-D 2007-12-13T02:45:31
+C ORDER\sBY\sin\sa\scompound\sSELECT\swill\sfirst\smatch\sagainst\sthe\sleft-most\sSELECT.\nIf\sthere\sis\sno\smatch\sthere,\sit\sbegins\sworking\sits\sway\sto\sthe\sright.\s(CVS\s4621)
+D 2007-12-13T03:45:08
F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7
F Makefile.in 0590398f62fc2c456ff4c45e9741f5a718b7e2ac
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
F src/prepare.c f811fdb6fd4a82cca673a6e1d5b041d6caf567f1
F src/printf.c 5732e393c45be7c09bfca9a786daef017e0066ef
F src/random.c 4a22746501bf36b0a088c66e38dde5daba6a35da
-F src/select.c 63cc67c9a9cc3f32ec2205d2c769d94cd2fc6f60
+F src/select.c c2de6d7ba6f98d83e03dabc405e46f439cb37f20
F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96
F src/shell.c c97be281cfc3dcb14902f45e4b16f20038eb83ff
F src/sqlite.h.in b16a7127dad4a3e5b1b26b3d64241f3373aa12ea
F src/sqlite3ext.h a93f59cdee3638dc0c9c086f80df743a4e68c3cb
-F src/sqliteInt.h 5c390e902c88648035110d0fe156a279dcace271
+F src/sqliteInt.h 445530263725d19d6315f137f234aea08ad59303
F src/sqliteLimit.h 3657c8eb75addce54a46354a29050a9673845a85
F src/table.c 1aeb9eab57b4235db86fe15a35dec76fb445a9c4
F src/tclsqlite.c 9923abeffc9b3d7dad58e92b319661521f60debf
F test/misc7.test 3fbd0a9e3dd03331d9d76acd47bc179e1a97e15e
F test/misuse.test 30b3a458e5a70c31e74c291937b6c82204c59f33
F test/notnull.test 44d600f916b770def8b095a9962dbe3be5a70d82
-F test/null.test 93e48033673841240f137fd621317cc73b69eeb8
+F test/null.test 6adcb4efd433e02c60499f96328014de87cff8b1
F test/onefile.test b9cce375fd2a41ee3afa79a0a808954046b74458
F test/openv2.test f5dd6b23e4dce828eb211649b600763c42a668df
F test/pager.test 60303481b22b240c18d6dd1b64edcecc2f4b5a97
F test/select1.test 79784038f0e7df66bb420e149c6fb91e61e11fb7
F test/select2.test f3c2678c3a9f3cf08ec4988a3845bda64be6d9e3
F test/select3.test 47439f28862489626b483b0c718cfb0562e6f6d5
-F test/select4.test 2dd28cfea6f50281fb29cf136cf50df8ead6a5d2
+F test/select4.test 566b4ca1152e16d7090d76f98d93c80b9a1f6c53
F test/select5.test 0b47058d3e916c1fc9fe81f44b438e02bade21ce
F test/select6.test 399f14b9ba37b768afe5d2cd8c12e4f340a69db8
F test/select7.test 7906735805cfbee4dddc0bed4c14e68d7f5f9c5f
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
-P c0689409320de1532be0c0cae12b4b716f6bffb9
-R 1ec374c4daffe98452f78ad79abdb48f
+P bbddf16ac9539c7d48adfc73c5a90eecb8df6865
+R 377fa996f832a29c87d12a5f182c500b
U drh
-Z 92df68b2adbb4d9afb7d6635a4dfe3d8
+Z f7fa31d1f83b3a0d837ffef0df0c17c3
-bbddf16ac9539c7d48adfc73c5a90eecb8df6865
\ No newline at end of file
+56063ec84b130bcdb0e90bc76fabca394d0d867f
\ No newline at end of file
** This file contains C code routines that are called by the parser
** to handle SELECT statements in SQLite.
**
-** $Id: select.c,v 1.366 2007/12/13 02:45:31 drh Exp $
+** $Id: select.c,v 1.367 2007/12/13 03:45:08 drh Exp $
*/
#include "sqliteInt.h"
nc.allowAgg = 1;
nc.nErr = 0;
if( sqlite3ExprResolveNames(&nc, pE) ){
- return -1;
+ if( isCompound ){
+ sqlite3ErrorClear(pParse);
+ return 0;
+ }else{
+ return -1;
+ }
}
if( nc.hasAgg && pHasAgg ){
*pHasAgg = 1;
return i+1;
}
}
- sqlite3ErrorMsg(pParse, "%r ORDER BY term does not match any "
- "column in the result set of the left-most SELECT", idx);
- return -1;
- }else{
- return 0;
}
+ return 0;
}
int i;
ExprList *pOrderBy;
ExprList *pEList;
+ sqlite3 *db;
+ int moreToDo = 1;
pOrderBy = pSelect->pOrderBy;
if( pOrderBy==0 ) return 0;
sqlite3ErrorMsg(pParse, "too many terms in ORDER BY clause");
return 1;
}
+ db = pParse->db;
+ for(i=0; i<pOrderBy->nExpr; i++){
+ pOrderBy->a[i].done = 0;
+ }
while( pSelect->pPrior ){
pSelect = pSelect->pPrior;
}
- pEList = pSelect->pEList;
- if( pEList==0 ){
- return 1;
+ while( pSelect && moreToDo ){
+ moreToDo = 0;
+ for(i=0; i<pOrderBy->nExpr; i++){
+ int iCol;
+ Expr *pE;
+ if( pOrderBy->a[i].done ) continue;
+ pE = pOrderBy->a[i].pExpr;
+ Expr *pDup = sqlite3ExprDup(db, pE);
+ if( pDup==0 ){
+ return 1;
+ }
+ iCol = matchOrderByTermToExprList(pParse, pSelect, pDup, i+1, 1, 0);
+ sqlite3ExprDelete(pDup);
+ if( iCol<0 ){
+ return 1;
+ }
+ pEList = pSelect->pEList;
+ if( pEList==0 ){
+ return 1;
+ }
+ if( iCol>pEList->nExpr ){
+ sqlite3ErrorMsg(pParse,
+ "%r ORDER BY term out of range - should be "
+ "between 1 and %d", i+1, pEList->nExpr);
+ return 1;
+ }
+ if( iCol>0 ){
+ pE->op = TK_COLUMN;
+ pE->iTable = iTable;
+ pE->iAgg = -1;
+ pE->iColumn = iCol-1;
+ pE->pTab = 0;
+ pOrderBy->a[i].done = 1;
+ }else{
+ moreToDo = 1;
+ }
+ }
+ pSelect = pSelect->pNext;
}
for(i=0; i<pOrderBy->nExpr; i++){
- int iCol;
- Expr *pE = pOrderBy->a[i].pExpr;
- iCol = matchOrderByTermToExprList(pParse, pSelect, pE, i+1, 1, 0);
- if( iCol<0 ){
- return 1;
- }
- if( iCol>pEList->nExpr ){
- sqlite3ErrorMsg(pParse,
- "%r ORDER BY term out of range - should be "
- "between 1 and %d", i+1, pEList->nExpr);
+ if( pOrderBy->a[i].done==0 ){
+ sqlite3ErrorMsg(pParse, "%r ORDER BY term does not match any "
+ "column in the result set", i+1);
return 1;
}
- pE->op = TK_COLUMN;
- pE->iTable = iTable;
- pE->iAgg = -1;
- pE->iColumn = iCol-1;
- pE->pTab = 0;
}
return 0;
}
*/
if( p->pPrior ){
if( p->pRightmost==0 ){
- Select *pLoop;
+ Select *pLoop, *pRight = 0;
int cnt = 0;
for(pLoop=p; pLoop; pLoop=pLoop->pPrior, cnt++){
pLoop->pRightmost = p;
+ pLoop->pNext = pRight;
+ pRight = pLoop;
}
if( SQLITE_MAX_COMPOUND_SELECT>0 && cnt>SQLITE_MAX_COMPOUND_SELECT ){
sqlite3ErrorMsg(pParse, "too many terms in compound SELECT");
*************************************************************************
** Internal interface definitions for SQLite.
**
-** @(#) $Id: sqliteInt.h,v 1.625 2007/12/11 19:34:45 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.626 2007/12/13 03:45:08 drh Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_
Expr *pHaving; /* The HAVING clause */
ExprList *pOrderBy; /* The ORDER BY clause */
Select *pPrior; /* Prior select in a compound select statement */
+ Select *pNext; /* Next select to the left in a compound */
Select *pRightmost; /* Right-most select in a compound select statement */
Expr *pLimit; /* LIMIT expression. NULL means not used. */
Expr *pOffset; /* OFFSET expression. NULL means not used. */
} {{} 0 1}
# A UNION to two queries should treat NULL values
-# as distinct
+# as distinct.
+#
+# (Later:) We also take this opportunity to test the ability
+# of an ORDER BY clause to bind to either SELECT of a UNION.
+# The left-most SELECT is preferred. In standard SQL, only
+# the left SELECT can be used. The ability to match an ORDER
+# BY term to the right SELECT is an SQLite extension.
#
ifcapable compound {
do_test null-6.1 {
select b from t1 union select c from t1 order by main.t1.b;
}
} {{} 0 1}
+ do_test null-6.5 {
+ execsql {
+ select b from t1 union select c from t1 order by t1.a;
+ }
+ } {{} 0 1}
+ do_test null-6.6 {
+ execsql {
+ select b from t1 union select c from t1 order by main.t1.a;
+ }
+ } {{} 0 1}
} ;# ifcapable compound
# The UNIQUE constraint only applies to non-null values
# focus of this file is testing UNION, INTERSECT and EXCEPT operators
# in SELECT statements.
#
-# $Id: select4.test,v 1.22 2007/12/10 18:51:48 danielk1977 Exp $
+# $Id: select4.test,v 1.23 2007/12/13 03:45:08 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
do_test select4-4.1.2 {
execsql {
- SELECT DISTINCT log FROM t1 UNION ALL SELECT 6
+ SELECT DISTINCT log FROM t1
+ UNION ALL
+ SELECT 6
INTERSECT
SELECT n FROM t1 WHERE log=3
- ORDER BY log;
+ ORDER BY t1.log;
}
} {5 6}
+
do_test select4-4.1.3 {
execsql {
CREATE TABLE t2 AS