mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-14 00:22:38 +03:00
Better resolution of ORDER BY terms in compound queries. Candidate
solution for ticket #2822. Needs more testing and documentation before going final. (CVS 4602) FossilOrigin-Name: 62a78d212c53a9cb1759d03134653a75f3a086b6
This commit is contained in:
16
manifest
16
manifest
@@ -1,5 +1,5 @@
|
|||||||
C Strengthen\sthe\stests\sfor\saggregate\sfunctions\sin\sGROUP\sBY\sclauses.\nChanges\sto\stest\scases\sonly.\s\sNo\schanges\sto\scode.\s(CVS\s4601)
|
C Better\sresolution\sof\sORDER\sBY\sterms\sin\scompound\squeries.\s\sCandidate\nsolution\sfor\sticket\s#2822.\s\sNeeds\smore\stesting\sand\sdocumentation\nbefore\sgoing\sfinal.\s(CVS\s4602)
|
||||||
D 2007-12-08T18:01:31
|
D 2007-12-08T21:10:20
|
||||||
F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7
|
F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7
|
||||||
F Makefile.in 30789bf70614bad659351660d76b8e533f3340e9
|
F Makefile.in 30789bf70614bad659351660d76b8e533f3340e9
|
||||||
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
|
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
|
||||||
@@ -131,7 +131,7 @@ F src/pragma.c 0246032dbe681dded8710ac43eaf654eead1434e
|
|||||||
F src/prepare.c f811fdb6fd4a82cca673a6e1d5b041d6caf567f1
|
F src/prepare.c f811fdb6fd4a82cca673a6e1d5b041d6caf567f1
|
||||||
F src/printf.c c94a2571a828b927c64f5e3ed3584da8a91fcaec
|
F src/printf.c c94a2571a828b927c64f5e3ed3584da8a91fcaec
|
||||||
F src/random.c 4a22746501bf36b0a088c66e38dde5daba6a35da
|
F src/random.c 4a22746501bf36b0a088c66e38dde5daba6a35da
|
||||||
F src/select.c 7c0ab94b8f287eb94fdb1eb101be603832ecfc34
|
F src/select.c 2c08239b55cf93c03a79cbdedf1ac89967fd6acb
|
||||||
F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96
|
F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96
|
||||||
F src/shell.c c97be281cfc3dcb14902f45e4b16f20038eb83ff
|
F src/shell.c c97be281cfc3dcb14902f45e4b16f20038eb83ff
|
||||||
F src/sqlite.h.in 544587c10005dde0ad8f132dd9b7816b132b2bea
|
F src/sqlite.h.in 544587c10005dde0ad8f132dd9b7816b132b2bea
|
||||||
@@ -411,10 +411,10 @@ F test/rowid.test d125991eea1ffdea800d48471afd8fc4acc10b01
|
|||||||
F test/safety.test 4a06934e45d03b8b50ebcd8d174eb0367d2fd851
|
F test/safety.test 4a06934e45d03b8b50ebcd8d174eb0367d2fd851
|
||||||
F test/schema.test a8b000723375fd42c68d310091bdbd744fde647c
|
F test/schema.test a8b000723375fd42c68d310091bdbd744fde647c
|
||||||
F test/schema2.test 35e1c9696443d6694c8980c411497c2b5190d32e
|
F test/schema2.test 35e1c9696443d6694c8980c411497c2b5190d32e
|
||||||
F test/select1.test 7603a4d406ea00516233e26539d2fac0cc85e732
|
F test/select1.test d091e1c8ad23c9bd6d7d55d2dd16b08e68e16f63
|
||||||
F test/select2.test f3c2678c3a9f3cf08ec4988a3845bda64be6d9e3
|
F test/select2.test f3c2678c3a9f3cf08ec4988a3845bda64be6d9e3
|
||||||
F test/select3.test 47439f28862489626b483b0c718cfb0562e6f6d5
|
F test/select3.test 47439f28862489626b483b0c718cfb0562e6f6d5
|
||||||
F test/select4.test 305ba0a6e97efc5544def5e5cb49b54e1bf87fd9
|
F test/select4.test 4192e6c712194d53b4b77f094eb9d880b8d5ac0e
|
||||||
F test/select5.test 0b47058d3e916c1fc9fe81f44b438e02bade21ce
|
F test/select5.test 0b47058d3e916c1fc9fe81f44b438e02bade21ce
|
||||||
F test/select6.test 399f14b9ba37b768afe5d2cd8c12e4f340a69db8
|
F test/select6.test 399f14b9ba37b768afe5d2cd8c12e4f340a69db8
|
||||||
F test/select7.test 7906735805cfbee4dddc0bed4c14e68d7f5f9c5f
|
F test/select7.test 7906735805cfbee4dddc0bed4c14e68d7f5f9c5f
|
||||||
@@ -597,7 +597,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130
|
|||||||
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
|
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
|
||||||
F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
|
F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
|
||||||
F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
|
F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
|
||||||
P 1d6a9f5fafb862fb31c8589fa118a5672bad6abd
|
P 4be8e6765bf8bc48747b2542f2ed77066fb9dcb9
|
||||||
R 378bf8f52e8d83775a501365b0bea297
|
R adfe92f0c9624e9b76a7c1a73370b4bd
|
||||||
U drh
|
U drh
|
||||||
Z 0788daae7a5c65291d88fcc1de49b7ff
|
Z af9ac541bec9448e79940f97cacc1ce8
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
4be8e6765bf8bc48747b2542f2ed77066fb9dcb9
|
62a78d212c53a9cb1759d03134653a75f3a086b6
|
||||||
95
src/select.c
95
src/select.c
@@ -12,7 +12,7 @@
|
|||||||
** This file contains C code routines that are called by the parser
|
** This file contains C code routines that are called by the parser
|
||||||
** to handle SELECT statements in SQLite.
|
** to handle SELECT statements in SQLite.
|
||||||
**
|
**
|
||||||
** $Id: select.c,v 1.363 2007/11/23 13:42:52 drh Exp $
|
** $Id: select.c,v 1.364 2007/12/08 21:10:20 drh Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
|
|
||||||
@@ -1412,6 +1412,15 @@ static int prepSelectStmt(Parse *pParse, Select *p){
|
|||||||
return rc;
|
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
|
#ifndef SQLITE_OMIT_COMPOUND_SELECT
|
||||||
/*
|
/*
|
||||||
** This routine associates entries in an ORDER BY expression list with
|
** This routine associates entries in an ORDER BY expression list with
|
||||||
@@ -1431,33 +1440,43 @@ static int matchOrderbyToColumn(
|
|||||||
Select *pSelect, /* Match to result columns of this SELECT */
|
Select *pSelect, /* Match to result columns of this SELECT */
|
||||||
ExprList *pOrderBy, /* The ORDER BY values to match against columns */
|
ExprList *pOrderBy, /* The ORDER BY values to match against columns */
|
||||||
int iTable, /* Insert this value in iTable */
|
int iTable, /* Insert this value in iTable */
|
||||||
int mustComplete /* If TRUE all ORDER BYs must match */
|
int rightMost /* TRUE for outermost recursive invocation */
|
||||||
){
|
){
|
||||||
int nErr = 0;
|
int nErr = 0;
|
||||||
int i, j;
|
int i, j;
|
||||||
ExprList *pEList;
|
ExprList *pEList;
|
||||||
sqlite3 *db = pParse->db;
|
sqlite3 *db = pParse->db;
|
||||||
|
NameContext nc;
|
||||||
|
|
||||||
if( pSelect==0 || pOrderBy==0 ) return 1;
|
if( pSelect==0 || pOrderBy==0 ) return 1;
|
||||||
if( mustComplete ){
|
if( rightMost ){
|
||||||
for(i=0; i<pOrderBy->nExpr; i++){ pOrderBy->a[i].done = 0; }
|
assert( pSelect->pOrderBy==pOrderBy );
|
||||||
}
|
|
||||||
if( prepSelectStmt(pParse, pSelect) ){
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if( pSelect->pPrior ){
|
|
||||||
if( matchOrderbyToColumn(pParse, pSelect->pPrior, pOrderBy, iTable, 0) ){
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pEList = pSelect->pEList;
|
|
||||||
for(i=0; i<pOrderBy->nExpr; i++){
|
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;
|
||||||
|
for(i=0; nErr==0 && i<pOrderBy->nExpr; i++){
|
||||||
struct ExprList_item *pItem;
|
struct ExprList_item *pItem;
|
||||||
Expr *pE = pOrderBy->a[i].pExpr;
|
Expr *pE = pOrderBy->a[i].pExpr;
|
||||||
int iCol = -1;
|
int iCol = -1;
|
||||||
char *zLabel;
|
int match = ORDERBY_MATCH_NONE;
|
||||||
|
Expr *pDup;
|
||||||
|
|
||||||
if( pOrderBy->a[i].done ) continue;
|
if( pOrderBy->a[i].done==ORDERBY_MATCH_EXACT ){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if( sqlite3ExprIsInteger(pE, &iCol) ){
|
if( sqlite3ExprIsInteger(pE, &iCol) ){
|
||||||
if( iCol<=0 || iCol>pEList->nExpr ){
|
if( iCol<=0 || iCol>pEList->nExpr ){
|
||||||
sqlite3ErrorMsg(pParse,
|
sqlite3ErrorMsg(pParse,
|
||||||
@@ -1466,34 +1485,38 @@ static int matchOrderbyToColumn(
|
|||||||
nErr++;
|
nErr++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if( !mustComplete ) continue;
|
if( !rightMost ) continue;
|
||||||
iCol--;
|
iCol--;
|
||||||
|
match = ORDERBY_MATCH_EXACT;
|
||||||
}
|
}
|
||||||
if( iCol<0 && (zLabel = sqlite3NameFromToken(db, &pE->token))!=0 ){
|
if( !match && pParse->nErr==0 && (pDup = sqlite3ExprDup(db, pE))!=0 ){
|
||||||
for(j=0, pItem=pEList->a; j<pEList->nExpr; j++, pItem++){
|
nc.nErr = 0;
|
||||||
char *zName;
|
assert( pParse->zErrMsg==0 );
|
||||||
int isMatch;
|
if( sqlite3ExprResolveNames(&nc, pDup) ){
|
||||||
if( pItem->zName ){
|
sqlite3ErrorClear(pParse);
|
||||||
zName = sqlite3DbStrDup(db, pItem->zName);
|
|
||||||
}else{
|
}else{
|
||||||
zName = sqlite3NameFromToken(db, &pItem->pExpr->token);
|
for(j=0, pItem=pEList->a; j<pEList->nExpr; j++, pItem++){
|
||||||
}
|
if( sqlite3ExprCompare(pItem->pExpr, pDup) ){
|
||||||
isMatch = zName && sqlite3StrICmp(zName, zLabel)==0;
|
|
||||||
sqlite3_free(zName);
|
|
||||||
if( isMatch ){
|
|
||||||
iCol = j;
|
iCol = j;
|
||||||
|
match = ORDERBY_MATCH_PARTIAL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sqlite3_free(zLabel);
|
|
||||||
}
|
}
|
||||||
if( iCol>=0 ){
|
sqlite3ExprDelete(pDup);
|
||||||
|
}
|
||||||
|
if( match ){
|
||||||
pE->op = TK_COLUMN;
|
pE->op = TK_COLUMN;
|
||||||
pE->iColumn = iCol;
|
|
||||||
pE->iTable = iTable;
|
pE->iTable = iTable;
|
||||||
pE->iAgg = -1;
|
pE->iAgg = -1;
|
||||||
pOrderBy->a[i].done = 1;
|
if( pOrderBy->a[i].done!=ORDERBY_MATCH_NONE && pE->iColumn!=iCol ){
|
||||||
}else if( mustComplete ){
|
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,
|
sqlite3ErrorMsg(pParse,
|
||||||
"ORDER BY term number %d does not match any result column", i+1);
|
"ORDER BY term number %d does not match any result column", i+1);
|
||||||
nErr++;
|
nErr++;
|
||||||
@@ -2720,11 +2743,11 @@ int sqlite3SelectResolve(
|
|||||||
sqlite3ExprResolveNames(&sNC, p->pHaving) ){
|
sqlite3ExprResolveNames(&sNC, p->pHaving) ){
|
||||||
return SQLITE_ERROR;
|
return SQLITE_ERROR;
|
||||||
}
|
}
|
||||||
if( p->pPrior==0 ){
|
if( p->pPrior==0 && processOrderGroupBy(&sNC, p->pOrderBy, "ORDER") ){
|
||||||
if( processOrderGroupBy(&sNC, p->pOrderBy, "ORDER") ||
|
|
||||||
processOrderGroupBy(&sNC, pGroupBy, "GROUP") ){
|
|
||||||
return SQLITE_ERROR;
|
return SQLITE_ERROR;
|
||||||
}
|
}
|
||||||
|
if( processOrderGroupBy(&sNC, pGroupBy, "GROUP") ){
|
||||||
|
return SQLITE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( pParse->db->mallocFailed ){
|
if( pParse->db->mallocFailed ){
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
# This file implements regression tests for SQLite library. The
|
# This file implements regression tests for SQLite library. The
|
||||||
# focus of this file is testing the SELECT statement.
|
# focus of this file is testing the SELECT statement.
|
||||||
#
|
#
|
||||||
# $Id: select1.test,v 1.54 2007/07/23 22:51:15 drh Exp $
|
# $Id: select1.test,v 1.55 2007/12/08 21:10:20 drh Exp $
|
||||||
|
|
||||||
set testdir [file dirname $argv0]
|
set testdir [file dirname $argv0]
|
||||||
source $testdir/tester.tcl
|
source $testdir/tester.tcl
|
||||||
@@ -517,7 +517,7 @@ do_test select1-6.10 {
|
|||||||
do_test select1-6.11 {
|
do_test select1-6.11 {
|
||||||
set v [catch {execsql2 {
|
set v [catch {execsql2 {
|
||||||
SELECT f1 FROM test1 UNION SELECT f2+100 FROM test1
|
SELECT f1 FROM test1 UNION SELECT f2+100 FROM test1
|
||||||
ORDER BY f2+100;
|
ORDER BY f2+101;
|
||||||
}} msg]
|
}} msg]
|
||||||
lappend v $msg
|
lappend v $msg
|
||||||
} {1 {ORDER BY term number 1 does not match any result column}}
|
} {1 {ORDER BY term number 1 does not match any result column}}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
# focus of this file is testing UNION, INTERSECT and EXCEPT operators
|
# focus of this file is testing UNION, INTERSECT and EXCEPT operators
|
||||||
# in SELECT statements.
|
# in SELECT statements.
|
||||||
#
|
#
|
||||||
# $Id: select4.test,v 1.20 2006/06/20 11:01:09 danielk1977 Exp $
|
# $Id: select4.test,v 1.21 2007/12/08 21:10:20 drh Exp $
|
||||||
|
|
||||||
set testdir [file dirname $argv0]
|
set testdir [file dirname $argv0]
|
||||||
source $testdir/tester.tcl
|
source $testdir/tester.tcl
|
||||||
@@ -283,7 +283,7 @@ do_test select4-5.2b {
|
|||||||
SELECT DISTINCT log AS xyzzy FROM t1
|
SELECT DISTINCT log AS xyzzy FROM t1
|
||||||
UNION ALL
|
UNION ALL
|
||||||
SELECT n FROM t1 WHERE log=3
|
SELECT n FROM t1 WHERE log=3
|
||||||
ORDER BY 'xyzzy';
|
ORDER BY "xyzzy";
|
||||||
}} msg]
|
}} msg]
|
||||||
lappend v $msg
|
lappend v $msg
|
||||||
} {0 {0 1 2 3 4 5 5 6 7 8}}
|
} {0 {0 1 2 3 4 5 5 6 7 8}}
|
||||||
@@ -292,7 +292,7 @@ do_test select4-5.2c {
|
|||||||
SELECT DISTINCT log FROM t1
|
SELECT DISTINCT log FROM t1
|
||||||
UNION ALL
|
UNION ALL
|
||||||
SELECT n FROM t1 WHERE log=3
|
SELECT n FROM t1 WHERE log=3
|
||||||
ORDER BY 'xyzzy';
|
ORDER BY "xyzzy";
|
||||||
}} msg]
|
}} msg]
|
||||||
lappend v $msg
|
lappend v $msg
|
||||||
} {1 {ORDER BY term number 1 does not match any result column}}
|
} {1 {ORDER BY term number 1 does not match any result column}}
|
||||||
@@ -301,7 +301,7 @@ do_test select4-5.2d {
|
|||||||
SELECT DISTINCT log FROM t1
|
SELECT DISTINCT log FROM t1
|
||||||
INTERSECT
|
INTERSECT
|
||||||
SELECT n FROM t1 WHERE log=3
|
SELECT n FROM t1 WHERE log=3
|
||||||
ORDER BY 'xyzzy';
|
ORDER BY "xyzzy";
|
||||||
}} msg]
|
}} msg]
|
||||||
lappend v $msg
|
lappend v $msg
|
||||||
} {1 {ORDER BY term number 1 does not match any result column}}
|
} {1 {ORDER BY term number 1 does not match any result column}}
|
||||||
|
|||||||
Reference in New Issue
Block a user