From: drh Date: Tue, 18 Oct 2011 18:10:40 +0000 (+0000) Subject: Improved handling of USING and NATURAL JOIN in 3-way and higher joins. X-Git-Tag: version-3.7.9~21 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=e802c5da0101e9a3b4ad5e8925f47e636f8a9f3b;p=thirdparty%2Fsqlite.git Improved handling of USING and NATURAL JOIN in 3-way and higher joins. Ticket [3338b3fa19ac4ab] FossilOrigin-Name: 551ce407bd77149865423511bd52eba2f404161a --- diff --git a/manifest b/manifest index ecd1811831..ff182816e5 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sa\sfloating-point\sexception\sthat\scan\soccur\swhen\san\sFTS4\squery\scontains\sa\slarge\snumber\sof\stokens\sconnected\sby\sAND\sor\sNEAR\soperators. -D 2011-10-18T12:44:04.580 +C Improved\shandling\sof\sUSING\sand\sNATURAL\sJOIN\sin\s3-way\sand\shigher\sjoins.\nTicket\s[3338b3fa19ac4ab] +D 2011-10-18T18:10:40.151 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f F Makefile.in a162fe39e249b8ed4a65ee947c30152786cfe897 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23 @@ -177,7 +177,7 @@ F src/pragma.c da8ef96b3eec351e81e0061c39810e548bcc96d7 F src/prepare.c e64261559a3187698a3e7e6c8b001a4f4f98dab4 F src/printf.c 03104cbff6959ff45df69dc9060ba6212f60a869 F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50 -F src/resolve.c 36368f44569208fa074e61f4dd0b6c4fb60ca2b4 +F src/resolve.c 365ab1c870e38596d6869e76fb544fe6e4ffc809 F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697 F src/select.c 80f3ac44a8514b1d107b80f5df4a424ae059d2b6 F src/shell.c f0ab793261ab045a0b8c47fa2707e8a894d2898f @@ -913,7 +913,7 @@ F test/walslow.test e7be6d9888f83aa5d3d3c7c08aa9b5c28b93609a F test/walthread.test a2ed5270eb695284d4ad27d252517bdc3317ee2a F test/where.test de337a3fe0a459ec7c93db16a519657a90552330 F test/where2.test 43d4becaf5a5df854e6c21d624a1cb84c6904554 -F test/where3.test 8e1175c7ef710c70502858fc4fb08d784b3620b9 +F test/where3.test 667e75642102c97a00bf9b23d3cb267db321d006 F test/where4.test e9b9e2f2f98f00379e6031db6a6fca29bae782a2 F test/where5.test fdf66f96d29a064b63eb543e28da4dfdccd81ad2 F test/where6.test 5da5a98cec820d488e82708301b96cb8c18a258b @@ -970,7 +970,7 @@ F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/warnings-clang.sh 9f406d66e750e8ac031c63a9ef3248aaa347ef2a F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381 -P 491ff5fb2504173d6905e38b8ea35737338aaa84 -R 58f061e71ad84767d73477085e2bfcf6 -U dan -Z b0882f47410096d3d98223e9ef02aa47 +P 3126754c72351c724be29d75a194bfc3e7b67205 +R ed8534091276e292d87550ffda27999e +U drh +Z a262b8d3562a7e10f8c3ec0f3139747f diff --git a/manifest.uuid b/manifest.uuid index 40229f72ff..bbfaa20303 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -3126754c72351c724be29d75a194bfc3e7b67205 \ No newline at end of file +551ce407bd77149865423511bd52eba2f404161a \ No newline at end of file diff --git a/src/resolve.c b/src/resolve.c index d29d2a8344..6d857f0074 100644 --- a/src/resolve.c +++ b/src/resolve.c @@ -98,6 +98,24 @@ static void resolveAlias( sqlite3DbFree(db, pDup); } + +/* +** Return TRUE if the name zCol occurs anywhere in the USING clause. +** +** Return FALSE if the USING clause is NULL or if it does not contain +** zCol. +*/ +static int nameInUsingClause(IdList *pUsing, const char *zCol){ + if( pUsing ){ + int k; + for(k=0; knId; k++){ + if( sqlite3StrICmp(pUsing->a[k].zName, zCol)==0 ) return 1; + } + } + return 0; +} + + /* ** Given the name of a column of the form X.Y.Z or Y.Z or just Z, look up ** that name in the set of source tables in pSrcList and make the pExpr @@ -189,7 +207,14 @@ static int lookupName( } for(j=0, pCol=pTab->aCol; jnCol; j++, pCol++){ if( sqlite3StrICmp(pCol->zName, zCol)==0 ){ - IdList *pUsing; + /* If there has been exactly one prior match and this match + ** is for the right-hand table of a NATURAL JOIN or is in a + ** USING clause, then skip this match. + */ + if( cnt==1 ){ + if( pItem->jointype & JT_NATURAL ) continue; + if( nameInUsingClause(pItem->pUsing, zCol) ) continue; + } cnt++; pExpr->iTable = pItem->iCursor; pExpr->pTab = pTab; @@ -197,26 +222,6 @@ static int lookupName( pSchema = pTab->pSchema; /* Substitute the rowid (column -1) for the INTEGER PRIMARY KEY */ pExpr->iColumn = j==pTab->iPKey ? -1 : (i16)j; - if( inSrc-1 ){ - if( pItem[1].jointype & JT_NATURAL ){ - /* If this match occurred in the left table of a natural join, - ** then skip the right table to avoid a duplicate match */ - pItem++; - i++; - }else if( (pUsing = pItem[1].pUsing)!=0 ){ - /* If this match occurs on a column that is in the USING clause - ** of a join, skip the search of the right table of the join - ** to avoid a duplicate match there. */ - int k; - for(k=0; knId; k++){ - if( sqlite3StrICmp(pUsing->a[k].zName, zCol)==0 ){ - pItem++; - i++; - break; - } - } - } - } break; } } diff --git a/test/where3.test b/test/where3.test index ab75fdec19..e08f9051e2 100644 --- a/test/where3.test +++ b/test/where3.test @@ -342,4 +342,87 @@ do_execsql_test where3-5.3 { 0 0 0 {USE TEMP B-TREE FOR ORDER BY} } +# Name resolution with NATURAL JOIN and USING +# +do_test where3-6.setup { + db eval { + CREATE TABLE t6w(a, w); + INSERT INTO t6w VALUES(1, 'w-one'); + INSERT INTO t6w VALUES(2, 'w-two'); + INSERT INTO t6w VALUES(9, 'w-nine'); + CREATE TABLE t6x(a, x); + INSERT INTO t6x VALUES(1, 'x-one'); + INSERT INTO t6x VALUES(3, 'x-three'); + INSERT INTO t6x VALUES(9, 'x-nine'); + CREATE TABLE t6y(a, y); + INSERT INTO t6y VALUES(1, 'y-one'); + INSERT INTO t6y VALUES(4, 'y-four'); + INSERT INTO t6y VALUES(9, 'y-nine'); + CREATE TABLE t6z(a, z); + INSERT INTO t6z VALUES(1, 'z-one'); + INSERT INTO t6z VALUES(5, 'z-five'); + INSERT INTO t6z VALUES(9, 'z-nine'); + } +} {} +set cnt 0 +foreach predicate { + {} + {ORDER BY a} + {ORDER BY t6w.a} + {WHERE a>0} + {WHERE t6y.a>0} + {WHERE a>0 ORDER BY a} +} { + incr cnt + do_test where3-6.$cnt.1 { + set sql "SELECT * FROM t6w NATURAL JOIN t6x NATURAL JOIN t6y" + append sql " NATURAL JOIN t6z " + append sql $::predicate + db eval $sql + } {1 w-one x-one y-one z-one 9 w-nine x-nine y-nine z-nine} + do_test where3-6.$cnt.2 { + set sql "SELECT * FROM t6w JOIN t6x USING(a) JOIN t6y USING(a)" + append sql " JOIN t6z USING(a) " + append sql $::predicate + db eval $sql + } {1 w-one x-one y-one z-one 9 w-nine x-nine y-nine z-nine} + do_test where3-6.$cnt.3 { + set sql "SELECT * FROM t6w NATURAL JOIN t6x JOIN t6y USING(a)" + append sql " JOIN t6z USING(a) " + append sql $::predicate + db eval $sql + } {1 w-one x-one y-one z-one 9 w-nine x-nine y-nine z-nine} + do_test where3-6.$cnt.4 { + set sql "SELECT * FROM t6w JOIN t6x USING(a) NATURAL JOIN t6y" + append sql " JOIN t6z USING(a) " + append sql $::predicate + db eval $sql + } {1 w-one x-one y-one z-one 9 w-nine x-nine y-nine z-nine} + do_test where3-6.$cnt.5 { + set sql "SELECT * FROM t6w JOIN t6x USING(a) JOIN t6y USING(a)" + append sql " NATURAL JOIN t6z " + append sql $::predicate + db eval $sql + } {1 w-one x-one y-one z-one 9 w-nine x-nine y-nine z-nine} + do_test where3-6.$cnt.6 { + set sql "SELECT * FROM t6w JOIN t6x USING(a) NATURAL JOIN t6y" + append sql " NATURAL JOIN t6z " + append sql $::predicate + db eval $sql + } {1 w-one x-one y-one z-one 9 w-nine x-nine y-nine z-nine} + do_test where3-6.$cnt.7 { + set sql "SELECT * FROM t6w NATURAL JOIN t6x JOIN t6y USING(a)" + append sql " NATURAL JOIN t6z " + append sql $::predicate + db eval $sql + } {1 w-one x-one y-one z-one 9 w-nine x-nine y-nine z-nine} + do_test where3-6.$cnt.8 { + set sql "SELECT * FROM t6w NATURAL JOIN t6x NATURAL JOIN t6y" + append sql " JOIN t6z USING(a) " + append sql $::predicate + db eval $sql + } {1 w-one x-one y-one z-one 9 w-nine x-nine y-nine z-nine} +} + + finish_test