]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
The USING clause and NATURAL JOIN look at all tables to the left when
authordrh <drh@noemail.net>
Wed, 9 Dec 2009 17:36:39 +0000 (17:36 +0000)
committerdrh <drh@noemail.net>
Wed, 9 Dec 2009 17:36:39 +0000 (17:36 +0000)
searching for a match, not just the one table to the immediate left.
Tables further to the left are preferred.
Fix for ticket [f74beaabde].  Still need to add test cases to complete
the ticket.

FossilOrigin-Name: b558e96f0a3cd2cbbe86e44293246a4730960d52

manifest
manifest.uuid
src/select.c

index c0c8f772878d07611c69122794315d1e2377840d..bbd8d3af0df4e985403feece8599bcf462816e21 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,8 @@
-C Improve\stest\scoverage\sof\sfts3.c.
-D 2009-12-09T14:39:41
+-----BEGIN PGP SIGNED MESSAGE-----
+Hash: SHA1
+
+C The\sUSING\sclause\sand\sNATURAL\sJOIN\slook\sat\sall\stables\sto\sthe\sleft\swhen\nsearching\sfor\sa\smatch,\snot\sjust\sthe\sone\stable\sto\sthe\simmediate\sleft.\nTables\sfurther\sto\sthe\sleft\sare\spreferred.\nFix\sfor\sticket\s[f74beaabde].\s\sStill\sneed\sto\sadd\stest\scases\sto\scomplete\nthe\sticket.
+D 2009-12-09T17:36:40
 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
 F Makefile.in c5827ead754ab32b9585487177c93bb00b9497b3
 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@@ -162,7 +165,7 @@ F src/printf.c 644bc7d59df3dc56d6d8b9a510914bfc6b51bc69
 F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50
 F src/resolve.c d052e5c44bab34f83b3c1741aaa07478d18b5dd5
 F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697
-F src/select.c 2f9ed7482e7a25b0b127fc41693bbdbe1caf5647
+F src/select.c 68c58dc49341472e4e5661a47a1a9e5f8a161340
 F src/shell.c f4948cb6d30665d755a6b5e0ec313d1094aab828
 F src/sqlite.h.in 338e1ac00faa7e3a536e7f1120827dd1f6432981
 F src/sqlite3ext.h 69dfb8116af51b84a029cddb3b35062354270c89
@@ -777,7 +780,14 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
 F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
-P a9038306c33c88120d8bef27209d8f0641c85c9b
-R db340fa6c4afcd8bc8679373cdbca6c1
-U dan
-Z eeb82c42887166b9ef7e8ca6456b81ff
+P 56b6432f8622d53ffd3a4d9a2244114f8531ed71
+R c60687f3ab920ee77b412f18848340fb
+U drh
+Z 12648e9ade5661889385face890b1540
+-----BEGIN PGP SIGNATURE-----
+Version: GnuPG v1.4.6 (GNU/Linux)
+
+iD8DBQFLH+AsoxKgR168RlERAqq+AJ42LhMfpcSfI/s5lEGDLv5D00O41wCfWMQf
+iT/qNX5HigqUQ+DEbiPla9M=
+=Wtyb
+-----END PGP SIGNATURE-----
index 9571b8bc18da48f7dd441e03374d17668dd3e659..54c0a97ffc9888bf21319056d2c1a3c13e3c6ab2 100644 (file)
@@ -1 +1 @@
-56b6432f8622d53ffd3a4d9a2244114f8531ed71
\ No newline at end of file
+b558e96f0a3cd2cbbe86e44293246a4730960d52
\ No newline at end of file
index 7555a391c2504e6e2d4183a9cba5c89239b3f3fe..80c236686928f9fa4215679fc063a76d3b3b5bc2 100644 (file)
@@ -189,6 +189,39 @@ static int columnIndex(Table *pTab, const char *zCol){
   return -1;
 }
 
+/*
+** Search the first N tables in pSrc, from left to right, looking for a
+** table that has a column named zCol.  
+**
+** When found, set *piTab and *piCol to the table index and column index
+** of the matching column and return TRUE.
+**
+** If not found, return FALSE.
+*/
+static int tableAndColumnIndex(
+  SrcList *pSrc,       /* Array of tables to search */
+  int N,               /* Number of tables in pSrc->a[] to search */
+  const char *zCol,    /* Name of the column we are looking for */
+  int *piTab,          /* Write index of pSrc->a[] here */
+  int *piCol           /* Write index of pSrc->a[*piTab].pTab->aCol[] here */
+){
+  int i;               /* For looping over tables in pSrc */
+  int iCol;            /* Index of column matching zCol */
+
+  assert( (piTab==0)==(piCol==0) );  /* Both or neither are NULL */
+  for(i=0; i<N; i++){
+    iCol = columnIndex(pSrc->a[i].pTab, zCol);
+    if( iCol>=0 ){
+      if( piTab ){
+        *piTab = i;
+        *piCol = iCol;
+      }
+      return 1;
+    }
+  }
+  return 0;
+}
+
 /*
 ** This function is used to add terms implied by JOIN syntax to the
 ** WHERE clause expression of a SELECT statement. The new term, which
@@ -203,8 +236,9 @@ static int columnIndex(Table *pTab, const char *zCol){
 static void addWhereTerm(
   Parse *pParse,                  /* Parsing context */
   SrcList *pSrc,                  /* List of tables in FROM clause */
-  int iSrc,                       /* Index of first table to join in pSrc */
+  int iLeft,                      /* Index of first table to join in pSrc */
   int iColLeft,                   /* Index of column in first table */
+  int iRight,                     /* Index of second table in pSrc */
   int iColRight,                  /* Index of column in second table */
   int isOuterJoin,                /* True if this is an OUTER join */
   Expr **ppWhere                  /* IN/OUT: The WHERE clause to add to */
@@ -214,12 +248,13 @@ static void addWhereTerm(
   Expr *pE2;
   Expr *pEq;
 
-  assert( pSrc->nSrc>(iSrc+1) );
-  assert( pSrc->a[iSrc].pTab );
-  assert( pSrc->a[iSrc+1].pTab );
+  assert( iLeft<iRight );
+  assert( pSrc->nSrc>iRight );
+  assert( pSrc->a[iLeft].pTab );
+  assert( pSrc->a[iRight].pTab );
 
-  pE1 = sqlite3CreateColumnExpr(db, pSrc, iSrc, iColLeft);
-  pE2 = sqlite3CreateColumnExpr(db, pSrc, iSrc+1, iColRight);
+  pE1 = sqlite3CreateColumnExpr(db, pSrc, iLeft, iColLeft);
+  pE2 = sqlite3CreateColumnExpr(db, pSrc, iRight, iColRight);
 
   pEq = sqlite3PExpr(pParse, TK_EQ, pE1, pE2, 0);
   if( pEq && isOuterJoin ){
@@ -308,11 +343,15 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){
            "an ON or USING clause", 0);
         return 1;
       }
-      for(j=0; j<pLeftTab->nCol; j++){
-        char *zName = pLeftTab->aCol[j].zName;
-        int iRightCol = columnIndex(pRightTab, zName);
-        if( iRightCol>=0 ){
-          addWhereTerm(pParse, pSrc, i, j, iRightCol, isOuter, &p->pWhere);
+      for(j=0; j<pRightTab->nCol; j++){
+        char *zName;   /* Name of column in the right table */
+        int iLeft;     /* Matching left table */
+        int iLeftCol;  /* Matching column in the left table */
+
+        zName = pRightTab->aCol[j].zName;
+        if( tableAndColumnIndex(pSrc, i+1, zName, &iLeft, &iLeftCol) ){
+          addWhereTerm(pParse, pSrc, iLeft, iLeftCol, i+1, j,
+                       isOuter, &p->pWhere);
         }
       }
     }
@@ -344,15 +383,22 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){
     if( pRight->pUsing ){
       IdList *pList = pRight->pUsing;
       for(j=0; j<pList->nId; j++){
-        char *zName = pList->a[j].zName;
-        int iLeftCol = columnIndex(pLeftTab, zName);
-        int iRightCol = columnIndex(pRightTab, zName);
-        if( iLeftCol<0 || iRightCol<0 ){
+        char *zName;     /* Name of the term in the USING clause */
+        int iLeft;       /* Table on the left with matching column name */
+        int iLeftCol;    /* Column number of matching column on the left */
+        int iRightCol;   /* Column number of matching column on the right */
+
+        zName = pList->a[j].zName;
+        iRightCol = columnIndex(pRightTab, zName);
+        if( iRightCol<0
+         || !tableAndColumnIndex(pSrc, i+1, zName, &iLeft, &iLeftCol)
+        ){
           sqlite3ErrorMsg(pParse, "cannot join using column %s - column "
             "not present in both tables", zName);
           return 1;
         }
-        addWhereTerm(pParse, pSrc, i, iLeftCol, iRightCol, isOuter, &p->pWhere);
+        addWhereTerm(pParse, pSrc, iLeft, iLeftCol, i+1, iRightCol,
+                     isOuter, &p->pWhere);
       }
     }
   }
@@ -3169,14 +3215,14 @@ static int selectExpander(Walker *pWalker, Select *p){
             }
 
             if( i>0 && zTName==0 ){
-              struct SrcList_item *pLeft = &pTabList->a[i-1];
-              if( (pLeft[1].jointype & JT_NATURAL)!=0 &&
-                        columnIndex(pLeft->pTab, zName)>=0 ){
+              if( (pFrom->jointype & JT_NATURAL)!=0
+                && tableAndColumnIndex(pTabList, i, zName, 0, 0)
+              ){
                 /* In a NATURAL join, omit the join columns from the 
-                ** table on the right */
+                ** table to the right of the join */
                 continue;
               }
-              if( sqlite3IdListIndex(pLeft[1].pUsing, zName)>=0 ){
+              if( sqlite3IdListIndex(pFrom->pUsing, zName)>=0 ){
                 /* In a join with a USING clause, omit columns in the
                 ** using clause from the table on the right. */
                 continue;