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

When implementing a multi-way compound SELECT using merge, try to balance

the merge tree.

FossilOrigin-Name: bb8522fe0dc54282ec13672eba9b44ee08f9cb55c1663f1699a61bf96ec1fd04
This commit is contained in:
drh
2021-12-30 00:37:11 +00:00
parent 092ba22cca
commit 38cebe07bb
6 changed files with 180 additions and 23 deletions

View File

@@ -3296,6 +3296,8 @@ static int multiSelectOrderBy(
){
int i, j; /* Loop counters */
Select *pPrior; /* Another SELECT immediately to our left */
Select *pSplit; /* Left-most SELECT in the right-hand group */
int nSelect; /* Number of SELECT statements in the compound */
Vdbe *v; /* Generate code to this VDBE */
SelectDest destA; /* Destination for coroutine A */
SelectDest destB; /* Destination for coroutine B */
@@ -3341,8 +3343,7 @@ static int multiSelectOrderBy(
/* Patch up the ORDER BY clause
*/
op = p->op;
pPrior = p->pPrior;
assert( pPrior->pOrderBy==0 );
assert( p->pPrior->pOrderBy==0 );
pOrderBy = p->pOrderBy;
assert( pOrderBy );
nOrderBy = pOrderBy->nExpr;
@@ -3392,11 +3393,6 @@ static int multiSelectOrderBy(
pKeyMerge = 0;
}
/* Reattach the ORDER BY clause to the query.
*/
p->pOrderBy = pOrderBy;
pPrior->pOrderBy = sqlite3ExprListDup(pParse->db, pOrderBy, 0);
/* Allocate a range of temporary registers and the KeyInfo needed
** for the logic that removes duplicate result rows when the
** operator is UNION, EXCEPT, or INTERSECT (but not UNION ALL).
@@ -3421,9 +3417,30 @@ static int multiSelectOrderBy(
/* Separate the left and the right query from one another
*/
p->pPrior = 0;
nSelect = 1;
if( (op==TK_ALL || op==TK_UNION)
&& OptimizationEnabled(db, SQLITE_BalancedMerge)
){
for(pSplit=p; pSplit->pPrior!=0 && pSplit->op==op; pSplit=pSplit->pPrior){
nSelect++;
assert( pSplit->pPrior->pNext==pSplit );
}
}
if( nSelect<=3 ){
pSplit = p;
}else{
pSplit = p;
for(i=2; i<nSelect; i+=2){ pSplit = pSplit->pPrior; }
}
pPrior = pSplit->pPrior;
pSplit->pPrior = 0;
pPrior->pNext = 0;
sqlite3ResolveOrderGroupBy(pParse, p, p->pOrderBy, "ORDER");
assert( p->pOrderBy == pOrderBy );
assert( pOrderBy!=0 || db->mallocFailed );
pPrior->pOrderBy = sqlite3ExprListDup(pParse->db, pOrderBy, 0);
if( p->pPrior==0 ){
sqlite3ResolveOrderGroupBy(pParse, p, p->pOrderBy, "ORDER");
}
if( pPrior->pPrior==0 ){
sqlite3ResolveOrderGroupBy(pParse, pPrior, pPrior->pOrderBy, "ORDER");
}
@@ -3577,12 +3594,11 @@ static int multiSelectOrderBy(
/* Reassembly the compound query so that it will be freed correctly
** by the calling function */
if( p->pPrior ){
sqlite3SelectDelete(db, p->pPrior);
if( pSplit->pPrior ){
sqlite3SelectDelete(db, pSplit->pPrior);
}
p->pPrior = pPrior;
pPrior->pNext = p;
pSplit->pPrior = pPrior;
pPrior->pNext = pSplit;
sqlite3ExprListDelete(db, pPrior->pOrderBy);
pPrior->pOrderBy = 0;