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

Relax LEFT-JOIN restrictions on the push-down optimization.

FossilOrigin-Name: b5d3dd8cb0b1e42ed0671a12d22af05194ea9522e4f41fd4bb0deff70b8b0757
This commit is contained in:
drh
2018-03-21 01:59:46 +00:00
parent efce69de37
commit 7fbb101c54
3 changed files with 27 additions and 15 deletions

View File

@@ -390,7 +390,8 @@ static void setJoinExpr(Expr *p, int iTable){
*/
static void unsetJoinExpr(Expr *p, int iTable){
while( p ){
if( ExprHasProperty(p, EP_FromJoin) && p->iRightJoinTable==iTable ){
if( ExprHasProperty(p, EP_FromJoin)
&& (iTable<0 || p->iRightJoinTable==iTable) ){
ExprClearProperty(p, EP_FromJoin);
}
if( p->op==TK_FUNCTION && p->x.pList ){
@@ -3856,12 +3857,21 @@ static int flattenSubquery(
** (3) The inner query has a LIMIT clause (since the changes to the WHERE
** close would change the meaning of the LIMIT).
**
** (4) The inner query is the right operand of a LEFT JOIN. (The caller
** enforces this restriction since this routine does not have enough
** information to know.)
** (4) (** This restriction was removed on 2018-03-21. It used to read:
** The inner query is the right operand of a LEFT JOIN. **)
**
** (5) The WHERE clause expression originates in the ON or USING clause
** of a LEFT JOIN.
** of a LEFT JOIN where iCursor is not the right-hand table of that
** left join. An example:
**
** SELECT *
** FROM (SELECT 1 AS a1 UNION ALL SELECT 2) AS aa
** JOIN (SELECT 1 AS b2 UNION ALL SELECT 2) AS bb ON (a1=b2)
** LEFT JOIN (SELECT 8 AS c3 UNION ALL SELECT 9) AS cc ON (b2=2);
**
** The correct answer is three rows: (1,1,NULL),(2,2,8),(2,2,9).
** But if the (b2=2) term were to be pushed down into the bb subquery,
** then the (1,1,NULL) row would be suppressed.
**
** Return 0 if no changes are made and non-zero if one or more WHERE clause
** terms are duplicated into the subquery.
@@ -3897,12 +3907,15 @@ static int pushDownWhereTerms(
nChng += pushDownWhereTerms(pParse, pSubq, pWhere->pRight, iCursor);
pWhere = pWhere->pLeft;
}
if( ExprHasProperty(pWhere,EP_FromJoin) ) return 0; /* restriction (5) */
if( ExprHasProperty(pWhere,EP_FromJoin) && pWhere->iRightJoinTable!=iCursor ){
return 0; /* restriction (5) */
}
if( sqlite3ExprIsTableConstant(pWhere, iCursor) ){
nChng++;
while( pSubq ){
SubstContext x;
pNew = sqlite3ExprDup(pParse->db, pWhere, 0);
unsetJoinExpr(pNew, -1);
x.pParse = pParse;
x.iTable = iCursor;
x.iNewTable = iCursor;
@@ -5360,8 +5373,7 @@ int sqlite3Select(
/* Make copies of constant WHERE-clause terms in the outer query down
** inside the subquery. This can help the subquery to run more efficiently.
*/
if( (pItem->fg.jointype & JT_OUTER)==0
&& OptimizationEnabled(db, SQLITE_PushDown)
if( OptimizationEnabled(db, SQLITE_PushDown)
&& pushDownWhereTerms(pParse, pSub, p->pWhere, pItem->iCursor)
){
#if SELECTTRACE_ENABLED