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

Generated by: LCOV version 2.0-1