* UtilityContainsQuery
* Return the contained Query, or NULL if there is none
*
- * Certain utility statements, such as EXPLAIN, contain a Query.
+ * Certain utility statements, such as EXPLAIN, contain a plannable Query.
* This function encapsulates knowledge of exactly which ones do.
* We assume it is invoked only on already-parse-analyzed statements
* (else the contained parsetree isn't a Query yet).
+ *
+ * In some cases (currently, only EXPLAIN of CREATE TABLE AS/SELECT INTO),
+ * potentially Query-containing utility statements can be nested. This
+ * function will drill down to a non-utility Query, or return NULL if none.
*/
Query *
UtilityContainsQuery(Node *parsetree)
{
+ Query *qry;
+
switch (nodeTag(parsetree))
{
case T_ExplainStmt:
- Assert(IsA(((ExplainStmt *) parsetree)->query, Query));
- return (Query *) ((ExplainStmt *) parsetree)->query;
+ qry = (Query *) ((ExplainStmt *) parsetree)->query;
+ Assert(IsA(qry, Query));
+ if (qry->commandType == CMD_UTILITY)
+ return UtilityContainsQuery(qry->utilityStmt);
+ return qry;
case T_CreateTableAsStmt:
/* might or might not contain a Query ... */
- if (IsA(((CreateTableAsStmt *) parsetree)->query, Query))
- return (Query *) ((CreateTableAsStmt *) parsetree)->query;
- Assert(IsA(((CreateTableAsStmt *) parsetree)->query, ExecuteStmt));
+ qry = (Query *) ((CreateTableAsStmt *) parsetree)->query;
+ if (IsA(qry, Query))
+ {
+ /* Recursion currently can't be necessary here */
+ Assert(qry->commandType != CMD_UTILITY);
+ return qry;
+ }
+ Assert(IsA(qry, ExecuteStmt));
return NULL;
default: