Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit bde689f

Browse files
committed
Make UtilityContainsQuery recurse until it finds a non-utility Query.
The callers of UtilityContainsQuery want it to return a non-utility Query if it returns anything at all. However, since we made CREATE TABLE AS/SELECT INTO into a utility command instead of a variant of SELECT, a command like "EXPLAIN SELECT INTO" results in two nested utility statements. So what we need UtilityContainsQuery to do is drill down to the bottom non-utility Query. I had thought of this possibility in setrefs.c, and fixed it there by looping around the UtilityContainsQuery call; but overlooked that the call sites in plancache.c have a similar issue. In those cases it's notationally inconvenient to provide an external loop, so let's redefine UtilityContainsQuery as recursing down to a non-utility Query instead. Noted by Rushabh Lathia. This is a somewhat cleaned-up version of his proposed patch.
1 parent f786715 commit bde689f

File tree

2 files changed

+21
-7
lines changed

2 files changed

+21
-7
lines changed

src/backend/optimizer/plan/setrefs.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1937,7 +1937,7 @@ extract_query_dependencies_walker(Node *node, PlannerInfo *context)
19371937
Query *query = (Query *) node;
19381938
ListCell *lc;
19391939

1940-
while (query->commandType == CMD_UTILITY)
1940+
if (query->commandType == CMD_UTILITY)
19411941
{
19421942
/*
19431943
* Ignore utility statements, except those (such as EXPLAIN) that

src/backend/tcop/utility.c

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1351,25 +1351,39 @@ QueryReturnsTuples(Query *parsetree)
13511351
* UtilityContainsQuery
13521352
* Return the contained Query, or NULL if there is none
13531353
*
1354-
* Certain utility statements, such as EXPLAIN, contain a Query.
1354+
* Certain utility statements, such as EXPLAIN, contain a plannable Query.
13551355
* This function encapsulates knowledge of exactly which ones do.
13561356
* We assume it is invoked only on already-parse-analyzed statements
13571357
* (else the contained parsetree isn't a Query yet).
1358+
*
1359+
* In some cases (currently, only EXPLAIN of CREATE TABLE AS/SELECT INTO),
1360+
* potentially Query-containing utility statements can be nested. This
1361+
* function will drill down to a non-utility Query, or return NULL if none.
13581362
*/
13591363
Query *
13601364
UtilityContainsQuery(Node *parsetree)
13611365
{
1366+
Query *qry;
1367+
13621368
switch (nodeTag(parsetree))
13631369
{
13641370
case T_ExplainStmt:
1365-
Assert(IsA(((ExplainStmt *) parsetree)->query, Query));
1366-
return (Query *) ((ExplainStmt *) parsetree)->query;
1371+
qry = (Query *) ((ExplainStmt *) parsetree)->query;
1372+
Assert(IsA(qry, Query));
1373+
if (qry->commandType == CMD_UTILITY)
1374+
return UtilityContainsQuery(qry->utilityStmt);
1375+
return qry;
13671376

13681377
case T_CreateTableAsStmt:
13691378
/* might or might not contain a Query ... */
1370-
if (IsA(((CreateTableAsStmt *) parsetree)->query, Query))
1371-
return (Query *) ((CreateTableAsStmt *) parsetree)->query;
1372-
Assert(IsA(((CreateTableAsStmt *) parsetree)->query, ExecuteStmt));
1379+
qry = (Query *) ((CreateTableAsStmt *) parsetree)->query;
1380+
if (IsA(qry, Query))
1381+
{
1382+
/* Recursion currently can't be necessary here */
1383+
Assert(qry->commandType != CMD_UTILITY);
1384+
return qry;
1385+
}
1386+
Assert(IsA(qry, ExecuteStmt));
13731387
return NULL;
13741388

13751389
default:

0 commit comments

Comments
 (0)