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:
28
src/select.c
28
src/select.c
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user