Clean up the comments on the query flattener to more clearly and accurately
express the conditions under which the flattener is able to run. FossilOrigin-Name: 0840f9f824c16212ce3fd6c859e501176eb0a58924ea1728a54d5bdfd0c25c86
This commit is contained in:
parent
824d21aff3
commit
d981e8289a
12
manifest
12
manifest
@ -1,5 +1,5 @@
|
||||
C Make\ssure\sthe\s6th\sparameter\sto\sthe\sauthorizer\scallback\sfor\sview\ssubqueries\nhas\sthe\scorrect\sview\sname.
|
||||
D 2017-09-29T12:44:52.580
|
||||
C Clean\sup\sthe\scomments\son\sthe\squery\sflattener\sto\smore\sclearly\sand\saccurately\nexpress\sthe\sconditions\sunder\swhich\sthe\sflattener\sis\sable\sto\srun.
|
||||
D 2017-09-29T16:07:56.167
|
||||
F Makefile.in 4bc36d913c2e3e2d326d588d72f618ac9788b2fd4b7efda61102611a6495c3ff
|
||||
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
|
||||
F Makefile.msc 6033b51b6aea702ea059f6ab2d47b1d3cef648695f787247dd4fb395fe60673f
|
||||
@ -458,7 +458,7 @@ F src/printf.c 40aee47ae9be4bd3dbdc8968bd07fddc027be8edec8daddf24d3391d36698a1c
|
||||
F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
|
||||
F src/resolve.c 4324a94573b1e29286f8121e4881db59eaedc014afeb274c8d3e07ed282e0e20
|
||||
F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac
|
||||
F src/select.c 61f6ee59115ddba550504296587571fc82acc2a8f178a5cd172c7fff13f83685
|
||||
F src/select.c 733e7f727d4f83234983fcbcb71670229f6d9ae78ee724fbf40b4aa6904474e2
|
||||
F src/shell.c c1206a23d9239f8f51751d3be9b8c3b02fa4103546bea1add7f864d84a8276ab
|
||||
F src/shell.c.in bb9720a8c5c98d3984b16ab7540e7142bcae959666ecf248bfc523a1d44220ee
|
||||
F src/sqlite.h.in ab4f8a29d1580dfaeb6891fa1b83cff8229ba0daa56994707ceaca71495d9ab7
|
||||
@ -1655,7 +1655,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||
P 04ef40a8fea88776e0d8b73d942922d45d0c038fbfac1a9a82b9322181b4ad92
|
||||
R 366bed71d0ebda5b55c786e6b191d9a3
|
||||
P 2a45bbc9fd1c64f1c4c4dac38f063cd67480fcb6da24bf93fdefbfca66fd81ab
|
||||
R 5dd9d1abad7c6b3045de562026df2e52
|
||||
U drh
|
||||
Z 1e56973e5f1cf4ced8af06a37f0fc40f
|
||||
Z 40508487cfccebe9fe70dcdbc46f56d0
|
||||
|
@ -1 +1 @@
|
||||
2a45bbc9fd1c64f1c4c4dac38f063cd67480fcb6da24bf93fdefbfca66fd81ab
|
||||
0840f9f824c16212ce3fd6c859e501176eb0a58924ea1728a54d5bdfd0c25c86
|
113
src/select.c
113
src/select.c
@ -3296,68 +3296,71 @@ static void substSelect(
|
||||
** exist on the table t1, a complete scan of the data might be
|
||||
** avoided.
|
||||
**
|
||||
** Flattening is only attempted if all of the following are true:
|
||||
** Flattening is subject to the following constraints:
|
||||
**
|
||||
** (1) The subquery and the outer query do not both use aggregates.
|
||||
** (1) The subquery and the outer query cannot both be aggregates.
|
||||
**
|
||||
** (2) The subquery is not an aggregate or (2a) the outer query is not a join
|
||||
** and (2b) the outer query does not use subqueries other than the one
|
||||
** FROM-clause subquery that is a candidate for flattening. (2b is
|
||||
** due to ticket [2f7170d73bf9abf80] from 2015-02-09.)
|
||||
** (2) If the subquery is an aggregate then
|
||||
** (2a) the outer query must not be a join and
|
||||
** (2b) the outer query must not use subqueries
|
||||
** other than the one FROM-clause subquery that is a candidate
|
||||
** for flattening. (This is due to ticket [2f7170d73bf9abf80]
|
||||
** from 2015-02-09.)
|
||||
**
|
||||
** (3) The subquery is not the right operand of a LEFT JOIN
|
||||
** or (a) the subquery is not itself a join and (b) the FROM clause
|
||||
** of the subquery does not contain a virtual table and (c) the
|
||||
** outer query is not an aggregate.
|
||||
** (3) If the subquery is the right operand of a LEFT JOIN then
|
||||
** (3a) the subquery may not be a join and
|
||||
** (3b) the FROM clause of the subquery may not contain a virtual
|
||||
** table and
|
||||
** (3c) the outer query may not be an aggregate.
|
||||
**
|
||||
** (4) The subquery is not DISTINCT.
|
||||
** (4) The subquery can not be DISTINCT.
|
||||
**
|
||||
** (**) At one point restrictions (4) and (5) defined a subset of DISTINCT
|
||||
** sub-queries that were excluded from this optimization. Restriction
|
||||
** (4) has since been expanded to exclude all DISTINCT subqueries.
|
||||
**
|
||||
** (6) The subquery does not use aggregates or the outer query is not
|
||||
** DISTINCT.
|
||||
** (6) If the subquery is aggregate, the outer query may not be DISTINCT.
|
||||
**
|
||||
** (7) The subquery has a FROM clause. TODO: For subqueries without
|
||||
** (7) The subquery must have a FROM clause. TODO: For subqueries without
|
||||
** A FROM clause, consider adding a FROM clause with the special
|
||||
** table sqlite_once that consists of a single row containing a
|
||||
** single NULL.
|
||||
**
|
||||
** (8) The subquery does not use LIMIT or the outer query is not a join.
|
||||
** (8) If the subquery uses LIMIT then the outer query may not be a join.
|
||||
**
|
||||
** (9) The subquery does not use LIMIT or the outer query does not use
|
||||
** aggregates.
|
||||
** (9) If the subquery uses LIMIT then the outer query may not be aggregate.
|
||||
**
|
||||
** (**) Restriction (10) was removed from the code on 2005-02-05 but we
|
||||
** accidently carried the comment forward until 2014-09-15. Original
|
||||
** text: "The subquery does not use aggregates or the outer query
|
||||
** does not use LIMIT."
|
||||
** constraint: "If the subquery is aggregate then the outer query
|
||||
** may not use LIMIT."
|
||||
**
|
||||
** (11) The subquery and the outer query do not both have ORDER BY clauses.
|
||||
** (11) The subquery and the outer query may not both have ORDER BY clauses.
|
||||
**
|
||||
** (**) Not implemented. Subsumed into restriction (3). Was previously
|
||||
** a separate restriction deriving from ticket #350.
|
||||
**
|
||||
** (13) The subquery and outer query do not both use LIMIT.
|
||||
** (13) The subquery and outer query may not both use LIMIT.
|
||||
**
|
||||
** (14) The subquery does not use OFFSET.
|
||||
** (14) The subquery may not use OFFSET.
|
||||
**
|
||||
** (15) The outer query is not part of a compound select or the
|
||||
** subquery does not have a LIMIT clause.
|
||||
** (15) If the outer query is part of a compound select, then the
|
||||
** subquery may not use LIMIT.
|
||||
** (See ticket #2339 and ticket [02a8e81d44]).
|
||||
**
|
||||
** (16) The outer query is not an aggregate or the subquery does
|
||||
** not contain ORDER BY. (Ticket #2942) This used to not matter
|
||||
** (16) If the outer query is aggregate, then the subquery may not
|
||||
** use ORDER BY. (Ticket #2942) This used to not matter
|
||||
** until we introduced the group_concat() function.
|
||||
**
|
||||
** (17) The sub-query is not a compound select, or it is a UNION ALL
|
||||
** compound clause made up entirely of non-aggregate queries, and
|
||||
** the parent query:
|
||||
**
|
||||
** * is not itself part of a compound select,
|
||||
** * is not an aggregate or DISTINCT query, and
|
||||
** * is not a join
|
||||
** (17) If the subquery is a compound select, then
|
||||
** (17a) all compound operators must be a UNION ALL, and
|
||||
** (17b) no terms within the subquery compound may be aggregate
|
||||
** or DISTINT, and
|
||||
** (17c) every term within the subquery compound must have a FROM clause
|
||||
** (17d) the outer query may not be
|
||||
** (17d1) aggregate, or
|
||||
** (17d2) DISTINCT, or
|
||||
** (17d3) a join.
|
||||
**
|
||||
** The parent and sub-query may contain WHERE clauses. Subject to
|
||||
** rules (11), (13) and (14), they may also contain ORDER BY,
|
||||
@ -3373,10 +3376,10 @@ static void substSelect(
|
||||
** syntax error and return a detailed message.
|
||||
**
|
||||
** (18) If the sub-query is a compound select, then all terms of the
|
||||
** ORDER by clause of the parent must be simple references to
|
||||
** ORDER BY clause of the parent must be simple references to
|
||||
** columns of the sub-query.
|
||||
**
|
||||
** (19) The subquery does not use LIMIT or the outer query does not
|
||||
** (19) If the subquery uses LIMIT then the outer query may not
|
||||
** have a WHERE clause.
|
||||
**
|
||||
** (20) If the sub-query is a compound select, then it must not use
|
||||
@ -3385,17 +3388,17 @@ static void substSelect(
|
||||
** appear as unmodified result columns in the outer query. But we
|
||||
** have other optimizations in mind to deal with that case.
|
||||
**
|
||||
** (21) The subquery does not use LIMIT or the outer query is not
|
||||
** (21) If the subquery uses LIMIT then the outer query may not be
|
||||
** DISTINCT. (See ticket [752e1646fc]).
|
||||
**
|
||||
** (22) The subquery is not a recursive CTE.
|
||||
** (22) The subquery may not be a recursive CTE.
|
||||
**
|
||||
** (23) The parent is not a recursive CTE, or the sub-query is not a
|
||||
** compound query. This restriction is because transforming the
|
||||
** (23) If the outer query is a recursive CTE, then the sub-query may not be
|
||||
** a compound query. This restriction is because transforming the
|
||||
** parent to a compound query confuses the code that handles
|
||||
** recursive queries in multiSelect().
|
||||
**
|
||||
** (24) The subquery is not an aggregate that uses the built-in min() or
|
||||
** (24) The subquery may not be an aggregate that uses the built-in min() or
|
||||
** or max() functions. (Without this restriction, a query like:
|
||||
** "SELECT x FROM (SELECT max(y), x FROM t1)" would not necessarily
|
||||
** return the value X for which Y was maximal.)
|
||||
@ -3435,7 +3438,7 @@ static int flattenSubquery(
|
||||
/* Check to see if flattening is permitted. Return 0 if not.
|
||||
*/
|
||||
assert( p!=0 );
|
||||
assert( p->pPrior==0 ); /* Unable to flatten compound queries */
|
||||
assert( p->pPrior==0 );
|
||||
if( OptimizationDisabled(db, SQLITE_QueryFlattener) ) return 0;
|
||||
pSrc = p->pSrc;
|
||||
assert( pSrc && iFrom>=0 && iFrom<pSrc->nSrc );
|
||||
@ -3467,7 +3470,7 @@ static int flattenSubquery(
|
||||
return 0; /* Restriction (15) */
|
||||
}
|
||||
if( pSubSrc->nSrc==0 ) return 0; /* Restriction (7) */
|
||||
if( pSub->selFlags & SF_Distinct ) return 0; /* Restriction (5) */
|
||||
if( pSub->selFlags & SF_Distinct ) return 0; /* Restriction (4) */
|
||||
if( pSub->pLimit && (pSrc->nSrc>1 || isAgg) ){
|
||||
return 0; /* Restrictions (8)(9) */
|
||||
}
|
||||
@ -3493,7 +3496,8 @@ static int flattenSubquery(
|
||||
|
||||
/*
|
||||
** If the subquery is the right operand of a LEFT JOIN, then the
|
||||
** subquery may not be a join itself. Example of why this is not allowed:
|
||||
** subquery may not be a join itself (3a). Example of why this is not
|
||||
** allowed:
|
||||
**
|
||||
** t1 LEFT OUTER JOIN (t2 JOIN t3)
|
||||
**
|
||||
@ -3504,16 +3508,17 @@ static int flattenSubquery(
|
||||
** which is not at all the same thing.
|
||||
**
|
||||
** If the subquery is the right operand of a LEFT JOIN, then the outer
|
||||
** query cannot be an aggregate. This is an artifact of the way aggregates
|
||||
** are processed - there is no mechanism to determine if the LEFT JOIN
|
||||
** table should be all-NULL.
|
||||
** query cannot be an aggregate. (3c) This is an artifact of the way
|
||||
** aggregates are processed - there is no mechanism to determine if
|
||||
** the LEFT JOIN table should be all-NULL.
|
||||
**
|
||||
** See also tickets #306, #350, and #3300.
|
||||
*/
|
||||
if( (pSubitem->fg.jointype & JT_OUTER)!=0 ){
|
||||
isLeftJoin = 1;
|
||||
if( pSubSrc->nSrc>1 || isAgg || IsVirtual(pSubSrc->a[0].pTab) ){
|
||||
return 0; /* Restriction (3) */
|
||||
/* (3a) (3c) (3b) */
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#ifdef SQLITE_EXTRA_IFNULLROW
|
||||
@ -3526,33 +3531,33 @@ static int flattenSubquery(
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Restriction 17: If the sub-query is a compound SELECT, then it must
|
||||
/* Restriction (17): If the sub-query is a compound SELECT, then it must
|
||||
** use only the UNION ALL operator. And none of the simple select queries
|
||||
** that make up the compound SELECT are allowed to be aggregate or distinct
|
||||
** queries.
|
||||
*/
|
||||
if( pSub->pPrior ){
|
||||
if( pSub->pOrderBy ){
|
||||
return 0; /* Restriction 20 */
|
||||
return 0; /* Restriction (20) */
|
||||
}
|
||||
if( isAgg || (p->selFlags & SF_Distinct)!=0 || pSrc->nSrc!=1 ){
|
||||
return 0;
|
||||
return 0; /* (17d1), (17d2), or (17d3) */
|
||||
}
|
||||
for(pSub1=pSub; pSub1; pSub1=pSub1->pPrior){
|
||||
testcase( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct );
|
||||
testcase( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))==SF_Aggregate );
|
||||
assert( pSub->pSrc!=0 );
|
||||
assert( pSub->pEList->nExpr==pSub1->pEList->nExpr );
|
||||
if( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))!=0
|
||||
|| (pSub1->pPrior && pSub1->op!=TK_ALL)
|
||||
|| pSub1->pSrc->nSrc<1
|
||||
if( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))!=0 /* (17b) */
|
||||
|| (pSub1->pPrior && pSub1->op!=TK_ALL) /* (17a) */
|
||||
|| pSub1->pSrc->nSrc<1 /* (17c) */
|
||||
){
|
||||
return 0;
|
||||
}
|
||||
testcase( pSub1->pSrc->nSrc>1 );
|
||||
}
|
||||
|
||||
/* Restriction 18. */
|
||||
/* Restriction (18). */
|
||||
if( p->pOrderBy ){
|
||||
int ii;
|
||||
for(ii=0; ii<p->pOrderBy->nExpr; ii++){
|
||||
|
Loading…
Reference in New Issue
Block a user