From: drh Date: Tue, 10 Jun 2014 20:18:17 +0000 (+0000) Subject: Proposed change to the fix for ticket [1c69be2dafc28b] such that legacy X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=refs%2Fheads%2Fgroup-by-name-resolution;p=thirdparty%2Fsqlite.git Proposed change to the fix for ticket [1c69be2dafc28b] such that legacy applications that were exploiting the older buggy behavior in SQLite continue to work. FossilOrigin-Name: 401a0ca3dd7e214d07958b4659d947a443cbbc52 --- diff --git a/manifest b/manifest index 5eed2ac67e..3e8941918e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Avoid\san\sunnecessary\sinitialization\sof\sthe\sszFile\sfield\sof\sunixFile\sin\nthe\sunix\sVFS. -D 2014-06-09T20:39:03.676 +C Proposed\schange\sto\sthe\sfix\sfor\sticket\s[1c69be2dafc28b]\ssuch\sthat\slegacy\napplications\sthat\swere\sexploiting\sthe\solder\sbuggy\sbehavior\sin\sSQLite\ncontinue\sto\swork. +D 2014-06-10T20:18:17.534 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in dd2b1aba364ff9b05de41086f74407f285c57670 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -218,7 +218,7 @@ F src/pragma.c 810ef31ccfaa233201dcf100637a9777cc24e897 F src/prepare.c 677521ab7132615a8a26107a1d1c3132f44ae337 F src/printf.c af06f66927919730f03479fed6ae9854f73419f4 F src/random.c d10c1f85b6709ca97278428fd5db5bbb9c74eece -F src/resolve.c 273d5f47c4e2c05b2d3d2bffeda939551ab59e66 +F src/resolve.c f0c6db38b85433a5cbb85f1591c708707f58ead1 F src/rowset.c a9c9aae3234b44a6d7c6f5a3cadf90dce1e627be F src/select.c 6762c62e11b504aa014edceab8886495165e3a77 F src/shell.c 98ce7f52445aa0c2eac3d4553a4cdcbb6402a670 @@ -766,7 +766,7 @@ F test/regexp1.test 497ea812f264d12b6198d6e50a76be4a1973a9d8 F test/reindex.test 44edd3966b474468b823d481eafef0c305022254 F test/releasetest.mk 2eced2f9ae701fd0a29e714a241760503ccba25a F test/releasetest.tcl 06d289d8255794073a58d2850742f627924545ce -F test/resolver01.test 33abf37ff8335e6bf98f2b45a0af3e06996ccd9a +F test/resolver01.test 677dd35b245bdaef6403652feea073bb8f3c0a0c F test/rollback.test e9504a009a202c3ed711da2e6879ff60c5a4669c F test/rowhash.test 0bc1d31415e4575d10cacf31e1a66b5cc0f8be81 F test/rowid.test b78b30afb9537a73788ca1233a23a32190a3bb1f @@ -1174,7 +1174,10 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4 F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f -P 10707d35786403ea5392d980f593bfecdae063dd -R 5c924f630188cdd6e1f0b84a36c79d61 +P 6484fb5a25c2a0e5d26694285a4908a22c67ba17 +R 806d58b917ca6c1092af86ab71330c36 +T *branch * group-by-name-resolution +T *sym-group-by-name-resolution * +T -sym-trunk * U drh -Z b2fa1d596ef871591a5ab3a0251e8787 +Z 188b7f9184efcfb7e1d91d7e12607c6c diff --git a/manifest.uuid b/manifest.uuid index bf49aa9d51..a35257a2c7 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -6484fb5a25c2a0e5d26694285a4908a22c67ba17 \ No newline at end of file +401a0ca3dd7e214d07958b4659d947a443cbbc52 \ No newline at end of file diff --git a/src/resolve.c b/src/resolve.c index 86169c51c1..24af0cee67 100644 --- a/src/resolve.c +++ b/src/resolve.c @@ -797,12 +797,23 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ ** no match, or if pE is not a simple identifier, then this routine ** return 0. ** +** The sameNameOnly flag is set if pE comes from a GROUP BY clause. The +** arguments of a GROUP BY clause are not supposed to be able to match +** against AS names in SQL. But early versions of SQLite allowed this +** behavior by mistake. To provide backwards compatibility, a GROUP BY +** term will match as AS alias only if the corresponding result set expression +** refers to a table column by the same name. In other words: +** +** SELECT t1.x AS x, t2.x AS y FROM t1,t2 GROUP BY x; -- match +** SELECT t1.y AS x, t2.y AS y FROM t1,t2 GROUP BY x; -- no match +** ** pEList has been resolved. pE has not. */ static int resolveAsName( Parse *pParse, /* Parsing context for error messages */ ExprList *pEList, /* List of expressions to scan */ - Expr *pE /* Expression we are trying to match */ + Expr *pE, /* Expression we are trying to match */ + int sameNameOnly /* Only resolve if the alias matches the column name */ ){ int i; /* Loop counter */ @@ -812,9 +823,16 @@ static int resolveAsName( char *zCol = pE->u.zToken; for(i=0; inExpr; i++){ char *zAs = pEList->a[i].zName; - if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){ - return i+1; + if( zAs==0 ) continue; + if( sqlite3StrICmp(zAs, zCol)!=0 ) continue; + if( sameNameOnly ){ + Expr *p = pEList->a[i].pExpr; + Table *pTab; + if( p->op!=TK_COLUMN ) continue; + pTab = p->pTab; + if( sqlite3StrICmp(pTab->aCol[p->iColumn].zName, zAs)!=0 ) continue; } + return i+1; } } return 0; @@ -954,7 +972,7 @@ static int resolveCompoundOrderBy( return 1; } }else{ - iCol = resolveAsName(pParse, pEList, pE); + iCol = resolveAsName(pParse, pEList, pE, 0); if( iCol==0 ){ pDup = sqlite3ExprDup(db, pE, 0); if( !db->mallocFailed ){ @@ -1075,16 +1093,14 @@ static int resolveOrderGroupBy( for(i=0, pItem=pOrderBy->a; inExpr; i++, pItem++){ Expr *pE = pItem->pExpr; Expr *pE2 = sqlite3ExprSkipCollate(pE); - if( zType[0]!='G' ){ - iCol = resolveAsName(pParse, pSelect->pEList, pE2); - if( iCol>0 ){ - /* If an AS-name match is found, mark this ORDER BY column as being - ** a copy of the iCol-th result-set column. The subsequent call to - ** sqlite3ResolveOrderGroupBy() will convert the expression to a - ** copy of the iCol-th result-set expression. */ - pItem->u.x.iOrderByCol = (u16)iCol; - continue; - } + iCol = resolveAsName(pParse, pSelect->pEList, pE2, zType[0]=='G'); + if( iCol>0 ){ + /* If an AS-name match is found, mark this ORDER BY column as being + ** a copy of the iCol-th result-set column. The subsequent call to + ** sqlite3ResolveOrderGroupBy() will convert the expression to a + ** copy of the iCol-th result-set expression. */ + pItem->u.x.iOrderByCol = (u16)iCol; + continue; } if( sqlite3ExprIsInteger(pE2, &iCol) ){ /* The ORDER BY term is an integer constant. Again, set the column diff --git a/test/resolver01.test b/test/resolver01.test index 7d95a2132a..d7bbc44822 100644 --- a/test/resolver01.test +++ b/test/resolver01.test @@ -157,10 +157,10 @@ do_execsql_test resolver01-4.1 { # For SQLite version 3.7.17 the answer was two rows, which is wrong. # do_execsql_test resolver01-5.1 { - CREATE TABLE t5(m CHAR(2)); - INSERT INTO t5 VALUES('ax'); - INSERT INTO t5 VALUES('bx'); - INSERT INTO t5 VALUES('cy'); + CREATE TABLE t5(m CHAR(2), n); + INSERT INTO t5 VALUES('ax',1); + INSERT INTO t5 VALUES('bx',2); + INSERT INTO t5 VALUES('cy',2); SELECT count(*), substr(m,2,1) AS m FROM t5 GROUP BY m ORDER BY 1, 2; } {1 x 1 x 1 y} @@ -181,7 +181,7 @@ do_execsql_test resolver01-5.4 { GROUP BY substr(m,2,1) ORDER BY 1, 2; } {1 y 2 x} -# These test case weere provided in the 2013-08-14 email from Rob Golsteijn +# These test cases were provided in the 2013-08-14 email from Rob Golsteijn # that originally reported the problem of ticket [1c69be2dafc28]. # do_execsql_test resolver01-6.1 { @@ -201,8 +201,26 @@ do_execsql_test resolver01-6.3 { GROUP BY lower(name); } {1 {} 1 {}} - - - +# (2014-06-10) The fix to GROUP BY name binding has resulted in errors +# in some legacy Android applications. To work around this, GROUP BY terms +# can be bound to AS aliases as long as the corresponding expression is +# a column by the same name as the alias. Verify that this exception +# case works. Continuation of ticket [1c69be2dafc28]. +# +do_execsql_test resolver01-7.1 { + CREATE TABLE t7(m, x); + INSERT INTO t7 VALUES('bx',1),('ax',2),('dx',3); + SELECT count(*), t5.m AS m FROM t5, t7 GROUP BY m ORDER BY 2; +} {3 ax 3 bx 3 cy} +do_execsql_test resolver01-7.2 { + SELECT count(*), t5.m AS n FROM t5, t7 GROUP BY n ORDER BY 2; +} {3 ax 6 cy} +do_test resolver01-7.3 { + catchsql { + CREATE TABLE t7b(m, n); + INSERT INTO t7b SELECT * FROM t7; + SELECT count(*), t5.m AS n FROM t5, t7b GROUP BY n ORDER BY 2; + } +} {1 {ambiguous column name: n}} finish_test