Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Avoid assuming that an expression in an ON() clause that evaluates to zero implies that the query will return zero rows when the query contains a RIGHT JOIN. Forum Post 95849acbe1. |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
1783655ea422185e75593b89e4ef452a |
User & Date: | dan 2023-04-25 14:37:12 |
References
2023-05-10
| ||
00:33 | New restriction on the push-down optimization to prevent an ON or USING clause on the left side of a RIGHT JOIN from being pushed down into a subquery that is on the right side of that RIGHT JOIN. Forum post a7d4be7fb6. This is similar to an earlier problem fixed at [1783655ea422185e]. Also add comments to describe previously undocumented push-down optimization restrictions. (check-in: da3fba18 user: drh tags: trunk) | |
2023-04-25
| ||
14:54 | Remove unused variable ltoj accidentally added by [1783655e]. (check-in: faa1575c user: dan tags: trunk) | |
Context
2023-04-25
| ||
15:12 | If an ON clause to the left of a RIGHT JOIN is false, that does not imply that the query returns no rows. (Leaf check-in: 4011b9d3 user: drh tags: branch-3.41) | |
14:54 | Remove unused variable ltoj accidentally added by [1783655e]. (check-in: faa1575c user: dan tags: trunk) | |
14:37 | Avoid assuming that an expression in an ON() clause that evaluates to zero implies that the query will return zero rows when the query contains a RIGHT JOIN. Forum Post 95849acbe1. (check-in: 1783655e user: dan tags: trunk) | |
04:28 | Handle newline-trimmed input TEXT correctly in base64, base85 UDFs, an issue exposed in forum post 8d6ed893c0. (check-in: 8f637aae user: larrybr tags: trunk) | |
Changes
Changes to src/where.c.
︙ | ︙ | |||
5978 5979 5980 5981 5982 5983 5984 | /* Analyze all of the subexpressions. */ sqlite3WhereExprAnalyze(pTabList, &pWInfo->sWC); if( pSelect && pSelect->pLimit ){ sqlite3WhereAddLimit(&pWInfo->sWC, pSelect); } if( pParse->nErr ) goto whereBeginError; | > > | | > | > > > > > | | > | | | > > > > > > | > > > > > > | > > > | | 5978 5979 5980 5981 5982 5983 5984 5985 5986 5987 5988 5989 5990 5991 5992 5993 5994 5995 5996 5997 5998 5999 6000 6001 6002 6003 6004 6005 6006 6007 6008 6009 6010 6011 6012 6013 6014 6015 6016 6017 6018 6019 6020 6021 6022 6023 6024 6025 6026 6027 6028 6029 6030 6031 | /* Analyze all of the subexpressions. */ sqlite3WhereExprAnalyze(pTabList, &pWInfo->sWC); if( pSelect && pSelect->pLimit ){ sqlite3WhereAddLimit(&pWInfo->sWC, pSelect); } if( pParse->nErr ) goto whereBeginError; /* The False-WHERE-Term-Bypass optimization: ** ** If there are WHERE terms that are false, then no rows will be output, ** so skip over all of the code generated here. ** ** Conditions: ** ** (1) The WHERE term must not refer to any tables in the join. ** (2) The term must not come from an ON clause on the ** right-hand side of a LEFT or FULL JOIN. ** (3) The term must not come from an ON clause, or there must be ** no RIGHT or FULL OUTER joins in pTabList. ** (4) If the expression contains non-deterministic functions ** that are not within a sub-select. This is not required ** for correctness but rather to preserves SQLite's legacy ** behaviour in the following two cases: ** ** WHERE random()>0; -- eval random() once per row ** WHERE (SELECT random())>0; -- eval random() just once overall ** ** Note that the Where term need not be a constant in order for this ** optimization to apply, though it does need to be constant relative to ** the current subquery (condition 1). The term might include variables ** from outer queries so that the value of the term changes from one ** invocation of the current subquery to the next. */ for(ii=0; ii<sWLB.pWC->nBase; ii++){ WhereTerm *pT = &sWLB.pWC->a[ii]; /* A term of the WHERE clause */ Expr *pX; /* The expression of pT */ int ltoj; /* Left table of the join */ if( pT->wtFlags & TERM_VIRTUAL ) continue; pX = pT->pExpr; assert( pX!=0 ); assert( pT->prereqAll!=0 || !ExprHasProperty(pX, EP_OuterON) ); if( pT->prereqAll==0 /* Conditions (1) and (2) */ && (nTabList==0 || exprIsDeterministic(pX)) /* Condition (4) */ && !(ExprHasProperty(pX, EP_InnerON) /* Condition (3) */ && (pTabList->a[0].fg.jointype & JT_LTORJ)!=0 ) ){ sqlite3ExprIfFalse(pParse, pX, pWInfo->iBreak, SQLITE_JUMPIFNULL); pT->wtFlags |= TERM_CODED; } } if( wctrlFlags & WHERE_WANT_DISTINCT ){ if( OptimizationDisabled(db, SQLITE_DistinctOpt) ){ /* Disable the DISTINCT optimization if SQLITE_DistinctOpt is set via |
︙ | ︙ |
Changes to test/joinH.test.
︙ | ︙ | |||
85 86 87 88 89 90 91 92 93 | CREATE INDEX i1 ON t1( (d IS NULL), d ); } do_execsql_test 4.4 { SELECT (d IS NULL) FROM t1 RIGHT JOIN t2 ON (j=33); } {1} finish_test | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 | CREATE INDEX i1 ON t1( (d IS NULL), d ); } do_execsql_test 4.4 { SELECT (d IS NULL) FROM t1 RIGHT JOIN t2 ON (j=33); } {1} #------------------------------------------------------------------------- # reset_db do_execsql_test 5.0 { CREATE TABLE t0(w); CREATE TABLE t1(x); CREATE TABLE t2(y); CREATE TABLE t3(z); INSERT INTO t3 VALUES('t3val'); } do_execsql_test 5.1 { SELECT * FROM t1 INNER JOIN t2 ON (0) RIGHT OUTER JOIN t3; } {{} {} t3val} do_execsql_test 5.2 { SELECT * FROM t1 INNER JOIN t2 ON (0) FULL OUTER JOIN t3; } {{} {} t3val} do_execsql_test 5.3 { SELECT * FROM t3 LEFT JOIN t2 ON (0); } {t3val {}} do_execsql_test 5.4 { SELECT * FROM t0 RIGHT JOIN t1 INNER JOIN t2 ON (0) RIGHT JOIN t3 } {{} {} {} t3val} do_execsql_test 5.5 { SELECT * FROM t0 RIGHT JOIN t1 INNER JOIN t2 ON (0) } {} finish_test |