]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Improved handling of USING and NATURAL JOIN in 3-way and higher joins.
authordrh <drh@noemail.net>
Tue, 18 Oct 2011 18:10:40 +0000 (18:10 +0000)
committerdrh <drh@noemail.net>
Tue, 18 Oct 2011 18:10:40 +0000 (18:10 +0000)
Ticket [3338b3fa19ac4ab]

FossilOrigin-Name: 551ce407bd77149865423511bd52eba2f404161a

manifest
manifest.uuid
src/resolve.c
test/where3.test

index ecd1811831b1462bc01123c9d584cf6dedcda9de..ff182816e5275280eae433af71cac03b1aecc0d3 100644 (file)
--- 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
index 40229f72ff7728d892ddc4c4d288d67b2130cb3b..bbfaa203034d6de7cc79c6a245835ece623bdc43 100644 (file)
@@ -1 +1 @@
-3126754c72351c724be29d75a194bfc3e7b67205
\ No newline at end of file
+551ce407bd77149865423511bd52eba2f404161a
\ No newline at end of file
index d29d2a8344433a0c3eceb544f1465ca78c38af5d..6d857f0074380fbdd628b1a7e11822845ed21b08 100644 (file)
@@ -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; k<pUsing->nId; 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; j<pTab->nCol; 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( i<pSrcList->nSrc-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; k<pUsing->nId; k++){
-                  if( sqlite3StrICmp(pUsing->a[k].zName, zCol)==0 ){
-                    pItem++;
-                    i++;
-                    break;
-                  }
-                }
-              }
-            }
             break;
           }
         }
index ab75fdec1963c9fb02a7fc72fb1a23b6fa081e50..e08f9051e2482ea4ff96daf27e5712fa1fd061ac 100644 (file)
@@ -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