Further modifications to do with ORDER BY and compound SELECT queries. Related to ticket #2822. (CVS 4606)

FossilOrigin-Name: 0d9b0e6e3a8f8a66956878084085842e94c3cb2f
This commit is contained in:
danielk1977 2007-12-10 18:51:47 +00:00
parent 6ed4b78123
commit 70517ab9a1
5 changed files with 166 additions and 82 deletions

View File

@ -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

View File

@ -1 +1 @@
6adbe91efffc6b3f53dae87494430ede61d40ecc
0d9b0e6e3a8f8a66956878084085842e94c3cb2f

View 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;
}

View 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

102
test/tkt2822.test Normal file
View File

@ -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