1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-10 01:02:56 +03:00

Restore the LEFT JOIN strength reduction that was partially lost in

[d747afda5683ca5f] when strength reduction was generalized to all OUTER JOINs.

FossilOrigin-Name: 2d962b84dd8ac2d0968f0283f8f082c1c2a7a1f99b59053b2ad8f58745396447
This commit is contained in:
drh
2023-06-02 18:05:54 +00:00
parent a3f943942c
commit 038158e94a
5 changed files with 31 additions and 16 deletions

View File

@@ -4131,7 +4131,7 @@ static int exprCodeInlineFunction(
pA1 = pFarg->a[1].pExpr;
if( pA1->op==TK_COLUMN ){
sqlite3VdbeAddOp2(v, OP_Integer,
sqlite3ExprImpliesNonNullRow(pFarg->a[0].pExpr,pA1->iTable),
sqlite3ExprImpliesNonNullRow(pFarg->a[0].pExpr,pA1->iTable,1),
target);
}else{
sqlite3VdbeAddOp2(v, OP_Null, 0, target);
@@ -6010,6 +6010,10 @@ static void bothImplyNotNullRow(Walker *pWalker, Expr *pE1, Expr *pE2){
** If the expression node requires that the table at pWalker->iCur
** have one or more non-NULL column, then set pWalker->eCode to 1 and abort.
**
** pWalker->mWFlags is non-zero if this inquiry is being undertaking on
** behalf of a RIGHT JOIN (or FULL JOIN). That makes a difference when
** evaluting terms in the ON claue of an inner join.
**
** This routine controls an optimization. False positives (setting
** pWalker->eCode to 1 when it should not be) are deadly, but false-negatives
** (never setting pWalker->eCode) is a harmless missed optimization.
@@ -6017,7 +6021,15 @@ static void bothImplyNotNullRow(Walker *pWalker, Expr *pE1, Expr *pE2){
static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){
testcase( pExpr->op==TK_AGG_COLUMN );
testcase( pExpr->op==TK_AGG_FUNCTION );
if( ExprHasProperty(pExpr, EP_OuterON|EP_InnerON) ) return WRC_Prune;
if( ExprHasProperty(pExpr, EP_OuterON) ) return WRC_Prune;
if( ExprHasProperty(pExpr, EP_InnerON) && pWalker->mWFlags ){
/* If iCur is used in an inner-join ON clause to the left of a
** RIGHT JOIN, that does *not* mean that the table must be non-null.
** But it is difficult to check for that condition precisely.
** To keep things simple, any use of iCur from any inner-join is
** ignored while attempting to simplify a RIGHT JOIN. */
return WRC_Prune;
}
switch( pExpr->op ){
case TK_ISNOT:
case TK_ISNULL:
@@ -6137,7 +6149,7 @@ static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){
** be non-NULL, then the LEFT JOIN can be safely converted into an
** ordinary join.
*/
int sqlite3ExprImpliesNonNullRow(Expr *p, int iTab){
int sqlite3ExprImpliesNonNullRow(Expr *p, int iTab, int isRJ){
Walker w;
p = sqlite3ExprSkipCollateAndLikely(p);
if( p==0 ) return 0;
@@ -6145,7 +6157,7 @@ int sqlite3ExprImpliesNonNullRow(Expr *p, int iTab){
p = p->pLeft;
}else{
while( p->op==TK_AND ){
if( sqlite3ExprImpliesNonNullRow(p->pLeft, iTab) ) return 1;
if( sqlite3ExprImpliesNonNullRow(p->pLeft, iTab, isRJ) ) return 1;
p = p->pRight;
}
}
@@ -6153,6 +6165,7 @@ int sqlite3ExprImpliesNonNullRow(Expr *p, int iTab){
w.xSelectCallback = 0;
w.xSelectCallback2 = 0;
w.eCode = 0;
w.mWFlags = isRJ!=0;
w.u.iCur = iTab;
sqlite3WalkExpr(&w, p);
return w.eCode;