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:
24
manifest
24
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-----
|
||||
|
||||
@@ -1 +1 @@
|
||||
56b6432f8622d53ffd3a4d9a2244114f8531ed71
|
||||
b558e96f0a3cd2cbbe86e44293246a4730960d52
|
||||
88
src/select.c
88
src/select.c
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user