LCOV - code coverage report
Current view: top level - src/backend/tcop - utility.c (source / functions) Hit Total Coverage
Test: PostgreSQL 15devel Lines: 1440 1943 74.1 %
Date: 2021-12-05 02:08:31 Functions: 16 17 94.1 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * utility.c
       4             :  *    Contains functions which control the execution of the POSTGRES utility
       5             :  *    commands.  At one time acted as an interface between the Lisp and C
       6             :  *    systems.
       7             :  *
       8             :  * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
       9             :  * Portions Copyright (c) 1994, Regents of the University of California
      10             :  *
      11             :  *
      12             :  * IDENTIFICATION
      13             :  *    src/backend/tcop/utility.c
      14             :  *
      15             :  *-------------------------------------------------------------------------
      16             :  */
      17             : #include "postgres.h"
      18             : 
      19             : #include "access/htup_details.h"
      20             : #include "access/reloptions.h"
      21             : #include "access/twophase.h"
      22             : #include "access/xact.h"
      23             : #include "access/xlog.h"
      24             : #include "catalog/catalog.h"
      25             : #include "catalog/index.h"
      26             : #include "catalog/namespace.h"
      27             : #include "catalog/pg_authid.h"
      28             : #include "catalog/pg_inherits.h"
      29             : #include "catalog/toasting.h"
      30             : #include "commands/alter.h"
      31             : #include "commands/async.h"
      32             : #include "commands/cluster.h"
      33             : #include "commands/collationcmds.h"
      34             : #include "commands/comment.h"
      35             : #include "commands/conversioncmds.h"
      36             : #include "commands/copy.h"
      37             : #include "commands/createas.h"
      38             : #include "commands/dbcommands.h"
      39             : #include "commands/defrem.h"
      40             : #include "commands/discard.h"
      41             : #include "commands/event_trigger.h"
      42             : #include "commands/explain.h"
      43             : #include "commands/extension.h"
      44             : #include "commands/lockcmds.h"
      45             : #include "commands/matview.h"
      46             : #include "commands/policy.h"
      47             : #include "commands/portalcmds.h"
      48             : #include "commands/prepare.h"
      49             : #include "commands/proclang.h"
      50             : #include "commands/publicationcmds.h"
      51             : #include "commands/schemacmds.h"
      52             : #include "commands/seclabel.h"
      53             : #include "commands/sequence.h"
      54             : #include "commands/subscriptioncmds.h"
      55             : #include "commands/tablecmds.h"
      56             : #include "commands/tablespace.h"
      57             : #include "commands/trigger.h"
      58             : #include "commands/typecmds.h"
      59             : #include "commands/user.h"
      60             : #include "commands/vacuum.h"
      61             : #include "commands/view.h"
      62             : #include "miscadmin.h"
      63             : #include "parser/parse_utilcmd.h"
      64             : #include "postmaster/bgwriter.h"
      65             : #include "rewrite/rewriteDefine.h"
      66             : #include "rewrite/rewriteRemove.h"
      67             : #include "storage/fd.h"
      68             : #include "tcop/pquery.h"
      69             : #include "tcop/utility.h"
      70             : #include "utils/acl.h"
      71             : #include "utils/guc.h"
      72             : #include "utils/lsyscache.h"
      73             : #include "utils/rel.h"
      74             : #include "utils/syscache.h"
      75             : 
      76             : /* Hook for plugins to get control in ProcessUtility() */
      77             : ProcessUtility_hook_type ProcessUtility_hook = NULL;
      78             : 
      79             : /* local function declarations */
      80             : static int  ClassifyUtilityCommandAsReadOnly(Node *parsetree);
      81             : static void ProcessUtilitySlow(ParseState *pstate,
      82             :                                PlannedStmt *pstmt,
      83             :                                const char *queryString,
      84             :                                ProcessUtilityContext context,
      85             :                                ParamListInfo params,
      86             :                                QueryEnvironment *queryEnv,
      87             :                                DestReceiver *dest,
      88             :                                QueryCompletion *qc);
      89             : static void ExecDropStmt(DropStmt *stmt, bool isTopLevel);
      90             : 
      91             : /*
      92             :  * CommandIsReadOnly: is an executable query read-only?
      93             :  *
      94             :  * This is a much stricter test than we apply for XactReadOnly mode;
      95             :  * the query must be *in truth* read-only, because the caller wishes
      96             :  * not to do CommandCounterIncrement for it.
      97             :  *
      98             :  * Note: currently no need to support raw or analyzed queries here
      99             :  */
     100             : bool
     101        8348 : CommandIsReadOnly(PlannedStmt *pstmt)
     102             : {
     103             :     Assert(IsA(pstmt, PlannedStmt));
     104        8348 :     switch (pstmt->commandType)
     105             :     {
     106        8348 :         case CMD_SELECT:
     107        8348 :             if (pstmt->rowMarks != NIL)
     108           0 :                 return false;   /* SELECT FOR [KEY] UPDATE/SHARE */
     109        8348 :             else if (pstmt->hasModifyingCTE)
     110           0 :                 return false;   /* data-modifying CTE */
     111             :             else
     112        8348 :                 return true;
     113           0 :         case CMD_UPDATE:
     114             :         case CMD_INSERT:
     115             :         case CMD_DELETE:
     116           0 :             return false;
     117           0 :         case CMD_UTILITY:
     118             :             /* For now, treat all utility commands as read/write */
     119           0 :             return false;
     120           0 :         default:
     121           0 :             elog(WARNING, "unrecognized commandType: %d",
     122             :                  (int) pstmt->commandType);
     123           0 :             break;
     124             :     }
     125           0 :     return false;
     126             : }
     127             : 
     128             : /*
     129             :  * Determine the degree to which a utility command is read only.
     130             :  *
     131             :  * Note the definitions of the relevant flags in src/include/utility/tcop.h.
     132             :  */
     133             : static int
     134      534726 : ClassifyUtilityCommandAsReadOnly(Node *parsetree)
     135             : {
     136      534726 :     switch (nodeTag(parsetree))
     137             :     {
     138      437356 :         case T_AlterCollationStmt:
     139             :         case T_AlterDatabaseSetStmt:
     140             :         case T_AlterDatabaseStmt:
     141             :         case T_AlterDefaultPrivilegesStmt:
     142             :         case T_AlterDomainStmt:
     143             :         case T_AlterEnumStmt:
     144             :         case T_AlterEventTrigStmt:
     145             :         case T_AlterExtensionContentsStmt:
     146             :         case T_AlterExtensionStmt:
     147             :         case T_AlterFdwStmt:
     148             :         case T_AlterForeignServerStmt:
     149             :         case T_AlterFunctionStmt:
     150             :         case T_AlterObjectDependsStmt:
     151             :         case T_AlterObjectSchemaStmt:
     152             :         case T_AlterOpFamilyStmt:
     153             :         case T_AlterOperatorStmt:
     154             :         case T_AlterOwnerStmt:
     155             :         case T_AlterPolicyStmt:
     156             :         case T_AlterPublicationStmt:
     157             :         case T_AlterRoleSetStmt:
     158             :         case T_AlterRoleStmt:
     159             :         case T_AlterSeqStmt:
     160             :         case T_AlterStatsStmt:
     161             :         case T_AlterSubscriptionStmt:
     162             :         case T_AlterTSConfigurationStmt:
     163             :         case T_AlterTSDictionaryStmt:
     164             :         case T_AlterTableMoveAllStmt:
     165             :         case T_AlterTableSpaceOptionsStmt:
     166             :         case T_AlterTableStmt:
     167             :         case T_AlterTypeStmt:
     168             :         case T_AlterUserMappingStmt:
     169             :         case T_CommentStmt:
     170             :         case T_CompositeTypeStmt:
     171             :         case T_CreateAmStmt:
     172             :         case T_CreateCastStmt:
     173             :         case T_CreateConversionStmt:
     174             :         case T_CreateDomainStmt:
     175             :         case T_CreateEnumStmt:
     176             :         case T_CreateEventTrigStmt:
     177             :         case T_CreateExtensionStmt:
     178             :         case T_CreateFdwStmt:
     179             :         case T_CreateForeignServerStmt:
     180             :         case T_CreateForeignTableStmt:
     181             :         case T_CreateFunctionStmt:
     182             :         case T_CreateOpClassStmt:
     183             :         case T_CreateOpFamilyStmt:
     184             :         case T_CreatePLangStmt:
     185             :         case T_CreatePolicyStmt:
     186             :         case T_CreatePublicationStmt:
     187             :         case T_CreateRangeStmt:
     188             :         case T_CreateRoleStmt:
     189             :         case T_CreateSchemaStmt:
     190             :         case T_CreateSeqStmt:
     191             :         case T_CreateStatsStmt:
     192             :         case T_CreateStmt:
     193             :         case T_CreateSubscriptionStmt:
     194             :         case T_CreateTableAsStmt:
     195             :         case T_CreateTableSpaceStmt:
     196             :         case T_CreateTransformStmt:
     197             :         case T_CreateTrigStmt:
     198             :         case T_CreateUserMappingStmt:
     199             :         case T_CreatedbStmt:
     200             :         case T_DefineStmt:
     201             :         case T_DropOwnedStmt:
     202             :         case T_DropRoleStmt:
     203             :         case T_DropStmt:
     204             :         case T_DropSubscriptionStmt:
     205             :         case T_DropTableSpaceStmt:
     206             :         case T_DropUserMappingStmt:
     207             :         case T_DropdbStmt:
     208             :         case T_GrantRoleStmt:
     209             :         case T_GrantStmt:
     210             :         case T_ImportForeignSchemaStmt:
     211             :         case T_IndexStmt:
     212             :         case T_ReassignOwnedStmt:
     213             :         case T_RefreshMatViewStmt:
     214             :         case T_RenameStmt:
     215             :         case T_RuleStmt:
     216             :         case T_SecLabelStmt:
     217             :         case T_TruncateStmt:
     218             :         case T_ViewStmt:
     219             :             {
     220             :                 /* DDL is not read-only, and neither is TRUNCATE. */
     221      437356 :                 return COMMAND_IS_NOT_READ_ONLY;
     222             :             }
     223             : 
     224          58 :         case T_AlterSystemStmt:
     225             :             {
     226             :                 /*
     227             :                  * Surprisingly, ALTER SYSTEM meets all our definitions of
     228             :                  * read-only: it changes nothing that affects the output of
     229             :                  * pg_dump, it doesn't write WAL or imperil the application of
     230             :                  * future WAL, and it doesn't depend on any state that needs
     231             :                  * to be synchronized with parallel workers.
     232             :                  *
     233             :                  * So, despite the fact that it writes to a file, it's read
     234             :                  * only!
     235             :                  */
     236          58 :                 return COMMAND_IS_STRICTLY_READ_ONLY;
     237             :             }
     238             : 
     239        1000 :         case T_CallStmt:
     240             :         case T_DoStmt:
     241             :             {
     242             :                 /*
     243             :                  * Commands inside the DO block or the called procedure might
     244             :                  * not be read only, but they'll be checked separately when we
     245             :                  * try to execute them.  Here we only need to worry about the
     246             :                  * DO or CALL command itself.
     247             :                  */
     248        1000 :                 return COMMAND_IS_STRICTLY_READ_ONLY;
     249             :             }
     250             : 
     251         132 :         case T_CheckPointStmt:
     252             :             {
     253             :                 /*
     254             :                  * You might think that this should not be permitted in
     255             :                  * recovery, but we interpret a CHECKPOINT command during
     256             :                  * recovery as a request for a restartpoint instead. We allow
     257             :                  * this since it can be a useful way of reducing switchover
     258             :                  * time when using various forms of replication.
     259             :                  */
     260         132 :                 return COMMAND_IS_STRICTLY_READ_ONLY;
     261             :             }
     262             : 
     263       35860 :         case T_ClosePortalStmt:
     264             :         case T_ConstraintsSetStmt:
     265             :         case T_DeallocateStmt:
     266             :         case T_DeclareCursorStmt:
     267             :         case T_DiscardStmt:
     268             :         case T_ExecuteStmt:
     269             :         case T_FetchStmt:
     270             :         case T_LoadStmt:
     271             :         case T_PrepareStmt:
     272             :         case T_UnlistenStmt:
     273             :         case T_VariableSetStmt:
     274             :             {
     275             :                 /*
     276             :                  * These modify only backend-local state, so they're OK to run
     277             :                  * in a read-only transaction or on a standby. However, they
     278             :                  * are disallowed in parallel mode, because they either rely
     279             :                  * upon or modify backend-local state that might not be
     280             :                  * synchronized among cooperating backends.
     281             :                  */
     282       35860 :                 return COMMAND_OK_IN_RECOVERY | COMMAND_OK_IN_READ_ONLY_TXN;
     283             :             }
     284             : 
     285        8756 :         case T_ClusterStmt:
     286             :         case T_ReindexStmt:
     287             :         case T_VacuumStmt:
     288             :             {
     289             :                 /*
     290             :                  * These commands write WAL, so they're not strictly
     291             :                  * read-only, and running them in parallel workers isn't
     292             :                  * supported.
     293             :                  *
     294             :                  * However, they don't change the database state in a way that
     295             :                  * would affect pg_dump output, so it's fine to run them in a
     296             :                  * read-only transaction. (CLUSTER might change the order of
     297             :                  * rows on disk, which could affect the ordering of pg_dump
     298             :                  * output, but that's not semantically significant.)
     299             :                  */
     300        8756 :                 return COMMAND_OK_IN_READ_ONLY_TXN;
     301             :             }
     302             : 
     303        4942 :         case T_CopyStmt:
     304             :             {
     305        4942 :                 CopyStmt   *stmt = (CopyStmt *) parsetree;
     306             : 
     307             :                 /*
     308             :                  * You might think that COPY FROM is not at all read only, but
     309             :                  * it's OK to copy into a temporary table, because that
     310             :                  * wouldn't change the output of pg_dump.  If the target table
     311             :                  * turns out to be non-temporary, DoCopy itself will call
     312             :                  * PreventCommandIfReadOnly.
     313             :                  */
     314        4942 :                 if (stmt->is_from)
     315        1254 :                     return COMMAND_OK_IN_READ_ONLY_TXN;
     316             :                 else
     317        3688 :                     return COMMAND_IS_STRICTLY_READ_ONLY;
     318             :             }
     319             : 
     320       13918 :         case T_ExplainStmt:
     321             :         case T_VariableShowStmt:
     322             :             {
     323             :                 /*
     324             :                  * These commands don't modify any data and are safe to run in
     325             :                  * a parallel worker.
     326             :                  */
     327       13918 :                 return COMMAND_IS_STRICTLY_READ_ONLY;
     328             :             }
     329             : 
     330         124 :         case T_ListenStmt:
     331             :         case T_NotifyStmt:
     332             :             {
     333             :                 /*
     334             :                  * NOTIFY requires an XID assignment, so it can't be permitted
     335             :                  * on a standby. Perhaps LISTEN could, since without NOTIFY it
     336             :                  * would be OK to just do nothing, at least until promotion,
     337             :                  * but we currently prohibit it lest the user get the wrong
     338             :                  * idea.
     339             :                  *
     340             :                  * (We do allow T_UnlistenStmt on a standby, though, because
     341             :                  * it's a no-op.)
     342             :                  */
     343         124 :                 return COMMAND_OK_IN_READ_ONLY_TXN;
     344             :             }
     345             : 
     346        5514 :         case T_LockStmt:
     347             :             {
     348        5514 :                 LockStmt   *stmt = (LockStmt *) parsetree;
     349             : 
     350             :                 /*
     351             :                  * Only weaker locker modes are allowed during recovery. The
     352             :                  * restrictions here must match those in
     353             :                  * LockAcquireExtended().
     354             :                  */
     355        5514 :                 if (stmt->mode > RowExclusiveLock)
     356         274 :                     return COMMAND_OK_IN_READ_ONLY_TXN;
     357             :                 else
     358        5240 :                     return COMMAND_IS_STRICTLY_READ_ONLY;
     359             :             }
     360             : 
     361       27066 :         case T_TransactionStmt:
     362             :             {
     363       27066 :                 TransactionStmt *stmt = (TransactionStmt *) parsetree;
     364             : 
     365             :                 /*
     366             :                  * PREPARE, COMMIT PREPARED, and ROLLBACK PREPARED all write
     367             :                  * WAL, so they're not read-only in the strict sense; but the
     368             :                  * first and third do not change pg_dump output, so they're OK
     369             :                  * in a read-only transactions.
     370             :                  *
     371             :                  * We also consider COMMIT PREPARED to be OK in a read-only
     372             :                  * transaction environment, by way of exception.
     373             :                  */
     374       27066 :                 switch (stmt->kind)
     375             :                 {
     376       25714 :                     case TRANS_STMT_BEGIN:
     377             :                     case TRANS_STMT_START:
     378             :                     case TRANS_STMT_COMMIT:
     379             :                     case TRANS_STMT_ROLLBACK:
     380             :                     case TRANS_STMT_SAVEPOINT:
     381             :                     case TRANS_STMT_RELEASE:
     382             :                     case TRANS_STMT_ROLLBACK_TO:
     383       25714 :                         return COMMAND_IS_STRICTLY_READ_ONLY;
     384             : 
     385        1352 :                     case TRANS_STMT_PREPARE:
     386             :                     case TRANS_STMT_COMMIT_PREPARED:
     387             :                     case TRANS_STMT_ROLLBACK_PREPARED:
     388        1352 :                         return COMMAND_OK_IN_READ_ONLY_TXN;
     389             :                 }
     390           0 :                 elog(ERROR, "unrecognized TransactionStmtKind: %d",
     391             :                      (int) stmt->kind);
     392             :                 return 0;       /* silence stupider compilers */
     393             :             }
     394             : 
     395           0 :         default:
     396           0 :             elog(ERROR, "unrecognized node type: %d",
     397             :                  (int) nodeTag(parsetree));
     398             :             return 0;           /* silence stupider compilers */
     399             :     }
     400             : }
     401             : 
     402             : /*
     403             :  * PreventCommandIfReadOnly: throw error if XactReadOnly
     404             :  *
     405             :  * This is useful partly to ensure consistency of the error message wording;
     406             :  * some callers have checked XactReadOnly for themselves.
     407             :  */
     408             : void
     409       93484 : PreventCommandIfReadOnly(const char *cmdname)
     410             : {
     411       93484 :     if (XactReadOnly)
     412          28 :         ereport(ERROR,
     413             :                 (errcode(ERRCODE_READ_ONLY_SQL_TRANSACTION),
     414             :         /* translator: %s is name of a SQL command, eg CREATE */
     415             :                  errmsg("cannot execute %s in a read-only transaction",
     416             :                         cmdname)));
     417       93456 : }
     418             : 
     419             : /*
     420             :  * PreventCommandIfParallelMode: throw error if current (sub)transaction is
     421             :  * in parallel mode.
     422             :  *
     423             :  * This is useful partly to ensure consistency of the error message wording;
     424             :  * some callers have checked IsInParallelMode() for themselves.
     425             :  */
     426             : void
     427      175286 : PreventCommandIfParallelMode(const char *cmdname)
     428             : {
     429      175286 :     if (IsInParallelMode())
     430           0 :         ereport(ERROR,
     431             :                 (errcode(ERRCODE_INVALID_TRANSACTION_STATE),
     432             :         /* translator: %s is name of a SQL command, eg CREATE */
     433             :                  errmsg("cannot execute %s during a parallel operation",
     434             :                         cmdname)));
     435      175286 : }
     436             : 
     437             : /*
     438             :  * PreventCommandDuringRecovery: throw error if RecoveryInProgress
     439             :  *
     440             :  * The majority of operations that are unsafe in a Hot Standby
     441             :  * will be rejected by XactReadOnly tests.  However there are a few
     442             :  * commands that are allowed in "read-only" xacts but cannot be allowed
     443             :  * in Hot Standby mode.  Those commands should call this function.
     444             :  */
     445             : void
     446        7178 : PreventCommandDuringRecovery(const char *cmdname)
     447             : {
     448        7178 :     if (RecoveryInProgress())
     449           0 :         ereport(ERROR,
     450             :                 (errcode(ERRCODE_READ_ONLY_SQL_TRANSACTION),
     451             :         /* translator: %s is name of a SQL command, eg CREATE */
     452             :                  errmsg("cannot execute %s during recovery",
     453             :                         cmdname)));
     454        7178 : }
     455             : 
     456             : /*
     457             :  * CheckRestrictedOperation: throw error for hazardous command if we're
     458             :  * inside a security restriction context.
     459             :  *
     460             :  * This is needed to protect session-local state for which there is not any
     461             :  * better-defined protection mechanism, such as ownership.
     462             :  */
     463             : static void
     464        6236 : CheckRestrictedOperation(const char *cmdname)
     465             : {
     466        6236 :     if (InSecurityRestrictedOperation())
     467           0 :         ereport(ERROR,
     468             :                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
     469             :         /* translator: %s is name of a SQL command, eg PREPARE */
     470             :                  errmsg("cannot execute %s within security-restricted operation",
     471             :                         cmdname)));
     472        6236 : }
     473             : 
     474             : /*
     475             :  * ProcessUtility
     476             :  *      general utility function invoker
     477             :  *
     478             :  *  pstmt: PlannedStmt wrapper for the utility statement
     479             :  *  queryString: original source text of command
     480             :  *  readOnlyTree: if true, pstmt's node tree must not be modified
     481             :  *  context: identifies source of statement (toplevel client command,
     482             :  *      non-toplevel client command, subcommand of a larger utility command)
     483             :  *  params: parameters to use during execution
     484             :  *  queryEnv: environment for parse through execution (e.g., ephemeral named
     485             :  *      tables like trigger transition tables).  May be NULL.
     486             :  *  dest: where to send results
     487             :  *  qc: where to store command completion status data.  May be NULL,
     488             :  *      but if not, then caller must have initialized it.
     489             :  *
     490             :  * Caller MUST supply a queryString; it is not allowed (anymore) to pass NULL.
     491             :  * If you really don't have source text, you can pass a constant string,
     492             :  * perhaps "(query not available)".
     493             :  *
     494             :  * Note for users of ProcessUtility_hook: the same queryString may be passed
     495             :  * to multiple invocations of ProcessUtility when processing a query string
     496             :  * containing multiple semicolon-separated statements.  One should use
     497             :  * pstmt->stmt_location and pstmt->stmt_len to identify the substring
     498             :  * containing the current statement.  Keep in mind also that some utility
     499             :  * statements (e.g., CREATE SCHEMA) will recurse to ProcessUtility to process
     500             :  * sub-statements, often passing down the same queryString, stmt_location,
     501             :  * and stmt_len that were given for the whole statement.
     502             :  */
     503             : void
     504      534726 : ProcessUtility(PlannedStmt *pstmt,
     505             :                const char *queryString,
     506             :                bool readOnlyTree,
     507             :                ProcessUtilityContext context,
     508             :                ParamListInfo params,
     509             :                QueryEnvironment *queryEnv,
     510             :                DestReceiver *dest,
     511             :                QueryCompletion *qc)
     512             : {
     513             :     Assert(IsA(pstmt, PlannedStmt));
     514             :     Assert(pstmt->commandType == CMD_UTILITY);
     515             :     Assert(queryString != NULL);    /* required as of 8.4 */
     516             :     Assert(qc == NULL || qc->commandTag == CMDTAG_UNKNOWN);
     517             : 
     518             :     /*
     519             :      * We provide a function hook variable that lets loadable plugins get
     520             :      * control when ProcessUtility is called.  Such a plugin would normally
     521             :      * call standard_ProcessUtility().
     522             :      */
     523      534726 :     if (ProcessUtility_hook)
     524         300 :         (*ProcessUtility_hook) (pstmt, queryString, readOnlyTree,
     525             :                                 context, params, queryEnv,
     526             :                                 dest, qc);
     527             :     else
     528      534426 :         standard_ProcessUtility(pstmt, queryString, readOnlyTree,
     529             :                                 context, params, queryEnv,
     530             :                                 dest, qc);
     531      526434 : }
     532             : 
     533             : /*
     534             :  * standard_ProcessUtility itself deals only with utility commands for
     535             :  * which we do not provide event trigger support.  Commands that do have
     536             :  * such support are passed down to ProcessUtilitySlow, which contains the
     537             :  * necessary infrastructure for such triggers.
     538             :  *
     539             :  * This division is not just for performance: it's critical that the
     540             :  * event trigger code not be invoked when doing START TRANSACTION for
     541             :  * example, because we might need to refresh the event trigger cache,
     542             :  * which requires being in a valid transaction.
     543             :  */
     544             : void
     545      534726 : standard_ProcessUtility(PlannedStmt *pstmt,
     546             :                         const char *queryString,
     547             :                         bool readOnlyTree,
     548             :                         ProcessUtilityContext context,
     549             :                         ParamListInfo params,
     550             :                         QueryEnvironment *queryEnv,
     551             :                         DestReceiver *dest,
     552             :                         QueryCompletion *qc)
     553             : {
     554             :     Node       *parsetree;
     555      534726 :     bool        isTopLevel = (context == PROCESS_UTILITY_TOPLEVEL);
     556      534726 :     bool        isAtomicContext = (!(context == PROCESS_UTILITY_TOPLEVEL || context == PROCESS_UTILITY_QUERY_NONATOMIC) || IsTransactionBlock());
     557             :     ParseState *pstate;
     558             :     int         readonly_flags;
     559             : 
     560             :     /* This can recurse, so check for excessive recursion */
     561      534726 :     check_stack_depth();
     562             : 
     563             :     /*
     564             :      * If the given node tree is read-only, make a copy to ensure that parse
     565             :      * transformations don't damage the original tree.  This could be
     566             :      * refactored to avoid making unnecessary copies in more cases, but it's
     567             :      * not clear that it's worth a great deal of trouble over.  Statements
     568             :      * that are complex enough to be expensive to copy are exactly the ones
     569             :      * we'd need to copy, so that only marginal savings seem possible.
     570             :      */
     571      534726 :     if (readOnlyTree)
     572       10534 :         pstmt = copyObject(pstmt);
     573      534726 :     parsetree = pstmt->utilityStmt;
     574             : 
     575             :     /* Prohibit read/write commands in read-only states. */
     576      534726 :     readonly_flags = ClassifyUtilityCommandAsReadOnly(parsetree);
     577      534726 :     if (readonly_flags != COMMAND_IS_STRICTLY_READ_ONLY &&
     578      484976 :         (XactReadOnly || IsInParallelMode()))
     579             :     {
     580         732 :         CommandTag  commandtag = CreateCommandTag(parsetree);
     581             : 
     582         732 :         if ((readonly_flags & COMMAND_OK_IN_READ_ONLY_TXN) == 0)
     583           8 :             PreventCommandIfReadOnly(GetCommandTagName(commandtag));
     584         724 :         if ((readonly_flags & COMMAND_OK_IN_PARALLEL_MODE) == 0)
     585         724 :             PreventCommandIfParallelMode(GetCommandTagName(commandtag));
     586         724 :         if ((readonly_flags & COMMAND_OK_IN_RECOVERY) == 0)
     587           0 :             PreventCommandDuringRecovery(GetCommandTagName(commandtag));
     588             :     }
     589             : 
     590      534718 :     pstate = make_parsestate(NULL);
     591      534718 :     pstate->p_sourcetext = queryString;
     592      534718 :     pstate->p_queryEnv = queryEnv;
     593             : 
     594      534718 :     switch (nodeTag(parsetree))
     595             :     {
     596             :             /*
     597             :              * ******************** transactions ********************
     598             :              */
     599       27066 :         case T_TransactionStmt:
     600             :             {
     601       27066 :                 TransactionStmt *stmt = (TransactionStmt *) parsetree;
     602             : 
     603       27066 :                 switch (stmt->kind)
     604             :                 {
     605             :                         /*
     606             :                          * START TRANSACTION, as defined by SQL99: Identical
     607             :                          * to BEGIN.  Same code for both.
     608             :                          */
     609       12220 :                     case TRANS_STMT_BEGIN:
     610             :                     case TRANS_STMT_START:
     611             :                         {
     612             :                             ListCell   *lc;
     613             : 
     614       12220 :                             BeginTransactionBlock();
     615       18186 :                             foreach(lc, stmt->options)
     616             :                             {
     617        5966 :                                 DefElem    *item = (DefElem *) lfirst(lc);
     618             : 
     619        5966 :                                 if (strcmp(item->defname, "transaction_isolation") == 0)
     620        5324 :                                     SetPGVariable("transaction_isolation",
     621        5324 :                                                   list_make1(item->arg),
     622             :                                                   true);
     623         642 :                                 else if (strcmp(item->defname, "transaction_read_only") == 0)
     624         624 :                                     SetPGVariable("transaction_read_only",
     625         624 :                                                   list_make1(item->arg),
     626             :                                                   true);
     627          18 :                                 else if (strcmp(item->defname, "transaction_deferrable") == 0)
     628          18 :                                     SetPGVariable("transaction_deferrable",
     629          18 :                                                   list_make1(item->arg),
     630             :                                                   true);
     631             :                             }
     632             :                         }
     633       12220 :                         break;
     634             : 
     635       10060 :                     case TRANS_STMT_COMMIT:
     636       10060 :                         if (!EndTransactionBlock(stmt->chain))
     637             :                         {
     638             :                             /* report unsuccessful commit in qc */
     639         630 :                             if (qc)
     640         630 :                                 SetQueryCompletion(qc, CMDTAG_ROLLBACK, 0);
     641             :                         }
     642       10040 :                         break;
     643             : 
     644         706 :                     case TRANS_STMT_PREPARE:
     645         706 :                         if (!PrepareTransactionBlock(stmt->gid))
     646             :                         {
     647             :                             /* report unsuccessful commit in qc */
     648           2 :                             if (qc)
     649           2 :                                 SetQueryCompletion(qc, CMDTAG_ROLLBACK, 0);
     650             :                         }
     651         706 :                         break;
     652             : 
     653         604 :                     case TRANS_STMT_COMMIT_PREPARED:
     654         604 :                         PreventInTransactionBlock(isTopLevel, "COMMIT PREPARED");
     655         604 :                         FinishPreparedTransaction(stmt->gid, true);
     656         598 :                         break;
     657             : 
     658          42 :                     case TRANS_STMT_ROLLBACK_PREPARED:
     659          42 :                         PreventInTransactionBlock(isTopLevel, "ROLLBACK PREPARED");
     660          42 :                         FinishPreparedTransaction(stmt->gid, false);
     661          36 :                         break;
     662             : 
     663        1266 :                     case TRANS_STMT_ROLLBACK:
     664        1266 :                         UserAbortTransactionBlock(stmt->chain);
     665        1246 :                         break;
     666             : 
     667        1546 :                     case TRANS_STMT_SAVEPOINT:
     668        1546 :                         RequireTransactionBlock(isTopLevel, "SAVEPOINT");
     669        1542 :                         DefineSavepoint(stmt->savepoint_name);
     670        1534 :                         break;
     671             : 
     672         176 :                     case TRANS_STMT_RELEASE:
     673         176 :                         RequireTransactionBlock(isTopLevel, "RELEASE SAVEPOINT");
     674         172 :                         ReleaseSavepoint(stmt->savepoint_name);
     675         168 :                         break;
     676             : 
     677         446 :                     case TRANS_STMT_ROLLBACK_TO:
     678         446 :                         RequireTransactionBlock(isTopLevel, "ROLLBACK TO SAVEPOINT");
     679         442 :                         RollbackToSavepoint(stmt->savepoint_name);
     680             : 
     681             :                         /*
     682             :                          * CommitTransactionCommand is in charge of
     683             :                          * re-defining the savepoint again
     684             :                          */
     685         434 :                         break;
     686             :                 }
     687       26982 :             }
     688       26982 :             break;
     689             : 
     690             :             /*
     691             :              * Portal (cursor) manipulation
     692             :              */
     693        2338 :         case T_DeclareCursorStmt:
     694        2338 :             PerformCursorOpen(pstate, (DeclareCursorStmt *) parsetree, params,
     695             :                               isTopLevel);
     696        2328 :             break;
     697             : 
     698        1944 :         case T_ClosePortalStmt:
     699             :             {
     700        1944 :                 ClosePortalStmt *stmt = (ClosePortalStmt *) parsetree;
     701             : 
     702        1944 :                 CheckRestrictedOperation("CLOSE");
     703        1944 :                 PerformPortalClose(stmt->portalname);
     704             :             }
     705        1942 :             break;
     706             : 
     707        5138 :         case T_FetchStmt:
     708        5138 :             PerformPortalFetch((FetchStmt *) parsetree, dest, qc);
     709        5062 :             break;
     710             : 
     711         692 :         case T_DoStmt:
     712         692 :             ExecuteDoStmt(pstate, (DoStmt *) parsetree, isAtomicContext);
     713         388 :             break;
     714             : 
     715          40 :         case T_CreateTableSpaceStmt:
     716             :             /* no event triggers for global objects */
     717          40 :             PreventInTransactionBlock(isTopLevel, "CREATE TABLESPACE");
     718          40 :             CreateTableSpace((CreateTableSpaceStmt *) parsetree);
     719          28 :             break;
     720             : 
     721          24 :         case T_DropTableSpaceStmt:
     722             :             /* no event triggers for global objects */
     723          24 :             PreventInTransactionBlock(isTopLevel, "DROP TABLESPACE");
     724          24 :             DropTableSpace((DropTableSpaceStmt *) parsetree);
     725          16 :             break;
     726             : 
     727          16 :         case T_AlterTableSpaceOptionsStmt:
     728             :             /* no event triggers for global objects */
     729          16 :             AlterTableSpaceOptions((AlterTableSpaceOptionsStmt *) parsetree);
     730           8 :             break;
     731             : 
     732         924 :         case T_TruncateStmt:
     733         924 :             ExecuteTruncate((TruncateStmt *) parsetree);
     734         816 :             break;
     735             : 
     736        4942 :         case T_CopyStmt:
     737             :             {
     738             :                 uint64      processed;
     739             : 
     740        4942 :                 DoCopy(pstate, (CopyStmt *) parsetree,
     741             :                        pstmt->stmt_location, pstmt->stmt_len,
     742             :                        &processed);
     743        4596 :                 if (qc)
     744        4596 :                     SetQueryCompletion(qc, CMDTAG_COPY, processed);
     745             :             }
     746        4596 :             break;
     747             : 
     748         328 :         case T_PrepareStmt:
     749         328 :             CheckRestrictedOperation("PREPARE");
     750         328 :             PrepareQuery(pstate, (PrepareStmt *) parsetree,
     751             :                          pstmt->stmt_location, pstmt->stmt_len);
     752         320 :             break;
     753             : 
     754         834 :         case T_ExecuteStmt:
     755         834 :             ExecuteQuery(pstate,
     756             :                          (ExecuteStmt *) parsetree, NULL,
     757             :                          params,
     758             :                          dest, qc);
     759         768 :             break;
     760             : 
     761        3868 :         case T_DeallocateStmt:
     762        3868 :             CheckRestrictedOperation("DEALLOCATE");
     763        3868 :             DeallocateQuery((DeallocateStmt *) parsetree);
     764        3868 :             break;
     765             : 
     766        1606 :         case T_GrantRoleStmt:
     767             :             /* no event triggers for global objects */
     768        1606 :             GrantRole((GrantRoleStmt *) parsetree);
     769        1570 :             break;
     770             : 
     771        1262 :         case T_CreatedbStmt:
     772             :             /* no event triggers for global objects */
     773        1262 :             PreventInTransactionBlock(isTopLevel, "CREATE DATABASE");
     774        1262 :             createdb(pstate, (CreatedbStmt *) parsetree);
     775        1256 :             break;
     776             : 
     777           6 :         case T_AlterDatabaseStmt:
     778             :             /* no event triggers for global objects */
     779           6 :             AlterDatabase(pstate, (AlterDatabaseStmt *) parsetree, isTopLevel);
     780           6 :             break;
     781             : 
     782         900 :         case T_AlterDatabaseSetStmt:
     783             :             /* no event triggers for global objects */
     784         900 :             AlterDatabaseSet((AlterDatabaseSetStmt *) parsetree);
     785         900 :             break;
     786             : 
     787          40 :         case T_DropdbStmt:
     788             :             /* no event triggers for global objects */
     789          40 :             PreventInTransactionBlock(isTopLevel, "DROP DATABASE");
     790          40 :             DropDatabase(pstate, (DropdbStmt *) parsetree);
     791          28 :             break;
     792             : 
     793             :             /* Query-level asynchronous notification */
     794          82 :         case T_NotifyStmt:
     795             :             {
     796          82 :                 NotifyStmt *stmt = (NotifyStmt *) parsetree;
     797             : 
     798          82 :                 Async_Notify(stmt->conditionname, stmt->payload);
     799             :             }
     800          82 :             break;
     801             : 
     802          42 :         case T_ListenStmt:
     803             :             {
     804          42 :                 ListenStmt *stmt = (ListenStmt *) parsetree;
     805             : 
     806          42 :                 CheckRestrictedOperation("LISTEN");
     807             : 
     808             :                 /*
     809             :                  * We don't allow LISTEN in background processes, as there is
     810             :                  * no mechanism for them to collect NOTIFY messages, so they'd
     811             :                  * just block cleanout of the async SLRU indefinitely.
     812             :                  * (Authors of custom background workers could bypass this
     813             :                  * restriction by calling Async_Listen directly, but then it's
     814             :                  * on them to provide some mechanism to process the message
     815             :                  * queue.)  Note there seems no reason to forbid UNLISTEN.
     816             :                  */
     817          42 :                 if (MyBackendType != B_BACKEND)
     818           0 :                     ereport(ERROR,
     819             :                             (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
     820             :                     /* translator: %s is name of a SQL command, eg LISTEN */
     821             :                              errmsg("cannot execute %s within a background process",
     822             :                                     "LISTEN")));
     823             : 
     824          42 :                 Async_Listen(stmt->conditionname);
     825             :             }
     826          42 :             break;
     827             : 
     828          34 :         case T_UnlistenStmt:
     829             :             {
     830          34 :                 UnlistenStmt *stmt = (UnlistenStmt *) parsetree;
     831             : 
     832          34 :                 CheckRestrictedOperation("UNLISTEN");
     833          34 :                 if (stmt->conditionname)
     834           4 :                     Async_Unlisten(stmt->conditionname);
     835             :                 else
     836          30 :                     Async_UnlistenAll();
     837             :             }
     838          34 :             break;
     839             : 
     840          34 :         case T_LoadStmt:
     841             :             {
     842          34 :                 LoadStmt   *stmt = (LoadStmt *) parsetree;
     843             : 
     844          34 :                 closeAllVfds(); /* probably not necessary... */
     845             :                 /* Allowed names are restricted if you're not superuser */
     846          34 :                 load_file(stmt->filename, !superuser());
     847             :             }
     848          34 :             break;
     849             : 
     850         308 :         case T_CallStmt:
     851         308 :             ExecuteCallStmt(castNode(CallStmt, parsetree), params, isAtomicContext, dest);
     852         272 :             break;
     853             : 
     854         114 :         case T_ClusterStmt:
     855         114 :             cluster(pstate, (ClusterStmt *) parsetree, isTopLevel);
     856         106 :             break;
     857             : 
     858        8174 :         case T_VacuumStmt:
     859        8174 :             ExecVacuum(pstate, (VacuumStmt *) parsetree, isTopLevel);
     860        8064 :             break;
     861             : 
     862       13404 :         case T_ExplainStmt:
     863       13404 :             ExplainQuery(pstate, (ExplainStmt *) parsetree, params, dest);
     864       13356 :             break;
     865             : 
     866          58 :         case T_AlterSystemStmt:
     867          58 :             PreventInTransactionBlock(isTopLevel, "ALTER SYSTEM");
     868          58 :             AlterSystemSetConfigFile((AlterSystemStmt *) parsetree);
     869          58 :             break;
     870             : 
     871       21252 :         case T_VariableSetStmt:
     872       21252 :             ExecSetVariableStmt((VariableSetStmt *) parsetree, isTopLevel);
     873       21178 :             break;
     874             : 
     875         514 :         case T_VariableShowStmt:
     876             :             {
     877         514 :                 VariableShowStmt *n = (VariableShowStmt *) parsetree;
     878             : 
     879         514 :                 GetPGVariable(n->name, dest);
     880             :             }
     881         514 :             break;
     882             : 
     883          20 :         case T_DiscardStmt:
     884             :             /* should we allow DISCARD PLANS? */
     885          20 :             CheckRestrictedOperation("DISCARD");
     886          20 :             DiscardCommand((DiscardStmt *) parsetree, isTopLevel);
     887          20 :             break;
     888             : 
     889         114 :         case T_CreateEventTrigStmt:
     890             :             /* no event triggers on event triggers */
     891         114 :             CreateEventTrigger((CreateEventTrigStmt *) parsetree);
     892          70 :             break;
     893             : 
     894          22 :         case T_AlterEventTrigStmt:
     895             :             /* no event triggers on event triggers */
     896          22 :             AlterEventTrigger((AlterEventTrigStmt *) parsetree);
     897          22 :             break;
     898             : 
     899             :             /*
     900             :              * ******************************** ROLE statements ****
     901             :              */
     902         822 :         case T_CreateRoleStmt:
     903             :             /* no event triggers for global objects */
     904         822 :             CreateRole(pstate, (CreateRoleStmt *) parsetree);
     905         808 :             break;
     906             : 
     907         234 :         case T_AlterRoleStmt:
     908             :             /* no event triggers for global objects */
     909         234 :             AlterRole(pstate, (AlterRoleStmt *) parsetree);
     910         210 :             break;
     911             : 
     912          64 :         case T_AlterRoleSetStmt:
     913             :             /* no event triggers for global objects */
     914          64 :             AlterRoleSet((AlterRoleSetStmt *) parsetree);
     915          56 :             break;
     916             : 
     917         820 :         case T_DropRoleStmt:
     918             :             /* no event triggers for global objects */
     919         820 :             DropRole((DropRoleStmt *) parsetree);
     920         734 :             break;
     921             : 
     922          16 :         case T_ReassignOwnedStmt:
     923             :             /* no event triggers for global objects */
     924          16 :             ReassignOwnedObjects((ReassignOwnedStmt *) parsetree);
     925           8 :             break;
     926             : 
     927        5514 :         case T_LockStmt:
     928             : 
     929             :             /*
     930             :              * Since the lock would just get dropped immediately, LOCK TABLE
     931             :              * outside a transaction block is presumed to be user error.
     932             :              */
     933        5514 :             RequireTransactionBlock(isTopLevel, "LOCK TABLE");
     934        5514 :             LockTableCommand((LockStmt *) parsetree);
     935        5456 :             break;
     936             : 
     937          70 :         case T_ConstraintsSetStmt:
     938          70 :             WarnNoTransactionBlock(isTopLevel, "SET CONSTRAINTS");
     939          70 :             AfterTriggerSetState((ConstraintsSetStmt *) parsetree);
     940          58 :             break;
     941             : 
     942         132 :         case T_CheckPointStmt:
     943         132 :             if (!has_privs_of_role(GetUserId(), ROLE_PG_CHECKPOINTER))
     944           0 :                 ereport(ERROR,
     945             :                         (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
     946             :                          errmsg("must be superuser or have privileges of pg_checkpointer to do CHECKPOINT")));
     947             : 
     948         132 :             RequestCheckpoint(CHECKPOINT_IMMEDIATE | CHECKPOINT_WAIT |
     949         132 :                               (RecoveryInProgress() ? 0 : CHECKPOINT_FORCE));
     950         132 :             break;
     951             : 
     952         468 :         case T_ReindexStmt:
     953         468 :             ExecReindex(pstate, (ReindexStmt *) parsetree, isTopLevel);
     954         290 :             break;
     955             : 
     956             :             /*
     957             :              * The following statements are supported by Event Triggers only
     958             :              * in some cases, so we "fast path" them in the other cases.
     959             :              */
     960             : 
     961       75086 :         case T_GrantStmt:
     962             :             {
     963       75086 :                 GrantStmt  *stmt = (GrantStmt *) parsetree;
     964             : 
     965       75086 :                 if (EventTriggerSupportsObjectType(stmt->objtype))
     966       74084 :                     ProcessUtilitySlow(pstate, pstmt, queryString,
     967             :                                        context, params, queryEnv,
     968             :                                        dest, qc);
     969             :                 else
     970        1002 :                     ExecuteGrantStmt(stmt);
     971             :             }
     972       75006 :             break;
     973             : 
     974       15182 :         case T_DropStmt:
     975             :             {
     976       15182 :                 DropStmt   *stmt = (DropStmt *) parsetree;
     977             : 
     978       15182 :                 if (EventTriggerSupportsObjectType(stmt->removeType))
     979       15116 :                     ProcessUtilitySlow(pstate, pstmt, queryString,
     980             :                                        context, params, queryEnv,
     981             :                                        dest, qc);
     982             :                 else
     983          66 :                     ExecDropStmt(stmt, isTopLevel);
     984             :             }
     985       14532 :             break;
     986             : 
     987         798 :         case T_RenameStmt:
     988             :             {
     989         798 :                 RenameStmt *stmt = (RenameStmt *) parsetree;
     990             : 
     991         798 :                 if (EventTriggerSupportsObjectType(stmt->renameType))
     992         774 :                     ProcessUtilitySlow(pstate, pstmt, queryString,
     993             :                                        context, params, queryEnv,
     994             :                                        dest, qc);
     995             :                 else
     996          24 :                     ExecRenameStmt(stmt);
     997             :             }
     998         546 :             break;
     999             : 
    1000          46 :         case T_AlterObjectDependsStmt:
    1001             :             {
    1002          46 :                 AlterObjectDependsStmt *stmt = (AlterObjectDependsStmt *) parsetree;
    1003             : 
    1004          46 :                 if (EventTriggerSupportsObjectType(stmt->objectType))
    1005          46 :                     ProcessUtilitySlow(pstate, pstmt, queryString,
    1006             :                                        context, params, queryEnv,
    1007             :                                        dest, qc);
    1008             :                 else
    1009           0 :                     ExecAlterObjectDependsStmt(stmt, NULL);
    1010             :             }
    1011          46 :             break;
    1012             : 
    1013         250 :         case T_AlterObjectSchemaStmt:
    1014             :             {
    1015         250 :                 AlterObjectSchemaStmt *stmt = (AlterObjectSchemaStmt *) parsetree;
    1016             : 
    1017         250 :                 if (EventTriggerSupportsObjectType(stmt->objectType))
    1018         250 :                     ProcessUtilitySlow(pstate, pstmt, queryString,
    1019             :                                        context, params, queryEnv,
    1020             :                                        dest, qc);
    1021             :                 else
    1022           0 :                     ExecAlterObjectSchemaStmt(stmt, NULL);
    1023             :             }
    1024         164 :             break;
    1025             : 
    1026        1676 :         case T_AlterOwnerStmt:
    1027             :             {
    1028        1676 :                 AlterOwnerStmt *stmt = (AlterOwnerStmt *) parsetree;
    1029             : 
    1030        1676 :                 if (EventTriggerSupportsObjectType(stmt->objectType))
    1031        1630 :                     ProcessUtilitySlow(pstate, pstmt, queryString,
    1032             :                                        context, params, queryEnv,
    1033             :                                        dest, qc);
    1034             :                 else
    1035          46 :                     ExecAlterOwnerStmt(stmt);
    1036             :             }
    1037        1516 :             break;
    1038             : 
    1039       29680 :         case T_CommentStmt:
    1040             :             {
    1041       29680 :                 CommentStmt *stmt = (CommentStmt *) parsetree;
    1042             : 
    1043       29680 :                 if (EventTriggerSupportsObjectType(stmt->objtype))
    1044       28706 :                     ProcessUtilitySlow(pstate, pstmt, queryString,
    1045             :                                        context, params, queryEnv,
    1046             :                                        dest, qc);
    1047             :                 else
    1048         974 :                     CommentObject(stmt);
    1049       29578 :                 break;
    1050             :             }
    1051             : 
    1052          84 :         case T_SecLabelStmt:
    1053             :             {
    1054          84 :                 SecLabelStmt *stmt = (SecLabelStmt *) parsetree;
    1055             : 
    1056          84 :                 if (EventTriggerSupportsObjectType(stmt->objtype))
    1057          54 :                     ProcessUtilitySlow(pstate, pstmt, queryString,
    1058             :                                        context, params, queryEnv,
    1059             :                                        dest, qc);
    1060             :                 else
    1061          30 :                     ExecSecLabelStmt(stmt);
    1062          28 :                 break;
    1063             :             }
    1064             : 
    1065      307636 :         default:
    1066             :             /* All other statement types have event trigger support */
    1067      307636 :             ProcessUtilitySlow(pstate, pstmt, queryString,
    1068             :                                context, params, queryEnv,
    1069             :                                dest, qc);
    1070      302532 :             break;
    1071             :     }
    1072             : 
    1073      526434 :     free_parsestate(pstate);
    1074             : 
    1075             :     /*
    1076             :      * Make effects of commands visible, for instance so that
    1077             :      * PreCommit_on_commit_actions() can see them (see for example bug
    1078             :      * #15631).
    1079             :      */
    1080      526434 :     CommandCounterIncrement();
    1081      526434 : }
    1082             : 
    1083             : /*
    1084             :  * The "Slow" variant of ProcessUtility should only receive statements
    1085             :  * supported by the event triggers facility.  Therefore, we always
    1086             :  * perform the trigger support calls if the context allows it.
    1087             :  */
    1088             : static void
    1089      428296 : ProcessUtilitySlow(ParseState *pstate,
    1090             :                    PlannedStmt *pstmt,
    1091             :                    const char *queryString,
    1092             :                    ProcessUtilityContext context,
    1093             :                    ParamListInfo params,
    1094             :                    QueryEnvironment *queryEnv,
    1095             :                    DestReceiver *dest,
    1096             :                    QueryCompletion *qc)
    1097             : {
    1098      428296 :     Node       *parsetree = pstmt->utilityStmt;
    1099      428296 :     bool        isTopLevel = (context == PROCESS_UTILITY_TOPLEVEL);
    1100      428296 :     bool        isCompleteQuery = (context != PROCESS_UTILITY_SUBCOMMAND);
    1101             :     bool        needCleanup;
    1102      428296 :     bool        commandCollected = false;
    1103             :     ObjectAddress address;
    1104      428296 :     ObjectAddress secondaryObject = InvalidObjectAddress;
    1105             : 
    1106             :     /* All event trigger calls are done only when isCompleteQuery is true */
    1107      428296 :     needCleanup = isCompleteQuery && EventTriggerBeginCompleteQuery();
    1108             : 
    1109             :     /* PG_TRY block is to ensure we call EventTriggerEndCompleteQuery */
    1110      428296 :     PG_TRY();
    1111             :     {
    1112      428296 :         if (isCompleteQuery)
    1113      420832 :             EventTriggerDDLCommandStart(parsetree);
    1114             : 
    1115      428296 :         switch (nodeTag(parsetree))
    1116             :         {
    1117             :                 /*
    1118             :                  * relation and attribute manipulation
    1119             :                  */
    1120         952 :             case T_CreateSchemaStmt:
    1121         952 :                 CreateSchemaCommand((CreateSchemaStmt *) parsetree,
    1122             :                                     queryString,
    1123             :                                     pstmt->stmt_location,
    1124             :                                     pstmt->stmt_len);
    1125             : 
    1126             :                 /*
    1127             :                  * EventTriggerCollectSimpleCommand called by
    1128             :                  * CreateSchemaCommand
    1129             :                  */
    1130         930 :                 commandCollected = true;
    1131         930 :                 break;
    1132             : 
    1133       24282 :             case T_CreateStmt:
    1134             :             case T_CreateForeignTableStmt:
    1135             :                 {
    1136             :                     List       *stmts;
    1137       24282 :                     RangeVar   *table_rv = NULL;
    1138             : 
    1139             :                     /* Run parse analysis ... */
    1140       24282 :                     stmts = transformCreateStmt((CreateStmt *) parsetree,
    1141             :                                                 queryString);
    1142             : 
    1143             :                     /*
    1144             :                      * ... and do it.  We can't use foreach() because we may
    1145             :                      * modify the list midway through, so pick off the
    1146             :                      * elements one at a time, the hard way.
    1147             :                      */
    1148       54514 :                     while (stmts != NIL)
    1149             :                     {
    1150       31214 :                         Node       *stmt = (Node *) linitial(stmts);
    1151             : 
    1152       31214 :                         stmts = list_delete_first(stmts);
    1153             : 
    1154       31214 :                         if (IsA(stmt, CreateStmt))
    1155             :                         {
    1156       23820 :                             CreateStmt *cstmt = (CreateStmt *) stmt;
    1157             :                             Datum       toast_options;
    1158             :                             static char *validnsps[] = HEAP_RELOPT_NAMESPACES;
    1159             : 
    1160             :                             /* Remember transformed RangeVar for LIKE */
    1161       23820 :                             table_rv = cstmt->relation;
    1162             : 
    1163             :                             /* Create the table itself */
    1164       23820 :                             address = DefineRelation(cstmt,
    1165             :                                                      RELKIND_RELATION,
    1166             :                                                      InvalidOid, NULL,
    1167             :                                                      queryString);
    1168       23172 :                             EventTriggerCollectSimpleCommand(address,
    1169             :                                                              secondaryObject,
    1170             :                                                              stmt);
    1171             : 
    1172             :                             /*
    1173             :                              * Let NewRelationCreateToastTable decide if this
    1174             :                              * one needs a secondary relation too.
    1175             :                              */
    1176       23172 :                             CommandCounterIncrement();
    1177             : 
    1178             :                             /*
    1179             :                              * parse and validate reloptions for the toast
    1180             :                              * table
    1181             :                              */
    1182       23172 :                             toast_options = transformRelOptions((Datum) 0,
    1183             :                                                                 cstmt->options,
    1184             :                                                                 "toast",
    1185             :                                                                 validnsps,
    1186             :                                                                 true,
    1187             :                                                                 false);
    1188       23172 :                             (void) heap_reloptions(RELKIND_TOASTVALUE,
    1189             :                                                    toast_options,
    1190             :                                                    true);
    1191             : 
    1192       23168 :                             NewRelationCreateToastTable(address.objectId,
    1193             :                                                         toast_options);
    1194             :                         }
    1195        7394 :                         else if (IsA(stmt, CreateForeignTableStmt))
    1196             :                         {
    1197         344 :                             CreateForeignTableStmt *cstmt = (CreateForeignTableStmt *) stmt;
    1198             : 
    1199             :                             /* Remember transformed RangeVar for LIKE */
    1200         344 :                             table_rv = cstmt->base.relation;
    1201             : 
    1202             :                             /* Create the table itself */
    1203         344 :                             address = DefineRelation(&cstmt->base,
    1204             :                                                      RELKIND_FOREIGN_TABLE,
    1205             :                                                      InvalidOid, NULL,
    1206             :                                                      queryString);
    1207         330 :                             CreateForeignTable(cstmt,
    1208             :                                                address.objectId);
    1209         274 :                             EventTriggerCollectSimpleCommand(address,
    1210             :                                                              secondaryObject,
    1211             :                                                              stmt);
    1212             :                         }
    1213        7050 :                         else if (IsA(stmt, TableLikeClause))
    1214             :                         {
    1215             :                             /*
    1216             :                              * Do delayed processing of LIKE options.  This
    1217             :                              * will result in additional sub-statements for us
    1218             :                              * to process.  Those should get done before any
    1219             :                              * remaining actions, so prepend them to "stmts".
    1220             :                              */
    1221         106 :                             TableLikeClause *like = (TableLikeClause *) stmt;
    1222             :                             List       *morestmts;
    1223             : 
    1224             :                             Assert(table_rv != NULL);
    1225             : 
    1226         106 :                             morestmts = expandTableLikeClause(table_rv, like);
    1227         106 :                             stmts = list_concat(morestmts, stmts);
    1228             :                         }
    1229             :                         else
    1230             :                         {
    1231             :                             /*
    1232             :                              * Recurse for anything else.  Note the recursive
    1233             :                              * call will stash the objects so created into our
    1234             :                              * event trigger context.
    1235             :                              */
    1236             :                             PlannedStmt *wrapper;
    1237             : 
    1238        6944 :                             wrapper = makeNode(PlannedStmt);
    1239        6944 :                             wrapper->commandType = CMD_UTILITY;
    1240        6944 :                             wrapper->canSetTag = false;
    1241        6944 :                             wrapper->utilityStmt = stmt;
    1242        6944 :                             wrapper->stmt_location = pstmt->stmt_location;
    1243        6944 :                             wrapper->stmt_len = pstmt->stmt_len;
    1244             : 
    1245        6944 :                             ProcessUtility(wrapper,
    1246             :                                            queryString,
    1247             :                                            false,
    1248             :                                            PROCESS_UTILITY_SUBCOMMAND,
    1249             :                                            params,
    1250             :                                            NULL,
    1251             :                                            None_Receiver,
    1252             :                                            NULL);
    1253             :                         }
    1254             : 
    1255             :                         /* Need CCI between commands */
    1256       30338 :                         if (stmts != NIL)
    1257        7046 :                             CommandCounterIncrement();
    1258             :                     }
    1259             : 
    1260             :                     /*
    1261             :                      * The multiple commands generated here are stashed
    1262             :                      * individually, so disable collection below.
    1263             :                      */
    1264       23300 :                     commandCollected = true;
    1265             :                 }
    1266       23300 :                 break;
    1267             : 
    1268       63728 :             case T_AlterTableStmt:
    1269             :                 {
    1270       63728 :                     AlterTableStmt *atstmt = (AlterTableStmt *) parsetree;
    1271             :                     Oid         relid;
    1272             :                     LOCKMODE    lockmode;
    1273             :                     ListCell   *cell;
    1274             : 
    1275             :                     /*
    1276             :                      * Disallow ALTER TABLE .. DETACH CONCURRENTLY in a
    1277             :                      * transaction block or function.  (Perhaps it could be
    1278             :                      * allowed in a procedure, but don't hold your breath.)
    1279             :                      */
    1280      128044 :                     foreach(cell, atstmt->cmds)
    1281             :                     {
    1282       64320 :                         AlterTableCmd *cmd = (AlterTableCmd *) lfirst(cell);
    1283             : 
    1284             :                         /* Disallow DETACH CONCURRENTLY in a transaction block */
    1285       64320 :                         if (cmd->subtype == AT_DetachPartition)
    1286             :                         {
    1287         382 :                             if (((PartitionCmd *) cmd->def)->concurrent)
    1288         152 :                                 PreventInTransactionBlock(isTopLevel,
    1289             :                                                           "ALTER TABLE ... DETACH CONCURRENTLY");
    1290             :                         }
    1291             :                     }
    1292             : 
    1293             :                     /*
    1294             :                      * Figure out lock mode, and acquire lock.  This also does
    1295             :                      * basic permissions checks, so that we won't wait for a
    1296             :                      * lock on (for example) a relation on which we have no
    1297             :                      * permissions.
    1298             :                      */
    1299       63724 :                     lockmode = AlterTableGetLockLevel(atstmt->cmds);
    1300       63724 :                     relid = AlterTableLookupRelation(atstmt, lockmode);
    1301             : 
    1302       63682 :                     if (OidIsValid(relid))
    1303             :                     {
    1304             :                         AlterTableUtilityContext atcontext;
    1305             : 
    1306             :                         /* Set up info needed for recursive callbacks ... */
    1307       63590 :                         atcontext.pstmt = pstmt;
    1308       63590 :                         atcontext.queryString = queryString;
    1309       63590 :                         atcontext.relid = relid;
    1310       63590 :                         atcontext.params = params;
    1311       63590 :                         atcontext.queryEnv = queryEnv;
    1312             : 
    1313             :                         /* ... ensure we have an event trigger context ... */
    1314       63590 :                         EventTriggerAlterTableStart(parsetree);
    1315       63590 :                         EventTriggerAlterTableRelid(relid);
    1316             : 
    1317             :                         /* ... and do it */
    1318       63590 :                         AlterTable(atstmt, lockmode, &atcontext);
    1319             : 
    1320             :                         /* done */
    1321       61894 :                         EventTriggerAlterTableEnd();
    1322             :                     }
    1323             :                     else
    1324          92 :                         ereport(NOTICE,
    1325             :                                 (errmsg("relation \"%s\" does not exist, skipping",
    1326             :                                         atstmt->relation->relname)));
    1327             :                 }
    1328             : 
    1329             :                 /* ALTER TABLE stashes commands internally */
    1330       61986 :                 commandCollected = true;
    1331       61986 :                 break;
    1332             : 
    1333         152 :             case T_AlterDomainStmt:
    1334             :                 {
    1335         152 :                     AlterDomainStmt *stmt = (AlterDomainStmt *) parsetree;
    1336             : 
    1337             :                     /*
    1338             :                      * Some or all of these functions are recursive to cover
    1339             :                      * inherited things, so permission checks are done there.
    1340             :                      */
    1341         152 :                     switch (stmt->subtype)
    1342             :                     {
    1343           8 :                         case 'T':   /* ALTER DOMAIN DEFAULT */
    1344             : 
    1345             :                             /*
    1346             :                              * Recursively alter column default for table and,
    1347             :                              * if requested, for descendants
    1348             :                              */
    1349             :                             address =
    1350           8 :                                 AlterDomainDefault(stmt->typeName,
    1351             :                                                    stmt->def);
    1352           8 :                             break;
    1353           8 :                         case 'N':   /* ALTER DOMAIN DROP NOT NULL */
    1354             :                             address =
    1355           8 :                                 AlterDomainNotNull(stmt->typeName,
    1356             :                                                    false);
    1357           8 :                             break;
    1358          16 :                         case 'O':   /* ALTER DOMAIN SET NOT NULL */
    1359             :                             address =
    1360          16 :                                 AlterDomainNotNull(stmt->typeName,
    1361             :                                                    true);
    1362           8 :                             break;
    1363          84 :                         case 'C':   /* ADD CONSTRAINT */
    1364             :                             address =
    1365          84 :                                 AlterDomainAddConstraint(stmt->typeName,
    1366             :                                                          stmt->def,
    1367             :                                                          &secondaryObject);
    1368          44 :                             break;
    1369          28 :                         case 'X':   /* DROP CONSTRAINT */
    1370             :                             address =
    1371          28 :                                 AlterDomainDropConstraint(stmt->typeName,
    1372          28 :                                                           stmt->name,
    1373             :                                                           stmt->behavior,
    1374          28 :                                                           stmt->missing_ok);
    1375          24 :                             break;
    1376           8 :                         case 'V':   /* VALIDATE CONSTRAINT */
    1377             :                             address =
    1378           8 :                                 AlterDomainValidateConstraint(stmt->typeName,
    1379           8 :                                                               stmt->name);
    1380           4 :                             break;
    1381           0 :                         default:    /* oops */
    1382           0 :                             elog(ERROR, "unrecognized alter domain type: %d",
    1383             :                                  (int) stmt->subtype);
    1384             :                             break;
    1385             :                     }
    1386             :                 }
    1387          96 :                 break;
    1388             : 
    1389             :                 /*
    1390             :                  * ************* object creation / destruction **************
    1391             :                  */
    1392       30012 :             case T_DefineStmt:
    1393             :                 {
    1394       30012 :                     DefineStmt *stmt = (DefineStmt *) parsetree;
    1395             : 
    1396       30012 :                     switch (stmt->kind)
    1397             :                     {
    1398         640 :                         case OBJECT_AGGREGATE:
    1399             :                             address =
    1400         640 :                                 DefineAggregate(pstate, stmt->defnames, stmt->args,
    1401         640 :                                                 stmt->oldstyle,
    1402             :                                                 stmt->definition,
    1403         640 :                                                 stmt->replace);
    1404         420 :                             break;
    1405        1328 :                         case OBJECT_OPERATOR:
    1406             :                             Assert(stmt->args == NIL);
    1407        1328 :                             address = DefineOperator(stmt->defnames,
    1408             :                                                      stmt->definition);
    1409        1280 :                             break;
    1410         286 :                         case OBJECT_TYPE:
    1411             :                             Assert(stmt->args == NIL);
    1412         286 :                             address = DefineType(pstate,
    1413             :                                                  stmt->defnames,
    1414             :                                                  stmt->definition);
    1415         266 :                             break;
    1416          28 :                         case OBJECT_TSPARSER:
    1417             :                             Assert(stmt->args == NIL);
    1418          28 :                             address = DefineTSParser(stmt->defnames,
    1419             :                                                      stmt->definition);
    1420          24 :                             break;
    1421       13602 :                         case OBJECT_TSDICTIONARY:
    1422             :                             Assert(stmt->args == NIL);
    1423       13602 :                             address = DefineTSDictionary(stmt->defnames,
    1424             :                                                          stmt->definition);
    1425       13586 :                             break;
    1426         514 :                         case OBJECT_TSTEMPLATE:
    1427             :                             Assert(stmt->args == NIL);
    1428         514 :                             address = DefineTSTemplate(stmt->defnames,
    1429             :                                                        stmt->definition);
    1430         510 :                             break;
    1431       13554 :                         case OBJECT_TSCONFIGURATION:
    1432             :                             Assert(stmt->args == NIL);
    1433       13554 :                             address = DefineTSConfiguration(stmt->defnames,
    1434             :                                                             stmt->definition,
    1435             :                                                             &secondaryObject);
    1436       13554 :                             break;
    1437          60 :                         case OBJECT_COLLATION:
    1438             :                             Assert(stmt->args == NIL);
    1439          60 :                             address = DefineCollation(pstate,
    1440             :                                                       stmt->defnames,
    1441             :                                                       stmt->definition,
    1442          60 :                                                       stmt->if_not_exists);
    1443          12 :                             break;
    1444           0 :                         default:
    1445           0 :                             elog(ERROR, "unrecognized define stmt type: %d",
    1446             :                                  (int) stmt->kind);
    1447             :                             break;
    1448             :                     }
    1449             :                 }
    1450       29652 :                 break;
    1451             : 
    1452        8556 :             case T_IndexStmt:   /* CREATE INDEX */
    1453             :                 {
    1454        8556 :                     IndexStmt  *stmt = (IndexStmt *) parsetree;
    1455             :                     Oid         relid;
    1456             :                     LOCKMODE    lockmode;
    1457             :                     bool        is_alter_table;
    1458             : 
    1459        8556 :                     if (stmt->concurrent)
    1460         136 :                         PreventInTransactionBlock(isTopLevel,
    1461             :                                                   "CREATE INDEX CONCURRENTLY");
    1462             : 
    1463             :                     /*
    1464             :                      * Look up the relation OID just once, right here at the
    1465             :                      * beginning, so that we don't end up repeating the name
    1466             :                      * lookup later and latching onto a different relation
    1467             :                      * partway through.  To avoid lock upgrade hazards, it's
    1468             :                      * important that we take the strongest lock that will
    1469             :                      * eventually be needed here, so the lockmode calculation
    1470             :                      * needs to match what DefineIndex() does.
    1471             :                      */
    1472       17096 :                     lockmode = stmt->concurrent ? ShareUpdateExclusiveLock
    1473        8548 :                         : ShareLock;
    1474             :                     relid =
    1475        8548 :                         RangeVarGetRelidExtended(stmt->relation, lockmode,
    1476             :                                                  0,
    1477             :                                                  RangeVarCallbackOwnsRelation,
    1478             :                                                  NULL);
    1479             : 
    1480             :                     /*
    1481             :                      * CREATE INDEX on partitioned tables (but not regular
    1482             :                      * inherited tables) recurses to partitions, so we must
    1483             :                      * acquire locks early to avoid deadlocks.
    1484             :                      *
    1485             :                      * We also take the opportunity to verify that all
    1486             :                      * partitions are something we can put an index on, to
    1487             :                      * avoid building some indexes only to fail later.
    1488             :                      */
    1489        8542 :                     if (stmt->relation->inh &&
    1490        8432 :                         get_rel_relkind(relid) == RELKIND_PARTITIONED_TABLE)
    1491             :                     {
    1492             :                         ListCell   *lc;
    1493         640 :                         List       *inheritors = NIL;
    1494             : 
    1495         640 :                         inheritors = find_all_inheritors(relid, lockmode, NULL);
    1496        1662 :                         foreach(lc, inheritors)
    1497             :                         {
    1498        1030 :                             char        relkind = get_rel_relkind(lfirst_oid(lc));
    1499             : 
    1500        1030 :                             if (relkind != RELKIND_RELATION &&
    1501         704 :                                 relkind != RELKIND_MATVIEW &&
    1502          12 :                                 relkind != RELKIND_PARTITIONED_TABLE &&
    1503             :                                 relkind != RELKIND_FOREIGN_TABLE)
    1504           0 :                                 elog(ERROR, "unexpected relkind \"%c\" on partition \"%s\"",
    1505             :                                      relkind, stmt->relation->relname);
    1506             : 
    1507        1030 :                             if (relkind == RELKIND_FOREIGN_TABLE &&
    1508          12 :                                 (stmt->unique || stmt->primary))
    1509           8 :                                 ereport(ERROR,
    1510             :                                         (errcode(ERRCODE_WRONG_OBJECT_TYPE),
    1511             :                                          errmsg("cannot create unique index on partitioned table \"%s\"",
    1512             :                                                 stmt->relation->relname),
    1513             :                                          errdetail("Table \"%s\" contains partitions that are foreign tables.",
    1514             :                                                    stmt->relation->relname)));
    1515             :                         }
    1516         632 :                         list_free(inheritors);
    1517             :                     }
    1518             : 
    1519             :                     /*
    1520             :                      * If the IndexStmt is already transformed, it must have
    1521             :                      * come from generateClonedIndexStmt, which in current
    1522             :                      * usage means it came from expandTableLikeClause rather
    1523             :                      * than from original parse analysis.  And that means we
    1524             :                      * must treat it like ALTER TABLE ADD INDEX, not CREATE.
    1525             :                      * (This is a bit grotty, but currently it doesn't seem
    1526             :                      * worth adding a separate bool field for the purpose.)
    1527             :                      */
    1528        8534 :                     is_alter_table = stmt->transformed;
    1529             : 
    1530             :                     /* Run parse analysis ... */
    1531        8534 :                     stmt = transformIndexStmt(relid, stmt, queryString);
    1532             : 
    1533             :                     /* ... and do it */
    1534        8530 :                     EventTriggerAlterTableStart(parsetree);
    1535             :                     address =
    1536        8530 :                         DefineIndex(relid,  /* OID of heap relation */
    1537             :                                     stmt,
    1538             :                                     InvalidOid, /* no predefined OID */
    1539             :                                     InvalidOid, /* no parent index */
    1540             :                                     InvalidOid, /* no parent constraint */
    1541             :                                     is_alter_table,
    1542             :                                     true,   /* check_rights */
    1543             :                                     true,   /* check_not_in_use */
    1544             :                                     false,  /* skip_build */
    1545             :                                     false); /* quiet */
    1546             : 
    1547             :                     /*
    1548             :                      * Add the CREATE INDEX node itself to stash right away;
    1549             :                      * if there were any commands stashed in the ALTER TABLE
    1550             :                      * code, we need them to appear after this one.
    1551             :                      */
    1552        8306 :                     EventTriggerCollectSimpleCommand(address, secondaryObject,
    1553             :                                                      parsetree);
    1554        8306 :                     commandCollected = true;
    1555        8306 :                     EventTriggerAlterTableEnd();
    1556             :                 }
    1557        8306 :                 break;
    1558             : 
    1559         712 :             case T_CreateExtensionStmt:
    1560         712 :                 address = CreateExtension(pstate, (CreateExtensionStmt *) parsetree);
    1561         694 :                 break;
    1562             : 
    1563          14 :             case T_AlterExtensionStmt:
    1564          14 :                 address = ExecAlterExtensionStmt(pstate, (AlterExtensionStmt *) parsetree);
    1565          14 :                 break;
    1566             : 
    1567         142 :             case T_AlterExtensionContentsStmt:
    1568         142 :                 address = ExecAlterExtensionContentsStmt((AlterExtensionContentsStmt *) parsetree,
    1569             :                                                          &secondaryObject);
    1570         140 :                 break;
    1571             : 
    1572         120 :             case T_CreateFdwStmt:
    1573         120 :                 address = CreateForeignDataWrapper(pstate, (CreateFdwStmt *) parsetree);
    1574          86 :                 break;
    1575             : 
    1576          84 :             case T_AlterFdwStmt:
    1577          84 :                 address = AlterForeignDataWrapper(pstate, (AlterFdwStmt *) parsetree);
    1578          32 :                 break;
    1579             : 
    1580         186 :             case T_CreateForeignServerStmt:
    1581         186 :                 address = CreateForeignServer((CreateForeignServerStmt *) parsetree);
    1582         152 :                 break;
    1583             : 
    1584         126 :             case T_AlterForeignServerStmt:
    1585         126 :                 address = AlterForeignServer((AlterForeignServerStmt *) parsetree);
    1586          94 :                 break;
    1587             : 
    1588         182 :             case T_CreateUserMappingStmt:
    1589         182 :                 address = CreateUserMapping((CreateUserMappingStmt *) parsetree);
    1590         136 :                 break;
    1591             : 
    1592          88 :             case T_AlterUserMappingStmt:
    1593          88 :                 address = AlterUserMapping((AlterUserMappingStmt *) parsetree);
    1594          50 :                 break;
    1595             : 
    1596         100 :             case T_DropUserMappingStmt:
    1597         100 :                 RemoveUserMapping((DropUserMappingStmt *) parsetree);
    1598             :                 /* no commands stashed for DROP */
    1599          74 :                 commandCollected = true;
    1600          74 :                 break;
    1601             : 
    1602          36 :             case T_ImportForeignSchemaStmt:
    1603          36 :                 ImportForeignSchema((ImportForeignSchemaStmt *) parsetree);
    1604             :                 /* commands are stashed inside ImportForeignSchema */
    1605          10 :                 commandCollected = true;
    1606          10 :                 break;
    1607             : 
    1608         456 :             case T_CompositeTypeStmt:   /* CREATE TYPE (composite) */
    1609             :                 {
    1610         456 :                     CompositeTypeStmt *stmt = (CompositeTypeStmt *) parsetree;
    1611             : 
    1612         456 :                     address = DefineCompositeType(stmt->typevar,
    1613             :                                                   stmt->coldeflist);
    1614             :                 }
    1615         448 :                 break;
    1616             : 
    1617         348 :             case T_CreateEnumStmt:  /* CREATE TYPE AS ENUM */
    1618         348 :                 address = DefineEnum((CreateEnumStmt *) parsetree);
    1619         348 :                 break;
    1620             : 
    1621          90 :             case T_CreateRangeStmt: /* CREATE TYPE AS RANGE */
    1622          90 :                 address = DefineRange(pstate, (CreateRangeStmt *) parsetree);
    1623          74 :                 break;
    1624             : 
    1625         280 :             case T_AlterEnumStmt:   /* ALTER TYPE (enum) */
    1626         280 :                 address = AlterEnum((AlterEnumStmt *) parsetree);
    1627         260 :                 break;
    1628             : 
    1629       68176 :             case T_ViewStmt:    /* CREATE VIEW */
    1630       68176 :                 EventTriggerAlterTableStart(parsetree);
    1631       68176 :                 address = DefineView((ViewStmt *) parsetree, queryString,
    1632             :                                      pstmt->stmt_location, pstmt->stmt_len);
    1633       68136 :                 EventTriggerCollectSimpleCommand(address, secondaryObject,
    1634             :                                                  parsetree);
    1635             :                 /* stashed internally */
    1636       68136 :                 commandCollected = true;
    1637       68136 :                 EventTriggerAlterTableEnd();
    1638       68136 :                 break;
    1639             : 
    1640       53732 :             case T_CreateFunctionStmt:  /* CREATE FUNCTION */
    1641       53732 :                 address = CreateFunction(pstate, (CreateFunctionStmt *) parsetree);
    1642       53404 :                 break;
    1643             : 
    1644         464 :             case T_AlterFunctionStmt:   /* ALTER FUNCTION */
    1645         464 :                 address = AlterFunction(pstate, (AlterFunctionStmt *) parsetree);
    1646         444 :                 break;
    1647             : 
    1648        1520 :             case T_RuleStmt:    /* CREATE RULE */
    1649        1520 :                 address = DefineRule((RuleStmt *) parsetree, queryString);
    1650        1478 :                 break;
    1651             : 
    1652        1136 :             case T_CreateSeqStmt:
    1653        1136 :                 address = DefineSequence(pstate, (CreateSeqStmt *) parsetree);
    1654        1068 :                 break;
    1655             : 
    1656         850 :             case T_AlterSeqStmt:
    1657         850 :                 address = AlterSequence(pstate, (AlterSeqStmt *) parsetree);
    1658         818 :                 break;
    1659             : 
    1660        1096 :             case T_CreateTableAsStmt:
    1661        1096 :                 address = ExecCreateTableAs(pstate, (CreateTableAsStmt *) parsetree,
    1662             :                                             params, queryEnv, qc);
    1663        1032 :                 break;
    1664             : 
    1665         132 :             case T_RefreshMatViewStmt:
    1666             : 
    1667             :                 /*
    1668             :                  * REFRESH CONCURRENTLY executes some DDL commands internally.
    1669             :                  * Inhibit DDL command collection here to avoid those commands
    1670             :                  * from showing up in the deparsed command queue.  The refresh
    1671             :                  * command itself is queued, which is enough.
    1672             :                  */
    1673         132 :                 EventTriggerInhibitCommandCollection();
    1674         132 :                 PG_TRY();
    1675             :                 {
    1676         132 :                     address = ExecRefreshMatView((RefreshMatViewStmt *) parsetree,
    1677             :                                                  queryString, params, qc);
    1678             :                 }
    1679          40 :                 PG_FINALLY();
    1680             :                 {
    1681         132 :                     EventTriggerUndoInhibitCommandCollection();
    1682             :                 }
    1683         132 :                 PG_END_TRY();
    1684          92 :                 break;
    1685             : 
    1686        2130 :             case T_CreateTrigStmt:
    1687        2130 :                 address = CreateTrigger((CreateTrigStmt *) parsetree,
    1688             :                                         queryString, InvalidOid, InvalidOid,
    1689             :                                         InvalidOid, InvalidOid, InvalidOid,
    1690             :                                         InvalidOid, NULL, false, false);
    1691        1988 :                 break;
    1692             : 
    1693         524 :             case T_CreatePLangStmt:
    1694         524 :                 address = CreateProceduralLanguage((CreatePLangStmt *) parsetree);
    1695         524 :                 break;
    1696             : 
    1697        2862 :             case T_CreateDomainStmt:
    1698        2862 :                 address = DefineDomain((CreateDomainStmt *) parsetree);
    1699        2854 :                 break;
    1700             : 
    1701          44 :             case T_CreateConversionStmt:
    1702          44 :                 address = CreateConversionCommand((CreateConversionStmt *) parsetree);
    1703          36 :                 break;
    1704             : 
    1705         206 :             case T_CreateCastStmt:
    1706         206 :                 address = CreateCast((CreateCastStmt *) parsetree);
    1707         202 :                 break;
    1708             : 
    1709         326 :             case T_CreateOpClassStmt:
    1710         326 :                 DefineOpClass((CreateOpClassStmt *) parsetree);
    1711             :                 /* command is stashed in DefineOpClass */
    1712         326 :                 commandCollected = true;
    1713         326 :                 break;
    1714             : 
    1715         104 :             case T_CreateOpFamilyStmt:
    1716         104 :                 address = DefineOpFamily((CreateOpFamilyStmt *) parsetree);
    1717         104 :                 break;
    1718             : 
    1719          48 :             case T_CreateTransformStmt:
    1720          48 :                 address = CreateTransform((CreateTransformStmt *) parsetree);
    1721          38 :                 break;
    1722             : 
    1723         356 :             case T_AlterOpFamilyStmt:
    1724         356 :                 AlterOpFamily((AlterOpFamilyStmt *) parsetree);
    1725             :                 /* commands are stashed in AlterOpFamily */
    1726         252 :                 commandCollected = true;
    1727         252 :                 break;
    1728             : 
    1729          34 :             case T_AlterTSDictionaryStmt:
    1730          34 :                 address = AlterTSDictionary((AlterTSDictionaryStmt *) parsetree);
    1731          28 :                 break;
    1732             : 
    1733       40668 :             case T_AlterTSConfigurationStmt:
    1734       40668 :                 AlterTSConfiguration((AlterTSConfigurationStmt *) parsetree);
    1735             : 
    1736             :                 /*
    1737             :                  * Commands are stashed in MakeConfigurationMapping and
    1738             :                  * DropConfigurationMapping, which are called from
    1739             :                  * AlterTSConfiguration
    1740             :                  */
    1741       40668 :                 commandCollected = true;
    1742       40668 :                 break;
    1743             : 
    1744          12 :             case T_AlterTableMoveAllStmt:
    1745          12 :                 AlterTableMoveAll((AlterTableMoveAllStmt *) parsetree);
    1746             :                 /* commands are stashed in AlterTableMoveAll */
    1747          12 :                 commandCollected = true;
    1748          12 :                 break;
    1749             : 
    1750       15116 :             case T_DropStmt:
    1751       15116 :                 ExecDropStmt((DropStmt *) parsetree, isTopLevel);
    1752             :                 /* no commands stashed for DROP */
    1753       14482 :                 commandCollected = true;
    1754       14482 :                 break;
    1755             : 
    1756         774 :             case T_RenameStmt:
    1757         774 :                 address = ExecRenameStmt((RenameStmt *) parsetree);
    1758         526 :                 break;
    1759             : 
    1760          46 :             case T_AlterObjectDependsStmt:
    1761             :                 address =
    1762          46 :                     ExecAlterObjectDependsStmt((AlterObjectDependsStmt *) parsetree,
    1763             :                                                &secondaryObject);
    1764          46 :                 break;
    1765             : 
    1766         250 :             case T_AlterObjectSchemaStmt:
    1767             :                 address =
    1768         250 :                     ExecAlterObjectSchemaStmt((AlterObjectSchemaStmt *) parsetree,
    1769             :                                               &secondaryObject);
    1770         164 :                 break;
    1771             : 
    1772        1630 :             case T_AlterOwnerStmt:
    1773        1630 :                 address = ExecAlterOwnerStmt((AlterOwnerStmt *) parsetree);
    1774        1474 :                 break;
    1775             : 
    1776         484 :             case T_AlterOperatorStmt:
    1777         484 :                 address = AlterOperator((AlterOperatorStmt *) parsetree);
    1778         452 :                 break;
    1779             : 
    1780          48 :             case T_AlterTypeStmt:
    1781          48 :                 address = AlterType((AlterTypeStmt *) parsetree);
    1782          40 :                 break;
    1783             : 
    1784       28706 :             case T_CommentStmt:
    1785       28706 :                 address = CommentObject((CommentStmt *) parsetree);
    1786       28604 :                 break;
    1787             : 
    1788       74084 :             case T_GrantStmt:
    1789       74084 :                 ExecuteGrantStmt((GrantStmt *) parsetree);
    1790             :                 /* commands are stashed in ExecGrantStmt_oids */
    1791       74004 :                 commandCollected = true;
    1792       74004 :                 break;
    1793             : 
    1794          90 :             case T_DropOwnedStmt:
    1795          90 :                 DropOwnedObjects((DropOwnedStmt *) parsetree);
    1796             :                 /* no commands stashed for DROP */
    1797          78 :                 commandCollected = true;
    1798          78 :                 break;
    1799             : 
    1800         110 :             case T_AlterDefaultPrivilegesStmt:
    1801         110 :                 ExecAlterDefaultPrivilegesStmt(pstate, (AlterDefaultPrivilegesStmt *) parsetree);
    1802         106 :                 EventTriggerCollectAlterDefPrivs((AlterDefaultPrivilegesStmt *) parsetree);
    1803         106 :                 commandCollected = true;
    1804         106 :                 break;
    1805             : 
    1806         404 :             case T_CreatePolicyStmt:    /* CREATE POLICY */
    1807         404 :                 address = CreatePolicy((CreatePolicyStmt *) parsetree);
    1808         394 :                 break;
    1809             : 
    1810          56 :             case T_AlterPolicyStmt: /* ALTER POLICY */
    1811          56 :                 address = AlterPolicy((AlterPolicyStmt *) parsetree);
    1812          48 :                 break;
    1813             : 
    1814          54 :             case T_SecLabelStmt:
    1815          54 :                 address = ExecSecLabelStmt((SecLabelStmt *) parsetree);
    1816          24 :                 break;
    1817             : 
    1818          46 :             case T_CreateAmStmt:
    1819          46 :                 address = CreateAccessMethod((CreateAmStmt *) parsetree);
    1820          30 :                 break;
    1821             : 
    1822         286 :             case T_CreatePublicationStmt:
    1823         286 :                 address = CreatePublication(pstate, (CreatePublicationStmt *) parsetree);
    1824         224 :                 break;
    1825             : 
    1826         208 :             case T_AlterPublicationStmt:
    1827         208 :                 AlterPublication(pstate, (AlterPublicationStmt *) parsetree);
    1828             : 
    1829             :                 /*
    1830             :                  * AlterPublication calls EventTriggerCollectSimpleCommand
    1831             :                  * directly
    1832             :                  */
    1833         136 :                 commandCollected = true;
    1834         136 :                 break;
    1835             : 
    1836         186 :             case T_CreateSubscriptionStmt:
    1837         186 :                 address = CreateSubscription(pstate,
    1838             :                                              (CreateSubscriptionStmt *) parsetree,
    1839             :                                              isTopLevel);
    1840         122 :                 break;
    1841             : 
    1842         186 :             case T_AlterSubscriptionStmt:
    1843         186 :                 address = AlterSubscription(pstate,
    1844             :                                             (AlterSubscriptionStmt *) parsetree,
    1845             :                                             isTopLevel);
    1846         118 :                 break;
    1847             : 
    1848          82 :             case T_DropSubscriptionStmt:
    1849          82 :                 DropSubscription((DropSubscriptionStmt *) parsetree, isTopLevel);
    1850             :                 /* no commands stashed for DROP */
    1851          74 :                 commandCollected = true;
    1852          74 :                 break;
    1853             : 
    1854         366 :             case T_CreateStatsStmt:
    1855             :                 {
    1856             :                     Oid         relid;
    1857         366 :                     CreateStatsStmt *stmt = (CreateStatsStmt *) parsetree;
    1858         366 :                     RangeVar   *rel = (RangeVar *) linitial(stmt->relations);
    1859             : 
    1860         366 :                     if (!IsA(rel, RangeVar))
    1861           0 :                         ereport(ERROR,
    1862             :                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
    1863             :                                  errmsg("only a single relation is allowed in CREATE STATISTICS")));
    1864             : 
    1865             :                     /*
    1866             :                      * CREATE STATISTICS will influence future execution plans
    1867             :                      * but does not interfere with currently executing plans.
    1868             :                      * So it should be enough to take ShareUpdateExclusiveLock
    1869             :                      * on relation, conflicting with ANALYZE and other DDL
    1870             :                      * that sets statistical information, but not with normal
    1871             :                      * queries.
    1872             :                      *
    1873             :                      * XXX RangeVarCallbackOwnsRelation not needed here, to
    1874             :                      * keep the same behavior as before.
    1875             :                      */
    1876         366 :                     relid = RangeVarGetRelid(rel, ShareUpdateExclusiveLock, false);
    1877             : 
    1878             :                     /* Run parse analysis ... */
    1879         362 :                     stmt = transformStatsStmt(relid, stmt, queryString);
    1880             : 
    1881         362 :                     address = CreateStatistics(stmt);
    1882             :                 }
    1883         310 :                 break;
    1884             : 
    1885          18 :             case T_AlterStatsStmt:
    1886          18 :                 address = AlterStatistics((AlterStatsStmt *) parsetree);
    1887          14 :                 break;
    1888             : 
    1889           0 :             case T_AlterCollationStmt:
    1890           0 :                 address = AlterCollation((AlterCollationStmt *) parsetree);
    1891           0 :                 break;
    1892             : 
    1893           0 :             default:
    1894           0 :                 elog(ERROR, "unrecognized node type: %d",
    1895             :                      (int) nodeTag(parsetree));
    1896             :                 break;
    1897             :         }
    1898             : 
    1899             :         /*
    1900             :          * Remember the object so that ddl_command_end event triggers have
    1901             :          * access to it.
    1902             :          */
    1903      421856 :         if (!commandCollected)
    1904      128976 :             EventTriggerCollectSimpleCommand(address, secondaryObject,
    1905             :                                              parsetree);
    1906             : 
    1907      421856 :         if (isCompleteQuery)
    1908             :         {
    1909      414562 :             EventTriggerSQLDrop(parsetree);
    1910      414550 :             EventTriggerDDLCommandEnd(parsetree);
    1911             :         }
    1912             :     }
    1913        6452 :     PG_FINALLY();
    1914             :     {
    1915      428296 :         if (needCleanup)
    1916        1060 :             EventTriggerEndCompleteQuery();
    1917             :     }
    1918      428296 :     PG_END_TRY();
    1919      421844 : }
    1920             : 
    1921             : /*
    1922             :  * ProcessUtilityForAlterTable
    1923             :  *      Recursive entry from ALTER TABLE
    1924             :  *
    1925             :  * ALTER TABLE sometimes generates subcommands such as CREATE INDEX.
    1926             :  * It calls this, not the main entry point ProcessUtility, to execute
    1927             :  * such subcommands.
    1928             :  *
    1929             :  * stmt: the utility command to execute
    1930             :  * context: opaque passthrough struct with the info we need
    1931             :  *
    1932             :  * It's caller's responsibility to do CommandCounterIncrement after
    1933             :  * calling this, if needed.
    1934             :  */
    1935             : void
    1936         280 : ProcessUtilityForAlterTable(Node *stmt, AlterTableUtilityContext *context)
    1937             : {
    1938             :     PlannedStmt *wrapper;
    1939             : 
    1940             :     /*
    1941             :      * For event triggers, we must "close" the current complex-command set,
    1942             :      * and start a new one afterwards; this is needed to ensure the ordering
    1943             :      * of command events is consistent with the way they were executed.
    1944             :      */
    1945         280 :     EventTriggerAlterTableEnd();
    1946             : 
    1947             :     /* Create a suitable wrapper */
    1948         280 :     wrapper = makeNode(PlannedStmt);
    1949         280 :     wrapper->commandType = CMD_UTILITY;
    1950         280 :     wrapper->canSetTag = false;
    1951         280 :     wrapper->utilityStmt = stmt;
    1952         280 :     wrapper->stmt_location = context->pstmt->stmt_location;
    1953         280 :     wrapper->stmt_len = context->pstmt->stmt_len;
    1954             : 
    1955         280 :     ProcessUtility(wrapper,
    1956             :                    context->queryString,
    1957             :                    false,
    1958             :                    PROCESS_UTILITY_SUBCOMMAND,
    1959             :                    context->params,
    1960             :                    context->queryEnv,
    1961             :                    None_Receiver,
    1962             :                    NULL);
    1963             : 
    1964         272 :     EventTriggerAlterTableStart(context->pstmt->utilityStmt);
    1965         272 :     EventTriggerAlterTableRelid(context->relid);
    1966         272 : }
    1967             : 
    1968             : /*
    1969             :  * Dispatch function for DropStmt
    1970             :  */
    1971             : static void
    1972       15182 : ExecDropStmt(DropStmt *stmt, bool isTopLevel)
    1973             : {
    1974       15182 :     switch (stmt->removeType)
    1975             :     {
    1976         482 :         case OBJECT_INDEX:
    1977         482 :             if (stmt->concurrent)
    1978         112 :                 PreventInTransactionBlock(isTopLevel,
    1979             :                                           "DROP INDEX CONCURRENTLY");
    1980             :             /* fall through */
    1981             : 
    1982             :         case OBJECT_TABLE:
    1983             :         case OBJECT_SEQUENCE:
    1984             :         case OBJECT_VIEW:
    1985             :         case OBJECT_MATVIEW:
    1986             :         case OBJECT_FOREIGN_TABLE:
    1987       10192 :             RemoveRelations(stmt);
    1988        9992 :             break;
    1989        4986 :         default:
    1990        4986 :             RemoveObjects(stmt);
    1991        4552 :             break;
    1992             :     }
    1993       14544 : }
    1994             : 
    1995             : 
    1996             : /*
    1997             :  * UtilityReturnsTuples
    1998             :  *      Return "true" if this utility statement will send output to the
    1999             :  *      destination.
    2000             :  *
    2001             :  * Generally, there should be a case here for each case in ProcessUtility
    2002             :  * where "dest" is passed on.
    2003             :  */
    2004             : bool
    2005      516958 : UtilityReturnsTuples(Node *parsetree)
    2006             : {
    2007      516958 :     switch (nodeTag(parsetree))
    2008             :     {
    2009         286 :         case T_CallStmt:
    2010             :             {
    2011         286 :                 CallStmt   *stmt = (CallStmt *) parsetree;
    2012             : 
    2013         286 :                 return (stmt->funcexpr->funcresulttype == RECORDOID);
    2014             :             }
    2015        5138 :         case T_FetchStmt:
    2016             :             {
    2017        5138 :                 FetchStmt  *stmt = (FetchStmt *) parsetree;
    2018             :                 Portal      portal;
    2019             : 
    2020        5138 :                 if (stmt->ismove)
    2021          88 :                     return false;
    2022        5050 :                 portal = GetPortalByName(stmt->portalname);
    2023        5050 :                 if (!PortalIsValid(portal))
    2024          26 :                     return false;   /* not our business to raise error */
    2025        5024 :                 return portal->tupDesc ? true : false;
    2026             :             }
    2027             : 
    2028         838 :         case T_ExecuteStmt:
    2029             :             {
    2030         838 :                 ExecuteStmt *stmt = (ExecuteStmt *) parsetree;
    2031             :                 PreparedStatement *entry;
    2032             : 
    2033         838 :                 entry = FetchPreparedStatement(stmt->name, false);
    2034         838 :                 if (!entry)
    2035           0 :                     return false;   /* not our business to raise error */
    2036         838 :                 if (entry->plansource->resultDesc)
    2037         746 :                     return true;
    2038          92 :                 return false;
    2039             :             }
    2040             : 
    2041       18532 :         case T_ExplainStmt:
    2042       18532 :             return true;
    2043             : 
    2044         528 :         case T_VariableShowStmt:
    2045         528 :             return true;
    2046             : 
    2047      491636 :         default:
    2048      491636 :             return false;
    2049             :     }
    2050             : }
    2051             : 
    2052             : /*
    2053             :  * UtilityTupleDescriptor
    2054             :  *      Fetch the actual output tuple descriptor for a utility statement
    2055             :  *      for which UtilityReturnsTuples() previously returned "true".
    2056             :  *
    2057             :  * The returned descriptor is created in (or copied into) the current memory
    2058             :  * context.
    2059             :  */
    2060             : TupleDesc
    2061       24956 : UtilityTupleDescriptor(Node *parsetree)
    2062             : {
    2063       24956 :     switch (nodeTag(parsetree))
    2064             :     {
    2065         126 :         case T_CallStmt:
    2066         126 :             return CallStmtResultDesc((CallStmt *) parsetree);
    2067             : 
    2068        5024 :         case T_FetchStmt:
    2069             :             {
    2070        5024 :                 FetchStmt  *stmt = (FetchStmt *) parsetree;
    2071             :                 Portal      portal;
    2072             : 
    2073        5024 :                 if (stmt->ismove)
    2074           0 :                     return NULL;
    2075        5024 :                 portal = GetPortalByName(stmt->portalname);
    2076        5024 :                 if (!PortalIsValid(portal))
    2077           0 :                     return NULL;    /* not our business to raise error */
    2078        5024 :                 return CreateTupleDescCopy(portal->tupDesc);
    2079             :             }
    2080             : 
    2081         746 :         case T_ExecuteStmt:
    2082             :             {
    2083         746 :                 ExecuteStmt *stmt = (ExecuteStmt *) parsetree;
    2084             :                 PreparedStatement *entry;
    2085             : 
    2086         746 :                 entry = FetchPreparedStatement(stmt->name, false);
    2087         746 :                 if (!entry)
    2088           0 :                     return NULL;    /* not our business to raise error */
    2089         746 :                 return FetchPreparedStatementResultDesc(entry);
    2090             :             }
    2091             : 
    2092       18532 :         case T_ExplainStmt:
    2093       18532 :             return ExplainResultDesc((ExplainStmt *) parsetree);
    2094             : 
    2095         528 :         case T_VariableShowStmt:
    2096             :             {
    2097         528 :                 VariableShowStmt *n = (VariableShowStmt *) parsetree;
    2098             : 
    2099         528 :                 return GetPGVariableResultDesc(n->name);
    2100             :             }
    2101             : 
    2102           0 :         default:
    2103           0 :             return NULL;
    2104             :     }
    2105             : }
    2106             : 
    2107             : 
    2108             : /*
    2109             :  * QueryReturnsTuples
    2110             :  *      Return "true" if this Query will send output to the destination.
    2111             :  */
    2112             : #ifdef NOT_USED
    2113             : bool
    2114             : QueryReturnsTuples(Query *parsetree)
    2115             : {
    2116             :     switch (parsetree->commandType)
    2117             :     {
    2118             :         case CMD_SELECT:
    2119             :             /* returns tuples */
    2120             :             return true;
    2121             :         case CMD_INSERT:
    2122             :         case CMD_UPDATE:
    2123             :         case CMD_DELETE:
    2124             :             /* the forms with RETURNING return tuples */
    2125             :             if (parsetree->returningList)
    2126             :                 return true;
    2127             :             break;
    2128             :         case CMD_UTILITY:
    2129             :             return UtilityReturnsTuples(parsetree->utilityStmt);
    2130             :         case CMD_UNKNOWN:
    2131             :         case CMD_NOTHING:
    2132             :             /* probably shouldn't get here */
    2133             :             break;
    2134             :     }
    2135             :     return false;               /* default */
    2136             : }
    2137             : #endif
    2138             : 
    2139             : 
    2140             : /*
    2141             :  * UtilityContainsQuery
    2142             :  *      Return the contained Query, or NULL if there is none
    2143             :  *
    2144             :  * Certain utility statements, such as EXPLAIN, contain a plannable Query.
    2145             :  * This function encapsulates knowledge of exactly which ones do.
    2146             :  * We assume it is invoked only on already-parse-analyzed statements
    2147             :  * (else the contained parsetree isn't a Query yet).
    2148             :  *
    2149             :  * In some cases (currently, only EXPLAIN of CREATE TABLE AS/SELECT INTO and
    2150             :  * CREATE MATERIALIZED VIEW), potentially Query-containing utility statements
    2151             :  * can be nested.  This function will drill down to a non-utility Query, or
    2152             :  * return NULL if none.
    2153             :  */
    2154             : Query *
    2155       32650 : UtilityContainsQuery(Node *parsetree)
    2156             : {
    2157             :     Query      *qry;
    2158             : 
    2159       32650 :     switch (nodeTag(parsetree))
    2160             :     {
    2161        3004 :         case T_DeclareCursorStmt:
    2162        3004 :             qry = castNode(Query, ((DeclareCursorStmt *) parsetree)->query);
    2163        3004 :             if (qry->commandType == CMD_UTILITY)
    2164           0 :                 return UtilityContainsQuery(qry->utilityStmt);
    2165        3004 :             return qry;
    2166             : 
    2167       10256 :         case T_ExplainStmt:
    2168       10256 :             qry = castNode(Query, ((ExplainStmt *) parsetree)->query);
    2169       10256 :             if (qry->commandType == CMD_UTILITY)
    2170          40 :                 return UtilityContainsQuery(qry->utilityStmt);
    2171       10216 :             return qry;
    2172             : 
    2173          44 :         case T_CreateTableAsStmt:
    2174          44 :             qry = castNode(Query, ((CreateTableAsStmt *) parsetree)->query);
    2175          44 :             if (qry->commandType == CMD_UTILITY)
    2176           0 :                 return UtilityContainsQuery(qry->utilityStmt);
    2177          44 :             return qry;
    2178             : 
    2179       19346 :         default:
    2180       19346 :             return NULL;
    2181             :     }
    2182             : }
    2183             : 
    2184             : 
    2185             : /*
    2186             :  * AlterObjectTypeCommandTag
    2187             :  *      helper function for CreateCommandTag
    2188             :  *
    2189             :  * This covers most cases where ALTER is used with an ObjectType enum.
    2190             :  */
    2191             : static CommandTag
    2192       65230 : AlterObjectTypeCommandTag(ObjectType objtype)
    2193             : {
    2194             :     CommandTag  tag;
    2195             : 
    2196       65230 :     switch (objtype)
    2197             :     {
    2198         176 :         case OBJECT_AGGREGATE:
    2199         176 :             tag = CMDTAG_ALTER_AGGREGATE;
    2200         176 :             break;
    2201          16 :         case OBJECT_ATTRIBUTE:
    2202          16 :             tag = CMDTAG_ALTER_TYPE;
    2203          16 :             break;
    2204           0 :         case OBJECT_CAST:
    2205           0 :             tag = CMDTAG_ALTER_CAST;
    2206           0 :             break;
    2207           0 :         case OBJECT_COLLATION:
    2208           0 :             tag = CMDTAG_ALTER_COLLATION;
    2209           0 :             break;
    2210           0 :         case OBJECT_COLUMN:
    2211           0 :             tag = CMDTAG_ALTER_TABLE;
    2212           0 :             break;
    2213          48 :         case OBJECT_CONVERSION:
    2214          48 :             tag = CMDTAG_ALTER_CONVERSION;
    2215          48 :             break;
    2216          34 :         case OBJECT_DATABASE:
    2217          34 :             tag = CMDTAG_ALTER_DATABASE;
    2218          34 :             break;
    2219          46 :         case OBJECT_DOMAIN:
    2220             :         case OBJECT_DOMCONSTRAINT:
    2221          46 :             tag = CMDTAG_ALTER_DOMAIN;
    2222          46 :             break;
    2223           0 :         case OBJECT_EXTENSION:
    2224           0 :             tag = CMDTAG_ALTER_EXTENSION;
    2225           0 :             break;
    2226          30 :         case OBJECT_FDW:
    2227          30 :             tag = CMDTAG_ALTER_FOREIGN_DATA_WRAPPER;
    2228          30 :             break;
    2229          62 :         case OBJECT_FOREIGN_SERVER:
    2230          62 :             tag = CMDTAG_ALTER_SERVER;
    2231          62 :             break;
    2232         354 :         case OBJECT_FOREIGN_TABLE:
    2233         354 :             tag = CMDTAG_ALTER_FOREIGN_TABLE;
    2234         354 :             break;
    2235         596 :         case OBJECT_FUNCTION:
    2236         596 :             tag = CMDTAG_ALTER_FUNCTION;
    2237         596 :             break;
    2238         500 :         case OBJECT_INDEX:
    2239         500 :             tag = CMDTAG_ALTER_INDEX;
    2240         500 :             break;
    2241          32 :         case OBJECT_LANGUAGE:
    2242          32 :             tag = CMDTAG_ALTER_LANGUAGE;
    2243          32 :             break;
    2244          10 :         case OBJECT_LARGEOBJECT:
    2245          10 :             tag = CMDTAG_ALTER_LARGE_OBJECT;
    2246          10 :             break;
    2247          68 :         case OBJECT_OPCLASS:
    2248          68 :             tag = CMDTAG_ALTER_OPERATOR_CLASS;
    2249          68 :             break;
    2250          50 :         case OBJECT_OPERATOR:
    2251          50 :             tag = CMDTAG_ALTER_OPERATOR;
    2252          50 :             break;
    2253          76 :         case OBJECT_OPFAMILY:
    2254          76 :             tag = CMDTAG_ALTER_OPERATOR_FAMILY;
    2255          76 :             break;
    2256          20 :         case OBJECT_POLICY:
    2257          20 :             tag = CMDTAG_ALTER_POLICY;
    2258          20 :             break;
    2259          18 :         case OBJECT_PROCEDURE:
    2260          18 :             tag = CMDTAG_ALTER_PROCEDURE;
    2261          18 :             break;
    2262          12 :         case OBJECT_ROLE:
    2263          12 :             tag = CMDTAG_ALTER_ROLE;
    2264          12 :             break;
    2265          16 :         case OBJECT_ROUTINE:
    2266          16 :             tag = CMDTAG_ALTER_ROUTINE;
    2267          16 :             break;
    2268          24 :         case OBJECT_RULE:
    2269          24 :             tag = CMDTAG_ALTER_RULE;
    2270          24 :             break;
    2271          46 :         case OBJECT_SCHEMA:
    2272          46 :             tag = CMDTAG_ALTER_SCHEMA;
    2273          46 :             break;
    2274          16 :         case OBJECT_SEQUENCE:
    2275          16 :             tag = CMDTAG_ALTER_SEQUENCE;
    2276          16 :             break;
    2277       62312 :         case OBJECT_TABLE:
    2278             :         case OBJECT_TABCONSTRAINT:
    2279       62312 :             tag = CMDTAG_ALTER_TABLE;
    2280       62312 :             break;
    2281           8 :         case OBJECT_TABLESPACE:
    2282           8 :             tag = CMDTAG_ALTER_TABLESPACE;
    2283           8 :             break;
    2284          38 :         case OBJECT_TRIGGER:
    2285          38 :             tag = CMDTAG_ALTER_TRIGGER;
    2286          38 :             break;
    2287          16 :         case OBJECT_EVENT_TRIGGER:
    2288          16 :             tag = CMDTAG_ALTER_EVENT_TRIGGER;
    2289          16 :             break;
    2290          56 :         case OBJECT_TSCONFIGURATION:
    2291          56 :             tag = CMDTAG_ALTER_TEXT_SEARCH_CONFIGURATION;
    2292          56 :             break;
    2293          66 :         case OBJECT_TSDICTIONARY:
    2294          66 :             tag = CMDTAG_ALTER_TEXT_SEARCH_DICTIONARY;
    2295          66 :             break;
    2296          20 :         case OBJECT_TSPARSER:
    2297          20 :             tag = CMDTAG_ALTER_TEXT_SEARCH_PARSER;
    2298          20 :             break;
    2299          20 :         case OBJECT_TSTEMPLATE:
    2300          20 :             tag = CMDTAG_ALTER_TEXT_SEARCH_TEMPLATE;
    2301          20 :             break;
    2302         234 :         case OBJECT_TYPE:
    2303         234 :             tag = CMDTAG_ALTER_TYPE;
    2304         234 :             break;
    2305          96 :         case OBJECT_VIEW:
    2306          96 :             tag = CMDTAG_ALTER_VIEW;
    2307          96 :             break;
    2308          20 :         case OBJECT_MATVIEW:
    2309          20 :             tag = CMDTAG_ALTER_MATERIALIZED_VIEW;
    2310          20 :             break;
    2311          16 :         case OBJECT_PUBLICATION:
    2312          16 :             tag = CMDTAG_ALTER_PUBLICATION;
    2313          16 :             break;
    2314          22 :         case OBJECT_SUBSCRIPTION:
    2315          22 :             tag = CMDTAG_ALTER_SUBSCRIPTION;
    2316          22 :             break;
    2317          56 :         case OBJECT_STATISTIC_EXT:
    2318          56 :             tag = CMDTAG_ALTER_STATISTICS;
    2319          56 :             break;
    2320           0 :         default:
    2321           0 :             tag = CMDTAG_UNKNOWN;
    2322           0 :             break;
    2323             :     }
    2324             : 
    2325       65230 :     return tag;
    2326             : }
    2327             : 
    2328             : /*
    2329             :  * CreateCommandTag
    2330             :  *      utility to get a CommandTag for the command operation,
    2331             :  *      given either a raw (un-analyzed) parsetree, an analyzed Query,
    2332             :  *      or a PlannedStmt.
    2333             :  *
    2334             :  * This must handle all command types, but since the vast majority
    2335             :  * of 'em are utility commands, it seems sensible to keep it here.
    2336             :  */
    2337             : CommandTag
    2338      800384 : CreateCommandTag(Node *parsetree)
    2339             : {
    2340             :     CommandTag  tag;
    2341             : 
    2342      800384 :     switch (nodeTag(parsetree))
    2343             :     {
    2344             :             /* recurse if we're given a RawStmt */
    2345           0 :         case T_RawStmt:
    2346           0 :             tag = CreateCommandTag(((RawStmt *) parsetree)->stmt);
    2347           0 :             break;
    2348             : 
    2349             :             /* raw plannable queries */
    2350       62226 :         case T_InsertStmt:
    2351       62226 :             tag = CMDTAG_INSERT;
    2352       62226 :             break;
    2353             : 
    2354        2476 :         case T_DeleteStmt:
    2355        2476 :             tag = CMDTAG_DELETE;
    2356        2476 :             break;
    2357             : 
    2358       10516 :         case T_UpdateStmt:
    2359       10516 :             tag = CMDTAG_UPDATE;
    2360       10516 :             break;
    2361             : 
    2362      210992 :         case T_SelectStmt:
    2363      210992 :             tag = CMDTAG_SELECT;
    2364      210992 :             break;
    2365             : 
    2366        2902 :         case T_PLAssignStmt:
    2367        2902 :             tag = CMDTAG_SELECT;
    2368        2902 :             break;
    2369             : 
    2370             :             /* utility statements --- same whether raw or cooked */
    2371       26816 :         case T_TransactionStmt:
    2372             :             {
    2373       26816 :                 TransactionStmt *stmt = (TransactionStmt *) parsetree;
    2374             : 
    2375       26816 :                 switch (stmt->kind)
    2376             :                 {
    2377       10810 :                     case TRANS_STMT_BEGIN:
    2378       10810 :                         tag = CMDTAG_BEGIN;
    2379       10810 :                         break;
    2380             : 
    2381        1276 :                     case TRANS_STMT_START:
    2382        1276 :                         tag = CMDTAG_START_TRANSACTION;
    2383        1276 :                         break;
    2384             : 
    2385        9926 :                     case TRANS_STMT_COMMIT:
    2386        9926 :                         tag = CMDTAG_COMMIT;
    2387        9926 :                         break;
    2388             : 
    2389        1716 :                     case TRANS_STMT_ROLLBACK:
    2390             :                     case TRANS_STMT_ROLLBACK_TO:
    2391        1716 :                         tag = CMDTAG_ROLLBACK;
    2392        1716 :                         break;
    2393             : 
    2394        1556 :                     case TRANS_STMT_SAVEPOINT:
    2395        1556 :                         tag = CMDTAG_SAVEPOINT;
    2396        1556 :                         break;
    2397             : 
    2398         180 :                     case TRANS_STMT_RELEASE:
    2399         180 :                         tag = CMDTAG_RELEASE;
    2400         180 :                         break;
    2401             : 
    2402         706 :                     case TRANS_STMT_PREPARE:
    2403         706 :                         tag = CMDTAG_PREPARE_TRANSACTION;
    2404         706 :                         break;
    2405             : 
    2406         604 :                     case TRANS_STMT_COMMIT_PREPARED:
    2407         604 :                         tag = CMDTAG_COMMIT_PREPARED;
    2408         604 :                         break;
    2409             : 
    2410          42 :                     case TRANS_STMT_ROLLBACK_PREPARED:
    2411          42 :                         tag = CMDTAG_ROLLBACK_PREPARED;
    2412          42 :                         break;
    2413             : 
    2414           0 :                     default:
    2415           0 :                         tag = CMDTAG_UNKNOWN;
    2416           0 :                         break;
    2417             :                 }
    2418             :             }
    2419       26816 :             break;
    2420             : 
    2421        2480 :         case T_DeclareCursorStmt:
    2422        2480 :             tag = CMDTAG_DECLARE_CURSOR;
    2423        2480 :             break;
    2424             : 
    2425        2040 :         case T_ClosePortalStmt:
    2426             :             {
    2427        2040 :                 ClosePortalStmt *stmt = (ClosePortalStmt *) parsetree;
    2428             : 
    2429        2040 :                 if (stmt->portalname == NULL)
    2430           8 :                     tag = CMDTAG_CLOSE_CURSOR_ALL;
    2431             :                 else
    2432        2032 :                     tag = CMDTAG_CLOSE_CURSOR;
    2433             :             }
    2434        2040 :             break;
    2435             : 
    2436        5354 :         case T_FetchStmt:
    2437             :             {
    2438        5354 :                 FetchStmt  *stmt = (FetchStmt *) parsetree;
    2439             : 
    2440        5354 :                 tag = (stmt->ismove) ? CMDTAG_MOVE : CMDTAG_FETCH;
    2441             :             }
    2442        5354 :             break;
    2443             : 
    2444        2866 :         case T_CreateDomainStmt:
    2445        2866 :             tag = CMDTAG_CREATE_DOMAIN;
    2446        2866 :             break;
    2447             : 
    2448         982 :         case T_CreateSchemaStmt:
    2449         982 :             tag = CMDTAG_CREATE_SCHEMA;
    2450         982 :             break;
    2451             : 
    2452       23988 :         case T_CreateStmt:
    2453       23988 :             tag = CMDTAG_CREATE_TABLE;
    2454       23988 :             break;
    2455             : 
    2456          40 :         case T_CreateTableSpaceStmt:
    2457          40 :             tag = CMDTAG_CREATE_TABLESPACE;
    2458          40 :             break;
    2459             : 
    2460          24 :         case T_DropTableSpaceStmt:
    2461          24 :             tag = CMDTAG_DROP_TABLESPACE;
    2462          24 :             break;
    2463             : 
    2464          16 :         case T_AlterTableSpaceOptionsStmt:
    2465          16 :             tag = CMDTAG_ALTER_TABLESPACE;
    2466          16 :             break;
    2467             : 
    2468         718 :         case T_CreateExtensionStmt:
    2469         718 :             tag = CMDTAG_CREATE_EXTENSION;
    2470         718 :             break;
    2471             : 
    2472          14 :         case T_AlterExtensionStmt:
    2473          14 :             tag = CMDTAG_ALTER_EXTENSION;
    2474          14 :             break;
    2475             : 
    2476         126 :         case T_AlterExtensionContentsStmt:
    2477         126 :             tag = CMDTAG_ALTER_EXTENSION;
    2478         126 :             break;
    2479             : 
    2480         124 :         case T_CreateFdwStmt:
    2481         124 :             tag = CMDTAG_CREATE_FOREIGN_DATA_WRAPPER;
    2482         124 :             break;
    2483             : 
    2484          84 :         case T_AlterFdwStmt:
    2485          84 :             tag = CMDTAG_ALTER_FOREIGN_DATA_WRAPPER;
    2486          84 :             break;
    2487             : 
    2488         196 :         case T_CreateForeignServerStmt:
    2489         196 :             tag = CMDTAG_CREATE_SERVER;
    2490         196 :             break;
    2491             : 
    2492         126 :         case T_AlterForeignServerStmt:
    2493         126 :             tag = CMDTAG_ALTER_SERVER;
    2494         126 :             break;
    2495             : 
    2496         192 :         case T_CreateUserMappingStmt:
    2497         192 :             tag = CMDTAG_CREATE_USER_MAPPING;
    2498         192 :             break;
    2499             : 
    2500          88 :         case T_AlterUserMappingStmt:
    2501          88 :             tag = CMDTAG_ALTER_USER_MAPPING;
    2502          88 :             break;
    2503             : 
    2504         100 :         case T_DropUserMappingStmt:
    2505         100 :             tag = CMDTAG_DROP_USER_MAPPING;
    2506         100 :             break;
    2507             : 
    2508         300 :         case T_CreateForeignTableStmt:
    2509         300 :             tag = CMDTAG_CREATE_FOREIGN_TABLE;
    2510         300 :             break;
    2511             : 
    2512          36 :         case T_ImportForeignSchemaStmt:
    2513          36 :             tag = CMDTAG_IMPORT_FOREIGN_SCHEMA;
    2514          36 :             break;
    2515             : 
    2516       14852 :         case T_DropStmt:
    2517       14852 :             switch (((DropStmt *) parsetree)->removeType)
    2518             :             {
    2519        9030 :                 case OBJECT_TABLE:
    2520        9030 :                     tag = CMDTAG_DROP_TABLE;
    2521        9030 :                     break;
    2522         114 :                 case OBJECT_SEQUENCE:
    2523         114 :                     tag = CMDTAG_DROP_SEQUENCE;
    2524         114 :                     break;
    2525         452 :                 case OBJECT_VIEW:
    2526         452 :                     tag = CMDTAG_DROP_VIEW;
    2527         452 :                     break;
    2528          48 :                 case OBJECT_MATVIEW:
    2529          48 :                     tag = CMDTAG_DROP_MATERIALIZED_VIEW;
    2530          48 :                     break;
    2531         490 :                 case OBJECT_INDEX:
    2532         490 :                     tag = CMDTAG_DROP_INDEX;
    2533         490 :                     break;
    2534         324 :                 case OBJECT_TYPE:
    2535         324 :                     tag = CMDTAG_DROP_TYPE;
    2536         324 :                     break;
    2537         240 :                 case OBJECT_DOMAIN:
    2538         240 :                     tag = CMDTAG_DROP_DOMAIN;
    2539         240 :                     break;
    2540          18 :                 case OBJECT_COLLATION:
    2541          18 :                     tag = CMDTAG_DROP_COLLATION;
    2542          18 :                     break;
    2543          24 :                 case OBJECT_CONVERSION:
    2544          24 :                     tag = CMDTAG_DROP_CONVERSION;
    2545          24 :                     break;
    2546         282 :                 case OBJECT_SCHEMA:
    2547         282 :                     tag = CMDTAG_DROP_SCHEMA;
    2548         282 :                     break;
    2549          12 :                 case OBJECT_TSPARSER:
    2550          12 :                     tag = CMDTAG_DROP_TEXT_SEARCH_PARSER;
    2551          12 :                     break;
    2552          16 :                 case OBJECT_TSDICTIONARY:
    2553          16 :                     tag = CMDTAG_DROP_TEXT_SEARCH_DICTIONARY;
    2554          16 :                     break;
    2555          12 :                 case OBJECT_TSTEMPLATE:
    2556          12 :                     tag = CMDTAG_DROP_TEXT_SEARCH_TEMPLATE;
    2557          12 :                     break;
    2558          16 :                 case OBJECT_TSCONFIGURATION:
    2559          16 :                     tag = CMDTAG_DROP_TEXT_SEARCH_CONFIGURATION;
    2560          16 :                     break;
    2561         100 :                 case OBJECT_FOREIGN_TABLE:
    2562         100 :                     tag = CMDTAG_DROP_FOREIGN_TABLE;
    2563         100 :                     break;
    2564          88 :                 case OBJECT_EXTENSION:
    2565          88 :                     tag = CMDTAG_DROP_EXTENSION;
    2566          88 :                     break;
    2567        1860 :                 case OBJECT_FUNCTION:
    2568        1860 :                     tag = CMDTAG_DROP_FUNCTION;
    2569        1860 :                     break;
    2570         104 :                 case OBJECT_PROCEDURE:
    2571         104 :                     tag = CMDTAG_DROP_PROCEDURE;
    2572         104 :                     break;
    2573          20 :                 case OBJECT_ROUTINE:
    2574          20 :                     tag = CMDTAG_DROP_ROUTINE;
    2575          20 :                     break;
    2576          70 :                 case OBJECT_AGGREGATE:
    2577          70 :                     tag = CMDTAG_DROP_AGGREGATE;
    2578          70 :                     break;
    2579          94 :                 case OBJECT_OPERATOR:
    2580          94 :                     tag = CMDTAG_DROP_OPERATOR;
    2581          94 :                     break;
    2582          18 :                 case OBJECT_LANGUAGE:
    2583          18 :                     tag = CMDTAG_DROP_LANGUAGE;
    2584          18 :                     break;
    2585          36 :                 case OBJECT_CAST:
    2586          36 :                     tag = CMDTAG_DROP_CAST;
    2587          36 :                     break;
    2588         530 :                 case OBJECT_TRIGGER:
    2589         530 :                     tag = CMDTAG_DROP_TRIGGER;
    2590         530 :                     break;
    2591          66 :                 case OBJECT_EVENT_TRIGGER:
    2592          66 :                     tag = CMDTAG_DROP_EVENT_TRIGGER;
    2593          66 :                     break;
    2594         134 :                 case OBJECT_RULE:
    2595         134 :                     tag = CMDTAG_DROP_RULE;
    2596         134 :                     break;
    2597          92 :                 case OBJECT_FDW:
    2598          92 :                     tag = CMDTAG_DROP_FOREIGN_DATA_WRAPPER;
    2599          92 :                     break;
    2600          80 :                 case OBJECT_FOREIGN_SERVER:
    2601          80 :                     tag = CMDTAG_DROP_SERVER;
    2602          80 :                     break;
    2603          38 :                 case OBJECT_OPCLASS:
    2604          38 :                     tag = CMDTAG_DROP_OPERATOR_CLASS;
    2605          38 :                     break;
    2606          86 :                 case OBJECT_OPFAMILY:
    2607          86 :                     tag = CMDTAG_DROP_OPERATOR_FAMILY;
    2608          86 :                     break;
    2609         102 :                 case OBJECT_POLICY:
    2610         102 :                     tag = CMDTAG_DROP_POLICY;
    2611         102 :                     break;
    2612          16 :                 case OBJECT_TRANSFORM:
    2613          16 :                     tag = CMDTAG_DROP_TRANSFORM;
    2614          16 :                     break;
    2615          24 :                 case OBJECT_ACCESS_METHOD:
    2616          24 :                     tag = CMDTAG_DROP_ACCESS_METHOD;
    2617          24 :                     break;
    2618         116 :                 case OBJECT_PUBLICATION:
    2619         116 :                     tag = CMDTAG_DROP_PUBLICATION;
    2620         116 :                     break;
    2621         100 :                 case OBJECT_STATISTIC_EXT:
    2622         100 :                     tag = CMDTAG_DROP_STATISTICS;
    2623         100 :                     break;
    2624           0 :                 default:
    2625           0 :                     tag = CMDTAG_UNKNOWN;
    2626             :             }
    2627       14852 :             break;
    2628             : 
    2629         924 :         case T_TruncateStmt:
    2630         924 :             tag = CMDTAG_TRUNCATE_TABLE;
    2631         924 :             break;
    2632             : 
    2633       29044 :         case T_CommentStmt:
    2634       29044 :             tag = CMDTAG_COMMENT;
    2635       29044 :             break;
    2636             : 
    2637          88 :         case T_SecLabelStmt:
    2638          88 :             tag = CMDTAG_SECURITY_LABEL;
    2639          88 :             break;
    2640             : 
    2641        4950 :         case T_CopyStmt:
    2642        4950 :             tag = CMDTAG_COPY;
    2643        4950 :             break;
    2644             : 
    2645         816 :         case T_RenameStmt:
    2646             : 
    2647             :             /*
    2648             :              * When the column is renamed, the command tag is created from its
    2649             :              * relation type
    2650             :              */
    2651         816 :             tag = AlterObjectTypeCommandTag(((RenameStmt *) parsetree)->renameType == OBJECT_COLUMN ?
    2652             :                                             ((RenameStmt *) parsetree)->relationType :
    2653             :                                             ((RenameStmt *) parsetree)->renameType);
    2654         816 :             break;
    2655             : 
    2656          46 :         case T_AlterObjectDependsStmt:
    2657          46 :             tag = AlterObjectTypeCommandTag(((AlterObjectDependsStmt *) parsetree)->objectType);
    2658          46 :             break;
    2659             : 
    2660         262 :         case T_AlterObjectSchemaStmt:
    2661         262 :             tag = AlterObjectTypeCommandTag(((AlterObjectSchemaStmt *) parsetree)->objectType);
    2662         262 :             break;
    2663             : 
    2664        1178 :         case T_AlterOwnerStmt:
    2665        1178 :             tag = AlterObjectTypeCommandTag(((AlterOwnerStmt *) parsetree)->objectType);
    2666        1178 :             break;
    2667             : 
    2668          12 :         case T_AlterTableMoveAllStmt:
    2669          12 :             tag = AlterObjectTypeCommandTag(((AlterTableMoveAllStmt *) parsetree)->objtype);
    2670          12 :             break;
    2671             : 
    2672       62916 :         case T_AlterTableStmt:
    2673       62916 :             tag = AlterObjectTypeCommandTag(((AlterTableStmt *) parsetree)->objtype);
    2674       62916 :             break;
    2675             : 
    2676         152 :         case T_AlterDomainStmt:
    2677         152 :             tag = CMDTAG_ALTER_DOMAIN;
    2678         152 :             break;
    2679             : 
    2680         120 :         case T_AlterFunctionStmt:
    2681         120 :             switch (((AlterFunctionStmt *) parsetree)->objtype)
    2682             :             {
    2683         108 :                 case OBJECT_FUNCTION:
    2684         108 :                     tag = CMDTAG_ALTER_FUNCTION;
    2685         108 :                     break;
    2686          12 :                 case OBJECT_PROCEDURE:
    2687          12 :                     tag = CMDTAG_ALTER_PROCEDURE;
    2688          12 :                     break;
    2689           0 :                 case OBJECT_ROUTINE:
    2690           0 :                     tag = CMDTAG_ALTER_ROUTINE;
    2691           0 :                     break;
    2692           0 :                 default:
    2693           0 :                     tag = CMDTAG_UNKNOWN;
    2694             :             }
    2695         120 :             break;
    2696             : 
    2697       74834 :         case T_GrantStmt:
    2698             :             {
    2699       74834 :                 GrantStmt  *stmt = (GrantStmt *) parsetree;
    2700             : 
    2701       74834 :                 tag = (stmt->is_grant) ? CMDTAG_GRANT : CMDTAG_REVOKE;
    2702             :             }
    2703       74834 :             break;
    2704             : 
    2705        1594 :         case T_GrantRoleStmt:
    2706             :             {
    2707        1594 :                 GrantRoleStmt *stmt = (GrantRoleStmt *) parsetree;
    2708             : 
    2709        1594 :                 tag = (stmt->is_grant) ? CMDTAG_GRANT_ROLE : CMDTAG_REVOKE_ROLE;
    2710             :             }
    2711        1594 :             break;
    2712             : 
    2713         128 :         case T_AlterDefaultPrivilegesStmt:
    2714         128 :             tag = CMDTAG_ALTER_DEFAULT_PRIVILEGES;
    2715         128 :             break;
    2716             : 
    2717       28836 :         case T_DefineStmt:
    2718       28836 :             switch (((DefineStmt *) parsetree)->kind)
    2719             :             {
    2720         632 :                 case OBJECT_AGGREGATE:
    2721         632 :                     tag = CMDTAG_CREATE_AGGREGATE;
    2722         632 :                     break;
    2723         246 :                 case OBJECT_OPERATOR:
    2724         246 :                     tag = CMDTAG_CREATE_OPERATOR;
    2725         246 :                     break;
    2726         198 :                 case OBJECT_TYPE:
    2727         198 :                     tag = CMDTAG_CREATE_TYPE;
    2728         198 :                     break;
    2729          28 :                 case OBJECT_TSPARSER:
    2730          28 :                     tag = CMDTAG_CREATE_TEXT_SEARCH_PARSER;
    2731          28 :                     break;
    2732       13598 :                 case OBJECT_TSDICTIONARY:
    2733       13598 :                     tag = CMDTAG_CREATE_TEXT_SEARCH_DICTIONARY;
    2734       13598 :                     break;
    2735         510 :                 case OBJECT_TSTEMPLATE:
    2736         510 :                     tag = CMDTAG_CREATE_TEXT_SEARCH_TEMPLATE;
    2737         510 :                     break;
    2738       13562 :                 case OBJECT_TSCONFIGURATION:
    2739       13562 :                     tag = CMDTAG_CREATE_TEXT_SEARCH_CONFIGURATION;
    2740       13562 :                     break;
    2741          62 :                 case OBJECT_COLLATION:
    2742          62 :                     tag = CMDTAG_CREATE_COLLATION;
    2743          62 :                     break;
    2744           0 :                 case OBJECT_ACCESS_METHOD:
    2745           0 :                     tag = CMDTAG_CREATE_ACCESS_METHOD;
    2746           0 :                     break;
    2747           0 :                 default:
    2748           0 :                     tag = CMDTAG_UNKNOWN;
    2749             :             }
    2750       28836 :             break;
    2751             : 
    2752         458 :         case T_CompositeTypeStmt:
    2753         458 :             tag = CMDTAG_CREATE_TYPE;
    2754         458 :             break;
    2755             : 
    2756         116 :         case T_CreateEnumStmt:
    2757         116 :             tag = CMDTAG_CREATE_TYPE;
    2758         116 :             break;
    2759             : 
    2760         100 :         case T_CreateRangeStmt:
    2761         100 :             tag = CMDTAG_CREATE_TYPE;
    2762         100 :             break;
    2763             : 
    2764         292 :         case T_AlterEnumStmt:
    2765         292 :             tag = CMDTAG_ALTER_TYPE;
    2766         292 :             break;
    2767             : 
    2768       68200 :         case T_ViewStmt:
    2769       68200 :             tag = CMDTAG_CREATE_VIEW;
    2770       68200 :             break;
    2771             : 
    2772       48402 :         case T_CreateFunctionStmt:
    2773       48402 :             if (((CreateFunctionStmt *) parsetree)->is_procedure)
    2774         248 :                 tag = CMDTAG_CREATE_PROCEDURE;
    2775             :             else
    2776       48154 :                 tag = CMDTAG_CREATE_FUNCTION;
    2777       48402 :             break;
    2778             : 
    2779        3870 :         case T_IndexStmt:
    2780        3870 :             tag = CMDTAG_CREATE_INDEX;
    2781        3870 :             break;
    2782             : 
    2783        1550 :         case T_RuleStmt:
    2784        1550 :             tag = CMDTAG_CREATE_RULE;
    2785        1550 :             break;
    2786             : 
    2787         454 :         case T_CreateSeqStmt:
    2788         454 :             tag = CMDTAG_CREATE_SEQUENCE;
    2789         454 :             break;
    2790             : 
    2791         168 :         case T_AlterSeqStmt:
    2792         168 :             tag = CMDTAG_ALTER_SEQUENCE;
    2793         168 :             break;
    2794             : 
    2795         684 :         case T_DoStmt:
    2796         684 :             tag = CMDTAG_DO;
    2797         684 :             break;
    2798             : 
    2799        1262 :         case T_CreatedbStmt:
    2800        1262 :             tag = CMDTAG_CREATE_DATABASE;
    2801        1262 :             break;
    2802             : 
    2803           6 :         case T_AlterDatabaseStmt:
    2804           6 :             tag = CMDTAG_ALTER_DATABASE;
    2805           6 :             break;
    2806             : 
    2807         900 :         case T_AlterDatabaseSetStmt:
    2808         900 :             tag = CMDTAG_ALTER_DATABASE;
    2809         900 :             break;
    2810             : 
    2811          40 :         case T_DropdbStmt:
    2812          40 :             tag = CMDTAG_DROP_DATABASE;
    2813          40 :             break;
    2814             : 
    2815          82 :         case T_NotifyStmt:
    2816          82 :             tag = CMDTAG_NOTIFY;
    2817          82 :             break;
    2818             : 
    2819          42 :         case T_ListenStmt:
    2820          42 :             tag = CMDTAG_LISTEN;
    2821          42 :             break;
    2822             : 
    2823          34 :         case T_UnlistenStmt:
    2824          34 :             tag = CMDTAG_UNLISTEN;
    2825          34 :             break;
    2826             : 
    2827          34 :         case T_LoadStmt:
    2828          34 :             tag = CMDTAG_LOAD;
    2829          34 :             break;
    2830             : 
    2831         306 :         case T_CallStmt:
    2832         306 :             tag = CMDTAG_CALL;
    2833         306 :             break;
    2834             : 
    2835         114 :         case T_ClusterStmt:
    2836         114 :             tag = CMDTAG_CLUSTER;
    2837         114 :             break;
    2838             : 
    2839        8158 :         case T_VacuumStmt:
    2840        8158 :             if (((VacuumStmt *) parsetree)->is_vacuumcmd)
    2841        4068 :                 tag = CMDTAG_VACUUM;
    2842             :             else
    2843        4090 :                 tag = CMDTAG_ANALYZE;
    2844        8158 :             break;
    2845             : 
    2846       13412 :         case T_ExplainStmt:
    2847       13412 :             tag = CMDTAG_EXPLAIN;
    2848       13412 :             break;
    2849             : 
    2850        1060 :         case T_CreateTableAsStmt:
    2851        1060 :             switch (((CreateTableAsStmt *) parsetree)->objtype)
    2852             :             {
    2853         748 :                 case OBJECT_TABLE:
    2854         748 :                     if (((CreateTableAsStmt *) parsetree)->is_select_into)
    2855           0 :                         tag = CMDTAG_SELECT_INTO;
    2856             :                     else
    2857         748 :                         tag = CMDTAG_CREATE_TABLE_AS;
    2858         748 :                     break;
    2859         312 :                 case OBJECT_MATVIEW:
    2860         312 :                     tag = CMDTAG_CREATE_MATERIALIZED_VIEW;
    2861         312 :                     break;
    2862           0 :                 default:
    2863           0 :                     tag = CMDTAG_UNKNOWN;
    2864             :             }
    2865        1060 :             break;
    2866             : 
    2867         138 :         case T_RefreshMatViewStmt:
    2868         138 :             tag = CMDTAG_REFRESH_MATERIALIZED_VIEW;
    2869         138 :             break;
    2870             : 
    2871          58 :         case T_AlterSystemStmt:
    2872          58 :             tag = CMDTAG_ALTER_SYSTEM;
    2873          58 :             break;
    2874             : 
    2875       14522 :         case T_VariableSetStmt:
    2876       14522 :             switch (((VariableSetStmt *) parsetree)->kind)
    2877             :             {
    2878       12434 :                 case VAR_SET_VALUE:
    2879             :                 case VAR_SET_CURRENT:
    2880             :                 case VAR_SET_DEFAULT:
    2881             :                 case VAR_SET_MULTI:
    2882       12434 :                     tag = CMDTAG_SET;
    2883       12434 :                     break;
    2884        2088 :                 case VAR_RESET:
    2885             :                 case VAR_RESET_ALL:
    2886        2088 :                     tag = CMDTAG_RESET;
    2887        2088 :                     break;
    2888           0 :                 default:
    2889           0 :                     tag = CMDTAG_UNKNOWN;
    2890             :             }
    2891       14522 :             break;
    2892             : 
    2893         528 :         case T_VariableShowStmt:
    2894         528 :             tag = CMDTAG_SHOW;
    2895         528 :             break;
    2896             : 
    2897          20 :         case T_DiscardStmt:
    2898          20 :             switch (((DiscardStmt *) parsetree)->target)
    2899             :             {
    2900           4 :                 case DISCARD_ALL:
    2901           4 :                     tag = CMDTAG_DISCARD_ALL;
    2902           4 :                     break;
    2903           4 :                 case DISCARD_PLANS:
    2904           4 :                     tag = CMDTAG_DISCARD_PLANS;
    2905           4 :                     break;
    2906           4 :                 case DISCARD_TEMP:
    2907           4 :                     tag = CMDTAG_DISCARD_TEMP;
    2908           4 :                     break;
    2909           8 :                 case DISCARD_SEQUENCES:
    2910           8 :                     tag = CMDTAG_DISCARD_SEQUENCES;
    2911           8 :                     break;
    2912           0 :                 default:
    2913           0 :                     tag = CMDTAG_UNKNOWN;
    2914             :             }
    2915          20 :             break;
    2916             : 
    2917          36 :         case T_CreateTransformStmt:
    2918          36 :             tag = CMDTAG_CREATE_TRANSFORM;
    2919          36 :             break;
    2920             : 
    2921        2138 :         case T_CreateTrigStmt:
    2922        2138 :             tag = CMDTAG_CREATE_TRIGGER;
    2923        2138 :             break;
    2924             : 
    2925         112 :         case T_CreateEventTrigStmt:
    2926         112 :             tag = CMDTAG_CREATE_EVENT_TRIGGER;
    2927         112 :             break;
    2928             : 
    2929          20 :         case T_AlterEventTrigStmt:
    2930          20 :             tag = CMDTAG_ALTER_EVENT_TRIGGER;
    2931          20 :             break;
    2932             : 
    2933          10 :         case T_CreatePLangStmt:
    2934          10 :             tag = CMDTAG_CREATE_LANGUAGE;
    2935          10 :             break;
    2936             : 
    2937         822 :         case T_CreateRoleStmt:
    2938         822 :             tag = CMDTAG_CREATE_ROLE;
    2939         822 :             break;
    2940             : 
    2941         234 :         case T_AlterRoleStmt:
    2942         234 :             tag = CMDTAG_ALTER_ROLE;
    2943         234 :             break;
    2944             : 
    2945          64 :         case T_AlterRoleSetStmt:
    2946          64 :             tag = CMDTAG_ALTER_ROLE;
    2947          64 :             break;
    2948             : 
    2949         820 :         case T_DropRoleStmt:
    2950         820 :             tag = CMDTAG_DROP_ROLE;
    2951         820 :             break;
    2952             : 
    2953          96 :         case T_DropOwnedStmt:
    2954          96 :             tag = CMDTAG_DROP_OWNED;
    2955          96 :             break;
    2956             : 
    2957          16 :         case T_ReassignOwnedStmt:
    2958          16 :             tag = CMDTAG_REASSIGN_OWNED;
    2959          16 :             break;
    2960             : 
    2961        5514 :         case T_LockStmt:
    2962        5514 :             tag = CMDTAG_LOCK_TABLE;
    2963        5514 :             break;
    2964             : 
    2965          70 :         case T_ConstraintsSetStmt:
    2966          70 :             tag = CMDTAG_SET_CONSTRAINTS;
    2967          70 :             break;
    2968             : 
    2969         132 :         case T_CheckPointStmt:
    2970         132 :             tag = CMDTAG_CHECKPOINT;
    2971         132 :             break;
    2972             : 
    2973         468 :         case T_ReindexStmt:
    2974         468 :             tag = CMDTAG_REINDEX;
    2975         468 :             break;
    2976             : 
    2977          52 :         case T_CreateConversionStmt:
    2978          52 :             tag = CMDTAG_CREATE_CONVERSION;
    2979          52 :             break;
    2980             : 
    2981         134 :         case T_CreateCastStmt:
    2982         134 :             tag = CMDTAG_CREATE_CAST;
    2983         134 :             break;
    2984             : 
    2985          82 :         case T_CreateOpClassStmt:
    2986          82 :             tag = CMDTAG_CREATE_OPERATOR_CLASS;
    2987          82 :             break;
    2988             : 
    2989         102 :         case T_CreateOpFamilyStmt:
    2990         102 :             tag = CMDTAG_CREATE_OPERATOR_FAMILY;
    2991         102 :             break;
    2992             : 
    2993         194 :         case T_AlterOpFamilyStmt:
    2994         194 :             tag = CMDTAG_ALTER_OPERATOR_FAMILY;
    2995         194 :             break;
    2996             : 
    2997          56 :         case T_AlterOperatorStmt:
    2998          56 :             tag = CMDTAG_ALTER_OPERATOR;
    2999          56 :             break;
    3000             : 
    3001          16 :         case T_AlterTypeStmt:
    3002          16 :             tag = CMDTAG_ALTER_TYPE;
    3003          16 :             break;
    3004             : 
    3005          34 :         case T_AlterTSDictionaryStmt:
    3006          34 :             tag = CMDTAG_ALTER_TEXT_SEARCH_DICTIONARY;
    3007          34 :             break;
    3008             : 
    3009       40674 :         case T_AlterTSConfigurationStmt:
    3010       40674 :             tag = CMDTAG_ALTER_TEXT_SEARCH_CONFIGURATION;
    3011       40674 :             break;
    3012             : 
    3013         412 :         case T_CreatePolicyStmt:
    3014         412 :             tag = CMDTAG_CREATE_POLICY;
    3015         412 :             break;
    3016             : 
    3017          64 :         case T_AlterPolicyStmt:
    3018          64 :             tag = CMDTAG_ALTER_POLICY;
    3019          64 :             break;
    3020             : 
    3021          38 :         case T_CreateAmStmt:
    3022          38 :             tag = CMDTAG_CREATE_ACCESS_METHOD;
    3023          38 :             break;
    3024             : 
    3025         292 :         case T_CreatePublicationStmt:
    3026         292 :             tag = CMDTAG_CREATE_PUBLICATION;
    3027         292 :             break;
    3028             : 
    3029         216 :         case T_AlterPublicationStmt:
    3030         216 :             tag = CMDTAG_ALTER_PUBLICATION;
    3031         216 :             break;
    3032             : 
    3033         188 :         case T_CreateSubscriptionStmt:
    3034         188 :             tag = CMDTAG_CREATE_SUBSCRIPTION;
    3035         188 :             break;
    3036             : 
    3037         182 :         case T_AlterSubscriptionStmt:
    3038         182 :             tag = CMDTAG_ALTER_SUBSCRIPTION;
    3039         182 :             break;
    3040             : 
    3041          82 :         case T_DropSubscriptionStmt:
    3042          82 :             tag = CMDTAG_DROP_SUBSCRIPTION;
    3043          82 :             break;
    3044             : 
    3045           0 :         case T_AlterCollationStmt:
    3046           0 :             tag = CMDTAG_ALTER_COLLATION;
    3047           0 :             break;
    3048             : 
    3049         332 :         case T_PrepareStmt:
    3050         332 :             tag = CMDTAG_PREPARE;
    3051         332 :             break;
    3052             : 
    3053         842 :         case T_ExecuteStmt:
    3054         842 :             tag = CMDTAG_EXECUTE;
    3055         842 :             break;
    3056             : 
    3057         348 :         case T_CreateStatsStmt:
    3058         348 :             tag = CMDTAG_CREATE_STATISTICS;
    3059         348 :             break;
    3060             : 
    3061          20 :         case T_AlterStatsStmt:
    3062          20 :             tag = CMDTAG_ALTER_STATISTICS;
    3063          20 :             break;
    3064             : 
    3065        3868 :         case T_DeallocateStmt:
    3066             :             {
    3067        3868 :                 DeallocateStmt *stmt = (DeallocateStmt *) parsetree;
    3068             : 
    3069        3868 :                 if (stmt->name == NULL)
    3070          28 :                     tag = CMDTAG_DEALLOCATE_ALL;
    3071             :                 else
    3072        3840 :                     tag = CMDTAG_DEALLOCATE;
    3073             :             }
    3074        3868 :             break;
    3075             : 
    3076             :             /* already-planned queries */
    3077          20 :         case T_PlannedStmt:
    3078             :             {
    3079          20 :                 PlannedStmt *stmt = (PlannedStmt *) parsetree;
    3080             : 
    3081          20 :                 switch (stmt->commandType)
    3082             :                 {
    3083           0 :                     case CMD_SELECT:
    3084             : 
    3085             :                         /*
    3086             :                          * We take a little extra care here so that the result
    3087             :                          * will be useful for complaints about read-only
    3088             :                          * statements
    3089             :                          */
    3090           0 :                         if (stmt->rowMarks != NIL)
    3091             :                         {
    3092             :                             /* not 100% but probably close enough */
    3093           0 :                             switch (((PlanRowMark *) linitial(stmt->rowMarks))->strength)
    3094             :                             {
    3095           0 :                                 case LCS_FORKEYSHARE:
    3096           0 :                                     tag = CMDTAG_SELECT_FOR_KEY_SHARE;
    3097           0 :                                     break;
    3098           0 :                                 case LCS_FORSHARE:
    3099           0 :                                     tag = CMDTAG_SELECT_FOR_SHARE;
    3100           0 :                                     break;
    3101           0 :                                 case LCS_FORNOKEYUPDATE:
    3102           0 :                                     tag = CMDTAG_SELECT_FOR_NO_KEY_UPDATE;
    3103           0 :                                     break;
    3104           0 :                                 case LCS_FORUPDATE:
    3105           0 :                                     tag = CMDTAG_SELECT_FOR_UPDATE;
    3106           0 :                                     break;
    3107           0 :                                 default:
    3108           0 :                                     tag = CMDTAG_SELECT;
    3109           0 :                                     break;
    3110             :                             }
    3111             :                         }
    3112             :                         else
    3113           0 :                             tag = CMDTAG_SELECT;
    3114           0 :                         break;
    3115           8 :                     case CMD_UPDATE:
    3116           8 :                         tag = CMDTAG_UPDATE;
    3117           8 :                         break;
    3118           8 :                     case CMD_INSERT:
    3119           8 :                         tag = CMDTAG_INSERT;
    3120           8 :                         break;
    3121           4 :                     case CMD_DELETE:
    3122           4 :                         tag = CMDTAG_DELETE;
    3123           4 :                         break;
    3124           0 :                     case CMD_UTILITY:
    3125           0 :                         tag = CreateCommandTag(stmt->utilityStmt);
    3126           0 :                         break;
    3127           0 :                     default:
    3128           0 :                         elog(WARNING, "unrecognized commandType: %d",
    3129             :                              (int) stmt->commandType);
    3130           0 :                         tag = CMDTAG_UNKNOWN;
    3131           0 :                         break;
    3132             :                 }
    3133             :             }
    3134          20 :             break;
    3135             : 
    3136             :             /* parsed-and-rewritten-but-not-planned queries */
    3137           0 :         case T_Query:
    3138             :             {
    3139           0 :                 Query      *stmt = (Query *) parsetree;
    3140             : 
    3141           0 :                 switch (stmt->commandType)
    3142             :                 {
    3143           0 :                     case CMD_SELECT:
    3144             : 
    3145             :                         /*
    3146             :                          * We take a little extra care here so that the result
    3147             :                          * will be useful for complaints about read-only
    3148             :                          * statements
    3149             :                          */
    3150           0 :                         if (stmt->rowMarks != NIL)
    3151             :                         {
    3152             :                             /* not 100% but probably close enough */
    3153           0 :                             switch (((RowMarkClause *) linitial(stmt->rowMarks))->strength)
    3154             :                             {
    3155           0 :                                 case LCS_FORKEYSHARE:
    3156           0 :                                     tag = CMDTAG_SELECT_FOR_KEY_SHARE;
    3157           0 :                                     break;
    3158           0 :                                 case LCS_FORSHARE:
    3159           0 :                                     tag = CMDTAG_SELECT_FOR_SHARE;
    3160           0 :                                     break;
    3161           0 :                                 case LCS_FORNOKEYUPDATE:
    3162           0 :                                     tag = CMDTAG_SELECT_FOR_NO_KEY_UPDATE;
    3163           0 :                                     break;
    3164           0 :                                 case LCS_FORUPDATE:
    3165           0 :                                     tag = CMDTAG_SELECT_FOR_UPDATE;
    3166           0 :                                     break;
    3167           0 :                                 default:
    3168           0 :                                     tag = CMDTAG_UNKNOWN;
    3169           0 :                                     break;
    3170             :                             }
    3171             :                         }
    3172             :                         else
    3173           0 :                             tag = CMDTAG_SELECT;
    3174           0 :                         break;
    3175           0 :                     case CMD_UPDATE:
    3176           0 :                         tag = CMDTAG_UPDATE;
    3177           0 :                         break;
    3178           0 :                     case CMD_INSERT:
    3179           0 :                         tag = CMDTAG_INSERT;
    3180           0 :                         break;
    3181           0 :                     case CMD_DELETE:
    3182           0 :                         tag = CMDTAG_DELETE;
    3183           0 :                         break;
    3184           0 :                     case CMD_UTILITY:
    3185           0 :                         tag = CreateCommandTag(stmt->utilityStmt);
    3186           0 :                         break;
    3187           0 :                     default:
    3188           0 :                         elog(WARNING, "unrecognized commandType: %d",
    3189             :                              (int) stmt->commandType);
    3190           0 :                         tag = CMDTAG_UNKNOWN;
    3191           0 :                         break;
    3192             :                 }
    3193             :             }
    3194           0 :             break;
    3195             : 
    3196           0 :         default:
    3197           0 :             elog(WARNING, "unrecognized node type: %d",
    3198             :                  (int) nodeTag(parsetree));
    3199           0 :             tag = CMDTAG_UNKNOWN;
    3200           0 :             break;
    3201             :     }
    3202             : 
    3203      800384 :     return tag;
    3204             : }
    3205             : 
    3206             : 
    3207             : /*
    3208             :  * GetCommandLogLevel
    3209             :  *      utility to get the minimum log_statement level for a command,
    3210             :  *      given either a raw (un-analyzed) parsetree, an analyzed Query,
    3211             :  *      or a PlannedStmt.
    3212             :  *
    3213             :  * This must handle all command types, but since the vast majority
    3214             :  * of 'em are utility commands, it seems sensible to keep it here.
    3215             :  */
    3216             : LogStmtLevel
    3217           0 : GetCommandLogLevel(Node *parsetree)
    3218             : {
    3219             :     LogStmtLevel lev;
    3220             : 
    3221           0 :     switch (nodeTag(parsetree))
    3222             :     {
    3223             :             /* recurse if we're given a RawStmt */
    3224           0 :         case T_RawStmt:
    3225           0 :             lev = GetCommandLogLevel(((RawStmt *) parsetree)->stmt);
    3226           0 :             break;
    3227             : 
    3228             :             /* raw plannable queries */
    3229           0 :         case T_InsertStmt:
    3230             :         case T_DeleteStmt:
    3231             :         case T_UpdateStmt:
    3232           0 :             lev = LOGSTMT_MOD;
    3233           0 :             break;
    3234             : 
    3235           0 :         case T_SelectStmt:
    3236           0 :             if (((SelectStmt *) parsetree)->intoClause)
    3237           0 :                 lev = LOGSTMT_DDL;  /* SELECT INTO */
    3238             :             else
    3239           0 :                 lev = LOGSTMT_ALL;
    3240           0 :             break;
    3241             : 
    3242           0 :         case T_PLAssignStmt:
    3243           0 :             lev = LOGSTMT_ALL;
    3244           0 :             break;
    3245             : 
    3246             :             /* utility statements --- same whether raw or cooked */
    3247           0 :         case T_TransactionStmt:
    3248           0 :             lev = LOGSTMT_ALL;
    3249           0 :             break;
    3250             : 
    3251           0 :         case T_DeclareCursorStmt:
    3252           0 :             lev = LOGSTMT_ALL;
    3253           0 :             break;
    3254             : 
    3255           0 :         case T_ClosePortalStmt:
    3256           0 :             lev = LOGSTMT_ALL;
    3257           0 :             break;
    3258             : 
    3259           0 :         case T_FetchStmt:
    3260           0 :             lev = LOGSTMT_ALL;
    3261           0 :             break;
    3262             : 
    3263           0 :         case T_CreateSchemaStmt:
    3264           0 :             lev = LOGSTMT_DDL;
    3265           0 :             break;
    3266             : 
    3267           0 :         case T_CreateStmt:
    3268             :         case T_CreateForeignTableStmt:
    3269           0 :             lev = LOGSTMT_DDL;
    3270           0 :             break;
    3271             : 
    3272           0 :         case T_CreateTableSpaceStmt:
    3273             :         case T_DropTableSpaceStmt:
    3274             :         case T_AlterTableSpaceOptionsStmt:
    3275           0 :             lev = LOGSTMT_DDL;
    3276           0 :             break;
    3277             : 
    3278           0 :         case T_CreateExtensionStmt:
    3279             :         case T_AlterExtensionStmt:
    3280             :         case T_AlterExtensionContentsStmt:
    3281           0 :             lev = LOGSTMT_DDL;
    3282           0 :             break;
    3283             : 
    3284           0 :         case T_CreateFdwStmt:
    3285             :         case T_AlterFdwStmt:
    3286             :         case T_CreateForeignServerStmt:
    3287             :         case T_AlterForeignServerStmt:
    3288             :         case T_CreateUserMappingStmt:
    3289             :         case T_AlterUserMappingStmt:
    3290             :         case T_DropUserMappingStmt:
    3291             :         case T_ImportForeignSchemaStmt:
    3292           0 :             lev = LOGSTMT_DDL;
    3293           0 :             break;
    3294             : 
    3295           0 :         case T_DropStmt:
    3296           0 :             lev = LOGSTMT_DDL;
    3297           0 :             break;
    3298             : 
    3299           0 :         case T_TruncateStmt:
    3300           0 :             lev = LOGSTMT_MOD;
    3301           0 :             break;
    3302             : 
    3303           0 :         case T_CommentStmt:
    3304           0 :             lev = LOGSTMT_DDL;
    3305           0 :             break;
    3306             : 
    3307           0 :         case T_SecLabelStmt:
    3308           0 :             lev = LOGSTMT_DDL;
    3309           0 :             break;
    3310             : 
    3311           0 :         case T_CopyStmt:
    3312           0 :             if (((CopyStmt *) parsetree)->is_from)
    3313           0 :                 lev = LOGSTMT_MOD;
    3314             :             else
    3315           0 :                 lev = LOGSTMT_ALL;
    3316           0 :             break;
    3317             : 
    3318           0 :         case T_PrepareStmt:
    3319             :             {
    3320           0 :                 PrepareStmt *stmt = (PrepareStmt *) parsetree;
    3321             : 
    3322             :                 /* Look through a PREPARE to the contained stmt */
    3323           0 :                 lev = GetCommandLogLevel(stmt->query);
    3324             :             }
    3325           0 :             break;
    3326             : 
    3327           0 :         case T_ExecuteStmt:
    3328             :             {
    3329           0 :                 ExecuteStmt *stmt = (ExecuteStmt *) parsetree;
    3330             :                 PreparedStatement *ps;
    3331             : 
    3332             :                 /* Look through an EXECUTE to the referenced stmt */
    3333           0 :                 ps = FetchPreparedStatement(stmt->name, false);
    3334           0 :                 if (ps && ps->plansource->raw_parse_tree)
    3335           0 :                     lev = GetCommandLogLevel(ps->plansource->raw_parse_tree->stmt);
    3336             :                 else
    3337           0 :                     lev = LOGSTMT_ALL;
    3338             :             }
    3339           0 :             break;
    3340             : 
    3341           0 :         case T_DeallocateStmt:
    3342           0 :             lev = LOGSTMT_ALL;
    3343           0 :             break;
    3344             : 
    3345           0 :         case T_RenameStmt:
    3346           0 :             lev = LOGSTMT_DDL;
    3347           0 :             break;
    3348             : 
    3349           0 :         case T_AlterObjectDependsStmt:
    3350           0 :             lev = LOGSTMT_DDL;
    3351           0 :             break;
    3352             : 
    3353           0 :         case T_AlterObjectSchemaStmt:
    3354           0 :             lev = LOGSTMT_DDL;
    3355           0 :             break;
    3356             : 
    3357           0 :         case T_AlterOwnerStmt:
    3358           0 :             lev = LOGSTMT_DDL;
    3359           0 :             break;
    3360             : 
    3361           0 :         case T_AlterOperatorStmt:
    3362           0 :             lev = LOGSTMT_DDL;
    3363           0 :             break;
    3364             : 
    3365           0 :         case T_AlterTypeStmt:
    3366           0 :             lev = LOGSTMT_DDL;
    3367           0 :             break;
    3368             : 
    3369           0 :         case T_AlterTableMoveAllStmt:
    3370             :         case T_AlterTableStmt:
    3371           0 :             lev = LOGSTMT_DDL;
    3372           0 :             break;
    3373             : 
    3374           0 :         case T_AlterDomainStmt:
    3375           0 :             lev = LOGSTMT_DDL;
    3376           0 :             break;
    3377             : 
    3378           0 :         case T_GrantStmt:
    3379           0 :             lev = LOGSTMT_DDL;
    3380           0 :             break;
    3381             : 
    3382           0 :         case T_GrantRoleStmt:
    3383           0 :             lev = LOGSTMT_DDL;
    3384           0 :             break;
    3385             : 
    3386           0 :         case T_AlterDefaultPrivilegesStmt:
    3387           0 :             lev = LOGSTMT_DDL;
    3388           0 :             break;
    3389             : 
    3390           0 :         case T_DefineStmt:
    3391           0 :             lev = LOGSTMT_DDL;
    3392           0 :             break;
    3393             : 
    3394           0 :         case T_CompositeTypeStmt:
    3395           0 :             lev = LOGSTMT_DDL;
    3396           0 :             break;
    3397             : 
    3398           0 :         case T_CreateEnumStmt:
    3399           0 :             lev = LOGSTMT_DDL;
    3400           0 :             break;
    3401             : 
    3402           0 :         case T_CreateRangeStmt:
    3403           0 :             lev = LOGSTMT_DDL;
    3404           0 :             break;
    3405             : 
    3406           0 :         case T_AlterEnumStmt:
    3407           0 :             lev = LOGSTMT_DDL;
    3408           0 :             break;
    3409             : 
    3410           0 :         case T_ViewStmt:
    3411           0 :             lev = LOGSTMT_DDL;
    3412           0 :             break;
    3413             : 
    3414           0 :         case T_CreateFunctionStmt:
    3415           0 :             lev = LOGSTMT_DDL;
    3416           0 :             break;
    3417             : 
    3418           0 :         case T_AlterFunctionStmt:
    3419           0 :             lev = LOGSTMT_DDL;
    3420           0 :             break;
    3421             : 
    3422           0 :         case T_IndexStmt:
    3423           0 :             lev = LOGSTMT_DDL;
    3424           0 :             break;
    3425             : 
    3426           0 :         case T_RuleStmt:
    3427           0 :             lev = LOGSTMT_DDL;
    3428           0 :             break;
    3429             : 
    3430           0 :         case T_CreateSeqStmt:
    3431           0 :             lev = LOGSTMT_DDL;
    3432           0 :             break;
    3433             : 
    3434           0 :         case T_AlterSeqStmt:
    3435           0 :             lev = LOGSTMT_DDL;
    3436           0 :             break;
    3437             : 
    3438           0 :         case T_DoStmt:
    3439           0 :             lev = LOGSTMT_ALL;
    3440           0 :             break;
    3441             : 
    3442           0 :         case T_CreatedbStmt:
    3443           0 :             lev = LOGSTMT_DDL;
    3444           0 :             break;
    3445             : 
    3446           0 :         case T_AlterDatabaseStmt:
    3447           0 :             lev = LOGSTMT_DDL;
    3448           0 :             break;
    3449             : 
    3450           0 :         case T_AlterDatabaseSetStmt:
    3451           0 :             lev = LOGSTMT_DDL;
    3452           0 :             break;
    3453             : 
    3454           0 :         case T_DropdbStmt:
    3455           0 :             lev = LOGSTMT_DDL;
    3456           0 :             break;
    3457             : 
    3458           0 :         case T_NotifyStmt:
    3459           0 :             lev = LOGSTMT_ALL;
    3460           0 :             break;
    3461             : 
    3462           0 :         case T_ListenStmt:
    3463           0 :             lev = LOGSTMT_ALL;
    3464           0 :             break;
    3465             : 
    3466           0 :         case T_UnlistenStmt:
    3467           0 :             lev = LOGSTMT_ALL;
    3468           0 :             break;
    3469             : 
    3470           0 :         case T_LoadStmt:
    3471           0 :             lev = LOGSTMT_ALL;
    3472           0 :             break;
    3473             : 
    3474           0 :         case T_CallStmt:
    3475           0 :             lev = LOGSTMT_ALL;
    3476           0 :             break;
    3477             : 
    3478           0 :         case T_ClusterStmt:
    3479           0 :             lev = LOGSTMT_DDL;
    3480           0 :             break;
    3481             : 
    3482           0 :         case T_VacuumStmt:
    3483           0 :             lev = LOGSTMT_ALL;
    3484           0 :             break;
    3485             : 
    3486           0 :         case T_ExplainStmt:
    3487             :             {
    3488           0 :                 ExplainStmt *stmt = (ExplainStmt *) parsetree;
    3489           0 :                 bool        analyze = false;
    3490             :                 ListCell   *lc;
    3491             : 
    3492             :                 /* Look through an EXPLAIN ANALYZE to the contained stmt */
    3493           0 :                 foreach(lc, stmt->options)
    3494             :                 {
    3495           0 :                     DefElem    *opt = (DefElem *) lfirst(lc);
    3496             : 
    3497           0 :                     if (strcmp(opt->defname, "analyze") == 0)
    3498           0 :                         analyze = defGetBoolean(opt);
    3499             :                     /* don't "break", as explain.c will use the last value */
    3500             :                 }
    3501           0 :                 if (analyze)
    3502           0 :                     return GetCommandLogLevel(stmt->query);
    3503             : 
    3504             :                 /* Plain EXPLAIN isn't so interesting */
    3505           0 :                 lev = LOGSTMT_ALL;
    3506             :             }
    3507           0 :             break;
    3508             : 
    3509           0 :         case T_CreateTableAsStmt:
    3510           0 :             lev = LOGSTMT_DDL;
    3511           0 :             break;
    3512             : 
    3513           0 :         case T_RefreshMatViewStmt:
    3514           0 :             lev = LOGSTMT_DDL;
    3515           0 :             break;
    3516             : 
    3517           0 :         case T_AlterSystemStmt:
    3518           0 :             lev = LOGSTMT_DDL;
    3519           0 :             break;
    3520             : 
    3521           0 :         case T_VariableSetStmt:
    3522           0 :             lev = LOGSTMT_ALL;
    3523           0 :             break;
    3524             : 
    3525           0 :         case T_VariableShowStmt:
    3526           0 :             lev = LOGSTMT_ALL;
    3527           0 :             break;
    3528             : 
    3529           0 :         case T_DiscardStmt:
    3530           0 :             lev = LOGSTMT_ALL;
    3531           0 :             break;
    3532             : 
    3533           0 :         case T_CreateTrigStmt:
    3534           0 :             lev = LOGSTMT_DDL;
    3535           0 :             break;
    3536             : 
    3537           0 :         case T_CreateEventTrigStmt:
    3538           0 :             lev = LOGSTMT_DDL;
    3539           0 :             break;
    3540             : 
    3541           0 :         case T_AlterEventTrigStmt:
    3542           0 :             lev = LOGSTMT_DDL;
    3543           0 :             break;
    3544             : 
    3545           0 :         case T_CreatePLangStmt:
    3546           0 :             lev = LOGSTMT_DDL;
    3547           0 :             break;
    3548             : 
    3549           0 :         case T_CreateDomainStmt:
    3550           0 :             lev = LOGSTMT_DDL;
    3551           0 :             break;
    3552             : 
    3553           0 :         case T_CreateRoleStmt:
    3554           0 :             lev = LOGSTMT_DDL;
    3555           0 :             break;
    3556             : 
    3557           0 :         case T_AlterRoleStmt:
    3558           0 :             lev = LOGSTMT_DDL;
    3559           0 :             break;
    3560             : 
    3561           0 :         case T_AlterRoleSetStmt:
    3562           0 :             lev = LOGSTMT_DDL;
    3563           0 :             break;
    3564             : 
    3565           0 :         case T_DropRoleStmt:
    3566           0 :             lev = LOGSTMT_DDL;
    3567           0 :             break;
    3568             : 
    3569           0 :         case T_DropOwnedStmt:
    3570           0 :             lev = LOGSTMT_DDL;
    3571           0 :             break;
    3572             : 
    3573           0 :         case T_ReassignOwnedStmt:
    3574           0 :             lev = LOGSTMT_DDL;
    3575           0 :             break;
    3576             : 
    3577           0 :         case T_LockStmt:
    3578           0 :             lev = LOGSTMT_ALL;
    3579           0 :             break;
    3580             : 
    3581           0 :         case T_ConstraintsSetStmt:
    3582           0 :             lev = LOGSTMT_ALL;
    3583           0 :             break;
    3584             : 
    3585           0 :         case T_CheckPointStmt:
    3586           0 :             lev = LOGSTMT_ALL;
    3587           0 :             break;
    3588             : 
    3589           0 :         case T_ReindexStmt:
    3590           0 :             lev = LOGSTMT_ALL;  /* should this be DDL? */
    3591           0 :             break;
    3592             : 
    3593           0 :         case T_CreateConversionStmt:
    3594           0 :             lev = LOGSTMT_DDL;
    3595           0 :             break;
    3596             : 
    3597           0 :         case T_CreateCastStmt:
    3598           0 :             lev = LOGSTMT_DDL;
    3599           0 :             break;
    3600             : 
    3601           0 :         case T_CreateOpClassStmt:
    3602           0 :             lev = LOGSTMT_DDL;
    3603           0 :             break;
    3604             : 
    3605           0 :         case T_CreateOpFamilyStmt:
    3606           0 :             lev = LOGSTMT_DDL;
    3607           0 :             break;
    3608             : 
    3609           0 :         case T_CreateTransformStmt:
    3610           0 :             lev = LOGSTMT_DDL;
    3611           0 :             break;
    3612             : 
    3613           0 :         case T_AlterOpFamilyStmt:
    3614           0 :             lev = LOGSTMT_DDL;
    3615           0 :             break;
    3616             : 
    3617           0 :         case T_CreatePolicyStmt:
    3618           0 :             lev = LOGSTMT_DDL;
    3619           0 :             break;
    3620             : 
    3621           0 :         case T_AlterPolicyStmt:
    3622           0 :             lev = LOGSTMT_DDL;
    3623           0 :             break;
    3624             : 
    3625           0 :         case T_AlterTSDictionaryStmt:
    3626           0 :             lev = LOGSTMT_DDL;
    3627           0 :             break;
    3628             : 
    3629           0 :         case T_AlterTSConfigurationStmt:
    3630           0 :             lev = LOGSTMT_DDL;
    3631           0 :             break;
    3632             : 
    3633           0 :         case T_CreateAmStmt:
    3634           0 :             lev = LOGSTMT_DDL;
    3635           0 :             break;
    3636             : 
    3637           0 :         case T_CreatePublicationStmt:
    3638           0 :             lev = LOGSTMT_DDL;
    3639           0 :             break;
    3640             : 
    3641           0 :         case T_AlterPublicationStmt:
    3642           0 :             lev = LOGSTMT_DDL;
    3643           0 :             break;
    3644             : 
    3645           0 :         case T_CreateSubscriptionStmt:
    3646           0 :             lev = LOGSTMT_DDL;
    3647           0 :             break;
    3648             : 
    3649           0 :         case T_AlterSubscriptionStmt:
    3650           0 :             lev = LOGSTMT_DDL;
    3651           0 :             break;
    3652             : 
    3653           0 :         case T_DropSubscriptionStmt:
    3654           0 :             lev = LOGSTMT_DDL;
    3655           0 :             break;
    3656             : 
    3657           0 :         case T_CreateStatsStmt:
    3658           0 :             lev = LOGSTMT_DDL;
    3659           0 :             break;
    3660             : 
    3661           0 :         case T_AlterStatsStmt:
    3662           0 :             lev = LOGSTMT_DDL;
    3663           0 :             break;
    3664             : 
    3665           0 :         case T_AlterCollationStmt:
    3666           0 :             lev = LOGSTMT_DDL;
    3667           0 :             break;
    3668             : 
    3669             :             /* already-planned queries */
    3670           0 :         case T_PlannedStmt:
    3671             :             {
    3672           0 :                 PlannedStmt *stmt = (PlannedStmt *) parsetree;
    3673             : 
    3674           0 :                 switch (stmt->commandType)
    3675             :                 {
    3676           0 :                     case CMD_SELECT:
    3677           0 :                         lev = LOGSTMT_ALL;
    3678           0 :                         break;
    3679             : 
    3680           0 :                     case CMD_UPDATE:
    3681             :                     case CMD_INSERT:
    3682             :                     case CMD_DELETE:
    3683           0 :                         lev = LOGSTMT_MOD;
    3684           0 :                         break;
    3685             : 
    3686           0 :                     case CMD_UTILITY:
    3687           0 :                         lev = GetCommandLogLevel(stmt->utilityStmt);
    3688           0 :                         break;
    3689             : 
    3690           0 :                     default:
    3691           0 :                         elog(WARNING, "unrecognized commandType: %d",
    3692             :                              (int) stmt->commandType);
    3693           0 :                         lev = LOGSTMT_ALL;
    3694           0 :                         break;
    3695             :                 }
    3696             :             }
    3697           0 :             break;
    3698             : 
    3699             :             /* parsed-and-rewritten-but-not-planned queries */
    3700           0 :         case T_Query:
    3701             :             {
    3702           0 :                 Query      *stmt = (Query *) parsetree;
    3703             : 
    3704           0 :                 switch (stmt->commandType)
    3705             :                 {
    3706           0 :                     case CMD_SELECT:
    3707           0 :                         lev = LOGSTMT_ALL;
    3708           0 :                         break;
    3709             : 
    3710           0 :                     case CMD_UPDATE:
    3711             :                     case CMD_INSERT:
    3712             :                     case CMD_DELETE:
    3713           0 :                         lev = LOGSTMT_MOD;
    3714           0 :                         break;
    3715             : 
    3716           0 :                     case CMD_UTILITY:
    3717           0 :                         lev = GetCommandLogLevel(stmt->utilityStmt);
    3718           0 :                         break;
    3719             : 
    3720           0 :                     default:
    3721           0 :                         elog(WARNING, "unrecognized commandType: %d",
    3722             :                              (int) stmt->commandType);
    3723           0 :                         lev = LOGSTMT_ALL;
    3724           0 :                         break;
    3725             :                 }
    3726             : 
    3727             :             }
    3728           0 :             break;
    3729             : 
    3730           0 :         default:
    3731           0 :             elog(WARNING, "unrecognized node type: %d",
    3732             :                  (int) nodeTag(parsetree));
    3733           0 :             lev = LOGSTMT_ALL;
    3734           0 :             break;
    3735             :     }
    3736             : 
    3737           0 :     return lev;
    3738             : }

Generated by: LCOV version 1.14