LCOV - code coverage report
Current view: top level - src/backend/tcop - utility.c (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 75.4 % 1968 1484
Test Date: 2026-03-14 10:14:47 Functions: 94.1 % 17 16
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        10005 : CommandIsReadOnly(PlannedStmt *pstmt)
      96              : {
      97              :     Assert(IsA(pstmt, PlannedStmt));
      98        10005 :     switch (pstmt->commandType)
      99              :     {
     100        10005 :         case CMD_SELECT:
     101        10005 :             if (pstmt->rowMarks != NIL)
     102            0 :                 return false;   /* SELECT FOR [KEY] UPDATE/SHARE */
     103        10005 :             else if (pstmt->hasModifyingCTE)
     104            0 :                 return false;   /* data-modifying CTE */
     105              :             else
     106        10005 :                 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       218226 : ClassifyUtilityCommandAsReadOnly(Node *parsetree)
     130              : {
     131       218226 :     switch (nodeTag(parsetree))
     132              :     {
     133       124345 :         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       124345 :                 return COMMAND_IS_NOT_READ_ONLY;
     218              :             }
     219              : 
     220          111 :         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          111 :                 return COMMAND_IS_STRICTLY_READ_ONLY;
     233              :             }
     234              : 
     235         1042 :         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         1042 :                 return COMMAND_IS_STRICTLY_READ_ONLY;
     245              :             }
     246              : 
     247          452 :         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          452 :                 return COMMAND_IS_STRICTLY_READ_ONLY;
     257              :             }
     258              : 
     259        39610 :         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        39610 :                 return COMMAND_OK_IN_RECOVERY | COMMAND_OK_IN_READ_ONLY_TXN;
     280              :             }
     281              : 
     282         8166 :         case T_ReindexStmt:
     283              :         case T_VacuumStmt:
     284              :         case T_RepackStmt:
     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. (REPACK/CLUSTER might change the
     294              :                  * order of rows on disk, which could affect the ordering of
     295              :                  * pg_dump output, but that's not semantically significant.)
     296              :                  */
     297         8166 :                 return COMMAND_OK_IN_READ_ONLY_TXN;
     298              :             }
     299              : 
     300         5915 :         case T_CopyStmt:
     301              :             {
     302         5915 :                 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         5915 :                 if (stmt->is_from)
     312          964 :                     return COMMAND_OK_IN_READ_ONLY_TXN;
     313              :                 else
     314         4951 :                     return COMMAND_IS_STRICTLY_READ_ONLY;
     315              :             }
     316              : 
     317        13140 :         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        13140 :                 return COMMAND_IS_STRICTLY_READ_ONLY;
     325              :             }
     326              : 
     327          119 :         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          119 :                 return COMMAND_OK_IN_READ_ONLY_TXN;
     341              :             }
     342              : 
     343          580 :         case T_LockStmt:
     344              :             {
     345          580 :                 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          580 :                 if (stmt->mode > RowExclusiveLock)
     353          249 :                     return COMMAND_OK_IN_READ_ONLY_TXN;
     354              :                 else
     355          331 :                     return COMMAND_IS_STRICTLY_READ_ONLY;
     356              :             }
     357              : 
     358        24746 :         case T_TransactionStmt:
     359              :             {
     360        24746 :                 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        24746 :                 switch (stmt->kind)
     372              :                 {
     373        24142 :                     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        24142 :                         return COMMAND_IS_STRICTLY_READ_ONLY;
     381              : 
     382          604 :                     case TRANS_STMT_PREPARE:
     383              :                     case TRANS_STMT_COMMIT_PREPARED:
     384              :                     case TRANS_STMT_ROLLBACK_PREPARED:
     385          604 :                         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       186454 : PreventCommandIfReadOnly(const char *cmdname)
     407              : {
     408       186454 :     if (XactReadOnly)
     409           50 :         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       186404 : }
     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       255466 : PreventCommandIfParallelMode(const char *cmdname)
     425              : {
     426       255466 :     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       255466 : }
     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         4021 : PreventCommandDuringRecovery(const char *cmdname)
     444              : {
     445         4021 :     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         4021 : }
     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         4426 : CheckRestrictedOperation(const char *cmdname)
     462              : {
     463         4426 :     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         4426 : }
     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       218226 : 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       218226 :     if (ProcessUtility_hook)
     521        36102 :         (*ProcessUtility_hook) (pstmt, queryString, readOnlyTree,
     522              :                                 context, params, queryEnv,
     523              :                                 dest, qc);
     524              :     else
     525       182124 :         standard_ProcessUtility(pstmt, queryString, readOnlyTree,
     526              :                                 context, params, queryEnv,
     527              :                                 dest, qc);
     528       209595 : }
     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       218226 : 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       218226 :     bool        isTopLevel = (context == PROCESS_UTILITY_TOPLEVEL);
     556       218226 :     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       218226 :     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       218226 :     if (readOnlyTree)
     572        16396 :         pstmt = copyObject(pstmt);
     573       218226 :     parsetree = pstmt->utilityStmt;
     574              : 
     575              :     /* Prohibit read/write commands in read-only states. */
     576       218226 :     readonly_flags = ClassifyUtilityCommandAsReadOnly(parsetree);
     577       218226 :     if (readonly_flags != COMMAND_IS_STRICTLY_READ_ONLY &&
     578       174057 :         (XactReadOnly || IsInParallelMode()))
     579              :     {
     580         8822 :         CommandTag  commandtag = CreateCommandTag(parsetree);
     581              : 
     582         8822 :         if ((readonly_flags & COMMAND_OK_IN_READ_ONLY_TXN) == 0)
     583            6 :             PreventCommandIfReadOnly(GetCommandTagName(commandtag));
     584         8816 :         if ((readonly_flags & COMMAND_OK_IN_PARALLEL_MODE) == 0)
     585         8816 :             PreventCommandIfParallelMode(GetCommandTagName(commandtag));
     586         8816 :         if ((readonly_flags & COMMAND_OK_IN_RECOVERY) == 0)
     587            0 :             PreventCommandDuringRecovery(GetCommandTagName(commandtag));
     588              :     }
     589              : 
     590       218220 :     pstate = make_parsestate(NULL);
     591       218220 :     pstate->p_sourcetext = queryString;
     592       218220 :     pstate->p_queryEnv = queryEnv;
     593              : 
     594       218220 :     switch (nodeTag(parsetree))
     595              :     {
     596              :             /*
     597              :              * ******************** transactions ********************
     598              :              */
     599        24746 :         case T_TransactionStmt:
     600              :             {
     601        24746 :                 TransactionStmt *stmt = (TransactionStmt *) parsetree;
     602              : 
     603        24746 :                 switch (stmt->kind)
     604              :                 {
     605              :                         /*
     606              :                          * START TRANSACTION, as defined by SQL99: Identical
     607              :                          * to BEGIN.  Same code for both.
     608              :                          */
     609        11620 :                     case TRANS_STMT_BEGIN:
     610              :                     case TRANS_STMT_START:
     611              :                         {
     612              :                             ListCell   *lc;
     613              : 
     614        11620 :                             BeginTransactionBlock();
     615        15451 :                             foreach(lc, stmt->options)
     616              :                             {
     617         3831 :                                 DefElem    *item = (DefElem *) lfirst(lc);
     618              : 
     619         3831 :                                 if (strcmp(item->defname, "transaction_isolation") == 0)
     620         3323 :                                     SetPGVariable("transaction_isolation",
     621         3323 :                                                   list_make1(item->arg),
     622              :                                                   true);
     623          508 :                                 else if (strcmp(item->defname, "transaction_read_only") == 0)
     624          484 :                                     SetPGVariable("transaction_read_only",
     625          484 :                                                   list_make1(item->arg),
     626              :                                                   true);
     627           24 :                                 else if (strcmp(item->defname, "transaction_deferrable") == 0)
     628           24 :                                     SetPGVariable("transaction_deferrable",
     629           24 :                                                   list_make1(item->arg),
     630              :                                                   true);
     631              :                             }
     632              :                         }
     633        11620 :                         break;
     634              : 
     635         9236 :                     case TRANS_STMT_COMMIT:
     636         9236 :                         if (!EndTransactionBlock(stmt->chain))
     637              :                         {
     638              :                             /* report unsuccessful commit in qc */
     639          415 :                             if (qc)
     640          415 :                                 SetQueryCompletion(qc, CMDTAG_ROLLBACK, 0);
     641              :                         }
     642         9221 :                         break;
     643              : 
     644          321 :                     case TRANS_STMT_PREPARE:
     645          321 :                         if (!PrepareTransactionBlock(stmt->gid))
     646              :                         {
     647              :                             /* report unsuccessful commit in qc */
     648            2 :                             if (qc)
     649            2 :                                 SetQueryCompletion(qc, CMDTAG_ROLLBACK, 0);
     650              :                         }
     651          321 :                         break;
     652              : 
     653          237 :                     case TRANS_STMT_COMMIT_PREPARED:
     654          237 :                         PreventInTransactionBlock(isTopLevel, "COMMIT PREPARED");
     655          237 :                         FinishPreparedTransaction(stmt->gid, true);
     656          232 :                         break;
     657              : 
     658           46 :                     case TRANS_STMT_ROLLBACK_PREPARED:
     659           46 :                         PreventInTransactionBlock(isTopLevel, "ROLLBACK PREPARED");
     660           46 :                         FinishPreparedTransaction(stmt->gid, false);
     661           44 :                         break;
     662              : 
     663         1775 :                     case TRANS_STMT_ROLLBACK:
     664         1775 :                         UserAbortTransactionBlock(stmt->chain);
     665         1760 :                         break;
     666              : 
     667          990 :                     case TRANS_STMT_SAVEPOINT:
     668          990 :                         RequireTransactionBlock(isTopLevel, "SAVEPOINT");
     669          983 :                         DefineSavepoint(stmt->savepoint_name);
     670          977 :                         break;
     671              : 
     672          148 :                     case TRANS_STMT_RELEASE:
     673          148 :                         RequireTransactionBlock(isTopLevel, "RELEASE SAVEPOINT");
     674          145 :                         ReleaseSavepoint(stmt->savepoint_name);
     675          142 :                         break;
     676              : 
     677          373 :                     case TRANS_STMT_ROLLBACK_TO:
     678          373 :                         RequireTransactionBlock(isTopLevel, "ROLLBACK TO SAVEPOINT");
     679          370 :                         RollbackToSavepoint(stmt->savepoint_name);
     680              : 
     681              :                         /*
     682              :                          * CommitTransactionCommand is in charge of
     683              :                          * re-defining the savepoint again
     684              :                          */
     685          364 :                         break;
     686              :                 }
     687              :             }
     688        24681 :             break;
     689              : 
     690              :             /*
     691              :              * Portal (cursor) manipulation
     692              :              */
     693         2257 :         case T_DeclareCursorStmt:
     694         2257 :             PerformCursorOpen(pstate, (DeclareCursorStmt *) parsetree, params,
     695              :                               isTopLevel);
     696         2250 :             break;
     697              : 
     698         1131 :         case T_ClosePortalStmt:
     699              :             {
     700         1131 :                 ClosePortalStmt *stmt = (ClosePortalStmt *) parsetree;
     701              : 
     702         1131 :                 CheckRestrictedOperation("CLOSE");
     703         1131 :                 PerformPortalClose(stmt->portalname);
     704              :             }
     705         1130 :             break;
     706              : 
     707         3871 :         case T_FetchStmt:
     708         3871 :             PerformPortalFetch((FetchStmt *) parsetree, dest, qc);
     709         3821 :             break;
     710              : 
     711          796 :         case T_DoStmt:
     712          796 :             ExecuteDoStmt(pstate, (DoStmt *) parsetree, isAtomicContext);
     713          591 :             break;
     714              : 
     715           70 :         case T_CreateTableSpaceStmt:
     716              :             /* no event triggers for global objects */
     717           70 :             PreventInTransactionBlock(isTopLevel, "CREATE TABLESPACE");
     718           70 :             CreateTableSpace((CreateTableSpaceStmt *) parsetree);
     719           54 :             break;
     720              : 
     721           32 :         case T_DropTableSpaceStmt:
     722              :             /* no event triggers for global objects */
     723           32 :             PreventInTransactionBlock(isTopLevel, "DROP TABLESPACE");
     724           32 :             DropTableSpace((DropTableSpaceStmt *) parsetree);
     725           25 :             break;
     726              : 
     727           12 :         case T_AlterTableSpaceOptionsStmt:
     728              :             /* no event triggers for global objects */
     729           12 :             AlterTableSpaceOptions((AlterTableSpaceOptionsStmt *) parsetree);
     730            6 :             break;
     731              : 
     732          930 :         case T_TruncateStmt:
     733          930 :             ExecuteTruncate((TruncateStmt *) parsetree);
     734          861 :             break;
     735              : 
     736         5915 :         case T_CopyStmt:
     737              :             {
     738              :                 uint64      processed;
     739              : 
     740         5915 :                 DoCopy(pstate, (CopyStmt *) parsetree,
     741              :                        pstmt->stmt_location, pstmt->stmt_len,
     742              :                        &processed);
     743         5402 :                 if (qc)
     744         5402 :                     SetQueryCompletion(qc, CMDTAG_COPY, processed);
     745              :             }
     746         5402 :             break;
     747              : 
     748         1089 :         case T_PrepareStmt:
     749         1089 :             CheckRestrictedOperation("PREPARE");
     750         1089 :             PrepareQuery(pstate, (PrepareStmt *) parsetree,
     751              :                          pstmt->stmt_location, pstmt->stmt_len);
     752         1083 :             break;
     753              : 
     754         8152 :         case T_ExecuteStmt:
     755         8152 :             ExecuteQuery(pstate,
     756              :                          (ExecuteStmt *) parsetree, NULL,
     757              :                          params,
     758              :                          dest, qc);
     759         8100 :             break;
     760              : 
     761         2051 :         case T_DeallocateStmt:
     762         2051 :             CheckRestrictedOperation("DEALLOCATE");
     763         2051 :             DeallocateQuery((DeallocateStmt *) parsetree);
     764         2051 :             break;
     765              : 
     766          321 :         case T_GrantRoleStmt:
     767              :             /* no event triggers for global objects */
     768          321 :             GrantRole(pstate, (GrantRoleStmt *) parsetree);
     769          258 :             break;
     770              : 
     771          422 :         case T_CreatedbStmt:
     772              :             /* no event triggers for global objects */
     773          422 :             PreventInTransactionBlock(isTopLevel, "CREATE DATABASE");
     774          422 :             createdb(pstate, (CreatedbStmt *) parsetree);
     775          398 :             break;
     776              : 
     777           46 :         case T_AlterDatabaseStmt:
     778              :             /* no event triggers for global objects */
     779           46 :             AlterDatabase(pstate, (AlterDatabaseStmt *) parsetree, isTopLevel);
     780           45 :             break;
     781              : 
     782            3 :         case T_AlterDatabaseRefreshCollStmt:
     783              :             /* no event triggers for global objects */
     784            3 :             AlterDatabaseRefreshColl((AlterDatabaseRefreshCollStmt *) parsetree);
     785            3 :             break;
     786              : 
     787          645 :         case T_AlterDatabaseSetStmt:
     788              :             /* no event triggers for global objects */
     789          645 :             AlterDatabaseSet((AlterDatabaseSetStmt *) parsetree);
     790          643 :             break;
     791              : 
     792           67 :         case T_DropdbStmt:
     793              :             /* no event triggers for global objects */
     794           67 :             PreventInTransactionBlock(isTopLevel, "DROP DATABASE");
     795           67 :             DropDatabase(pstate, (DropdbStmt *) parsetree);
     796           57 :             break;
     797              : 
     798              :             /* Query-level asynchronous notification */
     799           61 :         case T_NotifyStmt:
     800              :             {
     801           61 :                 NotifyStmt *stmt = (NotifyStmt *) parsetree;
     802              : 
     803           61 :                 Async_Notify(stmt->conditionname, stmt->payload);
     804              :             }
     805           61 :             break;
     806              : 
     807           58 :         case T_ListenStmt:
     808              :             {
     809           58 :                 ListenStmt *stmt = (ListenStmt *) parsetree;
     810              : 
     811           58 :                 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           58 :                 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           58 :                 Async_Listen(stmt->conditionname);
     830              :             }
     831           58 :             break;
     832              : 
     833           78 :         case T_UnlistenStmt:
     834              :             {
     835           78 :                 UnlistenStmt *stmt = (UnlistenStmt *) parsetree;
     836              : 
     837           78 :                 CheckRestrictedOperation("UNLISTEN");
     838           78 :                 if (stmt->conditionname)
     839            3 :                     Async_Unlisten(stmt->conditionname);
     840              :                 else
     841           75 :                     Async_UnlistenAll();
     842              :             }
     843           78 :             break;
     844              : 
     845           40 :         case T_LoadStmt:
     846              :             {
     847           40 :                 LoadStmt   *stmt = (LoadStmt *) parsetree;
     848              : 
     849           40 :                 closeAllVfds(); /* probably not necessary... */
     850              :                 /* Allowed names are restricted if you're not superuser */
     851           40 :                 load_file(stmt->filename, !superuser());
     852              :             }
     853           40 :             break;
     854              : 
     855          246 :         case T_CallStmt:
     856          246 :             ExecuteCallStmt(castNode(CallStmt, parsetree), params, isAtomicContext, dest);
     857          224 :             break;
     858              : 
     859         7455 :         case T_VacuumStmt:
     860         7455 :             ExecVacuum(pstate, (VacuumStmt *) parsetree, isTopLevel);
     861         7356 :             break;
     862              : 
     863          144 :         case T_RepackStmt:
     864          144 :             ExecRepack(pstate, (RepackStmt *) parsetree, isTopLevel);
     865          123 :             break;
     866              : 
     867        12704 :         case T_ExplainStmt:
     868        12704 :             ExplainQuery(pstate, (ExplainStmt *) parsetree, params, dest);
     869        12638 :             break;
     870              : 
     871          111 :         case T_AlterSystemStmt:
     872          111 :             PreventInTransactionBlock(isTopLevel, "ALTER SYSTEM");
     873          111 :             AlterSystemSetConfigFile((AlterSystemStmt *) parsetree);
     874           82 :             break;
     875              : 
     876        20816 :         case T_VariableSetStmt:
     877        20816 :             ExecSetVariableStmt((VariableSetStmt *) parsetree, isTopLevel);
     878        20672 :             break;
     879              : 
     880          436 :         case T_VariableShowStmt:
     881              :             {
     882          436 :                 VariableShowStmt *n = (VariableShowStmt *) parsetree;
     883              : 
     884          436 :                 GetPGVariable(n->name, dest);
     885              :             }
     886          436 :             break;
     887              : 
     888           19 :         case T_DiscardStmt:
     889              :             /* should we allow DISCARD PLANS? */
     890           19 :             CheckRestrictedOperation("DISCARD");
     891           19 :             DiscardCommand((DiscardStmt *) parsetree, isTopLevel);
     892           19 :             break;
     893              : 
     894          100 :         case T_CreateEventTrigStmt:
     895              :             /* no event triggers on event triggers */
     896          100 :             CreateEventTrigger((CreateEventTrigStmt *) parsetree);
     897           67 :             break;
     898              : 
     899           24 :         case T_AlterEventTrigStmt:
     900              :             /* no event triggers on event triggers */
     901           24 :             AlterEventTrigger((AlterEventTrigStmt *) parsetree);
     902           24 :             break;
     903              : 
     904              :             /*
     905              :              * ******************************** ROLE statements ****
     906              :              */
     907          973 :         case T_CreateRoleStmt:
     908              :             /* no event triggers for global objects */
     909          973 :             CreateRole(pstate, (CreateRoleStmt *) parsetree);
     910          905 :             break;
     911              : 
     912          239 :         case T_AlterRoleStmt:
     913              :             /* no event triggers for global objects */
     914          239 :             AlterRole(pstate, (AlterRoleStmt *) parsetree);
     915          194 :             break;
     916              : 
     917           46 :         case T_AlterRoleSetStmt:
     918              :             /* no event triggers for global objects */
     919           46 :             AlterRoleSet((AlterRoleSetStmt *) parsetree);
     920           40 :             break;
     921              : 
     922          887 :         case T_DropRoleStmt:
     923              :             /* no event triggers for global objects */
     924          887 :             DropRole((DropRoleStmt *) parsetree);
     925          770 :             break;
     926              : 
     927           23 :         case T_ReassignOwnedStmt:
     928              :             /* no event triggers for global objects */
     929           23 :             ReassignOwnedObjects((ReassignOwnedStmt *) parsetree);
     930           14 :             break;
     931              : 
     932          580 :         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          580 :             RequireTransactionBlock(isTopLevel, "LOCK TABLE");
     939          576 :             LockTableCommand((LockStmt *) parsetree);
     940          538 :             break;
     941              : 
     942           51 :         case T_ConstraintsSetStmt:
     943           51 :             WarnNoTransactionBlock(isTopLevel, "SET CONSTRAINTS");
     944           51 :             AfterTriggerSetState((ConstraintsSetStmt *) parsetree);
     945           43 :             break;
     946              : 
     947          452 :         case T_CheckPointStmt:
     948          452 :             ExecCheckpoint(pstate, (CheckPointStmt *) parsetree);
     949          446 :             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        10831 :         case T_GrantStmt:
     957              :             {
     958        10831 :                 GrantStmt  *stmt = (GrantStmt *) parsetree;
     959              : 
     960        10831 :                 if (EventTriggerSupportsObjectType(stmt->objtype))
     961        10606 :                     ProcessUtilitySlow(pstate, pstmt, queryString,
     962              :                                        context, params, queryEnv,
     963              :                                        dest, qc);
     964              :                 else
     965          225 :                     ExecuteGrantStmt(stmt);
     966              :             }
     967        10761 :             break;
     968              : 
     969        13732 :         case T_DropStmt:
     970              :             {
     971        13732 :                 DropStmt   *stmt = (DropStmt *) parsetree;
     972              : 
     973        13732 :                 if (EventTriggerSupportsObjectType(stmt->removeType))
     974        13670 :                     ProcessUtilitySlow(pstate, pstmt, queryString,
     975              :                                        context, params, queryEnv,
     976              :                                        dest, qc);
     977              :                 else
     978           62 :                     ExecDropStmt(stmt, isTopLevel);
     979              :             }
     980        13236 :             break;
     981              : 
     982          779 :         case T_RenameStmt:
     983              :             {
     984          779 :                 RenameStmt *stmt = (RenameStmt *) parsetree;
     985              : 
     986          779 :                 if (EventTriggerSupportsObjectType(stmt->renameType))
     987          745 :                     ProcessUtilitySlow(pstate, pstmt, queryString,
     988              :                                        context, params, queryEnv,
     989              :                                        dest, qc);
     990              :                 else
     991           34 :                     ExecRenameStmt(stmt);
     992              :             }
     993          577 :             break;
     994              : 
     995           23 :         case T_AlterObjectDependsStmt:
     996              :             {
     997           23 :                 AlterObjectDependsStmt *stmt = (AlterObjectDependsStmt *) parsetree;
     998              : 
     999           23 :                 if (EventTriggerSupportsObjectType(stmt->objectType))
    1000           23 :                     ProcessUtilitySlow(pstate, pstmt, queryString,
    1001              :                                        context, params, queryEnv,
    1002              :                                        dest, qc);
    1003              :                 else
    1004            0 :                     ExecAlterObjectDependsStmt(stmt, NULL);
    1005              :             }
    1006           23 :             break;
    1007              : 
    1008          199 :         case T_AlterObjectSchemaStmt:
    1009              :             {
    1010          199 :                 AlterObjectSchemaStmt *stmt = (AlterObjectSchemaStmt *) parsetree;
    1011              : 
    1012          199 :                 if (EventTriggerSupportsObjectType(stmt->objectType))
    1013          199 :                     ProcessUtilitySlow(pstate, pstmt, queryString,
    1014              :                                        context, params, queryEnv,
    1015              :                                        dest, qc);
    1016              :                 else
    1017            0 :                     ExecAlterObjectSchemaStmt(stmt, NULL);
    1018              :             }
    1019          133 :             break;
    1020              : 
    1021          842 :         case T_AlterOwnerStmt:
    1022              :             {
    1023          842 :                 AlterOwnerStmt *stmt = (AlterOwnerStmt *) parsetree;
    1024              : 
    1025          842 :                 if (EventTriggerSupportsObjectType(stmt->objectType))
    1026          787 :                     ProcessUtilitySlow(pstate, pstmt, queryString,
    1027              :                                        context, params, queryEnv,
    1028              :                                        dest, qc);
    1029              :                 else
    1030           55 :                     ExecAlterOwnerStmt(stmt);
    1031              :             }
    1032          715 :             break;
    1033              : 
    1034         3899 :         case T_CommentStmt:
    1035              :             {
    1036         3899 :                 CommentStmt *stmt = (CommentStmt *) parsetree;
    1037              : 
    1038         3899 :                 if (EventTriggerSupportsObjectType(stmt->objtype))
    1039         3758 :                     ProcessUtilitySlow(pstate, pstmt, queryString,
    1040              :                                        context, params, queryEnv,
    1041              :                                        dest, qc);
    1042              :                 else
    1043          141 :                     CommentObject(stmt);
    1044         3820 :                 break;
    1045              :             }
    1046              : 
    1047           59 :         case T_SecLabelStmt:
    1048              :             {
    1049           59 :                 SecLabelStmt *stmt = (SecLabelStmt *) parsetree;
    1050              : 
    1051           59 :                 if (EventTriggerSupportsObjectType(stmt->objtype))
    1052           40 :                     ProcessUtilitySlow(pstate, pstmt, queryString,
    1053              :                                        context, params, queryEnv,
    1054              :                                        dest, qc);
    1055              :                 else
    1056           19 :                     ExecSecLabelStmt(stmt);
    1057           23 :                 break;
    1058              :             }
    1059              : 
    1060           55 :         case T_WaitStmt:
    1061              :             {
    1062           55 :                 ExecWaitStmt(pstate, (WaitStmt *) parsetree, dest);
    1063              :             }
    1064           38 :             break;
    1065              : 
    1066        89702 :         default:
    1067              :             /* All other statement types have event trigger support */
    1068        89702 :             ProcessUtilitySlow(pstate, pstmt, queryString,
    1069              :                                context, params, queryEnv,
    1070              :                                dest, qc);
    1071        83982 :             break;
    1072              :     }
    1073              : 
    1074       209595 :     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       209595 :     CommandCounterIncrement();
    1082       209595 : }
    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       119530 : 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       119530 :     Node       *parsetree = pstmt->utilityStmt;
    1100       119530 :     bool        isTopLevel = (context == PROCESS_UTILITY_TOPLEVEL);
    1101       119530 :     bool        isCompleteQuery = (context != PROCESS_UTILITY_SUBCOMMAND);
    1102              :     bool        needCleanup;
    1103       119530 :     bool        commandCollected = false;
    1104              :     ObjectAddress address;
    1105       119530 :     ObjectAddress secondaryObject = InvalidObjectAddress;
    1106              : 
    1107              :     /* All event trigger calls are done only when isCompleteQuery is true */
    1108       119530 :     needCleanup = isCompleteQuery && EventTriggerBeginCompleteQuery();
    1109              : 
    1110              :     /* PG_TRY block is to ensure we call EventTriggerEndCompleteQuery */
    1111       119530 :     PG_TRY();
    1112              :     {
    1113       119530 :         if (isCompleteQuery)
    1114       113072 :             EventTriggerDDLCommandStart(parsetree);
    1115              : 
    1116       119530 :         switch (nodeTag(parsetree))
    1117              :         {
    1118              :                 /*
    1119              :                  * relation and attribute manipulation
    1120              :                  */
    1121          565 :             case T_CreateSchemaStmt:
    1122          565 :                 CreateSchemaCommand((CreateSchemaStmt *) parsetree,
    1123              :                                     queryString,
    1124              :                                     pstmt->stmt_location,
    1125              :                                     pstmt->stmt_len);
    1126              : 
    1127              :                 /*
    1128              :                  * EventTriggerCollectSimpleCommand called by
    1129              :                  * CreateSchemaCommand
    1130              :                  */
    1131          500 :                 commandCollected = true;
    1132          500 :                 break;
    1133              : 
    1134        20484 :             case T_CreateStmt:
    1135              :             case T_CreateForeignTableStmt:
    1136              :                 {
    1137              :                     List       *stmts;
    1138        20484 :                     RangeVar   *table_rv = NULL;
    1139              : 
    1140              :                     /* Run parse analysis ... */
    1141        20484 :                     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        45689 :                     while (stmts != NIL)
    1150              :                     {
    1151        26297 :                         Node       *stmt = (Node *) linitial(stmts);
    1152              : 
    1153        26297 :                         stmts = list_delete_first(stmts);
    1154              : 
    1155        26297 :                         if (IsA(stmt, CreateStmt))
    1156              :                         {
    1157        20065 :                             CreateStmt *cstmt = (CreateStmt *) stmt;
    1158              :                             Datum       toast_options;
    1159        20065 :                             const char *const validnsps[] = HEAP_RELOPT_NAMESPACES;
    1160              : 
    1161              :                             /* Remember transformed RangeVar for LIKE */
    1162        20065 :                             table_rv = cstmt->relation;
    1163              : 
    1164              :                             /* Create the table itself */
    1165        20065 :                             address = DefineRelation(cstmt,
    1166              :                                                      RELKIND_RELATION,
    1167              :                                                      InvalidOid, NULL,
    1168              :                                                      queryString);
    1169        19406 :                             EventTriggerCollectSimpleCommand(address,
    1170              :                                                              secondaryObject,
    1171              :                                                              stmt);
    1172              : 
    1173              :                             /*
    1174              :                              * Let NewRelationCreateToastTable decide if this
    1175              :                              * one needs a secondary relation too.
    1176              :                              */
    1177        19406 :                             CommandCounterIncrement();
    1178              : 
    1179              :                             /*
    1180              :                              * parse and validate reloptions for the toast
    1181              :                              * table
    1182              :                              */
    1183        19406 :                             toast_options = transformRelOptions((Datum) 0,
    1184              :                                                                 cstmt->options,
    1185              :                                                                 "toast",
    1186              :                                                                 validnsps,
    1187              :                                                                 true,
    1188              :                                                                 false);
    1189        19406 :                             (void) heap_reloptions(RELKIND_TOASTVALUE,
    1190              :                                                    toast_options,
    1191              :                                                    true);
    1192              : 
    1193        19403 :                             NewRelationCreateToastTable(address.objectId,
    1194              :                                                         toast_options);
    1195              :                         }
    1196         6232 :                         else if (IsA(stmt, CreateForeignTableStmt))
    1197              :                         {
    1198          251 :                             CreateForeignTableStmt *cstmt = (CreateForeignTableStmt *) stmt;
    1199              : 
    1200              :                             /* Remember transformed RangeVar for LIKE */
    1201          251 :                             table_rv = cstmt->base.relation;
    1202              : 
    1203              :                             /* Create the table itself */
    1204          251 :                             address = DefineRelation(&cstmt->base,
    1205              :                                                      RELKIND_FOREIGN_TABLE,
    1206              :                                                      InvalidOid, NULL,
    1207              :                                                      queryString);
    1208          238 :                             CreateForeignTable(cstmt,
    1209              :                                                address.objectId);
    1210          200 :                             EventTriggerCollectSimpleCommand(address,
    1211              :                                                              secondaryObject,
    1212              :                                                              stmt);
    1213              :                         }
    1214         5981 :                         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           97 :                             TableLikeClause *like = (TableLikeClause *) stmt;
    1223              :                             List       *morestmts;
    1224              : 
    1225              :                             Assert(table_rv != NULL);
    1226              : 
    1227           97 :                             morestmts = expandTableLikeClause(table_rv, like);
    1228           97 :                             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         5884 :                             wrapper = makeNode(PlannedStmt);
    1240         5884 :                             wrapper->commandType = CMD_UTILITY;
    1241         5884 :                             wrapper->canSetTag = false;
    1242         5884 :                             wrapper->utilityStmt = stmt;
    1243         5884 :                             wrapper->stmt_location = pstmt->stmt_location;
    1244         5884 :                             wrapper->stmt_len = pstmt->stmt_len;
    1245         5884 :                             wrapper->planOrigin = PLAN_STMT_INTERNAL;
    1246              : 
    1247         5884 :                             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        25366 :                         if (stmts != NIL)
    1259         5978 :                             CommandCounterIncrement();
    1260              :                     }
    1261              : 
    1262              :                     /*
    1263              :                      * The multiple commands generated here are stashed
    1264              :                      * individually, so disable collection below.
    1265              :                      */
    1266        19392 :                     commandCollected = true;
    1267              :                 }
    1268        19392 :                 break;
    1269              : 
    1270        17064 :             case T_AlterTableStmt:
    1271              :                 {
    1272        17064 :                     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        34727 :                     foreach(cell, atstmt->cmds)
    1283              :                     {
    1284        17666 :                         AlterTableCmd *cmd = (AlterTableCmd *) lfirst(cell);
    1285              : 
    1286              :                         /* Disallow DETACH CONCURRENTLY in a transaction block */
    1287        17666 :                         if (cmd->subtype == AT_DetachPartition)
    1288              :                         {
    1289          304 :                             if (((PartitionCmd *) cmd->def)->concurrent)
    1290           85 :                                 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        17061 :                     lockmode = AlterTableGetLockLevel(atstmt->cmds);
    1302        17061 :                     relid = AlterTableLookupRelation(atstmt, lockmode);
    1303              : 
    1304        17011 :                     if (OidIsValid(relid))
    1305              :                     {
    1306              :                         AlterTableUtilityContext atcontext;
    1307              : 
    1308              :                         /* Set up info needed for recursive callbacks ... */
    1309        16930 :                         atcontext.pstmt = pstmt;
    1310        16930 :                         atcontext.queryString = queryString;
    1311        16930 :                         atcontext.relid = relid;
    1312        16930 :                         atcontext.params = params;
    1313        16930 :                         atcontext.queryEnv = queryEnv;
    1314              : 
    1315              :                         /* ... ensure we have an event trigger context ... */
    1316        16930 :                         EventTriggerAlterTableStart(parsetree);
    1317        16930 :                         EventTriggerAlterTableRelid(relid);
    1318              : 
    1319              :                         /* ... and do it */
    1320        16930 :                         AlterTable(atstmt, lockmode, &atcontext);
    1321              : 
    1322              :                         /* done */
    1323        14842 :                         EventTriggerAlterTableEnd();
    1324              :                     }
    1325              :                     else
    1326           81 :                         ereport(NOTICE,
    1327              :                                 (errmsg("relation \"%s\" does not exist, skipping",
    1328              :                                         atstmt->relation->relname)));
    1329              :                 }
    1330              : 
    1331              :                 /* ALTER TABLE stashes commands internally */
    1332        14923 :                 commandCollected = true;
    1333        14923 :                 break;
    1334              : 
    1335          145 :             case T_AlterDomainStmt:
    1336              :                 {
    1337          145 :                     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          145 :                     switch (stmt->subtype)
    1344              :                     {
    1345            7 :                         case AD_AlterDefault:
    1346              : 
    1347              :                             /*
    1348              :                              * Recursively alter column default for table and,
    1349              :                              * if requested, for descendants
    1350              :                              */
    1351              :                             address =
    1352            7 :                                 AlterDomainDefault(stmt->typeName,
    1353              :                                                    stmt->def);
    1354            7 :                             break;
    1355            6 :                         case AD_DropNotNull:
    1356              :                             address =
    1357            6 :                                 AlterDomainNotNull(stmt->typeName,
    1358              :                                                    false);
    1359            6 :                             break;
    1360           12 :                         case AD_SetNotNull:
    1361              :                             address =
    1362           12 :                                 AlterDomainNotNull(stmt->typeName,
    1363              :                                                    true);
    1364            6 :                             break;
    1365           84 :                         case AD_AddConstraint:
    1366              :                             address =
    1367           84 :                                 AlterDomainAddConstraint(stmt->typeName,
    1368              :                                                          stmt->def,
    1369              :                                                          &secondaryObject);
    1370           48 :                             break;
    1371           30 :                         case AD_DropConstraint:
    1372              :                             address =
    1373           30 :                                 AlterDomainDropConstraint(stmt->typeName,
    1374           30 :                                                           stmt->name,
    1375              :                                                           stmt->behavior,
    1376           30 :                                                           stmt->missing_ok);
    1377           27 :                             break;
    1378            6 :                         case AD_ValidateConstraint:
    1379              :                             address =
    1380            6 :                                 AlterDomainValidateConstraint(stmt->typeName,
    1381            6 :                                                               stmt->name);
    1382            3 :                             break;
    1383            0 :                         default:    /* oops */
    1384            0 :                             elog(ERROR, "unrecognized alter domain type: %d",
    1385              :                                  (int) stmt->subtype);
    1386              :                             break;
    1387              :                     }
    1388              :                 }
    1389           97 :                 break;
    1390              : 
    1391              :                 /*
    1392              :                  * ************* object creation / destruction **************
    1393              :                  */
    1394         4907 :             case T_DefineStmt:
    1395              :                 {
    1396         4907 :                     DefineStmt *stmt = (DefineStmt *) parsetree;
    1397              : 
    1398         4907 :                     switch (stmt->kind)
    1399              :                     {
    1400          453 :                         case OBJECT_AGGREGATE:
    1401              :                             address =
    1402          453 :                                 DefineAggregate(pstate, stmt->defnames, stmt->args,
    1403          453 :                                                 stmt->oldstyle,
    1404              :                                                 stmt->definition,
    1405          453 :                                                 stmt->replace);
    1406          288 :                             break;
    1407          826 :                         case OBJECT_OPERATOR:
    1408              :                             Assert(stmt->args == NIL);
    1409          826 :                             address = DefineOperator(stmt->defnames,
    1410              :                                                      stmt->definition);
    1411          777 :                             break;
    1412          199 :                         case OBJECT_TYPE:
    1413              :                             Assert(stmt->args == NIL);
    1414          199 :                             address = DefineType(pstate,
    1415              :                                                  stmt->defnames,
    1416              :                                                  stmt->definition);
    1417          181 :                             break;
    1418           20 :                         case OBJECT_TSPARSER:
    1419              :                             Assert(stmt->args == NIL);
    1420           20 :                             address = DefineTSParser(stmt->defnames,
    1421              :                                                      stmt->definition);
    1422           17 :                             break;
    1423         1592 :                         case OBJECT_TSDICTIONARY:
    1424              :                             Assert(stmt->args == NIL);
    1425         1592 :                             address = DefineTSDictionary(stmt->defnames,
    1426              :                                                          stmt->definition);
    1427         1580 :                             break;
    1428           71 :                         case OBJECT_TSTEMPLATE:
    1429              :                             Assert(stmt->args == NIL);
    1430           71 :                             address = DefineTSTemplate(stmt->defnames,
    1431              :                                                        stmt->definition);
    1432           68 :                             break;
    1433         1564 :                         case OBJECT_TSCONFIGURATION:
    1434              :                             Assert(stmt->args == NIL);
    1435         1564 :                             address = DefineTSConfiguration(stmt->defnames,
    1436              :                                                             stmt->definition,
    1437              :                                                             &secondaryObject);
    1438         1564 :                             break;
    1439          182 :                         case OBJECT_COLLATION:
    1440              :                             Assert(stmt->args == NIL);
    1441          182 :                             address = DefineCollation(pstate,
    1442              :                                                       stmt->defnames,
    1443              :                                                       stmt->definition,
    1444          182 :                                                       stmt->if_not_exists);
    1445          109 :                             break;
    1446            0 :                         default:
    1447            0 :                             elog(ERROR, "unrecognized define stmt type: %d",
    1448              :                                  (int) stmt->kind);
    1449              :                             break;
    1450              :                     }
    1451              :                 }
    1452         4584 :                 break;
    1453              : 
    1454         7217 :             case T_IndexStmt:   /* CREATE INDEX */
    1455              :                 {
    1456         7217 :                     IndexStmt  *stmt = (IndexStmt *) parsetree;
    1457              :                     Oid         relid;
    1458              :                     LOCKMODE    lockmode;
    1459         7217 :                     int         nparts = -1;
    1460              :                     bool        is_alter_table;
    1461              : 
    1462         7217 :                     if (stmt->concurrent)
    1463          134 :                         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        14422 :                     lockmode = stmt->concurrent ? ShareUpdateExclusiveLock
    1476         7211 :                         : ShareLock;
    1477              :                     relid =
    1478         7211 :                         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         7210 :                     if (stmt->relation->inh &&
    1495         7108 :                         get_rel_relkind(relid) == RELKIND_PARTITIONED_TABLE)
    1496              :                     {
    1497              :                         ListCell   *lc;
    1498          743 :                         List       *inheritors = NIL;
    1499              : 
    1500          743 :                         inheritors = find_all_inheritors(relid, lockmode, NULL);
    1501         1956 :                         foreach(lc, inheritors)
    1502              :                         {
    1503         1219 :                             Oid         partrelid = lfirst_oid(lc);
    1504         1219 :                             char        relkind = get_rel_relkind(partrelid);
    1505              : 
    1506         1219 :                             if (relkind != RELKIND_RELATION &&
    1507          814 :                                 relkind != RELKIND_MATVIEW &&
    1508            9 :                                 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         1219 :                             if (relkind == RELKIND_FOREIGN_TABLE &&
    1514            9 :                                 (stmt->unique || stmt->primary))
    1515            6 :                                 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          737 :                         nparts = list_length(inheritors) - 1;
    1524          737 :                         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         7204 :                     is_alter_table = stmt->transformed;
    1537              : 
    1538              :                     /* Run parse analysis ... */
    1539         7204 :                     stmt = transformIndexStmt(relid, stmt, queryString);
    1540              : 
    1541              :                     /* ... and do it */
    1542         7198 :                     EventTriggerAlterTableStart(parsetree);
    1543              :                     address =
    1544         7198 :                         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         6908 :                     EventTriggerCollectSimpleCommand(address, secondaryObject,
    1563              :                                                      parsetree);
    1564         6908 :                     commandCollected = true;
    1565         6908 :                     EventTriggerAlterTableEnd();
    1566              :                 }
    1567         6908 :                 break;
    1568              : 
    1569          567 :             case T_ReindexStmt:
    1570          567 :                 ExecReindex(pstate, (ReindexStmt *) parsetree, isTopLevel);
    1571              : 
    1572              :                 /* EventTriggerCollectSimpleCommand is called directly */
    1573          406 :                 commandCollected = true;
    1574          406 :                 break;
    1575              : 
    1576          293 :             case T_CreateExtensionStmt:
    1577          293 :                 address = CreateExtension(pstate, (CreateExtensionStmt *) parsetree);
    1578          271 :                 break;
    1579              : 
    1580           19 :             case T_AlterExtensionStmt:
    1581           19 :                 address = ExecAlterExtensionStmt(pstate, (AlterExtensionStmt *) parsetree);
    1582           17 :                 break;
    1583              : 
    1584          128 :             case T_AlterExtensionContentsStmt:
    1585          128 :                 address = ExecAlterExtensionContentsStmt((AlterExtensionContentsStmt *) parsetree,
    1586              :                                                          &secondaryObject);
    1587          127 :                 break;
    1588              : 
    1589          106 :             case T_CreateFdwStmt:
    1590          106 :                 address = CreateForeignDataWrapper(pstate, (CreateFdwStmt *) parsetree);
    1591           81 :                 break;
    1592              : 
    1593           68 :             case T_AlterFdwStmt:
    1594           68 :                 address = AlterForeignDataWrapper(pstate, (AlterFdwStmt *) parsetree);
    1595           31 :                 break;
    1596              : 
    1597          154 :             case T_CreateForeignServerStmt:
    1598          154 :                 address = CreateForeignServer((CreateForeignServerStmt *) parsetree);
    1599          129 :                 break;
    1600              : 
    1601          116 :             case T_AlterForeignServerStmt:
    1602          116 :                 address = AlterForeignServer((AlterForeignServerStmt *) parsetree);
    1603           89 :                 break;
    1604              : 
    1605          134 :             case T_CreateUserMappingStmt:
    1606          134 :                 address = CreateUserMapping((CreateUserMappingStmt *) parsetree);
    1607          100 :                 break;
    1608              : 
    1609           59 :             case T_AlterUserMappingStmt:
    1610           59 :                 address = AlterUserMapping((AlterUserMappingStmt *) parsetree);
    1611           29 :                 break;
    1612              : 
    1613           66 :             case T_DropUserMappingStmt:
    1614           66 :                 RemoveUserMapping((DropUserMappingStmt *) parsetree);
    1615              :                 /* no commands stashed for DROP */
    1616           47 :                 commandCollected = true;
    1617           47 :                 break;
    1618              : 
    1619           24 :             case T_ImportForeignSchemaStmt:
    1620           24 :                 ImportForeignSchema((ImportForeignSchemaStmt *) parsetree);
    1621              :                 /* commands are stashed inside ImportForeignSchema */
    1622            7 :                 commandCollected = true;
    1623            7 :                 break;
    1624              : 
    1625         2254 :             case T_CompositeTypeStmt:   /* CREATE TYPE (composite) */
    1626              :                 {
    1627         2254 :                     CompositeTypeStmt *stmt = (CompositeTypeStmt *) parsetree;
    1628              : 
    1629         2254 :                     address = DefineCompositeType(stmt->typevar,
    1630              :                                                   stmt->coldeflist);
    1631              :                 }
    1632         2248 :                 break;
    1633              : 
    1634          222 :             case T_CreateEnumStmt:  /* CREATE TYPE AS ENUM */
    1635          222 :                 address = DefineEnum((CreateEnumStmt *) parsetree);
    1636          218 :                 break;
    1637              : 
    1638           92 :             case T_CreateRangeStmt: /* CREATE TYPE AS RANGE */
    1639           92 :                 address = DefineRange(pstate, (CreateRangeStmt *) parsetree);
    1640           80 :                 break;
    1641              : 
    1642          198 :             case T_AlterEnumStmt:   /* ALTER TYPE (enum) */
    1643          198 :                 address = AlterEnum((AlterEnumStmt *) parsetree);
    1644          183 :                 break;
    1645              : 
    1646         8797 :             case T_ViewStmt:    /* CREATE VIEW */
    1647         8797 :                 EventTriggerAlterTableStart(parsetree);
    1648         8797 :                 address = DefineView((ViewStmt *) parsetree, queryString,
    1649              :                                      pstmt->stmt_location, pstmt->stmt_len);
    1650         8754 :                 EventTriggerCollectSimpleCommand(address, secondaryObject,
    1651              :                                                  parsetree);
    1652              :                 /* stashed internally */
    1653         8754 :                 commandCollected = true;
    1654         8754 :                 EventTriggerAlterTableEnd();
    1655         8754 :                 break;
    1656              : 
    1657        11286 :             case T_CreateFunctionStmt:  /* CREATE FUNCTION */
    1658        11286 :                 address = CreateFunction(pstate, (CreateFunctionStmt *) parsetree);
    1659        11039 :                 break;
    1660              : 
    1661          179 :             case T_AlterFunctionStmt:   /* ALTER FUNCTION */
    1662          179 :                 address = AlterFunction(pstate, (AlterFunctionStmt *) parsetree);
    1663          164 :                 break;
    1664              : 
    1665          554 :             case T_RuleStmt:    /* CREATE RULE */
    1666          554 :                 address = DefineRule((RuleStmt *) parsetree, queryString);
    1667          532 :                 break;
    1668              : 
    1669         1014 :             case T_CreateSeqStmt:
    1670         1014 :                 address = DefineSequence(pstate, (CreateSeqStmt *) parsetree);
    1671          965 :                 break;
    1672              : 
    1673          782 :             case T_AlterSeqStmt:
    1674          782 :                 address = AlterSequence(pstate, (AlterSeqStmt *) parsetree);
    1675          758 :                 break;
    1676              : 
    1677          926 :             case T_CreateTableAsStmt:
    1678          926 :                 address = ExecCreateTableAs(pstate, (CreateTableAsStmt *) parsetree,
    1679              :                                             params, queryEnv, qc);
    1680          873 :                 break;
    1681              : 
    1682          134 :             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          134 :                 EventTriggerInhibitCommandCollection();
    1691          134 :                 PG_TRY(2);
    1692              :                 {
    1693          134 :                     address = ExecRefreshMatView((RefreshMatViewStmt *) parsetree,
    1694              :                                                  queryString, qc);
    1695              :                 }
    1696           36 :                 PG_FINALLY(2);
    1697              :                 {
    1698          134 :                     EventTriggerUndoInhibitCommandCollection();
    1699              :                 }
    1700          134 :                 PG_END_TRY(2);
    1701           98 :                 break;
    1702              : 
    1703         1643 :             case T_CreateTrigStmt:
    1704         1643 :                 address = CreateTrigger((CreateTrigStmt *) parsetree,
    1705              :                                         queryString, InvalidOid, InvalidOid,
    1706              :                                         InvalidOid, InvalidOid, InvalidOid,
    1707              :                                         InvalidOid, NULL, false, false);
    1708         1531 :                 break;
    1709              : 
    1710           72 :             case T_CreatePLangStmt:
    1711           72 :                 address = CreateProceduralLanguage((CreatePLangStmt *) parsetree);
    1712           72 :                 break;
    1713              : 
    1714          758 :             case T_CreateDomainStmt:
    1715          758 :                 address = DefineDomain(pstate, (CreateDomainStmt *) parsetree);
    1716          701 :                 break;
    1717              : 
    1718           32 :             case T_CreateConversionStmt:
    1719           32 :                 address = CreateConversionCommand((CreateConversionStmt *) parsetree);
    1720           26 :                 break;
    1721              : 
    1722          139 :             case T_CreateCastStmt:
    1723          139 :                 address = CreateCast((CreateCastStmt *) parsetree);
    1724          136 :                 break;
    1725              : 
    1726          279 :             case T_CreateOpClassStmt:
    1727          279 :                 DefineOpClass((CreateOpClassStmt *) parsetree);
    1728              :                 /* command is stashed in DefineOpClass */
    1729          279 :                 commandCollected = true;
    1730          279 :                 break;
    1731              : 
    1732           74 :             case T_CreateOpFamilyStmt:
    1733           74 :                 address = DefineOpFamily((CreateOpFamilyStmt *) parsetree);
    1734              : 
    1735              :                 /*
    1736              :                  * DefineOpFamily calls EventTriggerCollectSimpleCommand
    1737              :                  * directly.
    1738              :                  */
    1739           74 :                 commandCollected = true;
    1740           74 :                 break;
    1741              : 
    1742           25 :             case T_CreateTransformStmt:
    1743           25 :                 address = CreateTransform((CreateTransformStmt *) parsetree);
    1744           20 :                 break;
    1745              : 
    1746          229 :             case T_AlterOpFamilyStmt:
    1747          229 :                 AlterOpFamily((AlterOpFamilyStmt *) parsetree);
    1748              :                 /* commands are stashed in AlterOpFamily */
    1749          148 :                 commandCollected = true;
    1750          148 :                 break;
    1751              : 
    1752           20 :             case T_AlterTSDictionaryStmt:
    1753           20 :                 address = AlterTSDictionary((AlterTSDictionaryStmt *) parsetree);
    1754           16 :                 break;
    1755              : 
    1756         4678 :             case T_AlterTSConfigurationStmt:
    1757         4678 :                 AlterTSConfiguration((AlterTSConfigurationStmt *) parsetree);
    1758              : 
    1759              :                 /*
    1760              :                  * Commands are stashed in MakeConfigurationMapping and
    1761              :                  * DropConfigurationMapping, which are called from
    1762              :                  * AlterTSConfiguration
    1763              :                  */
    1764         4666 :                 commandCollected = true;
    1765         4666 :                 break;
    1766              : 
    1767           15 :             case T_AlterTableMoveAllStmt:
    1768           15 :                 AlterTableMoveAll((AlterTableMoveAllStmt *) parsetree);
    1769              :                 /* commands are stashed in AlterTableMoveAll */
    1770           15 :                 commandCollected = true;
    1771           15 :                 break;
    1772              : 
    1773        13670 :             case T_DropStmt:
    1774        13670 :                 ExecDropStmt((DropStmt *) parsetree, isTopLevel);
    1775              :                 /* no commands stashed for DROP */
    1776        13186 :                 commandCollected = true;
    1777        13186 :                 break;
    1778              : 
    1779          745 :             case T_RenameStmt:
    1780          745 :                 address = ExecRenameStmt((RenameStmt *) parsetree);
    1781          552 :                 break;
    1782              : 
    1783           23 :             case T_AlterObjectDependsStmt:
    1784              :                 address =
    1785           23 :                     ExecAlterObjectDependsStmt((AlterObjectDependsStmt *) parsetree,
    1786              :                                                &secondaryObject);
    1787           23 :                 break;
    1788              : 
    1789          199 :             case T_AlterObjectSchemaStmt:
    1790              :                 address =
    1791          199 :                     ExecAlterObjectSchemaStmt((AlterObjectSchemaStmt *) parsetree,
    1792              :                                               &secondaryObject);
    1793          133 :                 break;
    1794              : 
    1795          787 :             case T_AlterOwnerStmt:
    1796          787 :                 address = ExecAlterOwnerStmt((AlterOwnerStmt *) parsetree);
    1797          663 :                 break;
    1798              : 
    1799          304 :             case T_AlterOperatorStmt:
    1800          304 :                 address = AlterOperator((AlterOperatorStmt *) parsetree);
    1801          271 :                 break;
    1802              : 
    1803           32 :             case T_AlterTypeStmt:
    1804           32 :                 address = AlterType((AlterTypeStmt *) parsetree);
    1805           26 :                 break;
    1806              : 
    1807         3758 :             case T_CommentStmt:
    1808         3758 :                 address = CommentObject((CommentStmt *) parsetree);
    1809         3682 :                 break;
    1810              : 
    1811        10606 :             case T_GrantStmt:
    1812        10606 :                 ExecuteGrantStmt((GrantStmt *) parsetree);
    1813              :                 /* commands are stashed in ExecGrantStmt_oids */
    1814        10537 :                 commandCollected = true;
    1815        10537 :                 break;
    1816              : 
    1817           74 :             case T_DropOwnedStmt:
    1818           74 :                 DropOwnedObjects((DropOwnedStmt *) parsetree);
    1819              :                 /* no commands stashed for DROP */
    1820           65 :                 commandCollected = true;
    1821           65 :                 break;
    1822              : 
    1823          103 :             case T_AlterDefaultPrivilegesStmt:
    1824          103 :                 ExecAlterDefaultPrivilegesStmt(pstate, (AlterDefaultPrivilegesStmt *) parsetree);
    1825           97 :                 EventTriggerCollectAlterDefPrivs((AlterDefaultPrivilegesStmt *) parsetree);
    1826           97 :                 commandCollected = true;
    1827           97 :                 break;
    1828              : 
    1829          395 :             case T_CreatePolicyStmt:    /* CREATE POLICY */
    1830          395 :                 address = CreatePolicy((CreatePolicyStmt *) parsetree);
    1831          388 :                 break;
    1832              : 
    1833           42 :             case T_AlterPolicyStmt: /* ALTER POLICY */
    1834           42 :                 address = AlterPolicy((AlterPolicyStmt *) parsetree);
    1835           36 :                 break;
    1836              : 
    1837           40 :             case T_SecLabelStmt:
    1838           40 :                 address = ExecSecLabelStmt((SecLabelStmt *) parsetree);
    1839           21 :                 break;
    1840              : 
    1841           37 :             case T_CreateAmStmt:
    1842           37 :                 address = CreateAccessMethod((CreateAmStmt *) parsetree);
    1843           25 :                 break;
    1844              : 
    1845          479 :             case T_CreatePublicationStmt:
    1846          479 :                 address = CreatePublication(pstate, (CreatePublicationStmt *) parsetree);
    1847          394 :                 break;
    1848              : 
    1849          553 :             case T_AlterPublicationStmt:
    1850          553 :                 AlterPublication(pstate, (AlterPublicationStmt *) parsetree);
    1851              : 
    1852              :                 /*
    1853              :                  * AlterPublication calls EventTriggerCollectSimpleCommand
    1854              :                  * directly
    1855              :                  */
    1856          442 :                 commandCollected = true;
    1857          442 :                 break;
    1858              : 
    1859          261 :             case T_CreateSubscriptionStmt:
    1860          261 :                 address = CreateSubscription(pstate,
    1861              :                                              (CreateSubscriptionStmt *) parsetree,
    1862              :                                              isTopLevel);
    1863          175 :                 break;
    1864              : 
    1865          277 :             case T_AlterSubscriptionStmt:
    1866          277 :                 address = AlterSubscription(pstate,
    1867              :                                             (AlterSubscriptionStmt *) parsetree,
    1868              :                                             isTopLevel);
    1869          217 :                 break;
    1870              : 
    1871          137 :             case T_DropSubscriptionStmt:
    1872          137 :                 DropSubscription((DropSubscriptionStmt *) parsetree, isTopLevel);
    1873              :                 /* no commands stashed for DROP */
    1874          127 :                 commandCollected = true;
    1875          127 :                 break;
    1876              : 
    1877          474 :             case T_CreateStatsStmt:
    1878              :                 {
    1879              :                     Oid         relid;
    1880          474 :                     CreateStatsStmt *stmt = (CreateStatsStmt *) parsetree;
    1881          474 :                     RangeVar   *rel = (RangeVar *) linitial(stmt->relations);
    1882              : 
    1883          474 :                     if (!IsA(rel, RangeVar))
    1884           21 :                         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          453 :                     relid = RangeVarGetRelid(rel, ShareUpdateExclusiveLock, false);
    1900              : 
    1901              :                     /* Run parse analysis ... */
    1902          450 :                     stmt = transformStatsStmt(relid, stmt, queryString);
    1903              : 
    1904          450 :                     address = CreateStatistics(stmt, true);
    1905              :                 }
    1906          372 :                 break;
    1907              : 
    1908           13 :             case T_AlterStatsStmt:
    1909           13 :                 address = AlterStatistics((AlterStatsStmt *) parsetree);
    1910           10 :                 break;
    1911              : 
    1912            3 :             case T_AlterCollationStmt:
    1913            3 :                 address = AlterCollation((AlterCollationStmt *) parsetree);
    1914            3 :                 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       112779 :         if (!commandCollected)
    1927        32206 :             EventTriggerCollectSimpleCommand(address, secondaryObject,
    1928              :                                              parsetree);
    1929              : 
    1930       112779 :         if (isCompleteQuery)
    1931              :         {
    1932       106553 :             EventTriggerSQLDrop(parsetree);
    1933       106544 :             EventTriggerDDLCommandEnd(parsetree);
    1934              :         }
    1935              :     }
    1936         6760 :     PG_FINALLY();
    1937              :     {
    1938       119530 :         if (needCleanup)
    1939         1537 :             EventTriggerEndCompleteQuery();
    1940              :     }
    1941       119530 :     PG_END_TRY();
    1942       112770 : }
    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          292 : 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          292 :     EventTriggerAlterTableEnd();
    1969              : 
    1970              :     /* Create a suitable wrapper */
    1971          292 :     wrapper = makeNode(PlannedStmt);
    1972          292 :     wrapper->commandType = CMD_UTILITY;
    1973          292 :     wrapper->canSetTag = false;
    1974          292 :     wrapper->utilityStmt = stmt;
    1975          292 :     wrapper->stmt_location = context->pstmt->stmt_location;
    1976          292 :     wrapper->stmt_len = context->pstmt->stmt_len;
    1977          292 :     wrapper->planOrigin = PLAN_STMT_INTERNAL;
    1978              : 
    1979          292 :     ProcessUtility(wrapper,
    1980              :                    context->queryString,
    1981              :                    false,
    1982              :                    PROCESS_UTILITY_SUBCOMMAND,
    1983              :                    context->params,
    1984              :                    context->queryEnv,
    1985              :                    None_Receiver,
    1986              :                    NULL);
    1987              : 
    1988          286 :     EventTriggerAlterTableStart(context->pstmt->utilityStmt);
    1989          286 :     EventTriggerAlterTableRelid(context->relid);
    1990          286 : }
    1991              : 
    1992              : /*
    1993              :  * Dispatch function for DropStmt
    1994              :  */
    1995              : static void
    1996        13732 : ExecDropStmt(DropStmt *stmt, bool isTopLevel)
    1997              : {
    1998        13732 :     switch (stmt->removeType)
    1999              :     {
    2000          449 :         case OBJECT_INDEX:
    2001          449 :             if (stmt->concurrent)
    2002          105 :                 PreventInTransactionBlock(isTopLevel,
    2003              :                                           "DROP INDEX CONCURRENTLY");
    2004              :             pg_fallthrough;
    2005              : 
    2006              :         case OBJECT_TABLE:
    2007              :         case OBJECT_SEQUENCE:
    2008              :         case OBJECT_VIEW:
    2009              :         case OBJECT_MATVIEW:
    2010              :         case OBJECT_FOREIGN_TABLE:
    2011         9181 :             RemoveRelations(stmt);
    2012         9029 :             break;
    2013         4548 :         default:
    2014         4548 :             RemoveObjects(stmt);
    2015         4216 :             break;
    2016              :     }
    2017        13245 : }
    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       201104 : UtilityReturnsTuples(Node *parsetree)
    2030              : {
    2031       201104 :     switch (nodeTag(parsetree))
    2032              :     {
    2033          240 :         case T_CallStmt:
    2034              :             {
    2035          240 :                 CallStmt   *stmt = (CallStmt *) parsetree;
    2036              : 
    2037          240 :                 return (stmt->funcexpr->funcresulttype == RECORDOID);
    2038              :             }
    2039         3871 :         case T_FetchStmt:
    2040              :             {
    2041         3871 :                 FetchStmt  *stmt = (FetchStmt *) parsetree;
    2042              :                 Portal      portal;
    2043              : 
    2044         3871 :                 if (stmt->ismove)
    2045           34 :                     return false;
    2046         3837 :                 portal = GetPortalByName(stmt->portalname);
    2047         3837 :                 if (!PortalIsValid(portal))
    2048           16 :                     return false;   /* not our business to raise error */
    2049         3821 :                 return portal->tupDesc ? true : false;
    2050              :             }
    2051              : 
    2052         8155 :         case T_ExecuteStmt:
    2053              :             {
    2054         8155 :                 ExecuteStmt *stmt = (ExecuteStmt *) parsetree;
    2055              :                 PreparedStatement *entry;
    2056              : 
    2057         8155 :                 entry = FetchPreparedStatement(stmt->name, false);
    2058         8155 :                 if (!entry)
    2059            0 :                     return false;   /* not our business to raise error */
    2060         8155 :                 if (entry->plansource->resultDesc)
    2061         8094 :                     return true;
    2062           61 :                 return false;
    2063              :             }
    2064              : 
    2065        16757 :         case T_ExplainStmt:
    2066        16757 :             return true;
    2067              : 
    2068          456 :         case T_VariableShowStmt:
    2069          456 :             return true;
    2070              : 
    2071           55 :         case T_WaitStmt:
    2072           55 :             return true;
    2073              : 
    2074       171570 :         default:
    2075       171570 :             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        29281 : UtilityTupleDescriptor(Node *parsetree)
    2089              : {
    2090        29281 :     switch (nodeTag(parsetree))
    2091              :     {
    2092           98 :         case T_CallStmt:
    2093           98 :             return CallStmtResultDesc((CallStmt *) parsetree);
    2094              : 
    2095         3821 :         case T_FetchStmt:
    2096              :             {
    2097         3821 :                 FetchStmt  *stmt = (FetchStmt *) parsetree;
    2098              :                 Portal      portal;
    2099              : 
    2100         3821 :                 if (stmt->ismove)
    2101            0 :                     return NULL;
    2102         3821 :                 portal = GetPortalByName(stmt->portalname);
    2103         3821 :                 if (!PortalIsValid(portal))
    2104            0 :                     return NULL;    /* not our business to raise error */
    2105         3821 :                 return CreateTupleDescCopy(portal->tupDesc);
    2106              :             }
    2107              : 
    2108         8094 :         case T_ExecuteStmt:
    2109              :             {
    2110         8094 :                 ExecuteStmt *stmt = (ExecuteStmt *) parsetree;
    2111              :                 PreparedStatement *entry;
    2112              : 
    2113         8094 :                 entry = FetchPreparedStatement(stmt->name, false);
    2114         8094 :                 if (!entry)
    2115            0 :                     return NULL;    /* not our business to raise error */
    2116         8094 :                 return FetchPreparedStatementResultDesc(entry);
    2117              :             }
    2118              : 
    2119        16757 :         case T_ExplainStmt:
    2120        16757 :             return ExplainResultDesc((ExplainStmt *) parsetree);
    2121              : 
    2122          456 :         case T_VariableShowStmt:
    2123              :             {
    2124          456 :                 VariableShowStmt *n = (VariableShowStmt *) parsetree;
    2125              : 
    2126          456 :                 return GetPGVariableResultDesc(n->name);
    2127              :             }
    2128              : 
    2129           55 :         case T_WaitStmt:
    2130           55 :             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        20366 : UtilityContainsQuery(Node *parsetree)
    2187              : {
    2188              :     Query      *qry;
    2189              : 
    2190        20366 :     switch (nodeTag(parsetree))
    2191              :     {
    2192         1724 :         case T_DeclareCursorStmt:
    2193         1724 :             qry = castNode(Query, ((DeclareCursorStmt *) parsetree)->query);
    2194         1724 :             if (qry->commandType == CMD_UTILITY)
    2195            0 :                 return UtilityContainsQuery(qry->utilityStmt);
    2196         1724 :             return qry;
    2197              : 
    2198         8106 :         case T_ExplainStmt:
    2199         8106 :             qry = castNode(Query, ((ExplainStmt *) parsetree)->query);
    2200         8106 :             if (qry->commandType == CMD_UTILITY)
    2201           54 :                 return UtilityContainsQuery(qry->utilityStmt);
    2202         8052 :             return qry;
    2203              : 
    2204           45 :         case T_CreateTableAsStmt:
    2205           45 :             qry = castNode(Query, ((CreateTableAsStmt *) parsetree)->query);
    2206           45 :             if (qry->commandType == CMD_UTILITY)
    2207            0 :                 return UtilityContainsQuery(qry->utilityStmt);
    2208           45 :             return qry;
    2209              : 
    2210        10491 :         default:
    2211        10491 :             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        18290 : AlterObjectTypeCommandTag(ObjectType objtype)
    2224              : {
    2225              :     CommandTag  tag;
    2226              : 
    2227        18290 :     switch (objtype)
    2228              :     {
    2229          104 :         case OBJECT_AGGREGATE:
    2230          104 :             tag = CMDTAG_ALTER_AGGREGATE;
    2231          104 :             break;
    2232           12 :         case OBJECT_ATTRIBUTE:
    2233           12 :             tag = CMDTAG_ALTER_TYPE;
    2234           12 :             break;
    2235            0 :         case OBJECT_CAST:
    2236            0 :             tag = CMDTAG_ALTER_CAST;
    2237            0 :             break;
    2238           21 :         case OBJECT_COLLATION:
    2239           21 :             tag = CMDTAG_ALTER_COLLATION;
    2240           21 :             break;
    2241            0 :         case OBJECT_COLUMN:
    2242            0 :             tag = CMDTAG_ALTER_TABLE;
    2243            0 :             break;
    2244           36 :         case OBJECT_CONVERSION:
    2245           36 :             tag = CMDTAG_ALTER_CONVERSION;
    2246           36 :             break;
    2247           52 :         case OBJECT_DATABASE:
    2248           52 :             tag = CMDTAG_ALTER_DATABASE;
    2249           52 :             break;
    2250           33 :         case OBJECT_DOMAIN:
    2251              :         case OBJECT_DOMCONSTRAINT:
    2252           33 :             tag = CMDTAG_ALTER_DOMAIN;
    2253           33 :             break;
    2254            6 :         case OBJECT_EXTENSION:
    2255            6 :             tag = CMDTAG_ALTER_EXTENSION;
    2256            6 :             break;
    2257           22 :         case OBJECT_FDW:
    2258           22 :             tag = CMDTAG_ALTER_FOREIGN_DATA_WRAPPER;
    2259           22 :             break;
    2260           46 :         case OBJECT_FOREIGN_SERVER:
    2261           46 :             tag = CMDTAG_ALTER_SERVER;
    2262           46 :             break;
    2263          282 :         case OBJECT_FOREIGN_TABLE:
    2264          282 :             tag = CMDTAG_ALTER_FOREIGN_TABLE;
    2265          282 :             break;
    2266          342 :         case OBJECT_FUNCTION:
    2267          342 :             tag = CMDTAG_ALTER_FUNCTION;
    2268          342 :             break;
    2269          436 :         case OBJECT_INDEX:
    2270          436 :             tag = CMDTAG_ALTER_INDEX;
    2271          436 :             break;
    2272           24 :         case OBJECT_LANGUAGE:
    2273           24 :             tag = CMDTAG_ALTER_LANGUAGE;
    2274           24 :             break;
    2275            8 :         case OBJECT_LARGEOBJECT:
    2276            8 :             tag = CMDTAG_ALTER_LARGE_OBJECT;
    2277            8 :             break;
    2278           51 :         case OBJECT_OPCLASS:
    2279           51 :             tag = CMDTAG_ALTER_OPERATOR_CLASS;
    2280           51 :             break;
    2281           32 :         case OBJECT_OPERATOR:
    2282           32 :             tag = CMDTAG_ALTER_OPERATOR;
    2283           32 :             break;
    2284           55 :         case OBJECT_OPFAMILY:
    2285           55 :             tag = CMDTAG_ALTER_OPERATOR_FAMILY;
    2286           55 :             break;
    2287           15 :         case OBJECT_POLICY:
    2288           15 :             tag = CMDTAG_ALTER_POLICY;
    2289           15 :             break;
    2290           12 :         case OBJECT_PROCEDURE:
    2291           12 :             tag = CMDTAG_ALTER_PROCEDURE;
    2292           12 :             break;
    2293           15 :         case OBJECT_ROLE:
    2294           15 :             tag = CMDTAG_ALTER_ROLE;
    2295           15 :             break;
    2296           12 :         case OBJECT_ROUTINE:
    2297           12 :             tag = CMDTAG_ALTER_ROUTINE;
    2298           12 :             break;
    2299           17 :         case OBJECT_RULE:
    2300           17 :             tag = CMDTAG_ALTER_RULE;
    2301           17 :             break;
    2302           42 :         case OBJECT_SCHEMA:
    2303           42 :             tag = CMDTAG_ALTER_SCHEMA;
    2304           42 :             break;
    2305           58 :         case OBJECT_SEQUENCE:
    2306           58 :             tag = CMDTAG_ALTER_SEQUENCE;
    2307           58 :             break;
    2308        15932 :         case OBJECT_TABLE:
    2309              :         case OBJECT_TABCONSTRAINT:
    2310        15932 :             tag = CMDTAG_ALTER_TABLE;
    2311        15932 :             break;
    2312            9 :         case OBJECT_TABLESPACE:
    2313            9 :             tag = CMDTAG_ALTER_TABLESPACE;
    2314            9 :             break;
    2315           25 :         case OBJECT_TRIGGER:
    2316           25 :             tag = CMDTAG_ALTER_TRIGGER;
    2317           25 :             break;
    2318           13 :         case OBJECT_EVENT_TRIGGER:
    2319           13 :             tag = CMDTAG_ALTER_EVENT_TRIGGER;
    2320           13 :             break;
    2321           40 :         case OBJECT_TSCONFIGURATION:
    2322           40 :             tag = CMDTAG_ALTER_TEXT_SEARCH_CONFIGURATION;
    2323           40 :             break;
    2324           45 :         case OBJECT_TSDICTIONARY:
    2325           45 :             tag = CMDTAG_ALTER_TEXT_SEARCH_DICTIONARY;
    2326           45 :             break;
    2327           15 :         case OBJECT_TSPARSER:
    2328           15 :             tag = CMDTAG_ALTER_TEXT_SEARCH_PARSER;
    2329           15 :             break;
    2330           15 :         case OBJECT_TSTEMPLATE:
    2331           15 :             tag = CMDTAG_ALTER_TEXT_SEARCH_TEMPLATE;
    2332           15 :             break;
    2333          175 :         case OBJECT_TYPE:
    2334          175 :             tag = CMDTAG_ALTER_TYPE;
    2335          175 :             break;
    2336          140 :         case OBJECT_VIEW:
    2337          140 :             tag = CMDTAG_ALTER_VIEW;
    2338          140 :             break;
    2339           41 :         case OBJECT_MATVIEW:
    2340           41 :             tag = CMDTAG_ALTER_MATERIALIZED_VIEW;
    2341           41 :             break;
    2342           39 :         case OBJECT_PUBLICATION:
    2343           39 :             tag = CMDTAG_ALTER_PUBLICATION;
    2344           39 :             break;
    2345           28 :         case OBJECT_SUBSCRIPTION:
    2346           28 :             tag = CMDTAG_ALTER_SUBSCRIPTION;
    2347           28 :             break;
    2348           40 :         case OBJECT_STATISTIC_EXT:
    2349           40 :             tag = CMDTAG_ALTER_STATISTICS;
    2350           40 :             break;
    2351            0 :         default:
    2352            0 :             tag = CMDTAG_UNKNOWN;
    2353            0 :             break;
    2354              :     }
    2355              : 
    2356        18290 :     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       423781 : CreateCommandTag(Node *parsetree)
    2370              : {
    2371              :     CommandTag  tag;
    2372              : 
    2373       423781 :     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        35663 :         case T_InsertStmt:
    2382        35663 :             tag = CMDTAG_INSERT;
    2383        35663 :             break;
    2384              : 
    2385         2082 :         case T_DeleteStmt:
    2386         2082 :             tag = CMDTAG_DELETE;
    2387         2082 :             break;
    2388              : 
    2389         6922 :         case T_UpdateStmt:
    2390         6922 :             tag = CMDTAG_UPDATE;
    2391         6922 :             break;
    2392              : 
    2393          925 :         case T_MergeStmt:
    2394          925 :             tag = CMDTAG_MERGE;
    2395          925 :             break;
    2396              : 
    2397       170049 :         case T_SelectStmt:
    2398       170049 :             tag = CMDTAG_SELECT;
    2399       170049 :             break;
    2400              : 
    2401         1963 :         case T_PLAssignStmt:
    2402         1963 :             tag = CMDTAG_SELECT;
    2403         1963 :             break;
    2404              : 
    2405              :             /* utility statements --- same whether raw or cooked */
    2406        24563 :         case T_TransactionStmt:
    2407              :             {
    2408        24563 :                 TransactionStmt *stmt = (TransactionStmt *) parsetree;
    2409              : 
    2410        24563 :                 switch (stmt->kind)
    2411              :                 {
    2412        10699 :                     case TRANS_STMT_BEGIN:
    2413        10699 :                         tag = CMDTAG_BEGIN;
    2414        10699 :                         break;
    2415              : 
    2416          824 :                     case TRANS_STMT_START:
    2417          824 :                         tag = CMDTAG_START_TRANSACTION;
    2418          824 :                         break;
    2419              : 
    2420         9139 :                     case TRANS_STMT_COMMIT:
    2421         9139 :                         tag = CMDTAG_COMMIT;
    2422         9139 :                         break;
    2423              : 
    2424         2150 :                     case TRANS_STMT_ROLLBACK:
    2425              :                     case TRANS_STMT_ROLLBACK_TO:
    2426         2150 :                         tag = CMDTAG_ROLLBACK;
    2427         2150 :                         break;
    2428              : 
    2429          996 :                     case TRANS_STMT_SAVEPOINT:
    2430          996 :                         tag = CMDTAG_SAVEPOINT;
    2431          996 :                         break;
    2432              : 
    2433          151 :                     case TRANS_STMT_RELEASE:
    2434          151 :                         tag = CMDTAG_RELEASE;
    2435          151 :                         break;
    2436              : 
    2437          321 :                     case TRANS_STMT_PREPARE:
    2438          321 :                         tag = CMDTAG_PREPARE_TRANSACTION;
    2439          321 :                         break;
    2440              : 
    2441          237 :                     case TRANS_STMT_COMMIT_PREPARED:
    2442          237 :                         tag = CMDTAG_COMMIT_PREPARED;
    2443          237 :                         break;
    2444              : 
    2445           46 :                     case TRANS_STMT_ROLLBACK_PREPARED:
    2446           46 :                         tag = CMDTAG_ROLLBACK_PREPARED;
    2447           46 :                         break;
    2448              : 
    2449            0 :                     default:
    2450            0 :                         tag = CMDTAG_UNKNOWN;
    2451            0 :                         break;
    2452              :                 }
    2453              :             }
    2454        24563 :             break;
    2455              : 
    2456         2359 :         case T_DeclareCursorStmt:
    2457         2359 :             tag = CMDTAG_DECLARE_CURSOR;
    2458         2359 :             break;
    2459              : 
    2460         1218 :         case T_ClosePortalStmt:
    2461              :             {
    2462         1218 :                 ClosePortalStmt *stmt = (ClosePortalStmt *) parsetree;
    2463              : 
    2464         1218 :                 if (stmt->portalname == NULL)
    2465            6 :                     tag = CMDTAG_CLOSE_CURSOR_ALL;
    2466              :                 else
    2467         1212 :                     tag = CMDTAG_CLOSE_CURSOR;
    2468              :             }
    2469         1218 :             break;
    2470              : 
    2471         4014 :         case T_FetchStmt:
    2472              :             {
    2473         4014 :                 FetchStmt  *stmt = (FetchStmt *) parsetree;
    2474              : 
    2475         4014 :                 tag = (stmt->ismove) ? CMDTAG_MOVE : CMDTAG_FETCH;
    2476              :             }
    2477         4014 :             break;
    2478              : 
    2479          763 :         case T_CreateDomainStmt:
    2480          763 :             tag = CMDTAG_CREATE_DOMAIN;
    2481          763 :             break;
    2482              : 
    2483          579 :         case T_CreateSchemaStmt:
    2484          579 :             tag = CMDTAG_CREATE_SCHEMA;
    2485          579 :             break;
    2486              : 
    2487        20183 :         case T_CreateStmt:
    2488        20183 :             tag = CMDTAG_CREATE_TABLE;
    2489        20183 :             break;
    2490              : 
    2491           70 :         case T_CreateTableSpaceStmt:
    2492           70 :             tag = CMDTAG_CREATE_TABLESPACE;
    2493           70 :             break;
    2494              : 
    2495           32 :         case T_DropTableSpaceStmt:
    2496           32 :             tag = CMDTAG_DROP_TABLESPACE;
    2497           32 :             break;
    2498              : 
    2499           12 :         case T_AlterTableSpaceOptionsStmt:
    2500           12 :             tag = CMDTAG_ALTER_TABLESPACE;
    2501           12 :             break;
    2502              : 
    2503          296 :         case T_CreateExtensionStmt:
    2504          296 :             tag = CMDTAG_CREATE_EXTENSION;
    2505          296 :             break;
    2506              : 
    2507           19 :         case T_AlterExtensionStmt:
    2508           19 :             tag = CMDTAG_ALTER_EXTENSION;
    2509           19 :             break;
    2510              : 
    2511           90 :         case T_AlterExtensionContentsStmt:
    2512           90 :             tag = CMDTAG_ALTER_EXTENSION;
    2513           90 :             break;
    2514              : 
    2515          100 :         case T_CreateFdwStmt:
    2516          100 :             tag = CMDTAG_CREATE_FOREIGN_DATA_WRAPPER;
    2517          100 :             break;
    2518              : 
    2519           64 :         case T_AlterFdwStmt:
    2520           64 :             tag = CMDTAG_ALTER_FOREIGN_DATA_WRAPPER;
    2521           64 :             break;
    2522              : 
    2523          154 :         case T_CreateForeignServerStmt:
    2524          154 :             tag = CMDTAG_CREATE_SERVER;
    2525          154 :             break;
    2526              : 
    2527          116 :         case T_AlterForeignServerStmt:
    2528          116 :             tag = CMDTAG_ALTER_SERVER;
    2529          116 :             break;
    2530              : 
    2531          141 :         case T_CreateUserMappingStmt:
    2532          141 :             tag = CMDTAG_CREATE_USER_MAPPING;
    2533          141 :             break;
    2534              : 
    2535           59 :         case T_AlterUserMappingStmt:
    2536           59 :             tag = CMDTAG_ALTER_USER_MAPPING;
    2537           59 :             break;
    2538              : 
    2539           66 :         case T_DropUserMappingStmt:
    2540           66 :             tag = CMDTAG_DROP_USER_MAPPING;
    2541           66 :             break;
    2542              : 
    2543          230 :         case T_CreateForeignTableStmt:
    2544          230 :             tag = CMDTAG_CREATE_FOREIGN_TABLE;
    2545          230 :             break;
    2546              : 
    2547           24 :         case T_ImportForeignSchemaStmt:
    2548           24 :             tag = CMDTAG_IMPORT_FOREIGN_SCHEMA;
    2549           24 :             break;
    2550              : 
    2551        13700 :         case T_DropStmt:
    2552        13700 :             switch (((DropStmt *) parsetree)->removeType)
    2553              :             {
    2554         8152 :                 case OBJECT_TABLE:
    2555         8152 :                     tag = CMDTAG_DROP_TABLE;
    2556         8152 :                     break;
    2557           89 :                 case OBJECT_SEQUENCE:
    2558           89 :                     tag = CMDTAG_DROP_SEQUENCE;
    2559           89 :                     break;
    2560          468 :                 case OBJECT_VIEW:
    2561          468 :                     tag = CMDTAG_DROP_VIEW;
    2562          468 :                     break;
    2563           63 :                 case OBJECT_MATVIEW:
    2564           63 :                     tag = CMDTAG_DROP_MATERIALIZED_VIEW;
    2565           63 :                     break;
    2566          463 :                 case OBJECT_INDEX:
    2567          463 :                     tag = CMDTAG_DROP_INDEX;
    2568          463 :                     break;
    2569          296 :                 case OBJECT_TYPE:
    2570          296 :                     tag = CMDTAG_DROP_TYPE;
    2571          296 :                     break;
    2572          292 :                 case OBJECT_DOMAIN:
    2573          292 :                     tag = CMDTAG_DROP_DOMAIN;
    2574          292 :                     break;
    2575           44 :                 case OBJECT_COLLATION:
    2576           44 :                     tag = CMDTAG_DROP_COLLATION;
    2577           44 :                     break;
    2578           18 :                 case OBJECT_CONVERSION:
    2579           18 :                     tag = CMDTAG_DROP_CONVERSION;
    2580           18 :                     break;
    2581          304 :                 case OBJECT_SCHEMA:
    2582          304 :                     tag = CMDTAG_DROP_SCHEMA;
    2583          304 :                     break;
    2584            9 :                 case OBJECT_TSPARSER:
    2585            9 :                     tag = CMDTAG_DROP_TEXT_SEARCH_PARSER;
    2586            9 :                     break;
    2587           12 :                 case OBJECT_TSDICTIONARY:
    2588           12 :                     tag = CMDTAG_DROP_TEXT_SEARCH_DICTIONARY;
    2589           12 :                     break;
    2590            9 :                 case OBJECT_TSTEMPLATE:
    2591            9 :                     tag = CMDTAG_DROP_TEXT_SEARCH_TEMPLATE;
    2592            9 :                     break;
    2593           15 :                 case OBJECT_TSCONFIGURATION:
    2594           15 :                     tag = CMDTAG_DROP_TEXT_SEARCH_CONFIGURATION;
    2595           15 :                     break;
    2596           85 :                 case OBJECT_FOREIGN_TABLE:
    2597           85 :                     tag = CMDTAG_DROP_FOREIGN_TABLE;
    2598           85 :                     break;
    2599           88 :                 case OBJECT_EXTENSION:
    2600           88 :                     tag = CMDTAG_DROP_EXTENSION;
    2601           88 :                     break;
    2602         1759 :                 case OBJECT_FUNCTION:
    2603         1759 :                     tag = CMDTAG_DROP_FUNCTION;
    2604         1759 :                     break;
    2605           73 :                 case OBJECT_PROCEDURE:
    2606           73 :                     tag = CMDTAG_DROP_PROCEDURE;
    2607           73 :                     break;
    2608           15 :                 case OBJECT_ROUTINE:
    2609           15 :                     tag = CMDTAG_DROP_ROUTINE;
    2610           15 :                     break;
    2611           52 :                 case OBJECT_AGGREGATE:
    2612           52 :                     tag = CMDTAG_DROP_AGGREGATE;
    2613           52 :                     break;
    2614           91 :                 case OBJECT_OPERATOR:
    2615           91 :                     tag = CMDTAG_DROP_OPERATOR;
    2616           91 :                     break;
    2617           13 :                 case OBJECT_LANGUAGE:
    2618           13 :                     tag = CMDTAG_DROP_LANGUAGE;
    2619           13 :                     break;
    2620           30 :                 case OBJECT_CAST:
    2621           30 :                     tag = CMDTAG_DROP_CAST;
    2622           30 :                     break;
    2623          390 :                 case OBJECT_TRIGGER:
    2624          390 :                     tag = CMDTAG_DROP_TRIGGER;
    2625          390 :                     break;
    2626           62 :                 case OBJECT_EVENT_TRIGGER:
    2627           62 :                     tag = CMDTAG_DROP_EVENT_TRIGGER;
    2628           62 :                     break;
    2629          121 :                 case OBJECT_RULE:
    2630          121 :                     tag = CMDTAG_DROP_RULE;
    2631          121 :                     break;
    2632           78 :                 case OBJECT_FDW:
    2633           78 :                     tag = CMDTAG_DROP_FOREIGN_DATA_WRAPPER;
    2634           78 :                     break;
    2635           70 :                 case OBJECT_FOREIGN_SERVER:
    2636           70 :                     tag = CMDTAG_DROP_SERVER;
    2637           70 :                     break;
    2638           28 :                 case OBJECT_OPCLASS:
    2639           28 :                     tag = CMDTAG_DROP_OPERATOR_CLASS;
    2640           28 :                     break;
    2641           64 :                 case OBJECT_OPFAMILY:
    2642           64 :                     tag = CMDTAG_DROP_OPERATOR_FAMILY;
    2643           64 :                     break;
    2644          103 :                 case OBJECT_POLICY:
    2645          103 :                     tag = CMDTAG_DROP_POLICY;
    2646          103 :                     break;
    2647            8 :                 case OBJECT_TRANSFORM:
    2648            8 :                     tag = CMDTAG_DROP_TRANSFORM;
    2649            8 :                     break;
    2650           24 :                 case OBJECT_ACCESS_METHOD:
    2651           24 :                     tag = CMDTAG_DROP_ACCESS_METHOD;
    2652           24 :                     break;
    2653          209 :                 case OBJECT_PUBLICATION:
    2654          209 :                     tag = CMDTAG_DROP_PUBLICATION;
    2655          209 :                     break;
    2656          103 :                 case OBJECT_STATISTIC_EXT:
    2657          103 :                     tag = CMDTAG_DROP_STATISTICS;
    2658          103 :                     break;
    2659            0 :                 default:
    2660            0 :                     tag = CMDTAG_UNKNOWN;
    2661              :             }
    2662        13700 :             break;
    2663              : 
    2664          930 :         case T_TruncateStmt:
    2665          930 :             tag = CMDTAG_TRUNCATE_TABLE;
    2666          930 :             break;
    2667              : 
    2668         3732 :         case T_CommentStmt:
    2669         3732 :             tag = CMDTAG_COMMENT;
    2670         3732 :             break;
    2671              : 
    2672           61 :         case T_SecLabelStmt:
    2673           61 :             tag = CMDTAG_SECURITY_LABEL;
    2674           61 :             break;
    2675              : 
    2676         5919 :         case T_CopyStmt:
    2677         5919 :             tag = CMDTAG_COPY;
    2678         5919 :             break;
    2679              : 
    2680          791 :         case T_RenameStmt:
    2681              : 
    2682              :             /*
    2683              :              * When the column is renamed, the command tag is created from its
    2684              :              * relation type
    2685              :              */
    2686          791 :             tag = AlterObjectTypeCommandTag(((RenameStmt *) parsetree)->renameType == OBJECT_COLUMN ?
    2687              :                                             ((RenameStmt *) parsetree)->relationType :
    2688              :                                             ((RenameStmt *) parsetree)->renameType);
    2689          791 :             break;
    2690              : 
    2691           23 :         case T_AlterObjectDependsStmt:
    2692           23 :             tag = AlterObjectTypeCommandTag(((AlterObjectDependsStmt *) parsetree)->objectType);
    2693           23 :             break;
    2694              : 
    2695          205 :         case T_AlterObjectSchemaStmt:
    2696          205 :             tag = AlterObjectTypeCommandTag(((AlterObjectSchemaStmt *) parsetree)->objectType);
    2697          205 :             break;
    2698              : 
    2699          785 :         case T_AlterOwnerStmt:
    2700          785 :             tag = AlterObjectTypeCommandTag(((AlterOwnerStmt *) parsetree)->objectType);
    2701          785 :             break;
    2702              : 
    2703           15 :         case T_AlterTableMoveAllStmt:
    2704           15 :             tag = AlterObjectTypeCommandTag(((AlterTableMoveAllStmt *) parsetree)->objtype);
    2705           15 :             break;
    2706              : 
    2707        16471 :         case T_AlterTableStmt:
    2708        16471 :             tag = AlterObjectTypeCommandTag(((AlterTableStmt *) parsetree)->objtype);
    2709        16471 :             break;
    2710              : 
    2711          148 :         case T_AlterDomainStmt:
    2712          148 :             tag = CMDTAG_ALTER_DOMAIN;
    2713          148 :             break;
    2714              : 
    2715          102 :         case T_AlterFunctionStmt:
    2716          102 :             switch (((AlterFunctionStmt *) parsetree)->objtype)
    2717              :             {
    2718           93 :                 case OBJECT_FUNCTION:
    2719           93 :                     tag = CMDTAG_ALTER_FUNCTION;
    2720           93 :                     break;
    2721            9 :                 case OBJECT_PROCEDURE:
    2722            9 :                     tag = CMDTAG_ALTER_PROCEDURE;
    2723            9 :                     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          102 :             break;
    2731              : 
    2732         6508 :         case T_GrantStmt:
    2733              :             {
    2734         6508 :                 GrantStmt  *stmt = (GrantStmt *) parsetree;
    2735              : 
    2736         6508 :                 tag = (stmt->is_grant) ? CMDTAG_GRANT : CMDTAG_REVOKE;
    2737              :             }
    2738         6508 :             break;
    2739              : 
    2740          297 :         case T_GrantRoleStmt:
    2741              :             {
    2742          297 :                 GrantRoleStmt *stmt = (GrantRoleStmt *) parsetree;
    2743              : 
    2744          297 :                 tag = (stmt->is_grant) ? CMDTAG_GRANT_ROLE : CMDTAG_REVOKE_ROLE;
    2745              :             }
    2746          297 :             break;
    2747              : 
    2748          114 :         case T_AlterDefaultPrivilegesStmt:
    2749          114 :             tag = CMDTAG_ALTER_DEFAULT_PRIVILEGES;
    2750          114 :             break;
    2751              : 
    2752         4222 :         case T_DefineStmt:
    2753         4222 :             switch (((DefineStmt *) parsetree)->kind)
    2754              :             {
    2755          446 :                 case OBJECT_AGGREGATE:
    2756          446 :                     tag = CMDTAG_CREATE_AGGREGATE;
    2757          446 :                     break;
    2758          212 :                 case OBJECT_OPERATOR:
    2759          212 :                     tag = CMDTAG_CREATE_OPERATOR;
    2760          212 :                     break;
    2761          139 :                 case OBJECT_TYPE:
    2762          139 :                     tag = CMDTAG_CREATE_TYPE;
    2763          139 :                     break;
    2764           20 :                 case OBJECT_TSPARSER:
    2765           20 :                     tag = CMDTAG_CREATE_TEXT_SEARCH_PARSER;
    2766           20 :                     break;
    2767         1590 :                 case OBJECT_TSDICTIONARY:
    2768         1590 :                     tag = CMDTAG_CREATE_TEXT_SEARCH_DICTIONARY;
    2769         1590 :                     break;
    2770           69 :                 case OBJECT_TSTEMPLATE:
    2771           69 :                     tag = CMDTAG_CREATE_TEXT_SEARCH_TEMPLATE;
    2772           69 :                     break;
    2773         1571 :                 case OBJECT_TSCONFIGURATION:
    2774         1571 :                     tag = CMDTAG_CREATE_TEXT_SEARCH_CONFIGURATION;
    2775         1571 :                     break;
    2776          175 :                 case OBJECT_COLLATION:
    2777          175 :                     tag = CMDTAG_CREATE_COLLATION;
    2778          175 :                     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         4222 :             break;
    2786              : 
    2787         2254 :         case T_CompositeTypeStmt:
    2788         2254 :             tag = CMDTAG_CREATE_TYPE;
    2789         2254 :             break;
    2790              : 
    2791          104 :         case T_CreateEnumStmt:
    2792          104 :             tag = CMDTAG_CREATE_TYPE;
    2793          104 :             break;
    2794              : 
    2795           95 :         case T_CreateRangeStmt:
    2796           95 :             tag = CMDTAG_CREATE_TYPE;
    2797           95 :             break;
    2798              : 
    2799          204 :         case T_AlterEnumStmt:
    2800          204 :             tag = CMDTAG_ALTER_TYPE;
    2801          204 :             break;
    2802              : 
    2803         8788 :         case T_ViewStmt:
    2804         8788 :             tag = CMDTAG_CREATE_VIEW;
    2805         8788 :             break;
    2806              : 
    2807         7636 :         case T_CreateFunctionStmt:
    2808         7636 :             if (((CreateFunctionStmt *) parsetree)->is_procedure)
    2809          191 :                 tag = CMDTAG_CREATE_PROCEDURE;
    2810              :             else
    2811         7445 :                 tag = CMDTAG_CREATE_FUNCTION;
    2812         7636 :             break;
    2813              : 
    2814         3375 :         case T_IndexStmt:
    2815         3375 :             tag = CMDTAG_CREATE_INDEX;
    2816         3375 :             break;
    2817              : 
    2818          567 :         case T_RuleStmt:
    2819          567 :             tag = CMDTAG_CREATE_RULE;
    2820          567 :             break;
    2821              : 
    2822          353 :         case T_CreateSeqStmt:
    2823          353 :             tag = CMDTAG_CREATE_SEQUENCE;
    2824          353 :             break;
    2825              : 
    2826          127 :         case T_AlterSeqStmt:
    2827          127 :             tag = CMDTAG_ALTER_SEQUENCE;
    2828          127 :             break;
    2829              : 
    2830          575 :         case T_DoStmt:
    2831          575 :             tag = CMDTAG_DO;
    2832          575 :             break;
    2833              : 
    2834          422 :         case T_CreatedbStmt:
    2835          422 :             tag = CMDTAG_CREATE_DATABASE;
    2836          422 :             break;
    2837              : 
    2838          694 :         case T_AlterDatabaseStmt:
    2839              :         case T_AlterDatabaseRefreshCollStmt:
    2840              :         case T_AlterDatabaseSetStmt:
    2841          694 :             tag = CMDTAG_ALTER_DATABASE;
    2842          694 :             break;
    2843              : 
    2844           67 :         case T_DropdbStmt:
    2845           67 :             tag = CMDTAG_DROP_DATABASE;
    2846           67 :             break;
    2847              : 
    2848           61 :         case T_NotifyStmt:
    2849           61 :             tag = CMDTAG_NOTIFY;
    2850           61 :             break;
    2851              : 
    2852           58 :         case T_ListenStmt:
    2853           58 :             tag = CMDTAG_LISTEN;
    2854           58 :             break;
    2855              : 
    2856           78 :         case T_UnlistenStmt:
    2857           78 :             tag = CMDTAG_UNLISTEN;
    2858           78 :             break;
    2859              : 
    2860           40 :         case T_LoadStmt:
    2861           40 :             tag = CMDTAG_LOAD;
    2862           40 :             break;
    2863              : 
    2864          254 :         case T_CallStmt:
    2865          254 :             tag = CMDTAG_CALL;
    2866          254 :             break;
    2867              : 
    2868         7422 :         case T_VacuumStmt:
    2869         7422 :             if (((VacuumStmt *) parsetree)->is_vacuumcmd)
    2870         5011 :                 tag = CMDTAG_VACUUM;
    2871              :             else
    2872         2411 :                 tag = CMDTAG_ANALYZE;
    2873         7422 :             break;
    2874              : 
    2875          144 :         case T_RepackStmt:
    2876          144 :             if (((RepackStmt *) parsetree)->command == REPACK_COMMAND_CLUSTER)
    2877          120 :                 tag = CMDTAG_CLUSTER;
    2878              :             else
    2879           24 :                 tag = CMDTAG_REPACK;
    2880          144 :             break;
    2881              : 
    2882        12714 :         case T_ExplainStmt:
    2883        12714 :             tag = CMDTAG_EXPLAIN;
    2884        12714 :             break;
    2885              : 
    2886          902 :         case T_CreateTableAsStmt:
    2887          902 :             switch (((CreateTableAsStmt *) parsetree)->objtype)
    2888              :             {
    2889          649 :                 case OBJECT_TABLE:
    2890          649 :                     if (((CreateTableAsStmt *) parsetree)->is_select_into)
    2891            0 :                         tag = CMDTAG_SELECT_INTO;
    2892              :                     else
    2893          649 :                         tag = CMDTAG_CREATE_TABLE_AS;
    2894          649 :                     break;
    2895          253 :                 case OBJECT_MATVIEW:
    2896          253 :                     tag = CMDTAG_CREATE_MATERIALIZED_VIEW;
    2897          253 :                     break;
    2898            0 :                 default:
    2899            0 :                     tag = CMDTAG_UNKNOWN;
    2900              :             }
    2901          902 :             break;
    2902              : 
    2903          137 :         case T_RefreshMatViewStmt:
    2904          137 :             tag = CMDTAG_REFRESH_MATERIALIZED_VIEW;
    2905          137 :             break;
    2906              : 
    2907          121 :         case T_AlterSystemStmt:
    2908          121 :             tag = CMDTAG_ALTER_SYSTEM;
    2909          121 :             break;
    2910              : 
    2911        15773 :         case T_VariableSetStmt:
    2912        15773 :             switch (((VariableSetStmt *) parsetree)->kind)
    2913              :             {
    2914        13244 :                 case VAR_SET_VALUE:
    2915              :                 case VAR_SET_CURRENT:
    2916              :                 case VAR_SET_DEFAULT:
    2917              :                 case VAR_SET_MULTI:
    2918        13244 :                     tag = CMDTAG_SET;
    2919        13244 :                     break;
    2920         2529 :                 case VAR_RESET:
    2921              :                 case VAR_RESET_ALL:
    2922         2529 :                     tag = CMDTAG_RESET;
    2923         2529 :                     break;
    2924            0 :                 default:
    2925            0 :                     tag = CMDTAG_UNKNOWN;
    2926              :             }
    2927        15773 :             break;
    2928              : 
    2929          447 :         case T_VariableShowStmt:
    2930          447 :             tag = CMDTAG_SHOW;
    2931          447 :             break;
    2932              : 
    2933           19 :         case T_DiscardStmt:
    2934           19 :             switch (((DiscardStmt *) parsetree)->target)
    2935              :             {
    2936            3 :                 case DISCARD_ALL:
    2937            3 :                     tag = CMDTAG_DISCARD_ALL;
    2938            3 :                     break;
    2939            3 :                 case DISCARD_PLANS:
    2940            3 :                     tag = CMDTAG_DISCARD_PLANS;
    2941            3 :                     break;
    2942            7 :                 case DISCARD_TEMP:
    2943            7 :                     tag = CMDTAG_DISCARD_TEMP;
    2944            7 :                     break;
    2945            6 :                 case DISCARD_SEQUENCES:
    2946            6 :                     tag = CMDTAG_DISCARD_SEQUENCES;
    2947            6 :                     break;
    2948            0 :                 default:
    2949            0 :                     tag = CMDTAG_UNKNOWN;
    2950              :             }
    2951           19 :             break;
    2952              : 
    2953           19 :         case T_CreateTransformStmt:
    2954           19 :             tag = CMDTAG_CREATE_TRANSFORM;
    2955           19 :             break;
    2956              : 
    2957         1660 :         case T_CreateTrigStmt:
    2958         1660 :             tag = CMDTAG_CREATE_TRIGGER;
    2959         1660 :             break;
    2960              : 
    2961           99 :         case T_CreateEventTrigStmt:
    2962           99 :             tag = CMDTAG_CREATE_EVENT_TRIGGER;
    2963           99 :             break;
    2964              : 
    2965           23 :         case T_AlterEventTrigStmt:
    2966           23 :             tag = CMDTAG_ALTER_EVENT_TRIGGER;
    2967           23 :             break;
    2968              : 
    2969            7 :         case T_CreatePLangStmt:
    2970            7 :             tag = CMDTAG_CREATE_LANGUAGE;
    2971            7 :             break;
    2972              : 
    2973          974 :         case T_CreateRoleStmt:
    2974          974 :             tag = CMDTAG_CREATE_ROLE;
    2975          974 :             break;
    2976              : 
    2977          239 :         case T_AlterRoleStmt:
    2978          239 :             tag = CMDTAG_ALTER_ROLE;
    2979          239 :             break;
    2980              : 
    2981           46 :         case T_AlterRoleSetStmt:
    2982           46 :             tag = CMDTAG_ALTER_ROLE;
    2983           46 :             break;
    2984              : 
    2985          891 :         case T_DropRoleStmt:
    2986          891 :             tag = CMDTAG_DROP_ROLE;
    2987          891 :             break;
    2988              : 
    2989           78 :         case T_DropOwnedStmt:
    2990           78 :             tag = CMDTAG_DROP_OWNED;
    2991           78 :             break;
    2992              : 
    2993           23 :         case T_ReassignOwnedStmt:
    2994           23 :             tag = CMDTAG_REASSIGN_OWNED;
    2995           23 :             break;
    2996              : 
    2997          580 :         case T_LockStmt:
    2998          580 :             tag = CMDTAG_LOCK_TABLE;
    2999          580 :             break;
    3000              : 
    3001           51 :         case T_ConstraintsSetStmt:
    3002           51 :             tag = CMDTAG_SET_CONSTRAINTS;
    3003           51 :             break;
    3004              : 
    3005          133 :         case T_CheckPointStmt:
    3006          133 :             tag = CMDTAG_CHECKPOINT;
    3007          133 :             break;
    3008              : 
    3009          681 :         case T_ReindexStmt:
    3010          681 :             tag = CMDTAG_REINDEX;
    3011          681 :             break;
    3012              : 
    3013           36 :         case T_CreateConversionStmt:
    3014           36 :             tag = CMDTAG_CREATE_CONVERSION;
    3015           36 :             break;
    3016              : 
    3017           95 :         case T_CreateCastStmt:
    3018           95 :             tag = CMDTAG_CREATE_CAST;
    3019           95 :             break;
    3020              : 
    3021           74 :         case T_CreateOpClassStmt:
    3022           74 :             tag = CMDTAG_CREATE_OPERATOR_CLASS;
    3023           74 :             break;
    3024              : 
    3025           78 :         case T_CreateOpFamilyStmt:
    3026           78 :             tag = CMDTAG_CREATE_OPERATOR_FAMILY;
    3027           78 :             break;
    3028              : 
    3029          150 :         case T_AlterOpFamilyStmt:
    3030          150 :             tag = CMDTAG_ALTER_OPERATOR_FAMILY;
    3031          150 :             break;
    3032              : 
    3033           84 :         case T_AlterOperatorStmt:
    3034           84 :             tag = CMDTAG_ALTER_OPERATOR;
    3035           84 :             break;
    3036              : 
    3037           16 :         case T_AlterTypeStmt:
    3038           16 :             tag = CMDTAG_ALTER_TYPE;
    3039           16 :             break;
    3040              : 
    3041           20 :         case T_AlterTSDictionaryStmt:
    3042           20 :             tag = CMDTAG_ALTER_TEXT_SEARCH_DICTIONARY;
    3043           20 :             break;
    3044              : 
    3045         4684 :         case T_AlterTSConfigurationStmt:
    3046         4684 :             tag = CMDTAG_ALTER_TEXT_SEARCH_CONFIGURATION;
    3047         4684 :             break;
    3048              : 
    3049          413 :         case T_CreatePolicyStmt:
    3050          413 :             tag = CMDTAG_CREATE_POLICY;
    3051          413 :             break;
    3052              : 
    3053           48 :         case T_AlterPolicyStmt:
    3054           48 :             tag = CMDTAG_ALTER_POLICY;
    3055           48 :             break;
    3056              : 
    3057           32 :         case T_CreateAmStmt:
    3058           32 :             tag = CMDTAG_CREATE_ACCESS_METHOD;
    3059           32 :             break;
    3060              : 
    3061          489 :         case T_CreatePublicationStmt:
    3062          489 :             tag = CMDTAG_CREATE_PUBLICATION;
    3063          489 :             break;
    3064              : 
    3065          562 :         case T_AlterPublicationStmt:
    3066          562 :             tag = CMDTAG_ALTER_PUBLICATION;
    3067          562 :             break;
    3068              : 
    3069          264 :         case T_CreateSubscriptionStmt:
    3070          264 :             tag = CMDTAG_CREATE_SUBSCRIPTION;
    3071          264 :             break;
    3072              : 
    3073          277 :         case T_AlterSubscriptionStmt:
    3074          277 :             tag = CMDTAG_ALTER_SUBSCRIPTION;
    3075          277 :             break;
    3076              : 
    3077          137 :         case T_DropSubscriptionStmt:
    3078          137 :             tag = CMDTAG_DROP_SUBSCRIPTION;
    3079          137 :             break;
    3080              : 
    3081            3 :         case T_AlterCollationStmt:
    3082            3 :             tag = CMDTAG_ALTER_COLLATION;
    3083            3 :             break;
    3084              : 
    3085         1886 :         case T_PrepareStmt:
    3086         1886 :             tag = CMDTAG_PREPARE;
    3087         1886 :             break;
    3088              : 
    3089        15570 :         case T_ExecuteStmt:
    3090        15570 :             tag = CMDTAG_EXECUTE;
    3091        15570 :             break;
    3092              : 
    3093          457 :         case T_CreateStatsStmt:
    3094          457 :             tag = CMDTAG_CREATE_STATISTICS;
    3095          457 :             break;
    3096              : 
    3097           14 :         case T_AlterStatsStmt:
    3098           14 :             tag = CMDTAG_ALTER_STATISTICS;
    3099           14 :             break;
    3100              : 
    3101         2051 :         case T_DeallocateStmt:
    3102              :             {
    3103         2051 :                 DeallocateStmt *stmt = (DeallocateStmt *) parsetree;
    3104              : 
    3105         2051 :                 if (stmt->name == NULL)
    3106           36 :                     tag = CMDTAG_DEALLOCATE_ALL;
    3107              :                 else
    3108         2015 :                     tag = CMDTAG_DEALLOCATE;
    3109              :             }
    3110         2051 :             break;
    3111              : 
    3112          101 :         case T_WaitStmt:
    3113          101 :             tag = CMDTAG_WAIT;
    3114          101 :             break;
    3115              : 
    3116              :             /* already-planned queries */
    3117           14 :         case T_PlannedStmt:
    3118              :             {
    3119           14 :                 PlannedStmt *stmt = (PlannedStmt *) parsetree;
    3120              : 
    3121           14 :                 switch (stmt->commandType)
    3122              :                 {
    3123            0 :                     case CMD_SELECT:
    3124              : 
    3125              :                         /*
    3126              :                          * We take a little extra care here so that the result
    3127              :                          * will be useful for complaints about read-only
    3128              :                          * statements
    3129              :                          */
    3130            0 :                         if (stmt->rowMarks != NIL)
    3131              :                         {
    3132              :                             /* not 100% but probably close enough */
    3133            0 :                             switch (((PlanRowMark *) linitial(stmt->rowMarks))->strength)
    3134              :                             {
    3135            0 :                                 case LCS_FORKEYSHARE:
    3136            0 :                                     tag = CMDTAG_SELECT_FOR_KEY_SHARE;
    3137            0 :                                     break;
    3138            0 :                                 case LCS_FORSHARE:
    3139            0 :                                     tag = CMDTAG_SELECT_FOR_SHARE;
    3140            0 :                                     break;
    3141            0 :                                 case LCS_FORNOKEYUPDATE:
    3142            0 :                                     tag = CMDTAG_SELECT_FOR_NO_KEY_UPDATE;
    3143            0 :                                     break;
    3144            0 :                                 case LCS_FORUPDATE:
    3145            0 :                                     tag = CMDTAG_SELECT_FOR_UPDATE;
    3146            0 :                                     break;
    3147            0 :                                 default:
    3148            0 :                                     tag = CMDTAG_SELECT;
    3149            0 :                                     break;
    3150              :                             }
    3151              :                         }
    3152              :                         else
    3153            0 :                             tag = CMDTAG_SELECT;
    3154            0 :                         break;
    3155            6 :                     case CMD_UPDATE:
    3156            6 :                         tag = CMDTAG_UPDATE;
    3157            6 :                         break;
    3158            5 :                     case CMD_INSERT:
    3159            5 :                         tag = CMDTAG_INSERT;
    3160            5 :                         break;
    3161            3 :                     case CMD_DELETE:
    3162            3 :                         tag = CMDTAG_DELETE;
    3163            3 :                         break;
    3164            0 :                     case CMD_MERGE:
    3165            0 :                         tag = CMDTAG_MERGE;
    3166            0 :                         break;
    3167            0 :                     case CMD_UTILITY:
    3168            0 :                         tag = CreateCommandTag(stmt->utilityStmt);
    3169            0 :                         break;
    3170            0 :                     default:
    3171            0 :                         elog(WARNING, "unrecognized commandType: %d",
    3172              :                              (int) stmt->commandType);
    3173            0 :                         tag = CMDTAG_UNKNOWN;
    3174            0 :                         break;
    3175              :                 }
    3176              :             }
    3177           14 :             break;
    3178              : 
    3179              :             /* parsed-and-rewritten-but-not-planned queries */
    3180          512 :         case T_Query:
    3181              :             {
    3182          512 :                 Query      *stmt = (Query *) parsetree;
    3183              : 
    3184          512 :                 switch (stmt->commandType)
    3185              :                 {
    3186          509 :                     case CMD_SELECT:
    3187              : 
    3188              :                         /*
    3189              :                          * We take a little extra care here so that the result
    3190              :                          * will be useful for complaints about read-only
    3191              :                          * statements
    3192              :                          */
    3193          509 :                         if (stmt->rowMarks != NIL)
    3194              :                         {
    3195              :                             /* not 100% but probably close enough */
    3196            0 :                             switch (((RowMarkClause *) linitial(stmt->rowMarks))->strength)
    3197              :                             {
    3198            0 :                                 case LCS_FORKEYSHARE:
    3199            0 :                                     tag = CMDTAG_SELECT_FOR_KEY_SHARE;
    3200            0 :                                     break;
    3201            0 :                                 case LCS_FORSHARE:
    3202            0 :                                     tag = CMDTAG_SELECT_FOR_SHARE;
    3203            0 :                                     break;
    3204            0 :                                 case LCS_FORNOKEYUPDATE:
    3205            0 :                                     tag = CMDTAG_SELECT_FOR_NO_KEY_UPDATE;
    3206            0 :                                     break;
    3207            0 :                                 case LCS_FORUPDATE:
    3208            0 :                                     tag = CMDTAG_SELECT_FOR_UPDATE;
    3209            0 :                                     break;
    3210            0 :                                 default:
    3211            0 :                                     tag = CMDTAG_UNKNOWN;
    3212            0 :                                     break;
    3213              :                             }
    3214              :                         }
    3215              :                         else
    3216          509 :                             tag = CMDTAG_SELECT;
    3217          509 :                         break;
    3218            0 :                     case CMD_UPDATE:
    3219            0 :                         tag = CMDTAG_UPDATE;
    3220            0 :                         break;
    3221            3 :                     case CMD_INSERT:
    3222            3 :                         tag = CMDTAG_INSERT;
    3223            3 :                         break;
    3224            0 :                     case CMD_DELETE:
    3225            0 :                         tag = CMDTAG_DELETE;
    3226            0 :                         break;
    3227            0 :                     case CMD_MERGE:
    3228            0 :                         tag = CMDTAG_MERGE;
    3229            0 :                         break;
    3230            0 :                     case CMD_UTILITY:
    3231            0 :                         tag = CreateCommandTag(stmt->utilityStmt);
    3232            0 :                         break;
    3233            0 :                     default:
    3234            0 :                         elog(WARNING, "unrecognized commandType: %d",
    3235              :                              (int) stmt->commandType);
    3236            0 :                         tag = CMDTAG_UNKNOWN;
    3237            0 :                         break;
    3238              :                 }
    3239              :             }
    3240          512 :             break;
    3241              : 
    3242            0 :         default:
    3243            0 :             elog(WARNING, "unrecognized node type: %d",
    3244              :                  (int) nodeTag(parsetree));
    3245            0 :             tag = CMDTAG_UNKNOWN;
    3246            0 :             break;
    3247              :     }
    3248              : 
    3249       423781 :     return tag;
    3250              : }
    3251              : 
    3252              : 
    3253              : /*
    3254              :  * GetCommandLogLevel
    3255              :  *      utility to get the minimum log_statement level for a command,
    3256              :  *      given either a raw (un-analyzed) parsetree, an analyzed Query,
    3257              :  *      or a PlannedStmt.
    3258              :  *
    3259              :  * This must handle all command types, but since the vast majority
    3260              :  * of 'em are utility commands, it seems sensible to keep it here.
    3261              :  */
    3262              : LogStmtLevel
    3263            0 : GetCommandLogLevel(Node *parsetree)
    3264              : {
    3265              :     LogStmtLevel lev;
    3266              : 
    3267            0 :     switch (nodeTag(parsetree))
    3268              :     {
    3269              :             /* recurse if we're given a RawStmt */
    3270            0 :         case T_RawStmt:
    3271            0 :             lev = GetCommandLogLevel(((RawStmt *) parsetree)->stmt);
    3272            0 :             break;
    3273              : 
    3274              :             /* raw plannable queries */
    3275            0 :         case T_InsertStmt:
    3276              :         case T_DeleteStmt:
    3277              :         case T_UpdateStmt:
    3278              :         case T_MergeStmt:
    3279            0 :             lev = LOGSTMT_MOD;
    3280            0 :             break;
    3281              : 
    3282            0 :         case T_SelectStmt:
    3283            0 :             if (((SelectStmt *) parsetree)->intoClause)
    3284            0 :                 lev = LOGSTMT_DDL;  /* SELECT INTO */
    3285              :             else
    3286            0 :                 lev = LOGSTMT_ALL;
    3287            0 :             break;
    3288              : 
    3289            0 :         case T_PLAssignStmt:
    3290            0 :             lev = LOGSTMT_ALL;
    3291            0 :             break;
    3292              : 
    3293              :             /* utility statements --- same whether raw or cooked */
    3294            0 :         case T_TransactionStmt:
    3295            0 :             lev = LOGSTMT_ALL;
    3296            0 :             break;
    3297              : 
    3298            0 :         case T_DeclareCursorStmt:
    3299            0 :             lev = LOGSTMT_ALL;
    3300            0 :             break;
    3301              : 
    3302            0 :         case T_ClosePortalStmt:
    3303            0 :             lev = LOGSTMT_ALL;
    3304            0 :             break;
    3305              : 
    3306            0 :         case T_FetchStmt:
    3307            0 :             lev = LOGSTMT_ALL;
    3308            0 :             break;
    3309              : 
    3310            0 :         case T_CreateSchemaStmt:
    3311            0 :             lev = LOGSTMT_DDL;
    3312            0 :             break;
    3313              : 
    3314            0 :         case T_CreateStmt:
    3315              :         case T_CreateForeignTableStmt:
    3316            0 :             lev = LOGSTMT_DDL;
    3317            0 :             break;
    3318              : 
    3319            0 :         case T_CreateTableSpaceStmt:
    3320              :         case T_DropTableSpaceStmt:
    3321              :         case T_AlterTableSpaceOptionsStmt:
    3322            0 :             lev = LOGSTMT_DDL;
    3323            0 :             break;
    3324              : 
    3325            0 :         case T_CreateExtensionStmt:
    3326              :         case T_AlterExtensionStmt:
    3327              :         case T_AlterExtensionContentsStmt:
    3328            0 :             lev = LOGSTMT_DDL;
    3329            0 :             break;
    3330              : 
    3331            0 :         case T_CreateFdwStmt:
    3332              :         case T_AlterFdwStmt:
    3333              :         case T_CreateForeignServerStmt:
    3334              :         case T_AlterForeignServerStmt:
    3335              :         case T_CreateUserMappingStmt:
    3336              :         case T_AlterUserMappingStmt:
    3337              :         case T_DropUserMappingStmt:
    3338              :         case T_ImportForeignSchemaStmt:
    3339            0 :             lev = LOGSTMT_DDL;
    3340            0 :             break;
    3341              : 
    3342            0 :         case T_DropStmt:
    3343            0 :             lev = LOGSTMT_DDL;
    3344            0 :             break;
    3345              : 
    3346            0 :         case T_TruncateStmt:
    3347            0 :             lev = LOGSTMT_MOD;
    3348            0 :             break;
    3349              : 
    3350            0 :         case T_CommentStmt:
    3351            0 :             lev = LOGSTMT_DDL;
    3352            0 :             break;
    3353              : 
    3354            0 :         case T_SecLabelStmt:
    3355            0 :             lev = LOGSTMT_DDL;
    3356            0 :             break;
    3357              : 
    3358            0 :         case T_CopyStmt:
    3359            0 :             if (((CopyStmt *) parsetree)->is_from)
    3360            0 :                 lev = LOGSTMT_MOD;
    3361              :             else
    3362            0 :                 lev = LOGSTMT_ALL;
    3363            0 :             break;
    3364              : 
    3365            0 :         case T_PrepareStmt:
    3366              :             {
    3367            0 :                 PrepareStmt *stmt = (PrepareStmt *) parsetree;
    3368              : 
    3369              :                 /* Look through a PREPARE to the contained stmt */
    3370            0 :                 lev = GetCommandLogLevel(stmt->query);
    3371              :             }
    3372            0 :             break;
    3373              : 
    3374            0 :         case T_ExecuteStmt:
    3375              :             {
    3376            0 :                 ExecuteStmt *stmt = (ExecuteStmt *) parsetree;
    3377              :                 PreparedStatement *ps;
    3378              : 
    3379              :                 /* Look through an EXECUTE to the referenced stmt */
    3380            0 :                 ps = FetchPreparedStatement(stmt->name, false);
    3381            0 :                 if (ps && ps->plansource->raw_parse_tree)
    3382            0 :                     lev = GetCommandLogLevel(ps->plansource->raw_parse_tree->stmt);
    3383              :                 else
    3384            0 :                     lev = LOGSTMT_ALL;
    3385              :             }
    3386            0 :             break;
    3387              : 
    3388            0 :         case T_DeallocateStmt:
    3389            0 :             lev = LOGSTMT_ALL;
    3390            0 :             break;
    3391              : 
    3392            0 :         case T_RenameStmt:
    3393            0 :             lev = LOGSTMT_DDL;
    3394            0 :             break;
    3395              : 
    3396            0 :         case T_AlterObjectDependsStmt:
    3397            0 :             lev = LOGSTMT_DDL;
    3398            0 :             break;
    3399              : 
    3400            0 :         case T_AlterObjectSchemaStmt:
    3401            0 :             lev = LOGSTMT_DDL;
    3402            0 :             break;
    3403              : 
    3404            0 :         case T_AlterOwnerStmt:
    3405            0 :             lev = LOGSTMT_DDL;
    3406            0 :             break;
    3407              : 
    3408            0 :         case T_AlterOperatorStmt:
    3409            0 :             lev = LOGSTMT_DDL;
    3410            0 :             break;
    3411              : 
    3412            0 :         case T_AlterTypeStmt:
    3413            0 :             lev = LOGSTMT_DDL;
    3414            0 :             break;
    3415              : 
    3416            0 :         case T_AlterTableMoveAllStmt:
    3417              :         case T_AlterTableStmt:
    3418            0 :             lev = LOGSTMT_DDL;
    3419            0 :             break;
    3420              : 
    3421            0 :         case T_AlterDomainStmt:
    3422            0 :             lev = LOGSTMT_DDL;
    3423            0 :             break;
    3424              : 
    3425            0 :         case T_GrantStmt:
    3426            0 :             lev = LOGSTMT_DDL;
    3427            0 :             break;
    3428              : 
    3429            0 :         case T_GrantRoleStmt:
    3430            0 :             lev = LOGSTMT_DDL;
    3431            0 :             break;
    3432              : 
    3433            0 :         case T_AlterDefaultPrivilegesStmt:
    3434            0 :             lev = LOGSTMT_DDL;
    3435            0 :             break;
    3436              : 
    3437            0 :         case T_DefineStmt:
    3438            0 :             lev = LOGSTMT_DDL;
    3439            0 :             break;
    3440              : 
    3441            0 :         case T_CompositeTypeStmt:
    3442            0 :             lev = LOGSTMT_DDL;
    3443            0 :             break;
    3444              : 
    3445            0 :         case T_CreateEnumStmt:
    3446            0 :             lev = LOGSTMT_DDL;
    3447            0 :             break;
    3448              : 
    3449            0 :         case T_CreateRangeStmt:
    3450            0 :             lev = LOGSTMT_DDL;
    3451            0 :             break;
    3452              : 
    3453            0 :         case T_AlterEnumStmt:
    3454            0 :             lev = LOGSTMT_DDL;
    3455            0 :             break;
    3456              : 
    3457            0 :         case T_ViewStmt:
    3458            0 :             lev = LOGSTMT_DDL;
    3459            0 :             break;
    3460              : 
    3461            0 :         case T_CreateFunctionStmt:
    3462            0 :             lev = LOGSTMT_DDL;
    3463            0 :             break;
    3464              : 
    3465            0 :         case T_AlterFunctionStmt:
    3466            0 :             lev = LOGSTMT_DDL;
    3467            0 :             break;
    3468              : 
    3469            0 :         case T_IndexStmt:
    3470            0 :             lev = LOGSTMT_DDL;
    3471            0 :             break;
    3472              : 
    3473            0 :         case T_RuleStmt:
    3474            0 :             lev = LOGSTMT_DDL;
    3475            0 :             break;
    3476              : 
    3477            0 :         case T_CreateSeqStmt:
    3478            0 :             lev = LOGSTMT_DDL;
    3479            0 :             break;
    3480              : 
    3481            0 :         case T_AlterSeqStmt:
    3482            0 :             lev = LOGSTMT_DDL;
    3483            0 :             break;
    3484              : 
    3485            0 :         case T_DoStmt:
    3486            0 :             lev = LOGSTMT_ALL;
    3487            0 :             break;
    3488              : 
    3489            0 :         case T_CreatedbStmt:
    3490            0 :             lev = LOGSTMT_DDL;
    3491            0 :             break;
    3492              : 
    3493            0 :         case T_AlterDatabaseStmt:
    3494              :         case T_AlterDatabaseRefreshCollStmt:
    3495              :         case T_AlterDatabaseSetStmt:
    3496            0 :             lev = LOGSTMT_DDL;
    3497            0 :             break;
    3498              : 
    3499            0 :         case T_DropdbStmt:
    3500            0 :             lev = LOGSTMT_DDL;
    3501            0 :             break;
    3502              : 
    3503            0 :         case T_NotifyStmt:
    3504            0 :             lev = LOGSTMT_ALL;
    3505            0 :             break;
    3506              : 
    3507            0 :         case T_ListenStmt:
    3508            0 :             lev = LOGSTMT_ALL;
    3509            0 :             break;
    3510              : 
    3511            0 :         case T_UnlistenStmt:
    3512            0 :             lev = LOGSTMT_ALL;
    3513            0 :             break;
    3514              : 
    3515            0 :         case T_LoadStmt:
    3516            0 :             lev = LOGSTMT_ALL;
    3517            0 :             break;
    3518              : 
    3519            0 :         case T_CallStmt:
    3520            0 :             lev = LOGSTMT_ALL;
    3521            0 :             break;
    3522              : 
    3523            0 :         case T_RepackStmt:
    3524            0 :             lev = LOGSTMT_DDL;
    3525            0 :             break;
    3526              : 
    3527            0 :         case T_VacuumStmt:
    3528            0 :             lev = LOGSTMT_ALL;
    3529            0 :             break;
    3530              : 
    3531            0 :         case T_ExplainStmt:
    3532              :             {
    3533            0 :                 ExplainStmt *stmt = (ExplainStmt *) parsetree;
    3534            0 :                 bool        analyze = false;
    3535              :                 ListCell   *lc;
    3536              : 
    3537              :                 /* Look through an EXPLAIN ANALYZE to the contained stmt */
    3538            0 :                 foreach(lc, stmt->options)
    3539              :                 {
    3540            0 :                     DefElem    *opt = (DefElem *) lfirst(lc);
    3541              : 
    3542            0 :                     if (strcmp(opt->defname, "analyze") == 0)
    3543            0 :                         analyze = defGetBoolean(opt);
    3544              :                     /* don't "break", as explain.c will use the last value */
    3545              :                 }
    3546            0 :                 if (analyze)
    3547            0 :                     return GetCommandLogLevel(stmt->query);
    3548              : 
    3549              :                 /* Plain EXPLAIN isn't so interesting */
    3550            0 :                 lev = LOGSTMT_ALL;
    3551              :             }
    3552            0 :             break;
    3553              : 
    3554            0 :         case T_CreateTableAsStmt:
    3555            0 :             lev = LOGSTMT_DDL;
    3556            0 :             break;
    3557              : 
    3558            0 :         case T_RefreshMatViewStmt:
    3559            0 :             lev = LOGSTMT_DDL;
    3560            0 :             break;
    3561              : 
    3562            0 :         case T_AlterSystemStmt:
    3563            0 :             lev = LOGSTMT_DDL;
    3564            0 :             break;
    3565              : 
    3566            0 :         case T_VariableSetStmt:
    3567            0 :             lev = LOGSTMT_ALL;
    3568            0 :             break;
    3569              : 
    3570            0 :         case T_VariableShowStmt:
    3571            0 :             lev = LOGSTMT_ALL;
    3572            0 :             break;
    3573              : 
    3574            0 :         case T_DiscardStmt:
    3575            0 :             lev = LOGSTMT_ALL;
    3576            0 :             break;
    3577              : 
    3578            0 :         case T_CreateTrigStmt:
    3579            0 :             lev = LOGSTMT_DDL;
    3580            0 :             break;
    3581              : 
    3582            0 :         case T_CreateEventTrigStmt:
    3583            0 :             lev = LOGSTMT_DDL;
    3584            0 :             break;
    3585              : 
    3586            0 :         case T_AlterEventTrigStmt:
    3587            0 :             lev = LOGSTMT_DDL;
    3588            0 :             break;
    3589              : 
    3590            0 :         case T_CreatePLangStmt:
    3591            0 :             lev = LOGSTMT_DDL;
    3592            0 :             break;
    3593              : 
    3594            0 :         case T_CreateDomainStmt:
    3595            0 :             lev = LOGSTMT_DDL;
    3596            0 :             break;
    3597              : 
    3598            0 :         case T_CreateRoleStmt:
    3599            0 :             lev = LOGSTMT_DDL;
    3600            0 :             break;
    3601              : 
    3602            0 :         case T_AlterRoleStmt:
    3603            0 :             lev = LOGSTMT_DDL;
    3604            0 :             break;
    3605              : 
    3606            0 :         case T_AlterRoleSetStmt:
    3607            0 :             lev = LOGSTMT_DDL;
    3608            0 :             break;
    3609              : 
    3610            0 :         case T_DropRoleStmt:
    3611            0 :             lev = LOGSTMT_DDL;
    3612            0 :             break;
    3613              : 
    3614            0 :         case T_DropOwnedStmt:
    3615            0 :             lev = LOGSTMT_DDL;
    3616            0 :             break;
    3617              : 
    3618            0 :         case T_ReassignOwnedStmt:
    3619            0 :             lev = LOGSTMT_DDL;
    3620            0 :             break;
    3621              : 
    3622            0 :         case T_LockStmt:
    3623            0 :             lev = LOGSTMT_ALL;
    3624            0 :             break;
    3625              : 
    3626            0 :         case T_ConstraintsSetStmt:
    3627            0 :             lev = LOGSTMT_ALL;
    3628            0 :             break;
    3629              : 
    3630            0 :         case T_CheckPointStmt:
    3631            0 :             lev = LOGSTMT_ALL;
    3632            0 :             break;
    3633              : 
    3634            0 :         case T_ReindexStmt:
    3635            0 :             lev = LOGSTMT_ALL;  /* should this be DDL? */
    3636            0 :             break;
    3637              : 
    3638            0 :         case T_CreateConversionStmt:
    3639            0 :             lev = LOGSTMT_DDL;
    3640            0 :             break;
    3641              : 
    3642            0 :         case T_CreateCastStmt:
    3643            0 :             lev = LOGSTMT_DDL;
    3644            0 :             break;
    3645              : 
    3646            0 :         case T_CreateOpClassStmt:
    3647            0 :             lev = LOGSTMT_DDL;
    3648            0 :             break;
    3649              : 
    3650            0 :         case T_CreateOpFamilyStmt:
    3651            0 :             lev = LOGSTMT_DDL;
    3652            0 :             break;
    3653              : 
    3654            0 :         case T_CreateTransformStmt:
    3655            0 :             lev = LOGSTMT_DDL;
    3656            0 :             break;
    3657              : 
    3658            0 :         case T_AlterOpFamilyStmt:
    3659            0 :             lev = LOGSTMT_DDL;
    3660            0 :             break;
    3661              : 
    3662            0 :         case T_CreatePolicyStmt:
    3663            0 :             lev = LOGSTMT_DDL;
    3664            0 :             break;
    3665              : 
    3666            0 :         case T_AlterPolicyStmt:
    3667            0 :             lev = LOGSTMT_DDL;
    3668            0 :             break;
    3669              : 
    3670            0 :         case T_AlterTSDictionaryStmt:
    3671            0 :             lev = LOGSTMT_DDL;
    3672            0 :             break;
    3673              : 
    3674            0 :         case T_AlterTSConfigurationStmt:
    3675            0 :             lev = LOGSTMT_DDL;
    3676            0 :             break;
    3677              : 
    3678            0 :         case T_CreateAmStmt:
    3679            0 :             lev = LOGSTMT_DDL;
    3680            0 :             break;
    3681              : 
    3682            0 :         case T_CreatePublicationStmt:
    3683            0 :             lev = LOGSTMT_DDL;
    3684            0 :             break;
    3685              : 
    3686            0 :         case T_AlterPublicationStmt:
    3687            0 :             lev = LOGSTMT_DDL;
    3688            0 :             break;
    3689              : 
    3690            0 :         case T_CreateSubscriptionStmt:
    3691            0 :             lev = LOGSTMT_DDL;
    3692            0 :             break;
    3693              : 
    3694            0 :         case T_AlterSubscriptionStmt:
    3695            0 :             lev = LOGSTMT_DDL;
    3696            0 :             break;
    3697              : 
    3698            0 :         case T_DropSubscriptionStmt:
    3699            0 :             lev = LOGSTMT_DDL;
    3700            0 :             break;
    3701              : 
    3702            0 :         case T_CreateStatsStmt:
    3703            0 :             lev = LOGSTMT_DDL;
    3704            0 :             break;
    3705              : 
    3706            0 :         case T_AlterStatsStmt:
    3707            0 :             lev = LOGSTMT_DDL;
    3708            0 :             break;
    3709              : 
    3710            0 :         case T_AlterCollationStmt:
    3711            0 :             lev = LOGSTMT_DDL;
    3712            0 :             break;
    3713              : 
    3714            0 :         case T_WaitStmt:
    3715            0 :             lev = LOGSTMT_ALL;
    3716            0 :             break;
    3717              : 
    3718              :             /* already-planned queries */
    3719            0 :         case T_PlannedStmt:
    3720              :             {
    3721            0 :                 PlannedStmt *stmt = (PlannedStmt *) parsetree;
    3722              : 
    3723            0 :                 switch (stmt->commandType)
    3724              :                 {
    3725            0 :                     case CMD_SELECT:
    3726            0 :                         lev = LOGSTMT_ALL;
    3727            0 :                         break;
    3728              : 
    3729            0 :                     case CMD_UPDATE:
    3730              :                     case CMD_INSERT:
    3731              :                     case CMD_DELETE:
    3732              :                     case CMD_MERGE:
    3733            0 :                         lev = LOGSTMT_MOD;
    3734            0 :                         break;
    3735              : 
    3736            0 :                     case CMD_UTILITY:
    3737            0 :                         lev = GetCommandLogLevel(stmt->utilityStmt);
    3738            0 :                         break;
    3739              : 
    3740            0 :                     default:
    3741            0 :                         elog(WARNING, "unrecognized commandType: %d",
    3742              :                              (int) stmt->commandType);
    3743            0 :                         lev = LOGSTMT_ALL;
    3744            0 :                         break;
    3745              :                 }
    3746              :             }
    3747            0 :             break;
    3748              : 
    3749              :             /* parsed-and-rewritten-but-not-planned queries */
    3750            0 :         case T_Query:
    3751              :             {
    3752            0 :                 Query      *stmt = (Query *) parsetree;
    3753              : 
    3754            0 :                 switch (stmt->commandType)
    3755              :                 {
    3756            0 :                     case CMD_SELECT:
    3757            0 :                         lev = LOGSTMT_ALL;
    3758            0 :                         break;
    3759              : 
    3760            0 :                     case CMD_UPDATE:
    3761              :                     case CMD_INSERT:
    3762              :                     case CMD_DELETE:
    3763              :                     case CMD_MERGE:
    3764            0 :                         lev = LOGSTMT_MOD;
    3765            0 :                         break;
    3766              : 
    3767            0 :                     case CMD_UTILITY:
    3768            0 :                         lev = GetCommandLogLevel(stmt->utilityStmt);
    3769            0 :                         break;
    3770              : 
    3771            0 :                     default:
    3772            0 :                         elog(WARNING, "unrecognized commandType: %d",
    3773              :                              (int) stmt->commandType);
    3774            0 :                         lev = LOGSTMT_ALL;
    3775            0 :                         break;
    3776              :                 }
    3777              :             }
    3778            0 :             break;
    3779              : 
    3780            0 :         default:
    3781            0 :             elog(WARNING, "unrecognized node type: %d",
    3782              :                  (int) nodeTag(parsetree));
    3783            0 :             lev = LOGSTMT_ALL;
    3784            0 :             break;
    3785              :     }
    3786              : 
    3787            0 :     return lev;
    3788              : }
        

Generated by: LCOV version 2.0-1