diff options
author | drh <> | 2023-08-02 12:39:56 +0000 |
---|---|---|
committer | drh <> | 2023-08-02 12:39:56 +0000 |
commit | aa250db66aed4ed8f969d61f05bc374aa8c2c2e6 (patch) | |
tree | cf73d938b125cfed442ae210b7233a51efe7a284 /src | |
parent | 5e82c06cf89a5d3d57f8cbb206a7142c9c4c4a0c (diff) | |
download | sqlite-aa250db66aed4ed8f969d61f05bc374aa8c2c2e6.tar.gz sqlite-aa250db66aed4ed8f969d61f05bc374aa8c2c2e6.zip |
Simplify the select.c logic that enforces the optimization fence around
a MATERIALIZED common table expression. Do not allow the
reverse_unordered_selects setting to affect a fenced CTE that itself has
an ORDER BY clause.
FossilOrigin-Name: 165b9bda243777ae7fb6f51ee7ad58771c581b82ef9a70268eb9764e9e6eba6f
Diffstat (limited to 'src')
-rw-r--r-- | src/select.c | 24 | ||||
-rw-r--r-- | src/where.c | 21 |
2 files changed, 30 insertions, 15 deletions
diff --git a/src/select.c b/src/select.c index 7a3ba4a6f..482d7283c 100644 --- a/src/select.c +++ b/src/select.c @@ -7285,6 +7285,14 @@ int sqlite3Select( goto select_end; } + /* Do not attempt the usual optimizations (flattening and ORDER BY + ** elimination) on a MATERIALIZED common table expression because + ** a MATERIALIZED common table expression is an optimization fence. + */ + if( pItem->fg.isCte && pItem->u2.pCteUse->eM10d==M10d_Yes ){ + continue; + } + /* Do not try to flatten an aggregate subquery. ** ** Flattening an aggregate subquery is only possible if the outer query @@ -7315,21 +7323,14 @@ int sqlite3Select( ** (b) The subquery is part of a join ** See forum post 062d576715d277c8 ** - ** The above cases might get an incorrect result if ORDER BY is omitted. - ** The following constraints are not required for correct answers, but are - ** included in order to give developers more control over when a sort - ** occurs: - ** - ** (6) The subquery is really a MATERIALIZED CTE - ** (7) The OmitOrderBy optimization is disabled + ** Also retain the ORDER BY if the OmitOrderBy optimization is disabled. */ if( pSub->pOrderBy!=0 && (p->pOrderBy!=0 || pTabList->nSrc>1) /* Condition (5) */ && pSub->pLimit==0 /* Condition (1) */ && (pSub->selFlags & SF_OrderByReqd)==0 /* Condition (2) */ && (p->selFlags & SF_OrderByReqd)==0 /* Condition (3) and (4) */ - && (pItem->fg.isCte==0 || pItem->u2.pCteUse->eM10d!=M10d_Yes) /* (6) */ - && OptimizationEnabled(db, SQLITE_OmitOrderBy) /* (7) */ + && OptimizationEnabled(db, SQLITE_OmitOrderBy) ){ TREETRACE(0x800,pParse,p, ("omit superfluous ORDER BY on %r FROM-clause subquery\n",i+1)); @@ -7366,11 +7367,6 @@ int sqlite3Select( continue; } - /* Do not flatten a MATERIALIZED CTE */ - if( pItem->fg.isCte && pItem->u2.pCteUse->eM10d==M10d_Yes ){ - continue; - } - if( flattenSubquery(pParse, p, i, isAgg) ){ if( pParse->nErr ) goto select_end; /* This subquery can be absorbed into its parent. */ diff --git a/src/where.c b/src/where.c index c75834ff5..9992b2053 100644 --- a/src/where.c +++ b/src/where.c @@ -6122,8 +6122,27 @@ WhereInfo *sqlite3WhereBegin( if( db->mallocFailed ) goto whereBeginError; } } + assert( pWInfo->pTabList!=0 ); if( pWInfo->pOrderBy==0 && (db->flags & SQLITE_ReverseOrder)!=0 ){ - pWInfo->revMask = ALLBITS; + for(ii=0; ii<pWInfo->pTabList->nSrc; ii++){ + /* The PRAGMA reverse_unordered_selects=ON setting (also accessible + ** using SQLITE_DBCONFIG_REVERSE_SCANORDER) means to reverse the scan + ** order for any table that is part of a query that does not have an + ** ORDER BY clause. + ** + ** Except, do not reverse the output from MATERIALIZED common table + ** expression that has an internal ORDER BY clause, because a + ** MATERIALIZED common table expression is an optimization fence. + */ + SrcItem *pItem = &pWInfo->pTabList->a[ii]; + if( !pItem->fg.isCte + || pItem->u2.pCteUse->eM10d!=M10d_Yes + || NEVER(pItem->pSelect==0) + || pItem->pSelect->pOrderBy==0 + ){ + pWInfo->revMask |= MASKBIT(ii); + } + } } if( pParse->nErr ){ goto whereBeginError; |