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:
drh 2017-09-29 16:07:56 +00:00
parent 824d21aff3
commit d981e8289a
3 changed files with 66 additions and 61 deletions

View File

@ -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

View File

@ -1 +1 @@
2a45bbc9fd1c64f1c4c4dac38f063cd67480fcb6da24bf93fdefbfca66fd81ab
0840f9f824c16212ce3fd6c859e501176eb0a58924ea1728a54d5bdfd0c25c86

View File

@ -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++){