diff options
author | drh <> | 2023-05-15 02:06:35 +0000 |
---|---|---|
committer | drh <> | 2023-05-15 02:06:35 +0000 |
commit | eb4455e4e4db00014ece5dc6e3ae0216b8fae614 (patch) | |
tree | 8e31d73e5aed00ad3eb867b65abaf2698de4d1b8 /src/expr.c | |
parent | fa746af4a37b787251ee639a9f0e1891dca13802 (diff) | |
download | sqlite-eb4455e4e4db00014ece5dc6e3ae0216b8fae614.tar.gz sqlite-eb4455e4e4db00014ece5dc6e3ae0216b8fae614.zip |
As evidenced by [forum:/forumpost/f3f546025a|forum post f3f546025a], the
new RIGHT JOIN related restriction on the push-down optimization implemented
by [da3fba18742b6e0b] also needs to apply to the automatic index
(a.k.a. hash-join) optimization and to the Bloom filter optimization.
Computation of the restriction is now
moved into the sqlite3ExprIsSingleTableConstraint() routine.
FossilOrigin-Name: 4902015dcf3869f08d9986e422faa231d9218a5e0fc59ba8df0f407e4eb3d605
Diffstat (limited to 'src/expr.c')
-rw-r--r-- | src/expr.c | 44 |
1 files changed, 38 insertions, 6 deletions
diff --git a/src/expr.c b/src/expr.c index 52fc791c6..a81b4595b 100644 --- a/src/expr.c +++ b/src/expr.c @@ -2378,10 +2378,11 @@ int sqlite3ExprIsTableConstant(Expr *p, int iCur){ } /* -** Check pExpr to see if it is an constraint on the single data source pSrc. -** In other words, check to see if pExpr constrains pSrc but does not depend -** on any other tables or data sources anywhere else in the query. Return -** true (non-zero) if pExpr is a constraint on pSrc only. +** Check pExpr to see if it is an constraint on the single data source +** pSrc = &pSrcList->a[iSrc]. In other words, check to see if pExpr +** constrains pSrc but does not depend on any other tables or data +** sources anywhere else in the query. Return true (non-zero) if pExpr +** is a constraint on pSrc only. ** ** This is an optimization. False negatives will perhaps cause slower ** queries, but false positives will yield incorrect answers. So when in @@ -2398,13 +2399,31 @@ int sqlite3ExprIsTableConstant(Expr *p, int iCur){ ** ** (4) If pSrc is the right operand of a LEFT JOIN, then... ** (4a) pExpr must come from an ON clause.. - (4b) and specifically the ON clause associated with the LEFT JOIN. +** (4b) and specifically the ON clause associated with the LEFT JOIN. ** ** (5) If pSrc is not the right operand of a LEFT JOIN or the left ** operand of a RIGHT JOIN, then pExpr must be from the WHERE ** clause, not an ON clause. +** +** (6) Either: +** +** (6a) pExpr does not originate in an ON or USING clause, or +** +** (6b) The ON or USING clause from which pExpr is derived is +** not to the left of a RIGHT JOIN (or FULL JOIN). +** +** Without this restriction, accepting pExpr as a single-table +** constraint might move the the ON/USING filter expression +** from the left side of a RIGHT JOIN over to the right side, +** which leads to incorrect answers. See also restriction (9) +** on push-down. */ -int sqlite3ExprIsSingleTableConstraint(Expr *pExpr, const SrcItem *pSrc){ +int sqlite3ExprIsSingleTableConstraint( + Expr *pExpr, /* The constraint */ + const SrcList *pSrcList, /* Complete FROM clause */ + int iSrc /* Which element of pSrcList to use */ +){ + const SrcItem *pSrc = &pSrcList->a[iSrc]; if( pSrc->fg.jointype & JT_LTORJ ){ return 0; /* rule (3) */ } @@ -2414,6 +2433,19 @@ int sqlite3ExprIsSingleTableConstraint(Expr *pExpr, const SrcItem *pSrc){ }else{ if( ExprHasProperty(pExpr, EP_OuterON) ) return 0; /* rule (5) */ } + if( ExprHasProperty(pExpr, EP_OuterON|EP_InnerON) /* (6a) */ + && (pSrcList->a[0].fg.jointype & JT_LTORJ)!=0 /* Fast pre-test of (6b) */ + ){ + int jj; + for(jj=0; jj<iSrc; jj++){ + if( pExpr->w.iJoin==pSrcList->a[jj].iCursor ){ + if( (pSrcList->a[jj].fg.jointype & JT_LTORJ)!=0 ){ + return 0; /* restriction (6) */ + } + break; + } + } + } return sqlite3ExprIsTableConstant(pExpr, pSrc->iCursor); /* rules (1), (2) */ } |