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

Generated by: LCOV version 1.16