mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-15 11:41:13 +03:00
When generating WHERE clause terms internally for NATURAL and USING joins, identify the table by its position in the FROM list, not by its name or alias. Fix for [b73fb0bd64].
FossilOrigin-Name: 6fe6371175482d38ac4aeea994c7b20c18b7de01
This commit is contained in:
90
src/select.c
90
src/select.c
@@ -192,51 +192,45 @@ static int columnIndex(Table *pTab, const char *zCol){
|
||||
}
|
||||
|
||||
/*
|
||||
** Create an expression node for an identifier with the name of zName
|
||||
*/
|
||||
Expr *sqlite3CreateIdExpr(Parse *pParse, const char *zName){
|
||||
return sqlite3Expr(pParse->db, TK_ID, zName);
|
||||
}
|
||||
|
||||
/*
|
||||
** Add a term to the WHERE expression in *ppExpr that requires the
|
||||
** zCol column to be equal in the two tables pTab1 and pTab2.
|
||||
** This function is used to add terms implied by JOIN syntax to the
|
||||
** WHERE clause expression of a SELECT statement. The new term, which
|
||||
** is ANDed with the existing WHERE clause, is of the form:
|
||||
**
|
||||
** (tab1.col1 = tab2.col2)
|
||||
**
|
||||
** where tab1 is the iSrc'th table in SrcList pSrc and tab2 is the
|
||||
** (iSrc+1)'th. Column col1 is column iColLeft of tab1, and col2 is
|
||||
** column iColRight of tab2.
|
||||
*/
|
||||
static void addWhereTerm(
|
||||
Parse *pParse, /* Parsing context */
|
||||
const char *zCol, /* Name of the column */
|
||||
const Table *pTab1, /* First table */
|
||||
const char *zAlias1, /* Alias for first table. May be NULL */
|
||||
const Table *pTab2, /* Second table */
|
||||
const char *zAlias2, /* Alias for second table. May be NULL */
|
||||
int iRightJoinTable, /* VDBE cursor for the right table */
|
||||
Expr **ppExpr, /* Add the equality term to this expression */
|
||||
int isOuterJoin /* True if dealing with an OUTER join */
|
||||
Parse *pParse, /* Parsing context */
|
||||
SrcList *pSrc, /* List of tables in FROM clause */
|
||||
int iSrc, /* Index of first table to join in pSrc */
|
||||
int iColLeft, /* Index of column in first table */
|
||||
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 */
|
||||
){
|
||||
Expr *pE1a, *pE1b, *pE1c;
|
||||
Expr *pE2a, *pE2b, *pE2c;
|
||||
Expr *pE;
|
||||
sqlite3 *db = pParse->db;
|
||||
Expr *pE1;
|
||||
Expr *pE2;
|
||||
Expr *pEq;
|
||||
|
||||
pE1a = sqlite3CreateIdExpr(pParse, zCol);
|
||||
pE2a = sqlite3CreateIdExpr(pParse, zCol);
|
||||
if( zAlias1==0 ){
|
||||
zAlias1 = pTab1->zName;
|
||||
assert( pSrc->nSrc>(iSrc+1) );
|
||||
assert( pSrc->a[iSrc].pTab );
|
||||
assert( pSrc->a[iSrc+1].pTab );
|
||||
|
||||
pE1 = sqlite3CreateColumnExpr(db, pSrc, iSrc, iColLeft);
|
||||
pE2 = sqlite3CreateColumnExpr(db, pSrc, iSrc+1, iColRight);
|
||||
|
||||
pEq = sqlite3PExpr(pParse, TK_EQ, pE1, pE2, 0);
|
||||
if( pEq && isOuterJoin ){
|
||||
ExprSetProperty(pEq, EP_FromJoin);
|
||||
assert( !ExprHasAnyProperty(pEq, EP_TokenOnly|EP_Reduced) );
|
||||
ExprSetIrreducible(pEq);
|
||||
pEq->iRightJoinTable = (i16)pE2->iTable;
|
||||
}
|
||||
pE1b = sqlite3CreateIdExpr(pParse, zAlias1);
|
||||
if( zAlias2==0 ){
|
||||
zAlias2 = pTab2->zName;
|
||||
}
|
||||
pE2b = sqlite3CreateIdExpr(pParse, zAlias2);
|
||||
pE1c = sqlite3PExpr(pParse, TK_DOT, pE1b, pE1a, 0);
|
||||
pE2c = sqlite3PExpr(pParse, TK_DOT, pE2b, pE2a, 0);
|
||||
pE = sqlite3PExpr(pParse, TK_EQ, pE1c, pE2c, 0);
|
||||
if( pE && isOuterJoin ){
|
||||
ExprSetProperty(pE, EP_FromJoin);
|
||||
assert( !ExprHasAnyProperty(pE, EP_TokenOnly|EP_Reduced) );
|
||||
ExprSetIrreducible(pE);
|
||||
pE->iRightJoinTable = (i16)iRightJoinTable;
|
||||
}
|
||||
*ppExpr = sqlite3ExprAnd(pParse->db,*ppExpr, pE);
|
||||
*ppWhere = sqlite3ExprAnd(db, *ppWhere, pEq);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -318,11 +312,9 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){
|
||||
}
|
||||
for(j=0; j<pLeftTab->nCol; j++){
|
||||
char *zName = pLeftTab->aCol[j].zName;
|
||||
if( columnIndex(pRightTab, zName)>=0 ){
|
||||
addWhereTerm(pParse, zName, pLeftTab, pLeft->zAlias,
|
||||
pRightTab, pRight->zAlias,
|
||||
pRight->iCursor, &p->pWhere, isOuter);
|
||||
|
||||
int iRightCol = columnIndex(pRightTab, zName);
|
||||
if( iRightCol>=0 ){
|
||||
addWhereTerm(pParse, pSrc, i, j, iRightCol, isOuter, &p->pWhere);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -355,14 +347,14 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){
|
||||
IdList *pList = pRight->pUsing;
|
||||
for(j=0; j<pList->nId; j++){
|
||||
char *zName = pList->a[j].zName;
|
||||
if( columnIndex(pLeftTab, zName)<0 || columnIndex(pRightTab, zName)<0 ){
|
||||
int iLeftCol = columnIndex(pLeftTab, zName);
|
||||
int iRightCol = columnIndex(pRightTab, zName);
|
||||
if( iLeftCol<0 || iRightCol<0 ){
|
||||
sqlite3ErrorMsg(pParse, "cannot join using column %s - column "
|
||||
"not present in both tables", zName);
|
||||
return 1;
|
||||
}
|
||||
addWhereTerm(pParse, zName, pLeftTab, pLeft->zAlias,
|
||||
pRightTab, pRight->zAlias,
|
||||
pRight->iCursor, &p->pWhere, isOuter);
|
||||
addWhereTerm(pParse, pSrc, i, iLeftCol, iRightCol, isOuter, &p->pWhere);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user