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

Do not remove the EP_CanBeNull flag from expressions during a LEFT JOIN

strength reduction if the query also contains a RIGHT JOIN. Fix for
the problem identified by
[forum/forumpost/b40696f50145d21c|forum post b40696f50145d21c].

FossilOrigin-Name: b1be2259e2e08ec22a88bc9a18b3ab4d83246ad4c635c05cdf80d3eff84df06a
This commit is contained in:
drh
2022-06-13 12:42:24 +00:00
parent 1cc5c4ac84
commit 92d1afba9b
4 changed files with 55 additions and 15 deletions

View File

@@ -429,15 +429,21 @@ void sqlite3SetJoinExpr(Expr *p, int iTable, u32 joinFlag){
** an ordinary term that omits the EP_OuterON mark.
**
** This happens when a LEFT JOIN is simplified into an ordinary JOIN.
**
** If nullable is true, that means that Expr p might evaluate to NULL even
** if it is a reference to a NOT NULL column. This can happen, for example,
** if the table that p references is on the left side of a RIGHT JOIN.
** If nullable is true, then take care to not remove the EP_CanBeNull bit.
** See forum thread https://sqlite.org/forum/forumpost/b40696f50145d21c
*/
static void unsetJoinExpr(Expr *p, int iTable){
static void unsetJoinExpr(Expr *p, int iTable, int nullable){
while( p ){
if( ExprHasProperty(p, EP_OuterON)
&& (iTable<0 || p->w.iJoin==iTable) ){
ExprClearProperty(p, EP_OuterON);
ExprSetProperty(p, EP_InnerON);
}
if( p->op==TK_COLUMN && p->iTable==iTable ){
if( p->op==TK_COLUMN && p->iTable==iTable && !nullable ){
ExprClearProperty(p, EP_CanBeNull);
}
if( p->op==TK_FUNCTION ){
@@ -445,11 +451,11 @@ static void unsetJoinExpr(Expr *p, int iTable){
if( p->x.pList ){
int i;
for(i=0; i<p->x.pList->nExpr; i++){
unsetJoinExpr(p->x.pList->a[i].pExpr, iTable);
unsetJoinExpr(p->x.pList->a[i].pExpr, iTable, nullable);
}
}
}
unsetJoinExpr(p->pLeft, iTable);
unsetJoinExpr(p->pLeft, iTable, nullable);
p = p->pRight;
}
}
@@ -5067,7 +5073,7 @@ static int pushDownWhereTerms(
while( pSubq ){
SubstContext x;
pNew = sqlite3ExprDup(pParse->db, pWhere, 0);
unsetJoinExpr(pNew, -1);
unsetJoinExpr(pNew, -1, 1);
x.pParse = pParse;
x.iTable = pSrc->iCursor;
x.iNewTable = pSrc->iCursor;
@@ -6751,7 +6757,8 @@ int sqlite3Select(
SELECTTRACE(0x100,pParse,p,
("LEFT-JOIN simplifies to JOIN on term %d\n",i));
pItem->fg.jointype &= ~(JT_LEFT|JT_OUTER);
unsetJoinExpr(p->pWhere, pItem->iCursor);
unsetJoinExpr(p->pWhere, pItem->iCursor,
pTabList->a[0].fg.jointype & JT_LTORJ);
}
/* No futher action if this term of the FROM clause is no a subquery */