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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy