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

Add restriction (9) to the push-down optimization: If the subquery is

a compound then all arms of the compound must have the same affinity.
dbsqlfuzz 3a548de406a50e896c1bf7142692d35d339d697f.

FossilOrigin-Name: 1ad41840c5e0fa702ba2c0df77a3ea126bd695b910b5d1271fa3129c38c58f5f
This commit is contained in:
drh
2022-11-25 15:52:00 +00:00
parent eb84c81c53
commit 23f61a4ba8
4 changed files with 74 additions and 24 deletions

View File

@@ -4050,6 +4050,34 @@ static ExprList *findLeftmostExprlist(Select *pSel){
return pSel->pEList;
}
/*
** Return true if any of the result-set columns in the compound query
** have incompatible affinities on one or more arms of the compound.
*/
static int compoundHasDifferentAffinities(Select *p){
int ii;
ExprList *pList;
assert( p!=0 );
assert( p->pEList!=0 );
assert( p->pPrior!=0 );
pList = p->pEList;
for(ii=0; ii<pList->nExpr; ii++){
char aff;
Select *pSub1;
assert( pList->a[ii].pExpr!=0 );
aff = sqlite3ExprAffinity(pList->a[ii].pExpr);
for(pSub1=p->pPrior; pSub1; pSub1=pSub1->pPrior){
assert( pSub1->pEList!=0 );
assert( pSub1->pEList->nExpr>ii );
assert( pSub1->pEList->a[ii].pExpr!=0 );
if( sqlite3ExprAffinity(pSub1->pEList->a[ii].pExpr)!=aff ){
return 1;
}
}
}
return 0;
}
#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
/*
** This routine attempts to flatten subqueries as a performance optimization.
@@ -4153,7 +4181,8 @@ static ExprList *findLeftmostExprlist(Select *pSel){
** query or there are no RIGHT or FULL JOINs in any arm
** of the subquery. (This is a duplicate of condition (27b).)
** (17h) The corresponding result set expressions in all arms of the
** compound must have the same affinity.
** compound must have the same affinity. (See restriction (9)
** on the push-down optimization.)
**
** The parent and sub-query may contain WHERE clauses. Subject to
** rules (11), (13) and (14), they may also contain ORDER BY,
@@ -4372,19 +4401,7 @@ static int flattenSubquery(
if( (p->selFlags & SF_Recursive) ) return 0;
/* Restriction (17h) */
for(ii=0; ii<pSub->pEList->nExpr; ii++){
char aff;
assert( pSub->pEList->a[ii].pExpr!=0 );
aff = sqlite3ExprAffinity(pSub->pEList->a[ii].pExpr);
for(pSub1=pSub->pPrior; pSub1; pSub1=pSub1->pPrior){
assert( pSub1->pEList!=0 );
assert( pSub1->pEList->nExpr>ii );
assert( pSub1->pEList->a[ii].pExpr!=0 );
if( sqlite3ExprAffinity(pSub1->pEList->a[ii].pExpr)!=aff ){
return 0;
}
}
}
if( compoundHasDifferentAffinities(pSub) ) return 0;
if( pSrc->nSrc>1 ){
if( pParse->nSelect>500 ) return 0;
@@ -5036,6 +5053,11 @@ static int pushDownWindowCheck(Parse *pParse, Select *pSubq, Expr *pExpr){
** But it is a lot of work to check that case for an obscure and
** minor optimization, so we omit it for now.)
**
** (9) If the subquery is a compound, then all arms of the compound must
** have the same affinity. (This is the same as restriction (17h)
** for query flattening.)
**
**
** Return 0 if no changes are made and non-zero if one or more WHERE clause
** terms are duplicated into the subquery.
*/
@@ -5061,6 +5083,9 @@ static int pushDownWhereTerms(
if( op!=TK_ALL && op!=TK_SELECT ) return 0; /* restriction (8) */
if( pSel->pWin ) return 0; /* restriction (6b) */
}
if( compoundHasDifferentAffinities(pSubq) ){
return 0; /* restriction (9) */
}
}else{
if( pSubq->pWin && pSubq->pWin->pPartition==0 ) return 0;
}