1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-11-14 00:22:38 +03:00

The USING clause and NATURAL JOIN look at all tables to the left when

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
This commit is contained in:
drh
2009-12-09 17:36:39 +00:00
parent 18ff7fa6b4
commit 2179b43465
3 changed files with 85 additions and 29 deletions

View File

@@ -1,5 +1,8 @@
C Improve\stest\scoverage\sof\sfts3.c. -----BEGIN PGP SIGNED MESSAGE-----
D 2009-12-09T14:39:41 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.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
F Makefile.in c5827ead754ab32b9585487177c93bb00b9497b3 F Makefile.in c5827ead754ab32b9585487177c93bb00b9497b3
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@@ -162,7 +165,7 @@ F src/printf.c 644bc7d59df3dc56d6d8b9a510914bfc6b51bc69
F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50 F src/random.c cd4a67b3953b88019f8cd4ccd81394a8ddfaba50
F src/resolve.c d052e5c44bab34f83b3c1741aaa07478d18b5dd5 F src/resolve.c d052e5c44bab34f83b3c1741aaa07478d18b5dd5
F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697 F src/rowset.c 69afa95a97c524ba6faf3805e717b5b7ae85a697
F src/select.c 2f9ed7482e7a25b0b127fc41693bbdbe1caf5647 F src/select.c 68c58dc49341472e4e5661a47a1a9e5f8a161340
F src/shell.c f4948cb6d30665d755a6b5e0ec313d1094aab828 F src/shell.c f4948cb6d30665d755a6b5e0ec313d1094aab828
F src/sqlite.h.in 338e1ac00faa7e3a536e7f1120827dd1f6432981 F src/sqlite.h.in 338e1ac00faa7e3a536e7f1120827dd1f6432981
F src/sqlite3ext.h 69dfb8116af51b84a029cddb3b35062354270c89 F src/sqlite3ext.h 69dfb8116af51b84a029cddb3b35062354270c89
@@ -777,7 +780,14 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
P a9038306c33c88120d8bef27209d8f0641c85c9b P 56b6432f8622d53ffd3a4d9a2244114f8531ed71
R db340fa6c4afcd8bc8679373cdbca6c1 R c60687f3ab920ee77b412f18848340fb
U dan U drh
Z eeb82c42887166b9ef7e8ca6456b81ff Z 12648e9ade5661889385face890b1540
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.6 (GNU/Linux)
iD8DBQFLH+AsoxKgR168RlERAqq+AJ42LhMfpcSfI/s5lEGDLv5D00O41wCfWMQf
iT/qNX5HigqUQ+DEbiPla9M=
=Wtyb
-----END PGP SIGNATURE-----

View File

@@ -1 +1 @@
56b6432f8622d53ffd3a4d9a2244114f8531ed71 b558e96f0a3cd2cbbe86e44293246a4730960d52

View File

@@ -189,6 +189,39 @@ static int columnIndex(Table *pTab, const char *zCol){
return -1; 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 ** This function is used to add terms implied by JOIN syntax to the
** WHERE clause expression of a SELECT statement. The new term, which ** 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( static void addWhereTerm(
Parse *pParse, /* Parsing context */ Parse *pParse, /* Parsing context */
SrcList *pSrc, /* List of tables in FROM clause */ 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 iColLeft, /* Index of column in first table */
int iRight, /* Index of second table in pSrc */
int iColRight, /* Index of column in second table */ int iColRight, /* Index of column in second table */
int isOuterJoin, /* True if this is an OUTER join */ int isOuterJoin, /* True if this is an OUTER join */
Expr **ppWhere /* IN/OUT: The WHERE clause to add to */ Expr **ppWhere /* IN/OUT: The WHERE clause to add to */
@@ -214,12 +248,13 @@ static void addWhereTerm(
Expr *pE2; Expr *pE2;
Expr *pEq; Expr *pEq;
assert( pSrc->nSrc>(iSrc+1) ); assert( iLeft<iRight );
assert( pSrc->a[iSrc].pTab ); assert( pSrc->nSrc>iRight );
assert( pSrc->a[iSrc+1].pTab ); assert( pSrc->a[iLeft].pTab );
assert( pSrc->a[iRight].pTab );
pE1 = sqlite3CreateColumnExpr(db, pSrc, iSrc, iColLeft); pE1 = sqlite3CreateColumnExpr(db, pSrc, iLeft, iColLeft);
pE2 = sqlite3CreateColumnExpr(db, pSrc, iSrc+1, iColRight); pE2 = sqlite3CreateColumnExpr(db, pSrc, iRight, iColRight);
pEq = sqlite3PExpr(pParse, TK_EQ, pE1, pE2, 0); pEq = sqlite3PExpr(pParse, TK_EQ, pE1, pE2, 0);
if( pEq && isOuterJoin ){ if( pEq && isOuterJoin ){
@@ -308,11 +343,15 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){
"an ON or USING clause", 0); "an ON or USING clause", 0);
return 1; return 1;
} }
for(j=0; j<pLeftTab->nCol; j++){ for(j=0; j<pRightTab->nCol; j++){
char *zName = pLeftTab->aCol[j].zName; char *zName; /* Name of column in the right table */
int iRightCol = columnIndex(pRightTab, zName); int iLeft; /* Matching left table */
if( iRightCol>=0 ){ int iLeftCol; /* Matching column in the left table */
addWhereTerm(pParse, pSrc, i, j, iRightCol, isOuter, &p->pWhere);
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 ){ if( pRight->pUsing ){
IdList *pList = pRight->pUsing; IdList *pList = pRight->pUsing;
for(j=0; j<pList->nId; j++){ for(j=0; j<pList->nId; j++){
char *zName = pList->a[j].zName; char *zName; /* Name of the term in the USING clause */
int iLeftCol = columnIndex(pLeftTab, zName); int iLeft; /* Table on the left with matching column name */
int iRightCol = columnIndex(pRightTab, zName); int iLeftCol; /* Column number of matching column on the left */
if( iLeftCol<0 || iRightCol<0 ){ 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 " sqlite3ErrorMsg(pParse, "cannot join using column %s - column "
"not present in both tables", zName); "not present in both tables", zName);
return 1; 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 ){ if( i>0 && zTName==0 ){
struct SrcList_item *pLeft = &pTabList->a[i-1]; if( (pFrom->jointype & JT_NATURAL)!=0
if( (pLeft[1].jointype & JT_NATURAL)!=0 && && tableAndColumnIndex(pTabList, i, zName, 0, 0)
columnIndex(pLeft->pTab, zName)>=0 ){ ){
/* In a NATURAL join, omit the join columns from the /* In a NATURAL join, omit the join columns from the
** table on the right */ ** table to the right of the join */
continue; 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 /* In a join with a USING clause, omit columns in the
** using clause from the table on the right. */ ** using clause from the table on the right. */
continue; continue;