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

Generated by: LCOV version 1.14