aboutsummaryrefslogtreecommitdiff
path: root/src/expr.c
diff options
context:
space:
mode:
authordrh <>2023-05-15 02:06:35 +0000
committerdrh <>2023-05-15 02:06:35 +0000
commiteb4455e4e4db00014ece5dc6e3ae0216b8fae614 (patch)
tree8e31d73e5aed00ad3eb867b65abaf2698de4d1b8 /src/expr.c
parentfa746af4a37b787251ee639a9f0e1891dca13802 (diff)
downloadsqlite-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.c44
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) */
}