Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | 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. |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
1ad41840c5e0fa702ba2c0df77a3ea12 |
User & Date: | drh 2022-11-25 15:52:00.241 |
References
2023-02-22
| ||
20:42 | Remove the push-down optimization restriction that was added by check-in [1ad41840c5e0fa70] because it is no longer needed after the enhancements to compound query processing in check-in [27655c9353620aa5] This resolves the performance regression reported by forum post bcc4375032. (check-in: aa6bd6dff7 user: drh tags: trunk) | |
Context
2022-11-25
| ||
16:10 | Improve the query planner such that it is able to make use of indexed expressions within an aggregate query with GROUP BY. This implements enhancement request [99378177930f87bd]. (check-in: b9190d3da7 user: drh tags: trunk) | |
15:52 | 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. (check-in: 1ad41840c5 user: drh tags: trunk) | |
2022-11-24
| ||
17:58 | Fix a test case in fts3expr4.test to account for different locales. (check-in: a2b6883ac2 user: dan tags: trunk) | |
Changes
Changes to src/select.c.
︙ | ︙ | |||
4045 4046 4047 4048 4049 4050 4051 4052 4053 4054 4055 4056 4057 4058 | */ static ExprList *findLeftmostExprlist(Select *pSel){ while( pSel->pPrior ){ pSel = pSel->pPrior; } return pSel->pEList; } #if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) /* ** This routine attempts to flatten subqueries as a performance optimization. ** This routine returns 1 if it makes changes and 0 if no flattening occurs. ** ** To understand the concept of flattening, consider the following | > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 4045 4046 4047 4048 4049 4050 4051 4052 4053 4054 4055 4056 4057 4058 4059 4060 4061 4062 4063 4064 4065 4066 4067 4068 4069 4070 4071 4072 4073 4074 4075 4076 4077 4078 4079 4080 4081 4082 4083 4084 4085 4086 | */ static ExprList *findLeftmostExprlist(Select *pSel){ while( pSel->pPrior ){ pSel = pSel->pPrior; } 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. ** This routine returns 1 if it makes changes and 0 if no flattening occurs. ** ** To understand the concept of flattening, consider the following |
︙ | ︙ | |||
4149 4150 4151 4152 4153 4154 4155 | ** (17d2) DISTINCT ** (17e) the subquery may not contain window functions, and ** (17f) the subquery must not be the RHS of a LEFT JOIN. ** (17g) either the subquery is the first element of the outer ** 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 | | > | 4177 4178 4179 4180 4181 4182 4183 4184 4185 4186 4187 4188 4189 4190 4191 4192 | ** (17d2) DISTINCT ** (17e) the subquery may not contain window functions, and ** (17f) the subquery must not be the RHS of a LEFT JOIN. ** (17g) either the subquery is the first element of the outer ** 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. (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, ** LIMIT and OFFSET clauses. The subquery cannot use any compound ** operator other than UNION ALL because all the other compound ** operators have an implied DISTINCT which is disallowed by ** restriction (4). |
︙ | ︙ | |||
4368 4369 4370 4371 4372 4373 4374 | } } /* Restriction (23) */ if( (p->selFlags & SF_Recursive) ) return 0; /* Restriction (17h) */ | < < < < < < < < < | < < < | 4397 4398 4399 4400 4401 4402 4403 4404 4405 4406 4407 4408 4409 4410 4411 | } } /* Restriction (23) */ if( (p->selFlags & SF_Recursive) ) return 0; /* Restriction (17h) */ if( compoundHasDifferentAffinities(pSub) ) return 0; if( pSrc->nSrc>1 ){ if( pParse->nSelect>500 ) return 0; if( OptimizationDisabled(db, SQLITE_FlttnUnionAll) ) return 0; aCsrMap = sqlite3DbMallocZero(db, ((i64)pParse->nTab+1)*sizeof(int)); if( aCsrMap ) aCsrMap[0] = pParse->nTab; } |
︙ | ︙ | |||
5031 5032 5033 5034 5035 5036 5037 5038 5039 5040 5041 5042 5043 5044 | ** ** (8) The subquery may not be a compound that uses UNION, INTERSECT, ** or EXCEPT. (We could, perhaps, relax this restriction to allow ** this case if none of the comparisons operators between left and ** right arms of the compound use a collation other than BINARY. ** But it is a lot of work to check that case for an obscure and ** minor optimization, so we omit it for now.) ** ** Return 0 if no changes are made and non-zero if one or more WHERE clause ** terms are duplicated into the subquery. */ static int pushDownWhereTerms( Parse *pParse, /* Parse context (for malloc() and error reporting) */ Select *pSubq, /* The subquery whose WHERE clause is to be augmented */ | > > > > > | 5048 5049 5050 5051 5052 5053 5054 5055 5056 5057 5058 5059 5060 5061 5062 5063 5064 5065 5066 | ** ** (8) The subquery may not be a compound that uses UNION, INTERSECT, ** or EXCEPT. (We could, perhaps, relax this restriction to allow ** this case if none of the comparisons operators between left and ** right arms of the compound use a collation other than BINARY. ** 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. */ static int pushDownWhereTerms( Parse *pParse, /* Parse context (for malloc() and error reporting) */ Select *pSubq, /* The subquery whose WHERE clause is to be augmented */ |
︙ | ︙ | |||
5056 5057 5058 5059 5060 5061 5062 5063 5064 5065 5066 5067 5068 5069 | Select *pSel; for(pSel=pSubq; pSel; pSel=pSel->pPrior){ u8 op = pSel->op; assert( op==TK_ALL || op==TK_SELECT || op==TK_UNION || op==TK_INTERSECT || op==TK_EXCEPT ); if( op!=TK_ALL && op!=TK_SELECT ) return 0; /* restriction (8) */ if( pSel->pWin ) return 0; /* restriction (6b) */ } }else{ if( pSubq->pWin && pSubq->pWin->pPartition==0 ) return 0; } #endif #ifdef SQLITE_DEBUG | > > > | 5078 5079 5080 5081 5082 5083 5084 5085 5086 5087 5088 5089 5090 5091 5092 5093 5094 | Select *pSel; for(pSel=pSubq; pSel; pSel=pSel->pPrior){ u8 op = pSel->op; assert( op==TK_ALL || op==TK_SELECT || op==TK_UNION || op==TK_INTERSECT || op==TK_EXCEPT ); 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; } #endif #ifdef SQLITE_DEBUG |
︙ | ︙ |
Changes to test/pushdown.test.
︙ | ︙ | |||
82 83 84 85 86 87 88 | SELECT * FROM u1 WHERE 123=( SELECT x FROM u2 WHERE x=a AND f('two') ) AND f('three')=123 } set L } {three} | > > > | > > > > > > > > > > > > > > > > > > > > > > | 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | SELECT * FROM u1 WHERE 123=( SELECT x FROM u2 WHERE x=a AND f('two') ) AND f('three')=123 } set L } {three} # 2022-11-25 dbsqlfuzz crash-3a548de406a50e896c1bf7142692d35d339d697f # Disable the push-down optimization for compound subqueries if any # arm of the compound has an incompatible affinity. # reset_db do_execsql_test 3.1 { CREATE TABLE t0(c0 INT); INSERT INTO t0 VALUES(0); CREATE TABLE t1_a(a INTEGER PRIMARY KEY, b TEXT); INSERT INTO t1_a VALUES(1,'one'); --,(4,'four'); CREATE TABLE t1_b(c INTEGER PRIMARY KEY, d TEXT); INSERT INTO t1_b VALUES(2,'two'); --,(5,'five'); CREATE VIEW v0 AS SELECT CAST(t0.c0 AS INTEGER) AS c0 FROM t0; CREATE VIEW t1 AS SELECT a, b FROM t1_a UNION ALL SELECT c, 0 FROM t1_b; SELECT t1.a, quote(t1.b), t0.c0 AS cd FROM t0 LEFT JOIN v0 ON v0.c0!=0,t1; } { 1 'one' 0 2 '0' 0 } do_execsql_test 3.2 { SELECT a, quote(b), cd FROM ( SELECT t1.a, t1.b, t0.c0 AS cd FROM t0 LEFT JOIN v0 ON v0.c0!=0,t1 ) WHERE a=2 AND b='0' AND cd=0; } { 2 '0' 0 } finish_test |