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

Generated by: LCOV version 1.16