LCOV - code coverage report
Current view: top level - src/backend/tcop - utility.c (source / functions) Hit Total Coverage
Test: PostgreSQL Lines: 954 1343 71.0 %
Date: 2017-09-29 13:40:31 Functions: 15 16 93.8 %
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-2017, 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/htup_details.h"
      20             : #include "access/reloptions.h"
      21             : #include "access/twophase.h"
      22             : #include "access/xact.h"
      23             : #include "access/xlog.h"
      24             : #include "catalog/catalog.h"
      25             : #include "catalog/namespace.h"
      26             : #include "catalog/toasting.h"
      27             : #include "commands/alter.h"
      28             : #include "commands/async.h"
      29             : #include "commands/cluster.h"
      30             : #include "commands/comment.h"
      31             : #include "commands/collationcmds.h"
      32             : #include "commands/conversioncmds.h"
      33             : #include "commands/copy.h"
      34             : #include "commands/createas.h"
      35             : #include "commands/dbcommands.h"
      36             : #include "commands/defrem.h"
      37             : #include "commands/discard.h"
      38             : #include "commands/event_trigger.h"
      39             : #include "commands/explain.h"
      40             : #include "commands/extension.h"
      41             : #include "commands/matview.h"
      42             : #include "commands/lockcmds.h"
      43             : #include "commands/policy.h"
      44             : #include "commands/portalcmds.h"
      45             : #include "commands/prepare.h"
      46             : #include "commands/proclang.h"
      47             : #include "commands/publicationcmds.h"
      48             : #include "commands/schemacmds.h"
      49             : #include "commands/seclabel.h"
      50             : #include "commands/sequence.h"
      51             : #include "commands/subscriptioncmds.h"
      52             : #include "commands/tablecmds.h"
      53             : #include "commands/tablespace.h"
      54             : #include "commands/trigger.h"
      55             : #include "commands/typecmds.h"
      56             : #include "commands/user.h"
      57             : #include "commands/vacuum.h"
      58             : #include "commands/view.h"
      59             : #include "miscadmin.h"
      60             : #include "parser/parse_utilcmd.h"
      61             : #include "postmaster/bgwriter.h"
      62             : #include "rewrite/rewriteDefine.h"
      63             : #include "rewrite/rewriteRemove.h"
      64             : #include "storage/fd.h"
      65             : #include "tcop/pquery.h"
      66             : #include "tcop/utility.h"
      67             : #include "utils/acl.h"
      68             : #include "utils/guc.h"
      69             : #include "utils/syscache.h"
      70             : 
      71             : 
      72             : /* Hook for plugins to get control in ProcessUtility() */
      73             : ProcessUtility_hook_type ProcessUtility_hook = NULL;
      74             : 
      75             : /* local function declarations */
      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             :                    char *completionTag);
      84             : static void ExecDropStmt(DropStmt *stmt, bool isTopLevel);
      85             : 
      86             : 
      87             : /*
      88             :  * CommandIsReadOnly: is an executable query read-only?
      89             :  *
      90             :  * This is a much stricter test than we apply for XactReadOnly mode;
      91             :  * the query must be *in truth* read-only, because the caller wishes
      92             :  * not to do CommandCounterIncrement for it.
      93             :  *
      94             :  * Note: currently no need to support raw or analyzed queries here
      95             :  */
      96             : bool
      97        1148 : CommandIsReadOnly(PlannedStmt *pstmt)
      98             : {
      99        1148 :     Assert(IsA(pstmt, PlannedStmt));
     100        1148 :     switch (pstmt->commandType)
     101             :     {
     102             :         case CMD_SELECT:
     103        1148 :             if (pstmt->rowMarks != NIL)
     104           0 :                 return false;   /* SELECT FOR [KEY] UPDATE/SHARE */
     105        1148 :             else if (pstmt->hasModifyingCTE)
     106           0 :                 return false;   /* data-modifying CTE */
     107             :             else
     108        1148 :                 return true;
     109             :         case CMD_UPDATE:
     110             :         case CMD_INSERT:
     111             :         case CMD_DELETE:
     112           0 :             return false;
     113             :         case CMD_UTILITY:
     114             :             /* For now, treat all utility commands as read/write */
     115           0 :             return false;
     116             :         default:
     117           0 :             elog(WARNING, "unrecognized commandType: %d",
     118             :                  (int) pstmt->commandType);
     119           0 :             break;
     120             :     }
     121           0 :     return false;
     122             : }
     123             : 
     124             : /*
     125             :  * check_xact_readonly: is a utility command read-only?
     126             :  *
     127             :  * Here we use the loose rules of XactReadOnly mode: no permanent effects
     128             :  * on the database are allowed.
     129             :  */
     130             : static void
     131       14044 : check_xact_readonly(Node *parsetree)
     132             : {
     133             :     /* Only perform the check if we have a reason to do so. */
     134       14044 :     if (!XactReadOnly && !IsInParallelMode())
     135       28069 :         return;
     136             : 
     137             :     /*
     138             :      * Note: Commands that need to do more complicated checking are handled
     139             :      * elsewhere, in particular COPY and plannable statements do their own
     140             :      * checking.  However they should all call PreventCommandIfReadOnly or
     141             :      * PreventCommandIfParallelMode to actually throw the error.
     142             :      */
     143             : 
     144          17 :     switch (nodeTag(parsetree))
     145             :     {
     146             :         case T_AlterDatabaseStmt:
     147             :         case T_AlterDatabaseSetStmt:
     148             :         case T_AlterDomainStmt:
     149             :         case T_AlterFunctionStmt:
     150             :         case T_AlterRoleStmt:
     151             :         case T_AlterRoleSetStmt:
     152             :         case T_AlterObjectDependsStmt:
     153             :         case T_AlterObjectSchemaStmt:
     154             :         case T_AlterOwnerStmt:
     155             :         case T_AlterOperatorStmt:
     156             :         case T_AlterSeqStmt:
     157             :         case T_AlterTableMoveAllStmt:
     158             :         case T_AlterTableStmt:
     159             :         case T_RenameStmt:
     160             :         case T_CommentStmt:
     161             :         case T_DefineStmt:
     162             :         case T_CreateCastStmt:
     163             :         case T_CreateEventTrigStmt:
     164             :         case T_AlterEventTrigStmt:
     165             :         case T_CreateConversionStmt:
     166             :         case T_CreatedbStmt:
     167             :         case T_CreateDomainStmt:
     168             :         case T_CreateFunctionStmt:
     169             :         case T_CreateRoleStmt:
     170             :         case T_IndexStmt:
     171             :         case T_CreatePLangStmt:
     172             :         case T_CreateOpClassStmt:
     173             :         case T_CreateOpFamilyStmt:
     174             :         case T_AlterOpFamilyStmt:
     175             :         case T_RuleStmt:
     176             :         case T_CreateSchemaStmt:
     177             :         case T_CreateSeqStmt:
     178             :         case T_CreateStmt:
     179             :         case T_CreateTableAsStmt:
     180             :         case T_RefreshMatViewStmt:
     181             :         case T_CreateTableSpaceStmt:
     182             :         case T_CreateTransformStmt:
     183             :         case T_CreateTrigStmt:
     184             :         case T_CompositeTypeStmt:
     185             :         case T_CreateEnumStmt:
     186             :         case T_CreateRangeStmt:
     187             :         case T_AlterEnumStmt:
     188             :         case T_ViewStmt:
     189             :         case T_DropStmt:
     190             :         case T_DropdbStmt:
     191             :         case T_DropTableSpaceStmt:
     192             :         case T_DropRoleStmt:
     193             :         case T_GrantStmt:
     194             :         case T_GrantRoleStmt:
     195             :         case T_AlterDefaultPrivilegesStmt:
     196             :         case T_TruncateStmt:
     197             :         case T_DropOwnedStmt:
     198             :         case T_ReassignOwnedStmt:
     199             :         case T_AlterTSDictionaryStmt:
     200             :         case T_AlterTSConfigurationStmt:
     201             :         case T_CreateExtensionStmt:
     202             :         case T_AlterExtensionStmt:
     203             :         case T_AlterExtensionContentsStmt:
     204             :         case T_CreateFdwStmt:
     205             :         case T_AlterFdwStmt:
     206             :         case T_CreateForeignServerStmt:
     207             :         case T_AlterForeignServerStmt:
     208             :         case T_CreateUserMappingStmt:
     209             :         case T_AlterUserMappingStmt:
     210             :         case T_DropUserMappingStmt:
     211             :         case T_AlterTableSpaceOptionsStmt:
     212             :         case T_CreateForeignTableStmt:
     213             :         case T_ImportForeignSchemaStmt:
     214             :         case T_SecLabelStmt:
     215             :         case T_CreatePublicationStmt:
     216             :         case T_AlterPublicationStmt:
     217             :         case T_CreateSubscriptionStmt:
     218             :         case T_AlterSubscriptionStmt:
     219             :         case T_DropSubscriptionStmt:
     220           2 :             PreventCommandIfReadOnly(CreateCommandTag(parsetree));
     221           0 :             PreventCommandIfParallelMode(CreateCommandTag(parsetree));
     222           0 :             break;
     223             :         default:
     224             :             /* do nothing */
     225          15 :             break;
     226             :     }
     227             : }
     228             : 
     229             : /*
     230             :  * PreventCommandIfReadOnly: throw error if XactReadOnly
     231             :  *
     232             :  * This is useful mainly to ensure consistency of the error message wording;
     233             :  * most callers have checked XactReadOnly for themselves.
     234             :  */
     235             : void
     236         306 : PreventCommandIfReadOnly(const char *cmdname)
     237             : {
     238         306 :     if (XactReadOnly)
     239           6 :         ereport(ERROR,
     240             :                 (errcode(ERRCODE_READ_ONLY_SQL_TRANSACTION),
     241             :         /* translator: %s is name of a SQL command, eg CREATE */
     242             :                  errmsg("cannot execute %s in a read-only transaction",
     243             :                         cmdname)));
     244         300 : }
     245             : 
     246             : /*
     247             :  * PreventCommandIfParallelMode: throw error if current (sub)transaction is
     248             :  * in parallel mode.
     249             :  *
     250             :  * This is useful mainly to ensure consistency of the error message wording;
     251             :  * most callers have checked IsInParallelMode() for themselves.
     252             :  */
     253             : void
     254         679 : PreventCommandIfParallelMode(const char *cmdname)
     255             : {
     256         679 :     if (IsInParallelMode())
     257           0 :         ereport(ERROR,
     258             :                 (errcode(ERRCODE_INVALID_TRANSACTION_STATE),
     259             :         /* translator: %s is name of a SQL command, eg CREATE */
     260             :                  errmsg("cannot execute %s during a parallel operation",
     261             :                         cmdname)));
     262         679 : }
     263             : 
     264             : /*
     265             :  * PreventCommandDuringRecovery: throw error if RecoveryInProgress
     266             :  *
     267             :  * The majority of operations that are unsafe in a Hot Standby
     268             :  * will be rejected by XactReadOnly tests.  However there are a few
     269             :  * commands that are allowed in "read-only" xacts but cannot be allowed
     270             :  * in Hot Standby mode.  Those commands should call this function.
     271             :  */
     272             : void
     273         485 : PreventCommandDuringRecovery(const char *cmdname)
     274             : {
     275         485 :     if (RecoveryInProgress())
     276           0 :         ereport(ERROR,
     277             :                 (errcode(ERRCODE_READ_ONLY_SQL_TRANSACTION),
     278             :         /* translator: %s is name of a SQL command, eg CREATE */
     279             :                  errmsg("cannot execute %s during recovery",
     280             :                         cmdname)));
     281         485 : }
     282             : 
     283             : /*
     284             :  * CheckRestrictedOperation: throw error for hazardous command if we're
     285             :  * inside a security restriction context.
     286             :  *
     287             :  * This is needed to protect session-local state for which there is not any
     288             :  * better-defined protection mechanism, such as ownership.
     289             :  */
     290             : static void
     291          95 : CheckRestrictedOperation(const char *cmdname)
     292             : {
     293          95 :     if (InSecurityRestrictedOperation())
     294           0 :         ereport(ERROR,
     295             :                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
     296             :         /* translator: %s is name of a SQL command, eg PREPARE */
     297             :                  errmsg("cannot execute %s within security-restricted operation",
     298             :                         cmdname)));
     299          95 : }
     300             : 
     301             : 
     302             : /*
     303             :  * ProcessUtility
     304             :  *      general utility function invoker
     305             :  *
     306             :  *  pstmt: PlannedStmt wrapper for the utility statement
     307             :  *  queryString: original source text of command
     308             :  *  context: identifies source of statement (toplevel client command,
     309             :  *      non-toplevel client command, subcommand of a larger utility command)
     310             :  *  params: parameters to use during execution
     311             :  *  queryEnv: environment for parse through execution (e.g., ephemeral named
     312             :  *      tables like trigger transition tables).  May be NULL.
     313             :  *  dest: where to send results
     314             :  *  completionTag: points to a buffer of size COMPLETION_TAG_BUFSIZE
     315             :  *      in which to store a command completion status string.
     316             :  *
     317             :  * Caller MUST supply a queryString; it is not allowed (anymore) to pass NULL.
     318             :  * If you really don't have source text, you can pass a constant string,
     319             :  * perhaps "(query not available)".
     320             :  *
     321             :  * completionTag is only set nonempty if we want to return a nondefault status.
     322             :  *
     323             :  * completionTag may be NULL if caller doesn't want a status string.
     324             :  *
     325             :  * Note for users of ProcessUtility_hook: the same queryString may be passed
     326             :  * to multiple invocations of ProcessUtility when processing a query string
     327             :  * containing multiple semicolon-separated statements.  One should use
     328             :  * pstmt->stmt_location and pstmt->stmt_len to identify the substring
     329             :  * containing the current statement.  Keep in mind also that some utility
     330             :  * statements (e.g., CREATE SCHEMA) will recurse to ProcessUtility to process
     331             :  * sub-statements, often passing down the same queryString, stmt_location,
     332             :  * and stmt_len that were given for the whole statement.
     333             :  */
     334             : void
     335       14044 : ProcessUtility(PlannedStmt *pstmt,
     336             :                const char *queryString,
     337             :                ProcessUtilityContext context,
     338             :                ParamListInfo params,
     339             :                QueryEnvironment *queryEnv,
     340             :                DestReceiver *dest,
     341             :                char *completionTag)
     342             : {
     343       14044 :     Assert(IsA(pstmt, PlannedStmt));
     344       14044 :     Assert(pstmt->commandType == CMD_UTILITY);
     345       14044 :     Assert(queryString != NULL);    /* required as of 8.4 */
     346             : 
     347             :     /*
     348             :      * We provide a function hook variable that lets loadable plugins get
     349             :      * control when ProcessUtility is called.  Such a plugin would normally
     350             :      * call standard_ProcessUtility().
     351             :      */
     352       14044 :     if (ProcessUtility_hook)
     353           0 :         (*ProcessUtility_hook) (pstmt, queryString,
     354             :                                 context, params, queryEnv,
     355             :                                 dest, completionTag);
     356             :     else
     357       14044 :         standard_ProcessUtility(pstmt, queryString,
     358             :                                 context, params, queryEnv,
     359             :                                 dest, completionTag);
     360       12745 : }
     361             : 
     362             : /*
     363             :  * standard_ProcessUtility itself deals only with utility commands for
     364             :  * which we do not provide event trigger support.  Commands that do have
     365             :  * such support are passed down to ProcessUtilitySlow, which contains the
     366             :  * necessary infrastructure for such triggers.
     367             :  *
     368             :  * This division is not just for performance: it's critical that the
     369             :  * event trigger code not be invoked when doing START TRANSACTION for
     370             :  * example, because we might need to refresh the event trigger cache,
     371             :  * which requires being in a valid transaction.
     372             :  */
     373             : void
     374       14044 : standard_ProcessUtility(PlannedStmt *pstmt,
     375             :                         const char *queryString,
     376             :                         ProcessUtilityContext context,
     377             :                         ParamListInfo params,
     378             :                         QueryEnvironment *queryEnv,
     379             :                         DestReceiver *dest,
     380             :                         char *completionTag)
     381             : {
     382       14044 :     Node       *parsetree = pstmt->utilityStmt;
     383       14044 :     bool        isTopLevel = (context == PROCESS_UTILITY_TOPLEVEL);
     384             :     ParseState *pstate;
     385             : 
     386       14044 :     check_xact_readonly(parsetree);
     387             : 
     388       14042 :     if (completionTag)
     389       13494 :         completionTag[0] = '\0';
     390             : 
     391       14042 :     pstate = make_parsestate(NULL);
     392       14042 :     pstate->p_sourcetext = queryString;
     393             : 
     394       14042 :     switch (nodeTag(parsetree))
     395             :     {
     396             :             /*
     397             :              * ******************** transactions ********************
     398             :              */
     399             :         case T_TransactionStmt:
     400             :             {
     401         764 :                 TransactionStmt *stmt = (TransactionStmt *) parsetree;
     402             : 
     403         764 :                 switch (stmt->kind)
     404             :                 {
     405             :                         /*
     406             :                          * START TRANSACTION, as defined by SQL99: Identical
     407             :                          * to BEGIN.  Same code for both.
     408             :                          */
     409             :                     case TRANS_STMT_BEGIN:
     410             :                     case TRANS_STMT_START:
     411             :                         {
     412             :                             ListCell   *lc;
     413             : 
     414         308 :                             BeginTransactionBlock();
     415         326 :                             foreach(lc, stmt->options)
     416             :                             {
     417          18 :                                 DefElem    *item = (DefElem *) lfirst(lc);
     418             : 
     419          18 :                                 if (strcmp(item->defname, "transaction_isolation") == 0)
     420          15 :                                     SetPGVariable("transaction_isolation",
     421          15 :                                                   list_make1(item->arg),
     422             :                                                   true);
     423           3 :                                 else if (strcmp(item->defname, "transaction_read_only") == 0)
     424           3 :                                     SetPGVariable("transaction_read_only",
     425           3 :                                                   list_make1(item->arg),
     426             :                                                   true);
     427           0 :                                 else if (strcmp(item->defname, "transaction_deferrable") == 0)
     428           0 :                                     SetPGVariable("transaction_deferrable",
     429           0 :                                                   list_make1(item->arg),
     430             :                                                   true);
     431             :                             }
     432             :                         }
     433         308 :                         break;
     434             : 
     435             :                     case TRANS_STMT_COMMIT:
     436         162 :                         if (!EndTransactionBlock())
     437             :                         {
     438             :                             /* report unsuccessful commit in completionTag */
     439          26 :                             if (completionTag)
     440          26 :                                 strcpy(completionTag, "ROLLBACK");
     441             :                         }
     442         162 :                         break;
     443             : 
     444             :                     case TRANS_STMT_PREPARE:
     445           8 :                         PreventCommandDuringRecovery("PREPARE TRANSACTION");
     446           8 :                         if (!PrepareTransactionBlock(stmt->gid))
     447             :                         {
     448             :                             /* report unsuccessful commit in completionTag */
     449           1 :                             if (completionTag)
     450           1 :                                 strcpy(completionTag, "ROLLBACK");
     451             :                         }
     452           8 :                         break;
     453             : 
     454             :                     case TRANS_STMT_COMMIT_PREPARED:
     455           3 :                         PreventTransactionChain(isTopLevel, "COMMIT PREPARED");
     456           3 :                         PreventCommandDuringRecovery("COMMIT PREPARED");
     457           3 :                         FinishPreparedTransaction(stmt->gid, true);
     458           3 :                         break;
     459             : 
     460             :                     case TRANS_STMT_ROLLBACK_PREPARED:
     461           3 :                         PreventTransactionChain(isTopLevel, "ROLLBACK PREPARED");
     462           3 :                         PreventCommandDuringRecovery("ROLLBACK PREPARED");
     463           3 :                         FinishPreparedTransaction(stmt->gid, false);
     464           3 :                         break;
     465             : 
     466             :                     case TRANS_STMT_ROLLBACK:
     467         141 :                         UserAbortTransactionBlock();
     468         141 :                         break;
     469             : 
     470             :                     case TRANS_STMT_SAVEPOINT:
     471             :                         {
     472             :                             ListCell   *cell;
     473          72 :                             char       *name = NULL;
     474             : 
     475          72 :                             RequireTransactionChain(isTopLevel, "SAVEPOINT");
     476             : 
     477         142 :                             foreach(cell, stmt->options)
     478             :                             {
     479          71 :                                 DefElem    *elem = lfirst(cell);
     480             : 
     481          71 :                                 if (strcmp(elem->defname, "savepoint_name") == 0)
     482          71 :                                     name = strVal(elem->arg);
     483             :                             }
     484             : 
     485          71 :                             Assert(PointerIsValid(name));
     486             : 
     487          71 :                             DefineSavepoint(name);
     488             :                         }
     489          71 :                         break;
     490             : 
     491             :                     case TRANS_STMT_RELEASE:
     492          16 :                         RequireTransactionChain(isTopLevel, "RELEASE SAVEPOINT");
     493          15 :                         ReleaseSavepoint(stmt->options);
     494          15 :                         break;
     495             : 
     496             :                     case TRANS_STMT_ROLLBACK_TO:
     497          51 :                         RequireTransactionChain(isTopLevel, "ROLLBACK TO SAVEPOINT");
     498          50 :                         RollbackToSavepoint(stmt->options);
     499             : 
     500             :                         /*
     501             :                          * CommitTransactionCommand is in charge of
     502             :                          * re-defining the savepoint again
     503             :                          */
     504          49 :                         break;
     505             :                 }
     506             :             }
     507         760 :             break;
     508             : 
     509             :             /*
     510             :              * Portal (cursor) manipulation
     511             :              */
     512             :         case T_DeclareCursorStmt:
     513          95 :             PerformCursorOpen((DeclareCursorStmt *) parsetree, params,
     514             :                               queryString, isTopLevel);
     515          95 :             break;
     516             : 
     517             :         case T_ClosePortalStmt:
     518             :             {
     519          42 :                 ClosePortalStmt *stmt = (ClosePortalStmt *) parsetree;
     520             : 
     521          42 :                 CheckRestrictedOperation("CLOSE");
     522          42 :                 PerformPortalClose(stmt->portalname);
     523             :             }
     524          42 :             break;
     525             : 
     526             :         case T_FetchStmt:
     527         203 :             PerformPortalFetch((FetchStmt *) parsetree, dest,
     528             :                                completionTag);
     529         192 :             break;
     530             : 
     531             :         case T_DoStmt:
     532          40 :             ExecuteDoStmt((DoStmt *) parsetree);
     533          19 :             break;
     534             : 
     535             :         case T_CreateTableSpaceStmt:
     536             :             /* no event triggers for global objects */
     537           4 :             PreventTransactionChain(isTopLevel, "CREATE TABLESPACE");
     538           4 :             CreateTableSpace((CreateTableSpaceStmt *) parsetree);
     539           2 :             break;
     540             : 
     541             :         case T_DropTableSpaceStmt:
     542             :             /* no event triggers for global objects */
     543           3 :             PreventTransactionChain(isTopLevel, "DROP TABLESPACE");
     544           3 :             DropTableSpace((DropTableSpaceStmt *) parsetree);
     545           2 :             break;
     546             : 
     547             :         case T_AlterTableSpaceOptionsStmt:
     548             :             /* no event triggers for global objects */
     549           4 :             AlterTableSpaceOptions((AlterTableSpaceOptionsStmt *) parsetree);
     550           2 :             break;
     551             : 
     552             :         case T_TruncateStmt:
     553          69 :             ExecuteTruncate((TruncateStmt *) parsetree);
     554          49 :             break;
     555             : 
     556             :         case T_CopyStmt:
     557             :             {
     558             :                 uint64      processed;
     559             : 
     560         226 :                 DoCopy(pstate, (CopyStmt *) parsetree,
     561             :                        pstmt->stmt_location, pstmt->stmt_len,
     562             :                        &processed);
     563         162 :                 if (completionTag)
     564         162 :                     snprintf(completionTag, COMPLETION_TAG_BUFSIZE,
     565             :                              "COPY " UINT64_FORMAT, processed);
     566             :             }
     567         162 :             break;
     568             : 
     569             :         case T_PrepareStmt:
     570          37 :             CheckRestrictedOperation("PREPARE");
     571          37 :             PrepareQuery((PrepareStmt *) parsetree, queryString,
     572             :                          pstmt->stmt_location, pstmt->stmt_len);
     573          34 :             break;
     574             : 
     575             :         case T_ExecuteStmt:
     576         135 :             ExecuteQuery((ExecuteStmt *) parsetree, NULL,
     577             :                          queryString, params,
     578             :                          dest, completionTag);
     579         119 :             break;
     580             : 
     581             :         case T_DeallocateStmt:
     582           8 :             CheckRestrictedOperation("DEALLOCATE");
     583           8 :             DeallocateQuery((DeallocateStmt *) parsetree);
     584           8 :             break;
     585             : 
     586             :         case T_GrantRoleStmt:
     587             :             /* no event triggers for global objects */
     588          20 :             GrantRole((GrantRoleStmt *) parsetree);
     589          16 :             break;
     590             : 
     591             :         case T_CreatedbStmt:
     592             :             /* no event triggers for global objects */
     593           3 :             PreventTransactionChain(isTopLevel, "CREATE DATABASE");
     594           3 :             createdb(pstate, (CreatedbStmt *) parsetree);
     595           3 :             break;
     596             : 
     597             :         case T_AlterDatabaseStmt:
     598             :             /* no event triggers for global objects */
     599           0 :             AlterDatabase(pstate, (AlterDatabaseStmt *) parsetree, isTopLevel);
     600           0 :             break;
     601             : 
     602             :         case T_AlterDatabaseSetStmt:
     603             :             /* no event triggers for global objects */
     604           6 :             AlterDatabaseSet((AlterDatabaseSetStmt *) parsetree);
     605           6 :             break;
     606             : 
     607             :         case T_DropdbStmt:
     608             :             {
     609           0 :                 DropdbStmt *stmt = (DropdbStmt *) parsetree;
     610             : 
     611             :                 /* no event triggers for global objects */
     612           0 :                 PreventTransactionChain(isTopLevel, "DROP DATABASE");
     613           0 :                 dropdb(stmt->dbname, stmt->missing_ok);
     614             :             }
     615           0 :             break;
     616             : 
     617             :             /* Query-level asynchronous notification */
     618             :         case T_NotifyStmt:
     619             :             {
     620           1 :                 NotifyStmt *stmt = (NotifyStmt *) parsetree;
     621             : 
     622           1 :                 PreventCommandDuringRecovery("NOTIFY");
     623           1 :                 Async_Notify(stmt->conditionname, stmt->payload);
     624             :             }
     625           1 :             break;
     626             : 
     627             :         case T_ListenStmt:
     628             :             {
     629           2 :                 ListenStmt *stmt = (ListenStmt *) parsetree;
     630             : 
     631           2 :                 PreventCommandDuringRecovery("LISTEN");
     632           2 :                 CheckRestrictedOperation("LISTEN");
     633           2 :                 Async_Listen(stmt->conditionname);
     634             :             }
     635           2 :             break;
     636             : 
     637             :         case T_UnlistenStmt:
     638             :             {
     639           2 :                 UnlistenStmt *stmt = (UnlistenStmt *) parsetree;
     640             : 
     641           2 :                 PreventCommandDuringRecovery("UNLISTEN");
     642           2 :                 CheckRestrictedOperation("UNLISTEN");
     643           2 :                 if (stmt->conditionname)
     644           1 :                     Async_Unlisten(stmt->conditionname);
     645             :                 else
     646           1 :                     Async_UnlistenAll();
     647             :             }
     648           2 :             break;
     649             : 
     650             :         case T_LoadStmt:
     651             :             {
     652           1 :                 LoadStmt   *stmt = (LoadStmt *) parsetree;
     653             : 
     654           1 :                 closeAllVfds(); /* probably not necessary... */
     655             :                 /* Allowed names are restricted if you're not superuser */
     656           1 :                 load_file(stmt->filename, !superuser());
     657             :             }
     658           1 :             break;
     659             : 
     660             :         case T_ClusterStmt:
     661             :             /* we choose to allow this during "read only" transactions */
     662          11 :             PreventCommandDuringRecovery("CLUSTER");
     663             :             /* forbidden in parallel mode due to CommandIsReadOnly */
     664          11 :             cluster((ClusterStmt *) parsetree, isTopLevel);
     665          10 :             break;
     666             : 
     667             :         case T_VacuumStmt:
     668             :             {
     669         128 :                 VacuumStmt *stmt = (VacuumStmt *) parsetree;
     670             : 
     671             :                 /* we choose to allow this during "read only" transactions */
     672         128 :                 PreventCommandDuringRecovery((stmt->options & VACOPT_VACUUM) ?
     673             :                                              "VACUUM" : "ANALYZE");
     674             :                 /* forbidden in parallel mode due to CommandIsReadOnly */
     675         128 :                 ExecVacuum(stmt, isTopLevel);
     676             :             }
     677         120 :             break;
     678             : 
     679             :         case T_ExplainStmt:
     680        1123 :             ExplainQuery(pstate, (ExplainStmt *) parsetree, queryString, params,
     681             :                          queryEnv, dest);
     682        1116 :             break;
     683             : 
     684             :         case T_AlterSystemStmt:
     685           0 :             PreventTransactionChain(isTopLevel, "ALTER SYSTEM");
     686           0 :             AlterSystemSetConfigFile((AlterSystemStmt *) parsetree);
     687           0 :             break;
     688             : 
     689             :         case T_VariableSetStmt:
     690        1964 :             ExecSetVariableStmt((VariableSetStmt *) parsetree, isTopLevel);
     691        1960 :             break;
     692             : 
     693             :         case T_VariableShowStmt:
     694             :             {
     695          64 :                 VariableShowStmt *n = (VariableShowStmt *) parsetree;
     696             : 
     697          64 :                 GetPGVariable(n->name, dest);
     698             :             }
     699          64 :             break;
     700             : 
     701             :         case T_DiscardStmt:
     702             :             /* should we allow DISCARD PLANS? */
     703           4 :             CheckRestrictedOperation("DISCARD");
     704           4 :             DiscardCommand((DiscardStmt *) parsetree, isTopLevel);
     705           4 :             break;
     706             : 
     707             :         case T_CreateEventTrigStmt:
     708             :             /* no event triggers on event triggers */
     709          21 :             CreateEventTrigger((CreateEventTrigStmt *) parsetree);
     710          10 :             break;
     711             : 
     712             :         case T_AlterEventTrigStmt:
     713             :             /* no event triggers on event triggers */
     714           4 :             AlterEventTrigger((AlterEventTrigStmt *) parsetree);
     715           4 :             break;
     716             : 
     717             :             /*
     718             :              * ******************************** ROLE statements ****
     719             :              */
     720             :         case T_CreateRoleStmt:
     721             :             /* no event triggers for global objects */
     722         118 :             CreateRole(pstate, (CreateRoleStmt *) parsetree);
     723         113 :             break;
     724             : 
     725             :         case T_AlterRoleStmt:
     726             :             /* no event triggers for global objects */
     727          52 :             AlterRole((AlterRoleStmt *) parsetree);
     728          44 :             break;
     729             : 
     730             :         case T_AlterRoleSetStmt:
     731             :             /* no event triggers for global objects */
     732          28 :             AlterRoleSet((AlterRoleSetStmt *) parsetree);
     733          24 :             break;
     734             : 
     735             :         case T_DropRoleStmt:
     736             :             /* no event triggers for global objects */
     737         141 :             DropRole((DropRoleStmt *) parsetree);
     738         120 :             break;
     739             : 
     740             :         case T_ReassignOwnedStmt:
     741             :             /* no event triggers for global objects */
     742           4 :             ReassignOwnedObjects((ReassignOwnedStmt *) parsetree);
     743           2 :             break;
     744             : 
     745             :         case T_LockStmt:
     746             : 
     747             :             /*
     748             :              * Since the lock would just get dropped immediately, LOCK TABLE
     749             :              * outside a transaction block is presumed to be user error.
     750             :              */
     751          40 :             RequireTransactionChain(isTopLevel, "LOCK TABLE");
     752             :             /* forbidden in parallel mode due to CommandIsReadOnly */
     753          40 :             LockTableCommand((LockStmt *) parsetree);
     754          28 :             break;
     755             : 
     756             :         case T_ConstraintsSetStmt:
     757          11 :             WarnNoTransactionChain(isTopLevel, "SET CONSTRAINTS");
     758          11 :             AfterTriggerSetState((ConstraintsSetStmt *) parsetree);
     759           7 :             break;
     760             : 
     761             :         case T_CheckPointStmt:
     762           0 :             if (!superuser())
     763           0 :                 ereport(ERROR,
     764             :                         (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
     765             :                          errmsg("must be superuser to do CHECKPOINT")));
     766             : 
     767             :             /*
     768             :              * You might think we should have a PreventCommandDuringRecovery()
     769             :              * here, but we interpret a CHECKPOINT command during recovery as
     770             :              * a request for a restartpoint instead. We allow this since it
     771             :              * can be a useful way of reducing switchover time when using
     772             :              * various forms of replication.
     773             :              */
     774           0 :             RequestCheckpoint(CHECKPOINT_IMMEDIATE | CHECKPOINT_WAIT |
     775           0 :                               (RecoveryInProgress() ? 0 : CHECKPOINT_FORCE));
     776           0 :             break;
     777             : 
     778             :         case T_ReindexStmt:
     779             :             {
     780          11 :                 ReindexStmt *stmt = (ReindexStmt *) parsetree;
     781             : 
     782             :                 /* we choose to allow this during "read only" transactions */
     783          11 :                 PreventCommandDuringRecovery("REINDEX");
     784             :                 /* forbidden in parallel mode due to CommandIsReadOnly */
     785          11 :                 switch (stmt->kind)
     786             :                 {
     787             :                     case REINDEX_OBJECT_INDEX:
     788           3 :                         ReindexIndex(stmt->relation, stmt->options);
     789           3 :                         break;
     790             :                     case REINDEX_OBJECT_TABLE:
     791           3 :                         ReindexTable(stmt->relation, stmt->options);
     792           2 :                         break;
     793             :                     case REINDEX_OBJECT_SCHEMA:
     794             :                     case REINDEX_OBJECT_SYSTEM:
     795             :                     case REINDEX_OBJECT_DATABASE:
     796             : 
     797             :                         /*
     798             :                          * This cannot run inside a user transaction block; if
     799             :                          * we were inside a transaction, then its commit- and
     800             :                          * start-transaction-command calls would not have the
     801             :                          * intended effect!
     802             :                          */
     803           5 :                         PreventTransactionChain(isTopLevel,
     804           5 :                                                 (stmt->kind == REINDEX_OBJECT_SCHEMA) ? "REINDEX SCHEMA" :
     805           0 :                                                 (stmt->kind == REINDEX_OBJECT_SYSTEM) ? "REINDEX SYSTEM" :
     806             :                                                 "REINDEX DATABASE");
     807           4 :                         ReindexMultipleTables(stmt->name, stmt->kind, stmt->options);
     808           2 :                         break;
     809             :                     default:
     810           0 :                         elog(ERROR, "unrecognized object type: %d",
     811             :                              (int) stmt->kind);
     812             :                         break;
     813             :                 }
     814             :             }
     815           7 :             break;
     816             : 
     817             :             /*
     818             :              * The following statements are supported by Event Triggers only
     819             :              * in some cases, so we "fast path" them in the other cases.
     820             :              */
     821             : 
     822             :         case T_GrantStmt:
     823             :             {
     824         359 :                 GrantStmt  *stmt = (GrantStmt *) parsetree;
     825             : 
     826         359 :                 if (EventTriggerSupportsGrantObjectType(stmt->objtype))
     827         354 :                     ProcessUtilitySlow(pstate, pstmt, queryString,
     828             :                                        context, params, queryEnv,
     829             :                                        dest, completionTag);
     830             :                 else
     831           5 :                     ExecuteGrantStmt(stmt);
     832             :             }
     833         343 :             break;
     834             : 
     835             :         case T_DropStmt:
     836             :             {
     837        1414 :                 DropStmt   *stmt = (DropStmt *) parsetree;
     838             : 
     839        1414 :                 if (EventTriggerSupportsObjectType(stmt->removeType))
     840        1402 :                     ProcessUtilitySlow(pstate, pstmt, queryString,
     841             :                                        context, params, queryEnv,
     842             :                                        dest, completionTag);
     843             :                 else
     844          12 :                     ExecDropStmt(stmt, isTopLevel);
     845             :             }
     846        1302 :             break;
     847             : 
     848             :         case T_RenameStmt:
     849             :             {
     850         156 :                 RenameStmt *stmt = (RenameStmt *) parsetree;
     851             : 
     852         156 :                 if (EventTriggerSupportsObjectType(stmt->renameType))
     853         150 :                     ProcessUtilitySlow(pstate, pstmt, queryString,
     854             :                                        context, params, queryEnv,
     855             :                                        dest, completionTag);
     856             :                 else
     857           6 :                     ExecRenameStmt(stmt);
     858             :             }
     859         104 :             break;
     860             : 
     861             :         case T_AlterObjectDependsStmt:
     862             :             {
     863           0 :                 AlterObjectDependsStmt *stmt = (AlterObjectDependsStmt *) parsetree;
     864             : 
     865           0 :                 if (EventTriggerSupportsObjectType(stmt->objectType))
     866           0 :                     ProcessUtilitySlow(pstate, pstmt, queryString,
     867             :                                        context, params, queryEnv,
     868             :                                        dest, completionTag);
     869             :                 else
     870           0 :                     ExecAlterObjectDependsStmt(stmt, NULL);
     871             :             }
     872           0 :             break;
     873             : 
     874             :         case T_AlterObjectSchemaStmt:
     875             :             {
     876          58 :                 AlterObjectSchemaStmt *stmt = (AlterObjectSchemaStmt *) parsetree;
     877             : 
     878          58 :                 if (EventTriggerSupportsObjectType(stmt->objectType))
     879          58 :                     ProcessUtilitySlow(pstate, pstmt, queryString,
     880             :                                        context, params, queryEnv,
     881             :                                        dest, completionTag);
     882             :                 else
     883           0 :                     ExecAlterObjectSchemaStmt(stmt, NULL);
     884             :             }
     885          37 :             break;
     886             : 
     887             :         case T_AlterOwnerStmt:
     888             :             {
     889          82 :                 AlterOwnerStmt *stmt = (AlterOwnerStmt *) parsetree;
     890             : 
     891          82 :                 if (EventTriggerSupportsObjectType(stmt->objectType))
     892          79 :                     ProcessUtilitySlow(pstate, pstmt, queryString,
     893             :                                        context, params, queryEnv,
     894             :                                        dest, completionTag);
     895             :                 else
     896           3 :                     ExecAlterOwnerStmt(stmt);
     897             :             }
     898          41 :             break;
     899             : 
     900             :         case T_CommentStmt:
     901             :             {
     902         396 :                 CommentStmt *stmt = (CommentStmt *) parsetree;
     903             : 
     904         396 :                 if (EventTriggerSupportsObjectType(stmt->objtype))
     905         393 :                     ProcessUtilitySlow(pstate, pstmt, queryString,
     906             :                                        context, params, queryEnv,
     907             :                                        dest, completionTag);
     908             :                 else
     909           3 :                     CommentObject(stmt);
     910         376 :                 break;
     911             :             }
     912             : 
     913             :         case T_SecLabelStmt:
     914             :             {
     915           8 :                 SecLabelStmt *stmt = (SecLabelStmt *) parsetree;
     916             : 
     917           8 :                 if (EventTriggerSupportsObjectType(stmt->objtype))
     918           4 :                     ProcessUtilitySlow(pstate, pstmt, queryString,
     919             :                                        context, params, queryEnv,
     920             :                                        dest, completionTag);
     921             :                 else
     922           4 :                     ExecSecLabelStmt(stmt);
     923           0 :                 break;
     924             :             }
     925             : 
     926             :         default:
     927             :             /* All other statement types have event trigger support */
     928        6180 :             ProcessUtilitySlow(pstate, pstmt, queryString,
     929             :                                context, params, queryEnv,
     930             :                                dest, completionTag);
     931        5392 :             break;
     932             :     }
     933             : 
     934       12745 :     free_parsestate(pstate);
     935       12745 : }
     936             : 
     937             : /*
     938             :  * The "Slow" variant of ProcessUtility should only receive statements
     939             :  * supported by the event triggers facility.  Therefore, we always
     940             :  * perform the trigger support calls if the context allows it.
     941             :  */
     942             : static void
     943        8620 : ProcessUtilitySlow(ParseState *pstate,
     944             :                    PlannedStmt *pstmt,
     945             :                    const char *queryString,
     946             :                    ProcessUtilityContext context,
     947             :                    ParamListInfo params,
     948             :                    QueryEnvironment *queryEnv,
     949             :                    DestReceiver *dest,
     950             :                    char *completionTag)
     951             : {
     952        8620 :     Node       *parsetree = pstmt->utilityStmt;
     953        8620 :     bool        isTopLevel = (context == PROCESS_UTILITY_TOPLEVEL);
     954        8620 :     bool        isCompleteQuery = (context <= PROCESS_UTILITY_QUERY);
     955             :     bool        needCleanup;
     956        8620 :     bool        commandCollected = false;
     957             :     ObjectAddress address;
     958        8620 :     ObjectAddress secondaryObject = InvalidObjectAddress;
     959             : 
     960             :     /* All event trigger calls are done only when isCompleteQuery is true */
     961        8620 :     needCleanup = isCompleteQuery && EventTriggerBeginCompleteQuery();
     962             : 
     963             :     /* PG_TRY block is to ensure we call EventTriggerEndCompleteQuery */
     964        8620 :     PG_TRY();
     965             :     {
     966        8620 :         if (isCompleteQuery)
     967        8082 :             EventTriggerDDLCommandStart(parsetree);
     968             : 
     969        8620 :         switch (nodeTag(parsetree))
     970             :         {
     971             :                 /*
     972             :                  * relation and attribute manipulation
     973             :                  */
     974             :             case T_CreateSchemaStmt:
     975          62 :                 CreateSchemaCommand((CreateSchemaStmt *) parsetree,
     976             :                                     queryString,
     977             :                                     pstmt->stmt_location,
     978             :                                     pstmt->stmt_len);
     979             : 
     980             :                 /*
     981             :                  * EventTriggerCollectSimpleCommand called by
     982             :                  * CreateSchemaCommand
     983             :                  */
     984          54 :                 commandCollected = true;
     985          54 :                 break;
     986             : 
     987             :             case T_CreateStmt:
     988             :             case T_CreateForeignTableStmt:
     989             :                 {
     990             :                     List       *stmts;
     991             :                     ListCell   *l;
     992             : 
     993             :                     /* Run parse analysis ... */
     994        1495 :                     stmts = transformCreateStmt((CreateStmt *) parsetree,
     995             :                                                 queryString);
     996             : 
     997             :                     /* ... and do it */
     998        3370 :                     foreach(l, stmts)
     999             :                     {
    1000        1984 :                         Node       *stmt = (Node *) lfirst(l);
    1001             : 
    1002        1984 :                         if (IsA(stmt, CreateStmt))
    1003             :                         {
    1004             :                             Datum       toast_options;
    1005             :                             static char *validnsps[] = HEAP_RELOPT_NAMESPACES;
    1006             : 
    1007             :                             /* Create the table itself */
    1008        1461 :                             address = DefineRelation((CreateStmt *) stmt,
    1009             :                                                      RELKIND_RELATION,
    1010             :                                                      InvalidOid, NULL,
    1011             :                                                      queryString);
    1012        1398 :                             EventTriggerCollectSimpleCommand(address,
    1013             :                                                              secondaryObject,
    1014             :                                                              stmt);
    1015             : 
    1016             :                             /*
    1017             :                              * Let NewRelationCreateToastTable decide if this
    1018             :                              * one needs a secondary relation too.
    1019             :                              */
    1020        1398 :                             CommandCounterIncrement();
    1021             : 
    1022             :                             /*
    1023             :                              * parse and validate reloptions for the toast
    1024             :                              * table
    1025             :                              */
    1026        1398 :                             toast_options = transformRelOptions((Datum) 0,
    1027             :                                                                 ((CreateStmt *) stmt)->options,
    1028             :                                                                 "toast",
    1029             :                                                                 validnsps,
    1030             :                                                                 true,
    1031             :                                                                 false);
    1032        1398 :                             (void) heap_reloptions(RELKIND_TOASTVALUE,
    1033             :                                                    toast_options,
    1034             :                                                    true);
    1035             : 
    1036        1398 :                             NewRelationCreateToastTable(address.objectId,
    1037             :                                                         toast_options);
    1038             :                         }
    1039         523 :                         else if (IsA(stmt, CreateForeignTableStmt))
    1040             :                         {
    1041             :                             /* Create the table itself */
    1042          11 :                             address = DefineRelation((CreateStmt *) stmt,
    1043             :                                                      RELKIND_FOREIGN_TABLE,
    1044             :                                                      InvalidOid, NULL,
    1045             :                                                      queryString);
    1046          11 :                             CreateForeignTable((CreateForeignTableStmt *) stmt,
    1047             :                                                address.objectId);
    1048          10 :                             EventTriggerCollectSimpleCommand(address,
    1049             :                                                              secondaryObject,
    1050             :                                                              stmt);
    1051             :                         }
    1052             :                         else
    1053             :                         {
    1054             :                             /*
    1055             :                              * Recurse for anything else.  Note the recursive
    1056             :                              * call will stash the objects so created into our
    1057             :                              * event trigger context.
    1058             :                              */
    1059             :                             PlannedStmt *wrapper;
    1060             : 
    1061         512 :                             wrapper = makeNode(PlannedStmt);
    1062         512 :                             wrapper->commandType = CMD_UTILITY;
    1063         512 :                             wrapper->canSetTag = false;
    1064         512 :                             wrapper->utilityStmt = stmt;
    1065         512 :                             wrapper->stmt_location = pstmt->stmt_location;
    1066         512 :                             wrapper->stmt_len = pstmt->stmt_len;
    1067             : 
    1068         512 :                             ProcessUtility(wrapper,
    1069             :                                            queryString,
    1070             :                                            PROCESS_UTILITY_SUBCOMMAND,
    1071             :                                            params,
    1072             :                                            NULL,
    1073             :                                            None_Receiver,
    1074             :                                            NULL);
    1075             :                         }
    1076             : 
    1077             :                         /* Need CCI between commands */
    1078        1895 :                         if (lnext(l) != NULL)
    1079         511 :                             CommandCounterIncrement();
    1080             :                     }
    1081             : 
    1082             :                     /*
    1083             :                      * The multiple commands generated here are stashed
    1084             :                      * individually, so disable collection below.
    1085             :                      */
    1086        1386 :                     commandCollected = true;
    1087             :                 }
    1088        1386 :                 break;
    1089             : 
    1090             :             case T_AlterTableStmt:
    1091             :                 {
    1092        1013 :                     AlterTableStmt *atstmt = (AlterTableStmt *) parsetree;
    1093             :                     Oid         relid;
    1094             :                     List       *stmts;
    1095             :                     ListCell   *l;
    1096             :                     LOCKMODE    lockmode;
    1097             : 
    1098             :                     /*
    1099             :                      * Figure out lock mode, and acquire lock.  This also does
    1100             :                      * basic permissions checks, so that we won't wait for a
    1101             :                      * lock on (for example) a relation on which we have no
    1102             :                      * permissions.
    1103             :                      */
    1104        1013 :                     lockmode = AlterTableGetLockLevel(atstmt->cmds);
    1105        1013 :                     relid = AlterTableLookupRelation(atstmt, lockmode);
    1106             : 
    1107        1005 :                     if (OidIsValid(relid))
    1108             :                     {
    1109             :                         /* Run parse analysis ... */
    1110         982 :                         stmts = transformAlterTableStmt(relid, atstmt,
    1111             :                                                         queryString);
    1112             : 
    1113             :                         /* ... ensure we have an event trigger context ... */
    1114         974 :                         EventTriggerAlterTableStart(parsetree);
    1115         974 :                         EventTriggerAlterTableRelid(relid);
    1116             : 
    1117             :                         /* ... and do it */
    1118        1696 :                         foreach(l, stmts)
    1119             :                         {
    1120         988 :                             Node       *stmt = (Node *) lfirst(l);
    1121             : 
    1122         988 :                             if (IsA(stmt, AlterTableStmt))
    1123             :                             {
    1124             :                                 /* Do the table alteration proper */
    1125         973 :                                 AlterTable(relid, lockmode,
    1126             :                                            (AlterTableStmt *) stmt);
    1127             :                             }
    1128             :                             else
    1129             :                             {
    1130             :                                 /*
    1131             :                                  * Recurse for anything else.  If we need to
    1132             :                                  * do so, "close" the current complex-command
    1133             :                                  * set, and start a new one at the bottom;
    1134             :                                  * this is needed to ensure the ordering of
    1135             :                                  * queued commands is consistent with the way
    1136             :                                  * they are executed here.
    1137             :                                  */
    1138             :                                 PlannedStmt *wrapper;
    1139             : 
    1140          15 :                                 EventTriggerAlterTableEnd();
    1141          15 :                                 wrapper = makeNode(PlannedStmt);
    1142          15 :                                 wrapper->commandType = CMD_UTILITY;
    1143          15 :                                 wrapper->canSetTag = false;
    1144          15 :                                 wrapper->utilityStmt = stmt;
    1145          15 :                                 wrapper->stmt_location = pstmt->stmt_location;
    1146          15 :                                 wrapper->stmt_len = pstmt->stmt_len;
    1147          15 :                                 ProcessUtility(wrapper,
    1148             :                                                queryString,
    1149             :                                                PROCESS_UTILITY_SUBCOMMAND,
    1150             :                                                params,
    1151             :                                                NULL,
    1152             :                                                None_Receiver,
    1153             :                                                NULL);
    1154          13 :                                 EventTriggerAlterTableStart(parsetree);
    1155          13 :                                 EventTriggerAlterTableRelid(relid);
    1156             :                             }
    1157             : 
    1158             :                             /* Need CCI between commands */
    1159         722 :                             if (lnext(l) != NULL)
    1160          14 :                                 CommandCounterIncrement();
    1161             :                         }
    1162             : 
    1163             :                         /* done */
    1164         708 :                         EventTriggerAlterTableEnd();
    1165             :                     }
    1166             :                     else
    1167          23 :                         ereport(NOTICE,
    1168             :                                 (errmsg("relation \"%s\" does not exist, skipping",
    1169             :                                         atstmt->relation->relname)));
    1170             :                 }
    1171             : 
    1172             :                 /* ALTER TABLE stashes commands internally */
    1173         731 :                 commandCollected = true;
    1174         731 :                 break;
    1175             : 
    1176             :             case T_AlterDomainStmt:
    1177             :                 {
    1178          32 :                     AlterDomainStmt *stmt = (AlterDomainStmt *) parsetree;
    1179             : 
    1180             :                     /*
    1181             :                      * Some or all of these functions are recursive to cover
    1182             :                      * inherited things, so permission checks are done there.
    1183             :                      */
    1184          32 :                     switch (stmt->subtype)
    1185             :                     {
    1186             :                         case 'T':   /* ALTER DOMAIN DEFAULT */
    1187             : 
    1188             :                             /*
    1189             :                              * Recursively alter column default for table and,
    1190             :                              * if requested, for descendants
    1191             :                              */
    1192           2 :                             address =
    1193           2 :                                 AlterDomainDefault(stmt->typeName,
    1194             :                                                    stmt->def);
    1195           2 :                             break;
    1196             :                         case 'N':   /* ALTER DOMAIN DROP NOT NULL */
    1197           2 :                             address =
    1198           2 :                                 AlterDomainNotNull(stmt->typeName,
    1199             :                                                    false);
    1200           2 :                             break;
    1201             :                         case 'O':   /* ALTER DOMAIN SET NOT NULL */
    1202           4 :                             address =
    1203           4 :                                 AlterDomainNotNull(stmt->typeName,
    1204             :                                                    true);
    1205           2 :                             break;
    1206             :                         case 'C':   /* ADD CONSTRAINT */
    1207          16 :                             address =
    1208          16 :                                 AlterDomainAddConstraint(stmt->typeName,
    1209             :                                                          stmt->def,
    1210             :                                                          &secondaryObject);
    1211           8 :                             break;
    1212             :                         case 'X':   /* DROP CONSTRAINT */
    1213           6 :                             address =
    1214          12 :                                 AlterDomainDropConstraint(stmt->typeName,
    1215           6 :                                                           stmt->name,
    1216             :                                                           stmt->behavior,
    1217           6 :                                                           stmt->missing_ok);
    1218           5 :                             break;
    1219             :                         case 'V':   /* VALIDATE CONSTRAINT */
    1220           2 :                             address =
    1221           2 :                                 AlterDomainValidateConstraint(stmt->typeName,
    1222             :                                                               stmt->name);
    1223           1 :                             break;
    1224             :                         default:    /* oops */
    1225           0 :                             elog(ERROR, "unrecognized alter domain type: %d",
    1226             :                                  (int) stmt->subtype);
    1227             :                             break;
    1228             :                     }
    1229             :                 }
    1230          20 :                 break;
    1231             : 
    1232             :                 /*
    1233             :                  * ************* object creation / destruction **************
    1234             :                  */
    1235             :             case T_DefineStmt:
    1236             :                 {
    1237         243 :                     DefineStmt *stmt = (DefineStmt *) parsetree;
    1238             : 
    1239         243 :                     switch (stmt->kind)
    1240             :                     {
    1241             :                         case OBJECT_AGGREGATE:
    1242         119 :                             address =
    1243         238 :                                 DefineAggregate(pstate, stmt->defnames, stmt->args,
    1244         119 :                                                 stmt->oldstyle,
    1245             :                                                 stmt->definition);
    1246          70 :                             break;
    1247             :                         case OBJECT_OPERATOR:
    1248          38 :                             Assert(stmt->args == NIL);
    1249          38 :                             address = DefineOperator(stmt->defnames,
    1250             :                                                      stmt->definition);
    1251          28 :                             break;
    1252             :                         case OBJECT_TYPE:
    1253          18 :                             Assert(stmt->args == NIL);
    1254          18 :                             address = DefineType(pstate,
    1255             :                                                  stmt->defnames,
    1256             :                                                  stmt->definition);
    1257          15 :                             break;
    1258             :                         case OBJECT_TSPARSER:
    1259           5 :                             Assert(stmt->args == NIL);
    1260           5 :                             address = DefineTSParser(stmt->defnames,
    1261             :                                                      stmt->definition);
    1262           5 :                             break;
    1263             :                         case OBJECT_TSDICTIONARY:
    1264          28 :                             Assert(stmt->args == NIL);
    1265          28 :                             address = DefineTSDictionary(stmt->defnames,
    1266             :                                                          stmt->definition);
    1267          28 :                             break;
    1268             :                         case OBJECT_TSTEMPLATE:
    1269           6 :                             Assert(stmt->args == NIL);
    1270           6 :                             address = DefineTSTemplate(stmt->defnames,
    1271             :                                                        stmt->definition);
    1272           6 :                             break;
    1273             :                         case OBJECT_TSCONFIGURATION:
    1274          26 :                             Assert(stmt->args == NIL);
    1275          26 :                             address = DefineTSConfiguration(stmt->defnames,
    1276             :                                                             stmt->definition,
    1277             :                                                             &secondaryObject);
    1278          26 :                             break;
    1279             :                         case OBJECT_COLLATION:
    1280           3 :                             Assert(stmt->args == NIL);
    1281           3 :                             address = DefineCollation(pstate,
    1282             :                                                       stmt->defnames,
    1283             :                                                       stmt->definition,
    1284           3 :                                                       stmt->if_not_exists);
    1285           2 :                             break;
    1286             :                         default:
    1287           0 :                             elog(ERROR, "unrecognized define stmt type: %d",
    1288             :                                  (int) stmt->kind);
    1289             :                             break;
    1290             :                     }
    1291             :                 }
    1292         180 :                 break;
    1293             : 
    1294             :             case T_IndexStmt:   /* CREATE INDEX */
    1295             :                 {
    1296         527 :                     IndexStmt  *stmt = (IndexStmt *) parsetree;
    1297             :                     Oid         relid;
    1298             :                     LOCKMODE    lockmode;
    1299             : 
    1300         527 :                     if (stmt->concurrent)
    1301           9 :                         PreventTransactionChain(isTopLevel,
    1302             :                                                 "CREATE INDEX CONCURRENTLY");
    1303             : 
    1304             :                     /*
    1305             :                      * Look up the relation OID just once, right here at the
    1306             :                      * beginning, so that we don't end up repeating the name
    1307             :                      * lookup later and latching onto a different relation
    1308             :                      * partway through.  To avoid lock upgrade hazards, it's
    1309             :                      * important that we take the strongest lock that will
    1310             :                      * eventually be needed here, so the lockmode calculation
    1311             :                      * needs to match what DefineIndex() does.
    1312             :                      */
    1313        1052 :                     lockmode = stmt->concurrent ? ShareUpdateExclusiveLock
    1314         526 :                         : ShareLock;
    1315         526 :                     relid =
    1316         526 :                         RangeVarGetRelidExtended(stmt->relation, lockmode,
    1317             :                                                  false, false,
    1318             :                                                  RangeVarCallbackOwnsRelation,
    1319             :                                                  NULL);
    1320             : 
    1321             :                     /* Run parse analysis ... */
    1322         526 :                     stmt = transformIndexStmt(relid, stmt, queryString);
    1323             : 
    1324             :                     /* ... and do it */
    1325         525 :                     EventTriggerAlterTableStart(parsetree);
    1326         525 :                     address =
    1327             :                         DefineIndex(relid,  /* OID of heap relation */
    1328             :                                     stmt,
    1329             :                                     InvalidOid, /* no predefined OID */
    1330             :                                     false,  /* is_alter_table */
    1331             :                                     true,   /* check_rights */
    1332             :                                     true,   /* check_not_in_use */
    1333             :                                     false,  /* skip_build */
    1334             :                                     false); /* quiet */
    1335             : 
    1336             :                     /*
    1337             :                      * Add the CREATE INDEX node itself to stash right away;
    1338             :                      * if there were any commands stashed in the ALTER TABLE
    1339             :                      * code, we need them to appear after this one.
    1340             :                      */
    1341         515 :                     EventTriggerCollectSimpleCommand(address, secondaryObject,
    1342             :                                                      parsetree);
    1343         515 :                     commandCollected = true;
    1344         515 :                     EventTriggerAlterTableEnd();
    1345             :                 }
    1346         515 :                 break;
    1347             : 
    1348             :             case T_CreateExtensionStmt:
    1349           1 :                 address = CreateExtension(pstate, (CreateExtensionStmt *) parsetree);
    1350           1 :                 break;
    1351             : 
    1352             :             case T_AlterExtensionStmt:
    1353           0 :                 address = ExecAlterExtensionStmt(pstate, (AlterExtensionStmt *) parsetree);
    1354           0 :                 break;
    1355             : 
    1356             :             case T_AlterExtensionContentsStmt:
    1357           0 :                 address = ExecAlterExtensionContentsStmt((AlterExtensionContentsStmt *) parsetree,
    1358             :                                                          &secondaryObject);
    1359           0 :                 break;
    1360             : 
    1361             :             case T_CreateFdwStmt:
    1362          20 :                 address = CreateForeignDataWrapper((CreateFdwStmt *) parsetree);
    1363          14 :                 break;
    1364             : 
    1365             :             case T_AlterFdwStmt:
    1366          15 :                 address = AlterForeignDataWrapper((AlterFdwStmt *) parsetree);
    1367           7 :                 break;
    1368             : 
    1369             :             case T_CreateForeignServerStmt:
    1370          38 :                 address = CreateForeignServer((CreateForeignServerStmt *) parsetree);
    1371          31 :                 break;
    1372             : 
    1373             :             case T_AlterForeignServerStmt:
    1374          13 :                 address = AlterForeignServer((AlterForeignServerStmt *) parsetree);
    1375           7 :                 break;
    1376             : 
    1377             :             case T_CreateUserMappingStmt:
    1378          44 :                 address = CreateUserMapping((CreateUserMappingStmt *) parsetree);
    1379          34 :                 break;
    1380             : 
    1381             :             case T_AlterUserMappingStmt:
    1382          20 :                 address = AlterUserMapping((AlterUserMappingStmt *) parsetree);
    1383          12 :                 break;
    1384             : 
    1385             :             case T_DropUserMappingStmt:
    1386          30 :                 RemoveUserMapping((DropUserMappingStmt *) parsetree);
    1387             :                 /* no commands stashed for DROP */
    1388          23 :                 commandCollected = true;
    1389          23 :                 break;
    1390             : 
    1391             :             case T_ImportForeignSchemaStmt:
    1392           4 :                 ImportForeignSchema((ImportForeignSchemaStmt *) parsetree);
    1393             :                 /* commands are stashed inside ImportForeignSchema */
    1394           0 :                 commandCollected = true;
    1395           0 :                 break;
    1396             : 
    1397             :             case T_CompositeTypeStmt:   /* CREATE TYPE (composite) */
    1398             :                 {
    1399          51 :                     CompositeTypeStmt *stmt = (CompositeTypeStmt *) parsetree;
    1400             : 
    1401          51 :                     address = DefineCompositeType(stmt->typevar,
    1402             :                                                   stmt->coldeflist);
    1403             :                 }
    1404          49 :                 break;
    1405             : 
    1406             :             case T_CreateEnumStmt:  /* CREATE TYPE AS ENUM */
    1407          15 :                 address = DefineEnum((CreateEnumStmt *) parsetree);
    1408          15 :                 break;
    1409             : 
    1410             :             case T_CreateRangeStmt: /* CREATE TYPE AS RANGE */
    1411          10 :                 address = DefineRange((CreateRangeStmt *) parsetree);
    1412           9 :                 break;
    1413             : 
    1414             :             case T_AlterEnumStmt:   /* ALTER TYPE (enum) */
    1415          47 :                 address = AlterEnum((AlterEnumStmt *) parsetree);
    1416          42 :                 break;
    1417             : 
    1418             :             case T_ViewStmt:    /* CREATE VIEW */
    1419         420 :                 EventTriggerAlterTableStart(parsetree);
    1420         420 :                 address = DefineView((ViewStmt *) parsetree, queryString,
    1421             :                                      pstmt->stmt_location, pstmt->stmt_len);
    1422         403 :                 EventTriggerCollectSimpleCommand(address, secondaryObject,
    1423             :                                                  parsetree);
    1424             :                 /* stashed internally */
    1425         403 :                 commandCollected = true;
    1426         403 :                 EventTriggerAlterTableEnd();
    1427         403 :                 break;
    1428             : 
    1429             :             case T_CreateFunctionStmt:  /* CREATE FUNCTION */
    1430         767 :                 address = CreateFunction(pstate, (CreateFunctionStmt *) parsetree);
    1431         711 :                 break;
    1432             : 
    1433             :             case T_AlterFunctionStmt:   /* ALTER FUNCTION */
    1434          19 :                 address = AlterFunction(pstate, (AlterFunctionStmt *) parsetree);
    1435          18 :                 break;
    1436             : 
    1437             :             case T_RuleStmt:    /* CREATE RULE */
    1438         101 :                 address = DefineRule((RuleStmt *) parsetree, queryString);
    1439          94 :                 break;
    1440             : 
    1441             :             case T_CreateSeqStmt:
    1442         150 :                 address = DefineSequence(pstate, (CreateSeqStmt *) parsetree);
    1443         133 :                 break;
    1444             : 
    1445             :             case T_AlterSeqStmt:
    1446         105 :                 address = AlterSequence(pstate, (AlterSeqStmt *) parsetree);
    1447          97 :                 break;
    1448             : 
    1449             :             case T_CreateTableAsStmt:
    1450         118 :                 address = ExecCreateTableAs((CreateTableAsStmt *) parsetree,
    1451             :                                             queryString, params, queryEnv,
    1452             :                                             completionTag);
    1453         105 :                 break;
    1454             : 
    1455             :             case T_RefreshMatViewStmt:
    1456             : 
    1457             :                 /*
    1458             :                  * REFRESH CONCURRENTLY executes some DDL commands internally.
    1459             :                  * Inhibit DDL command collection here to avoid those commands
    1460             :                  * from showing up in the deparsed command queue.  The refresh
    1461             :                  * command itself is queued, which is enough.
    1462             :                  */
    1463          21 :                 EventTriggerInhibitCommandCollection();
    1464          21 :                 PG_TRY();
    1465             :                 {
    1466          21 :                     address = ExecRefreshMatView((RefreshMatViewStmt *) parsetree,
    1467             :                                                  queryString, params, completionTag);
    1468             :                 }
    1469           5 :                 PG_CATCH();
    1470             :                 {
    1471           5 :                     EventTriggerUndoInhibitCommandCollection();
    1472           5 :                     PG_RE_THROW();
    1473             :                 }
    1474          16 :                 PG_END_TRY();
    1475          16 :                 EventTriggerUndoInhibitCommandCollection();
    1476          16 :                 break;
    1477             : 
    1478             :             case T_CreateTrigStmt:
    1479         208 :                 address = CreateTrigger((CreateTrigStmt *) parsetree,
    1480             :                                         queryString, InvalidOid, InvalidOid,
    1481             :                                         InvalidOid, InvalidOid, false);
    1482         181 :                 break;
    1483             : 
    1484             :             case T_CreatePLangStmt:
    1485           3 :                 address = CreateProceduralLanguage((CreatePLangStmt *) parsetree);
    1486           3 :                 break;
    1487             : 
    1488             :             case T_CreateDomainStmt:
    1489          77 :                 address = DefineDomain((CreateDomainStmt *) parsetree);
    1490          75 :                 break;
    1491             : 
    1492             :             case T_CreateConversionStmt:
    1493         142 :                 address = CreateConversionCommand((CreateConversionStmt *) parsetree);
    1494         140 :                 break;
    1495             : 
    1496             :             case T_CreateCastStmt:
    1497          11 :                 address = CreateCast((CreateCastStmt *) parsetree);
    1498          10 :                 break;
    1499             : 
    1500             :             case T_CreateOpClassStmt:
    1501           6 :                 DefineOpClass((CreateOpClassStmt *) parsetree);
    1502             :                 /* command is stashed in DefineOpClass */
    1503           6 :                 commandCollected = true;
    1504           6 :                 break;
    1505             : 
    1506             :             case T_CreateOpFamilyStmt:
    1507          20 :                 address = DefineOpFamily((CreateOpFamilyStmt *) parsetree);
    1508          20 :                 break;
    1509             : 
    1510             :             case T_CreateTransformStmt:
    1511           1 :                 address = CreateTransform((CreateTransformStmt *) parsetree);
    1512           1 :                 break;
    1513             : 
    1514             :             case T_AlterOpFamilyStmt:
    1515          38 :                 AlterOpFamily((AlterOpFamilyStmt *) parsetree);
    1516             :                 /* commands are stashed in AlterOpFamily */
    1517          16 :                 commandCollected = true;
    1518          16 :                 break;
    1519             : 
    1520             :             case T_AlterTSDictionaryStmt:
    1521           0 :                 address = AlterTSDictionary((AlterTSDictionaryStmt *) parsetree);
    1522           0 :                 break;
    1523             : 
    1524             :             case T_AlterTSConfigurationStmt:
    1525          51 :                 AlterTSConfiguration((AlterTSConfigurationStmt *) parsetree);
    1526             : 
    1527             :                 /*
    1528             :                  * Commands are stashed in MakeConfigurationMapping and
    1529             :                  * DropConfigurationMapping, which are called from
    1530             :                  * AlterTSConfiguration
    1531             :                  */
    1532          51 :                 commandCollected = true;
    1533          51 :                 break;
    1534             : 
    1535             :             case T_AlterTableMoveAllStmt:
    1536           3 :                 AlterTableMoveAll((AlterTableMoveAllStmt *) parsetree);
    1537             :                 /* commands are stashed in AlterTableMoveAll */
    1538           3 :                 commandCollected = true;
    1539           3 :                 break;
    1540             : 
    1541             :             case T_DropStmt:
    1542        1402 :                 ExecDropStmt((DropStmt *) parsetree, isTopLevel);
    1543             :                 /* no commands stashed for DROP */
    1544        1294 :                 commandCollected = true;
    1545        1294 :                 break;
    1546             : 
    1547             :             case T_RenameStmt:
    1548         150 :                 address = ExecRenameStmt((RenameStmt *) parsetree);
    1549          99 :                 break;
    1550             : 
    1551             :             case T_AlterObjectDependsStmt:
    1552           0 :                 address =
    1553             :                     ExecAlterObjectDependsStmt((AlterObjectDependsStmt *) parsetree,
    1554             :                                                &secondaryObject);
    1555           0 :                 break;
    1556             : 
    1557             :             case T_AlterObjectSchemaStmt:
    1558          58 :                 address =
    1559             :                     ExecAlterObjectSchemaStmt((AlterObjectSchemaStmt *) parsetree,
    1560             :                                               &secondaryObject);
    1561          37 :                 break;
    1562             : 
    1563             :             case T_AlterOwnerStmt:
    1564          79 :                 address = ExecAlterOwnerStmt((AlterOwnerStmt *) parsetree);
    1565          39 :                 break;
    1566             : 
    1567             :             case T_AlterOperatorStmt:
    1568          13 :                 address = AlterOperator((AlterOperatorStmt *) parsetree);
    1569           6 :                 break;
    1570             : 
    1571             :             case T_CommentStmt:
    1572         393 :                 address = CommentObject((CommentStmt *) parsetree);
    1573         373 :                 break;
    1574             : 
    1575             :             case T_GrantStmt:
    1576         354 :                 ExecuteGrantStmt((GrantStmt *) parsetree);
    1577             :                 /* commands are stashed in ExecGrantStmt_oids */
    1578         338 :                 commandCollected = true;
    1579         338 :                 break;
    1580             : 
    1581             :             case T_DropOwnedStmt:
    1582          16 :                 DropOwnedObjects((DropOwnedStmt *) parsetree);
    1583             :                 /* no commands stashed for DROP */
    1584          13 :                 commandCollected = true;
    1585          13 :                 break;
    1586             : 
    1587             :             case T_AlterDefaultPrivilegesStmt:
    1588          18 :                 ExecAlterDefaultPrivilegesStmt(pstate, (AlterDefaultPrivilegesStmt *) parsetree);
    1589          17 :                 EventTriggerCollectAlterDefPrivs((AlterDefaultPrivilegesStmt *) parsetree);
    1590          17 :                 commandCollected = true;
    1591          17 :                 break;
    1592             : 
    1593             :             case T_CreatePolicyStmt:    /* CREATE POLICY */
    1594          81 :                 address = CreatePolicy((CreatePolicyStmt *) parsetree);
    1595          79 :                 break;
    1596             : 
    1597             :             case T_AlterPolicyStmt: /* ALTER POLICY */
    1598          14 :                 address = AlterPolicy((AlterPolicyStmt *) parsetree);
    1599          12 :                 break;
    1600             : 
    1601             :             case T_SecLabelStmt:
    1602           4 :                 address = ExecSecLabelStmt((SecLabelStmt *) parsetree);
    1603           0 :                 break;
    1604             : 
    1605             :             case T_CreateAmStmt:
    1606           1 :                 address = CreateAccessMethod((CreateAmStmt *) parsetree);
    1607           1 :                 break;
    1608             : 
    1609             :             case T_CreatePublicationStmt:
    1610          13 :                 address = CreatePublication((CreatePublicationStmt *) parsetree);
    1611           8 :                 break;
    1612             : 
    1613             :             case T_AlterPublicationStmt:
    1614          17 :                 AlterPublication((AlterPublicationStmt *) parsetree);
    1615             : 
    1616             :                 /*
    1617             :                  * AlterPublication calls EventTriggerCollectSimpleCommand
    1618             :                  * directly
    1619             :                  */
    1620           9 :                 commandCollected = true;
    1621           9 :                 break;
    1622             : 
    1623             :             case T_CreateSubscriptionStmt:
    1624          16 :                 address = CreateSubscription((CreateSubscriptionStmt *) parsetree,
    1625             :                                              isTopLevel);
    1626           3 :                 break;
    1627             : 
    1628             :             case T_AlterSubscriptionStmt:
    1629          13 :                 address = AlterSubscription((AlterSubscriptionStmt *) parsetree);
    1630           7 :                 break;
    1631             : 
    1632             :             case T_DropSubscriptionStmt:
    1633           6 :                 DropSubscription((DropSubscriptionStmt *) parsetree, isTopLevel);
    1634             :                 /* no commands stashed for DROP */
    1635           4 :                 commandCollected = true;
    1636           4 :                 break;
    1637             : 
    1638             :             case T_CreateStatsStmt:
    1639          31 :                 address = CreateStatistics((CreateStatsStmt *) parsetree);
    1640          20 :                 break;
    1641             : 
    1642             :             case T_AlterCollationStmt:
    1643           0 :                 address = AlterCollation((AlterCollationStmt *) parsetree);
    1644           0 :                 break;
    1645             : 
    1646             :             default:
    1647           0 :                 elog(ERROR, "unrecognized node type: %d",
    1648             :                      (int) nodeTag(parsetree));
    1649             :                 break;
    1650             :         }
    1651             : 
    1652             :         /*
    1653             :          * Remember the object so that ddl_command_end event triggers have
    1654             :          * access to it.
    1655             :          */
    1656        7572 :         if (!commandCollected)
    1657        2709 :             EventTriggerCollectSimpleCommand(address, secondaryObject,
    1658             :                                              parsetree);
    1659             : 
    1660        7572 :         if (isCompleteQuery)
    1661             :         {
    1662        7062 :             EventTriggerSQLDrop(parsetree);
    1663        7059 :             EventTriggerDDLCommandEnd(parsetree);
    1664             :         }
    1665             :     }
    1666        1051 :     PG_CATCH();
    1667             :     {
    1668        1051 :         if (needCleanup)
    1669           6 :             EventTriggerEndCompleteQuery();
    1670        1051 :         PG_RE_THROW();
    1671             :     }
    1672        7569 :     PG_END_TRY();
    1673             : 
    1674        7569 :     if (needCleanup)
    1675          50 :         EventTriggerEndCompleteQuery();
    1676        7569 : }
    1677             : 
    1678             : /*
    1679             :  * Dispatch function for DropStmt
    1680             :  */
    1681             : static void
    1682        1414 : ExecDropStmt(DropStmt *stmt, bool isTopLevel)
    1683             : {
    1684        1414 :     switch (stmt->removeType)
    1685             :     {
    1686             :         case OBJECT_INDEX:
    1687          64 :             if (stmt->concurrent)
    1688           9 :                 PreventTransactionChain(isTopLevel,
    1689             :                                         "DROP INDEX CONCURRENTLY");
    1690             :             /* fall through */
    1691             : 
    1692             :         case OBJECT_TABLE:
    1693             :         case OBJECT_SEQUENCE:
    1694             :         case OBJECT_VIEW:
    1695             :         case OBJECT_MATVIEW:
    1696             :         case OBJECT_FOREIGN_TABLE:
    1697         819 :             RemoveRelations(stmt);
    1698         787 :             break;
    1699             :         default:
    1700         594 :             RemoveObjects(stmt);
    1701         518 :             break;
    1702             :     }
    1703        1305 : }
    1704             : 
    1705             : 
    1706             : /*
    1707             :  * UtilityReturnsTuples
    1708             :  *      Return "true" if this utility statement will send output to the
    1709             :  *      destination.
    1710             :  *
    1711             :  * Generally, there should be a case here for each case in ProcessUtility
    1712             :  * where "dest" is passed on.
    1713             :  */
    1714             : bool
    1715       13000 : UtilityReturnsTuples(Node *parsetree)
    1716             : {
    1717       13000 :     switch (nodeTag(parsetree))
    1718             :     {
    1719             :         case T_FetchStmt:
    1720             :             {
    1721         203 :                 FetchStmt  *stmt = (FetchStmt *) parsetree;
    1722             :                 Portal      portal;
    1723             : 
    1724         203 :                 if (stmt->ismove)
    1725           6 :                     return false;
    1726         197 :                 portal = GetPortalByName(stmt->portalname);
    1727         197 :                 if (!PortalIsValid(portal))
    1728           4 :                     return false;   /* not our business to raise error */
    1729         193 :                 return portal->tupDesc ? true : false;
    1730             :             }
    1731             : 
    1732             :         case T_ExecuteStmt:
    1733             :             {
    1734         135 :                 ExecuteStmt *stmt = (ExecuteStmt *) parsetree;
    1735             :                 PreparedStatement *entry;
    1736             : 
    1737         135 :                 entry = FetchPreparedStatement(stmt->name, false);
    1738         135 :                 if (!entry)
    1739           4 :                     return false;   /* not our business to raise error */
    1740         131 :                 if (entry->plansource->resultDesc)
    1741         128 :                     return true;
    1742           3 :                 return false;
    1743             :             }
    1744             : 
    1745             :         case T_ExplainStmt:
    1746        1623 :             return true;
    1747             : 
    1748             :         case T_VariableShowStmt:
    1749          64 :             return true;
    1750             : 
    1751             :         default:
    1752       10975 :             return false;
    1753             :     }
    1754             : }
    1755             : 
    1756             : /*
    1757             :  * UtilityTupleDescriptor
    1758             :  *      Fetch the actual output tuple descriptor for a utility statement
    1759             :  *      for which UtilityReturnsTuples() previously returned "true".
    1760             :  *
    1761             :  * The returned descriptor is created in (or copied into) the current memory
    1762             :  * context.
    1763             :  */
    1764             : TupleDesc
    1765        2008 : UtilityTupleDescriptor(Node *parsetree)
    1766             : {
    1767        2008 :     switch (nodeTag(parsetree))
    1768             :     {
    1769             :         case T_FetchStmt:
    1770             :             {
    1771         193 :                 FetchStmt  *stmt = (FetchStmt *) parsetree;
    1772             :                 Portal      portal;
    1773             : 
    1774         193 :                 if (stmt->ismove)
    1775           0 :                     return NULL;
    1776         193 :                 portal = GetPortalByName(stmt->portalname);
    1777         193 :                 if (!PortalIsValid(portal))
    1778           0 :                     return NULL;    /* not our business to raise error */
    1779         193 :                 return CreateTupleDescCopy(portal->tupDesc);
    1780             :             }
    1781             : 
    1782             :         case T_ExecuteStmt:
    1783             :             {
    1784         128 :                 ExecuteStmt *stmt = (ExecuteStmt *) parsetree;
    1785             :                 PreparedStatement *entry;
    1786             : 
    1787         128 :                 entry = FetchPreparedStatement(stmt->name, false);
    1788         128 :                 if (!entry)
    1789           0 :                     return NULL;    /* not our business to raise error */
    1790         128 :                 return FetchPreparedStatementResultDesc(entry);
    1791             :             }
    1792             : 
    1793             :         case T_ExplainStmt:
    1794        1623 :             return ExplainResultDesc((ExplainStmt *) parsetree);
    1795             : 
    1796             :         case T_VariableShowStmt:
    1797             :             {
    1798          64 :                 VariableShowStmt *n = (VariableShowStmt *) parsetree;
    1799             : 
    1800          64 :                 return GetPGVariableResultDesc(n->name);
    1801             :             }
    1802             : 
    1803             :         default:
    1804           0 :             return NULL;
    1805             :     }
    1806             : }
    1807             : 
    1808             : 
    1809             : /*
    1810             :  * QueryReturnsTuples
    1811             :  *      Return "true" if this Query will send output to the destination.
    1812             :  */
    1813             : #ifdef NOT_USED
    1814             : bool
    1815             : QueryReturnsTuples(Query *parsetree)
    1816             : {
    1817             :     switch (parsetree->commandType)
    1818             :     {
    1819             :         case CMD_SELECT:
    1820             :             /* returns tuples */
    1821             :             return true;
    1822             :         case CMD_INSERT:
    1823             :         case CMD_UPDATE:
    1824             :         case CMD_DELETE:
    1825             :             /* the forms with RETURNING return tuples */
    1826             :             if (parsetree->returningList)
    1827             :                 return true;
    1828             :             break;
    1829             :         case CMD_UTILITY:
    1830             :             return UtilityReturnsTuples(parsetree->utilityStmt);
    1831             :         case CMD_UNKNOWN:
    1832             :         case CMD_NOTHING:
    1833             :             /* probably shouldn't get here */
    1834             :             break;
    1835             :     }
    1836             :     return false;               /* default */
    1837             : }
    1838             : #endif
    1839             : 
    1840             : 
    1841             : /*
    1842             :  * UtilityContainsQuery
    1843             :  *      Return the contained Query, or NULL if there is none
    1844             :  *
    1845             :  * Certain utility statements, such as EXPLAIN, contain a plannable Query.
    1846             :  * This function encapsulates knowledge of exactly which ones do.
    1847             :  * We assume it is invoked only on already-parse-analyzed statements
    1848             :  * (else the contained parsetree isn't a Query yet).
    1849             :  *
    1850             :  * In some cases (currently, only EXPLAIN of CREATE TABLE AS/SELECT INTO and
    1851             :  * CREATE MATERIALIZED VIEW), potentially Query-containing utility statements
    1852             :  * can be nested.  This function will drill down to a non-utility Query, or
    1853             :  * return NULL if none.
    1854             :  */
    1855             : Query *
    1856        3267 : UtilityContainsQuery(Node *parsetree)
    1857             : {
    1858             :     Query      *qry;
    1859             : 
    1860        3267 :     switch (nodeTag(parsetree))
    1861             :     {
    1862             :         case T_DeclareCursorStmt:
    1863           0 :             qry = castNode(Query, ((DeclareCursorStmt *) parsetree)->query);
    1864           0 :             if (qry->commandType == CMD_UTILITY)
    1865           0 :                 return UtilityContainsQuery(qry->utilityStmt);
    1866           0 :             return qry;
    1867             : 
    1868             :         case T_ExplainStmt:
    1869        1000 :             qry = castNode(Query, ((ExplainStmt *) parsetree)->query);
    1870        1000 :             if (qry->commandType == CMD_UTILITY)
    1871           0 :                 return UtilityContainsQuery(qry->utilityStmt);
    1872        1000 :             return qry;
    1873             : 
    1874             :         case T_CreateTableAsStmt:
    1875           8 :             qry = castNode(Query, ((CreateTableAsStmt *) parsetree)->query);
    1876           8 :             if (qry->commandType == CMD_UTILITY)
    1877           0 :                 return UtilityContainsQuery(qry->utilityStmt);
    1878           8 :             return qry;
    1879             : 
    1880             :         default:
    1881        2259 :             return NULL;
    1882             :     }
    1883             : }
    1884             : 
    1885             : 
    1886             : /*
    1887             :  * AlterObjectTypeCommandTag
    1888             :  *      helper function for CreateCommandTag
    1889             :  *
    1890             :  * This covers most cases where ALTER is used with an ObjectType enum.
    1891             :  */
    1892             : static const char *
    1893        3377 : AlterObjectTypeCommandTag(ObjectType objtype)
    1894             : {
    1895             :     const char *tag;
    1896             : 
    1897        3377 :     switch (objtype)
    1898             :     {
    1899             :         case OBJECT_AGGREGATE:
    1900          59 :             tag = "ALTER AGGREGATE";
    1901          59 :             break;
    1902             :         case OBJECT_ATTRIBUTE:
    1903          10 :             tag = "ALTER TYPE";
    1904          10 :             break;
    1905             :         case OBJECT_CAST:
    1906           0 :             tag = "ALTER CAST";
    1907           0 :             break;
    1908             :         case OBJECT_COLLATION:
    1909           0 :             tag = "ALTER COLLATION";
    1910           0 :             break;
    1911             :         case OBJECT_COLUMN:
    1912         106 :             tag = "ALTER TABLE";
    1913         106 :             break;
    1914             :         case OBJECT_CONVERSION:
    1915          29 :             tag = "ALTER CONVERSION";
    1916          29 :             break;
    1917             :         case OBJECT_DATABASE:
    1918           0 :             tag = "ALTER DATABASE";
    1919           0 :             break;
    1920             :         case OBJECT_DOMAIN:
    1921             :         case OBJECT_DOMCONSTRAINT:
    1922           9 :             tag = "ALTER DOMAIN";
    1923           9 :             break;
    1924             :         case OBJECT_EXTENSION:
    1925           0 :             tag = "ALTER EXTENSION";
    1926           0 :             break;
    1927             :         case OBJECT_FDW:
    1928          18 :             tag = "ALTER FOREIGN DATA WRAPPER";
    1929          18 :             break;
    1930             :         case OBJECT_FOREIGN_SERVER:
    1931          40 :             tag = "ALTER SERVER";
    1932          40 :             break;
    1933             :         case OBJECT_FOREIGN_TABLE:
    1934         186 :             tag = "ALTER FOREIGN TABLE";
    1935         186 :             break;
    1936             :         case OBJECT_FUNCTION:
    1937          41 :             tag = "ALTER FUNCTION";
    1938          41 :             break;
    1939             :         case OBJECT_INDEX:
    1940          24 :             tag = "ALTER INDEX";
    1941          24 :             break;
    1942             :         case OBJECT_LANGUAGE:
    1943          20 :             tag = "ALTER LANGUAGE";
    1944          20 :             break;
    1945             :         case OBJECT_LARGEOBJECT:
    1946           3 :             tag = "ALTER LARGE OBJECT";
    1947           3 :             break;
    1948             :         case OBJECT_OPCLASS:
    1949          41 :             tag = "ALTER OPERATOR CLASS";
    1950          41 :             break;
    1951             :         case OBJECT_OPERATOR:
    1952          17 :             tag = "ALTER OPERATOR";
    1953          17 :             break;
    1954             :         case OBJECT_OPFAMILY:
    1955          41 :             tag = "ALTER OPERATOR FAMILY";
    1956          41 :             break;
    1957             :         case OBJECT_POLICY:
    1958          10 :             tag = "ALTER POLICY";
    1959          10 :             break;
    1960             :         case OBJECT_ROLE:
    1961           3 :             tag = "ALTER ROLE";
    1962           3 :             break;
    1963             :         case OBJECT_RULE:
    1964          12 :             tag = "ALTER RULE";
    1965          12 :             break;
    1966             :         case OBJECT_SCHEMA:
    1967           6 :             tag = "ALTER SCHEMA";
    1968           6 :             break;
    1969             :         case OBJECT_SEQUENCE:
    1970           0 :             tag = "ALTER SEQUENCE";
    1971           0 :             break;
    1972             :         case OBJECT_TABLE:
    1973             :         case OBJECT_TABCONSTRAINT:
    1974        2444 :             tag = "ALTER TABLE";
    1975        2444 :             break;
    1976             :         case OBJECT_TABLESPACE:
    1977           2 :             tag = "ALTER TABLESPACE";
    1978           2 :             break;
    1979             :         case OBJECT_TRIGGER:
    1980           0 :             tag = "ALTER TRIGGER";
    1981           0 :             break;
    1982             :         case OBJECT_EVENT_TRIGGER:
    1983           4 :             tag = "ALTER EVENT TRIGGER";
    1984           4 :             break;
    1985             :         case OBJECT_TSCONFIGURATION:
    1986          29 :             tag = "ALTER TEXT SEARCH CONFIGURATION";
    1987          29 :             break;
    1988             :         case OBJECT_TSDICTIONARY:
    1989          29 :             tag = "ALTER TEXT SEARCH DICTIONARY";
    1990          29 :             break;
    1991             :         case OBJECT_TSPARSER:
    1992          13 :             tag = "ALTER TEXT SEARCH PARSER";
    1993          13 :             break;
    1994             :         case OBJECT_TSTEMPLATE:
    1995          13 :             tag = "ALTER TEXT SEARCH TEMPLATE";
    1996          13 :             break;
    1997             :         case OBJECT_TYPE:
    1998          78 :             tag = "ALTER TYPE";
    1999          78 :             break;
    2000             :         case OBJECT_VIEW:
    2001          37 :             tag = "ALTER VIEW";
    2002          37 :             break;
    2003             :         case OBJECT_MATVIEW:
    2004           3 :             tag = "ALTER MATERIALIZED VIEW";
    2005           3 :             break;
    2006             :         case OBJECT_PUBLICATION:
    2007          11 :             tag = "ALTER PUBLICATION";
    2008          11 :             break;
    2009             :         case OBJECT_SUBSCRIPTION:
    2010          13 :             tag = "ALTER SUBSCRIPTION";
    2011          13 :             break;
    2012             :         case OBJECT_STATISTIC_EXT:
    2013          26 :             tag = "ALTER STATISTICS";
    2014          26 :             break;
    2015             :         default:
    2016           0 :             tag = "???";
    2017           0 :             break;
    2018             :     }
    2019             : 
    2020        3377 :     return tag;
    2021             : }
    2022             : 
    2023             : /*
    2024             :  * CreateCommandTag
    2025             :  *      utility to get a string representation of the command operation,
    2026             :  *      given either a raw (un-analyzed) parsetree, an analyzed Query,
    2027             :  *      or a PlannedStmt.
    2028             :  *
    2029             :  * This must handle all command types, but since the vast majority
    2030             :  * of 'em are utility commands, it seems sensible to keep it here.
    2031             :  *
    2032             :  * NB: all result strings must be shorter than COMPLETION_TAG_BUFSIZE.
    2033             :  * Also, the result must point at a true constant (permanent storage).
    2034             :  */
    2035             : const char *
    2036       43815 : CreateCommandTag(Node *parsetree)
    2037             : {
    2038             :     const char *tag;
    2039             : 
    2040       43815 :     switch (nodeTag(parsetree))
    2041             :     {
    2042             :             /* recurse if we're given a RawStmt */
    2043             :         case T_RawStmt:
    2044           0 :             tag = CreateCommandTag(((RawStmt *) parsetree)->stmt);
    2045           0 :             break;
    2046             : 
    2047             :             /* raw plannable queries */
    2048             :         case T_InsertStmt:
    2049        3522 :             tag = "INSERT";
    2050        3522 :             break;
    2051             : 
    2052             :         case T_DeleteStmt:
    2053         288 :             tag = "DELETE";
    2054         288 :             break;
    2055             : 
    2056             :         case T_UpdateStmt:
    2057         480 :             tag = "UPDATE";
    2058         480 :             break;
    2059             : 
    2060             :         case T_SelectStmt:
    2061       13556 :             tag = "SELECT";
    2062       13556 :             break;
    2063             : 
    2064             :             /* utility statements --- same whether raw or cooked */
    2065             :         case T_TransactionStmt:
    2066             :             {
    2067         766 :                 TransactionStmt *stmt = (TransactionStmt *) parsetree;
    2068             : 
    2069         766 :                 switch (stmt->kind)
    2070             :                 {
    2071             :                     case TRANS_STMT_BEGIN:
    2072         305 :                         tag = "BEGIN";
    2073         305 :                         break;
    2074             : 
    2075             :                     case TRANS_STMT_START:
    2076           3 :                         tag = "START TRANSACTION";
    2077           3 :                         break;
    2078             : 
    2079             :                     case TRANS_STMT_COMMIT:
    2080         162 :                         tag = "COMMIT";
    2081         162 :                         break;
    2082             : 
    2083             :                     case TRANS_STMT_ROLLBACK:
    2084             :                     case TRANS_STMT_ROLLBACK_TO:
    2085         192 :                         tag = "ROLLBACK";
    2086         192 :                         break;
    2087             : 
    2088             :                     case TRANS_STMT_SAVEPOINT:
    2089          73 :                         tag = "SAVEPOINT";
    2090          73 :                         break;
    2091             : 
    2092             :                     case TRANS_STMT_RELEASE:
    2093          17 :                         tag = "RELEASE";
    2094          17 :                         break;
    2095             : 
    2096             :                     case TRANS_STMT_PREPARE:
    2097           8 :                         tag = "PREPARE TRANSACTION";
    2098           8 :                         break;
    2099             : 
    2100             :                     case TRANS_STMT_COMMIT_PREPARED:
    2101           3 :                         tag = "COMMIT PREPARED";
    2102           3 :                         break;
    2103             : 
    2104             :                     case TRANS_STMT_ROLLBACK_PREPARED:
    2105           3 :                         tag = "ROLLBACK PREPARED";
    2106           3 :                         break;
    2107             : 
    2108             :                     default:
    2109           0 :                         tag = "???";
    2110           0 :                         break;
    2111             :                 }
    2112             :             }
    2113         766 :             break;
    2114             : 
    2115             :         case T_DeclareCursorStmt:
    2116          96 :             tag = "DECLARE CURSOR";
    2117          96 :             break;
    2118             : 
    2119             :         case T_ClosePortalStmt:
    2120             :             {
    2121          42 :                 ClosePortalStmt *stmt = (ClosePortalStmt *) parsetree;
    2122             : 
    2123          42 :                 if (stmt->portalname == NULL)
    2124           2 :                     tag = "CLOSE CURSOR ALL";
    2125             :                 else
    2126          40 :                     tag = "CLOSE CURSOR";
    2127             :             }
    2128          42 :             break;
    2129             : 
    2130             :         case T_FetchStmt:
    2131             :             {
    2132         203 :                 FetchStmt  *stmt = (FetchStmt *) parsetree;
    2133             : 
    2134         203 :                 tag = (stmt->ismove) ? "MOVE" : "FETCH";
    2135             :             }
    2136         203 :             break;
    2137             : 
    2138             :         case T_CreateDomainStmt:
    2139         219 :             tag = "CREATE DOMAIN";
    2140         219 :             break;
    2141             : 
    2142             :         case T_CreateSchemaStmt:
    2143         176 :             tag = "CREATE SCHEMA";
    2144         176 :             break;
    2145             : 
    2146             :         case T_CreateStmt:
    2147        4299 :             tag = "CREATE TABLE";
    2148        4299 :             break;
    2149             : 
    2150             :         case T_CreateTableSpaceStmt:
    2151           4 :             tag = "CREATE TABLESPACE";
    2152           4 :             break;
    2153             : 
    2154             :         case T_DropTableSpaceStmt:
    2155           3 :             tag = "DROP TABLESPACE";
    2156           3 :             break;
    2157             : 
    2158             :         case T_AlterTableSpaceOptionsStmt:
    2159           4 :             tag = "ALTER TABLESPACE";
    2160           4 :             break;
    2161             : 
    2162             :         case T_CreateExtensionStmt:
    2163           1 :             tag = "CREATE EXTENSION";
    2164           1 :             break;
    2165             : 
    2166             :         case T_AlterExtensionStmt:
    2167           0 :             tag = "ALTER EXTENSION";
    2168           0 :             break;
    2169             : 
    2170             :         case T_AlterExtensionContentsStmt:
    2171           0 :             tag = "ALTER EXTENSION";
    2172           0 :             break;
    2173             : 
    2174             :         case T_CreateFdwStmt:
    2175          56 :             tag = "CREATE FOREIGN DATA WRAPPER";
    2176          56 :             break;
    2177             : 
    2178             :         case T_AlterFdwStmt:
    2179          37 :             tag = "ALTER FOREIGN DATA WRAPPER";
    2180          37 :             break;
    2181             : 
    2182             :         case T_CreateForeignServerStmt:
    2183         109 :             tag = "CREATE SERVER";
    2184         109 :             break;
    2185             : 
    2186             :         case T_AlterForeignServerStmt:
    2187          33 :             tag = "ALTER SERVER";
    2188          33 :             break;
    2189             : 
    2190             :         case T_CreateUserMappingStmt:
    2191         124 :             tag = "CREATE USER MAPPING";
    2192         124 :             break;
    2193             : 
    2194             :         case T_AlterUserMappingStmt:
    2195          52 :             tag = "ALTER USER MAPPING";
    2196          52 :             break;
    2197             : 
    2198             :         case T_DropUserMappingStmt:
    2199          83 :             tag = "DROP USER MAPPING";
    2200          83 :             break;
    2201             : 
    2202             :         case T_CreateForeignTableStmt:
    2203          38 :             tag = "CREATE FOREIGN TABLE";
    2204          38 :             break;
    2205             : 
    2206             :         case T_ImportForeignSchemaStmt:
    2207           8 :             tag = "IMPORT FOREIGN SCHEMA";
    2208           8 :             break;
    2209             : 
    2210             :         case T_DropStmt:
    2211        4133 :             switch (((DropStmt *) parsetree)->removeType)
    2212             :             {
    2213             :                 case OBJECT_TABLE:
    2214        1897 :                     tag = "DROP TABLE";
    2215        1897 :                     break;
    2216             :                 case OBJECT_SEQUENCE:
    2217          64 :                     tag = "DROP SEQUENCE";
    2218          64 :                     break;
    2219             :                 case OBJECT_VIEW:
    2220         245 :                     tag = "DROP VIEW";
    2221         245 :                     break;
    2222             :                 case OBJECT_MATVIEW:
    2223          15 :                     tag = "DROP MATERIALIZED VIEW";
    2224          15 :                     break;
    2225             :                 case OBJECT_INDEX:
    2226         186 :                     tag = "DROP INDEX";
    2227         186 :                     break;
    2228             :                 case OBJECT_TYPE:
    2229         125 :                     tag = "DROP TYPE";
    2230         125 :                     break;
    2231             :                 case OBJECT_DOMAIN:
    2232         145 :                     tag = "DROP DOMAIN";
    2233         145 :                     break;
    2234             :                 case OBJECT_COLLATION:
    2235          11 :                     tag = "DROP COLLATION";
    2236          11 :                     break;
    2237             :                 case OBJECT_CONVERSION:
    2238          17 :                     tag = "DROP CONVERSION";
    2239          17 :                     break;
    2240             :                 case OBJECT_SCHEMA:
    2241         121 :                     tag = "DROP SCHEMA";
    2242         121 :                     break;
    2243             :                 case OBJECT_TSPARSER:
    2244           8 :                     tag = "DROP TEXT SEARCH PARSER";
    2245           8 :                     break;
    2246             :                 case OBJECT_TSDICTIONARY:
    2247          11 :                     tag = "DROP TEXT SEARCH DICTIONARY";
    2248          11 :                     break;
    2249             :                 case OBJECT_TSTEMPLATE:
    2250           8 :                     tag = "DROP TEXT SEARCH TEMPLATE";
    2251           8 :                     break;
    2252             :                 case OBJECT_TSCONFIGURATION:
    2253          11 :                     tag = "DROP TEXT SEARCH CONFIGURATION";
    2254          11 :                     break;
    2255             :                 case OBJECT_FOREIGN_TABLE:
    2256          28 :                     tag = "DROP FOREIGN TABLE";
    2257          28 :                     break;
    2258             :                 case OBJECT_EXTENSION:
    2259           5 :                     tag = "DROP EXTENSION";
    2260           5 :                     break;
    2261             :                 case OBJECT_FUNCTION:
    2262         613 :                     tag = "DROP FUNCTION";
    2263         613 :                     break;
    2264             :                 case OBJECT_AGGREGATE:
    2265          31 :                     tag = "DROP AGGREGATE";
    2266          31 :                     break;
    2267             :                 case OBJECT_OPERATOR:
    2268          44 :                     tag = "DROP OPERATOR";
    2269          44 :                     break;
    2270             :                 case OBJECT_LANGUAGE:
    2271          11 :                     tag = "DROP LANGUAGE";
    2272          11 :                     break;
    2273             :                 case OBJECT_CAST:
    2274          26 :                     tag = "DROP CAST";
    2275          26 :                     break;
    2276             :                 case OBJECT_TRIGGER:
    2277         159 :                     tag = "DROP TRIGGER";
    2278         159 :                     break;
    2279             :                 case OBJECT_EVENT_TRIGGER:
    2280          12 :                     tag = "DROP EVENT TRIGGER";
    2281          12 :                     break;
    2282             :                 case OBJECT_RULE:
    2283          88 :                     tag = "DROP RULE";
    2284          88 :                     break;
    2285             :                 case OBJECT_FDW:
    2286          54 :                     tag = "DROP FOREIGN DATA WRAPPER";
    2287          54 :                     break;
    2288             :                 case OBJECT_FOREIGN_SERVER:
    2289          44 :                     tag = "DROP SERVER";
    2290          44 :                     break;
    2291             :                 case OBJECT_OPCLASS:
    2292          12 :                     tag = "DROP OPERATOR CLASS";
    2293          12 :                     break;
    2294             :                 case OBJECT_OPFAMILY:
    2295          47 :                     tag = "DROP OPERATOR FAMILY";
    2296          47 :                     break;
    2297             :                 case OBJECT_POLICY:
    2298          52 :                     tag = "DROP POLICY";
    2299          52 :                     break;
    2300             :                 case OBJECT_TRANSFORM:
    2301           0 :                     tag = "DROP TRANSFORM";
    2302           0 :                     break;
    2303             :                 case OBJECT_ACCESS_METHOD:
    2304          10 :                     tag = "DROP ACCESS METHOD";
    2305          10 :                     break;
    2306             :                 case OBJECT_PUBLICATION:
    2307          21 :                     tag = "DROP PUBLICATION";
    2308          21 :                     break;
    2309             :                 case OBJECT_STATISTIC_EXT:
    2310          12 :                     tag = "DROP STATISTICS";
    2311          12 :                     break;
    2312             :                 default:
    2313           0 :                     tag = "???";
    2314             :             }
    2315        4133 :             break;
    2316             : 
    2317             :         case T_TruncateStmt:
    2318          69 :             tag = "TRUNCATE TABLE";
    2319          69 :             break;
    2320             : 
    2321             :         case T_CommentStmt:
    2322         531 :             tag = "COMMENT";
    2323         531 :             break;
    2324             : 
    2325             :         case T_SecLabelStmt:
    2326          12 :             tag = "SECURITY LABEL";
    2327          12 :             break;
    2328             : 
    2329             :         case T_CopyStmt:
    2330         226 :             tag = "COPY";
    2331         226 :             break;
    2332             : 
    2333             :         case T_RenameStmt:
    2334         407 :             tag = AlterObjectTypeCommandTag(((RenameStmt *) parsetree)->renameType);
    2335         407 :             break;
    2336             : 
    2337             :         case T_AlterObjectDependsStmt:
    2338           0 :             tag = AlterObjectTypeCommandTag(((AlterObjectDependsStmt *) parsetree)->objectType);
    2339           0 :             break;
    2340             : 
    2341             :         case T_AlterObjectSchemaStmt:
    2342         153 :             tag = AlterObjectTypeCommandTag(((AlterObjectSchemaStmt *) parsetree)->objectType);
    2343         153 :             break;
    2344             : 
    2345             :         case T_AlterOwnerStmt:
    2346         200 :             tag = AlterObjectTypeCommandTag(((AlterOwnerStmt *) parsetree)->objectType);
    2347         200 :             break;
    2348             : 
    2349             :         case T_AlterTableMoveAllStmt:
    2350           9 :             tag = AlterObjectTypeCommandTag(((AlterTableMoveAllStmt *) parsetree)->objtype);
    2351           9 :             break;
    2352             : 
    2353             :         case T_AlterTableStmt:
    2354        2608 :             tag = AlterObjectTypeCommandTag(((AlterTableStmt *) parsetree)->relkind);
    2355        2608 :             break;
    2356             : 
    2357             :         case T_AlterDomainStmt:
    2358          84 :             tag = "ALTER DOMAIN";
    2359          84 :             break;
    2360             : 
    2361             :         case T_AlterFunctionStmt:
    2362          56 :             tag = "ALTER FUNCTION";
    2363          56 :             break;
    2364             : 
    2365             :         case T_GrantStmt:
    2366             :             {
    2367         861 :                 GrantStmt  *stmt = (GrantStmt *) parsetree;
    2368             : 
    2369         861 :                 tag = (stmt->is_grant) ? "GRANT" : "REVOKE";
    2370             :             }
    2371         861 :             break;
    2372             : 
    2373             :         case T_GrantRoleStmt:
    2374             :             {
    2375          18 :                 GrantRoleStmt *stmt = (GrantRoleStmt *) parsetree;
    2376             : 
    2377          18 :                 tag = (stmt->is_grant) ? "GRANT ROLE" : "REVOKE ROLE";
    2378             :             }
    2379          18 :             break;
    2380             : 
    2381             :         case T_AlterDefaultPrivilegesStmt:
    2382          55 :             tag = "ALTER DEFAULT PRIVILEGES";
    2383          55 :             break;
    2384             : 
    2385             :         case T_DefineStmt:
    2386         604 :             switch (((DefineStmt *) parsetree)->kind)
    2387             :             {
    2388             :                 case OBJECT_AGGREGATE:
    2389         308 :                     tag = "CREATE AGGREGATE";
    2390         308 :                     break;
    2391             :                 case OBJECT_OPERATOR:
    2392         104 :                     tag = "CREATE OPERATOR";
    2393         104 :                     break;
    2394             :                 case OBJECT_TYPE:
    2395          51 :                     tag = "CREATE TYPE";
    2396          51 :                     break;
    2397             :                 case OBJECT_TSPARSER:
    2398          15 :                     tag = "CREATE TEXT SEARCH PARSER";
    2399          15 :                     break;
    2400             :                 case OBJECT_TSDICTIONARY:
    2401          54 :                     tag = "CREATE TEXT SEARCH DICTIONARY";
    2402          54 :                     break;
    2403             :                 case OBJECT_TSTEMPLATE:
    2404          16 :                     tag = "CREATE TEXT SEARCH TEMPLATE";
    2405          16 :                     break;
    2406             :                 case OBJECT_TSCONFIGURATION:
    2407          48 :                     tag = "CREATE TEXT SEARCH CONFIGURATION";
    2408          48 :                     break;
    2409             :                 case OBJECT_COLLATION:
    2410           8 :                     tag = "CREATE COLLATION";
    2411           8 :                     break;
    2412             :                 case OBJECT_ACCESS_METHOD:
    2413           0 :                     tag = "CREATE ACCESS METHOD";
    2414           0 :                     break;
    2415             :                 default:
    2416           0 :                     tag = "???";
    2417             :             }
    2418         604 :             break;
    2419             : 
    2420             :         case T_CompositeTypeStmt:
    2421         151 :             tag = "CREATE TYPE";
    2422         151 :             break;
    2423             : 
    2424             :         case T_CreateEnumStmt:
    2425          45 :             tag = "CREATE TYPE";
    2426          45 :             break;
    2427             : 
    2428             :         case T_CreateRangeStmt:
    2429          29 :             tag = "CREATE TYPE";
    2430          29 :             break;
    2431             : 
    2432             :         case T_AlterEnumStmt:
    2433         136 :             tag = "ALTER TYPE";
    2434         136 :             break;
    2435             : 
    2436             :         case T_ViewStmt:
    2437         999 :             tag = "CREATE VIEW";
    2438         999 :             break;
    2439             : 
    2440             :         case T_CreateFunctionStmt:
    2441        1921 :             tag = "CREATE FUNCTION";
    2442        1921 :             break;
    2443             : 
    2444             :         case T_IndexStmt:
    2445         765 :             tag = "CREATE INDEX";
    2446         765 :             break;
    2447             : 
    2448             :         case T_RuleStmt:
    2449         292 :             tag = "CREATE RULE";
    2450         292 :             break;
    2451             : 
    2452             :         case T_CreateSeqStmt:
    2453         189 :             tag = "CREATE SEQUENCE";
    2454         189 :             break;
    2455             : 
    2456             :         case T_AlterSeqStmt:
    2457          68 :             tag = "ALTER SEQUENCE";
    2458          68 :             break;
    2459             : 
    2460             :         case T_DoStmt:
    2461          40 :             tag = "DO";
    2462          40 :             break;
    2463             : 
    2464             :         case T_CreatedbStmt:
    2465           3 :             tag = "CREATE DATABASE";
    2466           3 :             break;
    2467             : 
    2468             :         case T_AlterDatabaseStmt:
    2469           0 :             tag = "ALTER DATABASE";
    2470           0 :             break;
    2471             : 
    2472             :         case T_AlterDatabaseSetStmt:
    2473           6 :             tag = "ALTER DATABASE";
    2474           6 :             break;
    2475             : 
    2476             :         case T_DropdbStmt:
    2477           0 :             tag = "DROP DATABASE";
    2478           0 :             break;
    2479             : 
    2480             :         case T_NotifyStmt:
    2481           1 :             tag = "NOTIFY";
    2482           1 :             break;
    2483             : 
    2484             :         case T_ListenStmt:
    2485           2 :             tag = "LISTEN";
    2486           2 :             break;
    2487             : 
    2488             :         case T_UnlistenStmt:
    2489           2 :             tag = "UNLISTEN";
    2490           2 :             break;
    2491             : 
    2492             :         case T_LoadStmt:
    2493           1 :             tag = "LOAD";
    2494           1 :             break;
    2495             : 
    2496             :         case T_ClusterStmt:
    2497          11 :             tag = "CLUSTER";
    2498          11 :             break;
    2499             : 
    2500             :         case T_VacuumStmt:
    2501         124 :             if (((VacuumStmt *) parsetree)->options & VACOPT_VACUUM)
    2502          48 :                 tag = "VACUUM";
    2503             :             else
    2504          76 :                 tag = "ANALYZE";
    2505         124 :             break;
    2506             : 
    2507             :         case T_ExplainStmt:
    2508        1124 :             tag = "EXPLAIN";
    2509        1124 :             break;
    2510             : 
    2511             :         case T_CreateTableAsStmt:
    2512         324 :             switch (((CreateTableAsStmt *) parsetree)->relkind)
    2513             :             {
    2514             :                 case OBJECT_TABLE:
    2515         235 :                     if (((CreateTableAsStmt *) parsetree)->is_select_into)
    2516          32 :                         tag = "SELECT INTO";
    2517             :                     else
    2518         203 :                         tag = "CREATE TABLE AS";
    2519         235 :                     break;
    2520             :                 case OBJECT_MATVIEW:
    2521          89 :                     tag = "CREATE MATERIALIZED VIEW";
    2522          89 :                     break;
    2523             :                 default:
    2524           0 :                     tag = "???";
    2525             :             }
    2526         324 :             break;
    2527             : 
    2528             :         case T_RefreshMatViewStmt:
    2529          58 :             tag = "REFRESH MATERIALIZED VIEW";
    2530          58 :             break;
    2531             : 
    2532             :         case T_AlterSystemStmt:
    2533           0 :             tag = "ALTER SYSTEM";
    2534           0 :             break;
    2535             : 
    2536             :         case T_VariableSetStmt:
    2537         976 :             switch (((VariableSetStmt *) parsetree)->kind)
    2538             :             {
    2539             :                 case VAR_SET_VALUE:
    2540             :                 case VAR_SET_CURRENT:
    2541             :                 case VAR_SET_DEFAULT:
    2542             :                 case VAR_SET_MULTI:
    2543         754 :                     tag = "SET";
    2544         754 :                     break;
    2545             :                 case VAR_RESET:
    2546             :                 case VAR_RESET_ALL:
    2547         222 :                     tag = "RESET";
    2548         222 :                     break;
    2549             :                 default:
    2550           0 :                     tag = "???";
    2551             :             }
    2552         976 :             break;
    2553             : 
    2554             :         case T_VariableShowStmt:
    2555          64 :             tag = "SHOW";
    2556          64 :             break;
    2557             : 
    2558             :         case T_DiscardStmt:
    2559           4 :             switch (((DiscardStmt *) parsetree)->target)
    2560             :             {
    2561             :                 case DISCARD_ALL:
    2562           1 :                     tag = "DISCARD ALL";
    2563           1 :                     break;
    2564             :                 case DISCARD_PLANS:
    2565           0 :                     tag = "DISCARD PLANS";
    2566           0 :                     break;
    2567             :                 case DISCARD_TEMP:
    2568           1 :                     tag = "DISCARD TEMP";
    2569           1 :                     break;
    2570             :                 case DISCARD_SEQUENCES:
    2571           2 :                     tag = "DISCARD SEQUENCES";
    2572           2 :                     break;
    2573             :                 default:
    2574           0 :                     tag = "???";
    2575             :             }
    2576           4 :             break;
    2577             : 
    2578             :         case T_CreateTransformStmt:
    2579           3 :             tag = "CREATE TRANSFORM";
    2580           3 :             break;
    2581             : 
    2582             :         case T_CreateTrigStmt:
    2583         597 :             tag = "CREATE TRIGGER";
    2584         597 :             break;
    2585             : 
    2586             :         case T_CreateEventTrigStmt:
    2587          21 :             tag = "CREATE EVENT TRIGGER";
    2588          21 :             break;
    2589             : 
    2590             :         case T_AlterEventTrigStmt:
    2591           4 :             tag = "ALTER EVENT TRIGGER";
    2592           4 :             break;
    2593             : 
    2594             :         case T_CreatePLangStmt:
    2595           6 :             tag = "CREATE LANGUAGE";
    2596           6 :             break;
    2597             : 
    2598             :         case T_CreateRoleStmt:
    2599         118 :             tag = "CREATE ROLE";
    2600         118 :             break;
    2601             : 
    2602             :         case T_AlterRoleStmt:
    2603          52 :             tag = "ALTER ROLE";
    2604          52 :             break;
    2605             : 
    2606             :         case T_AlterRoleSetStmt:
    2607          28 :             tag = "ALTER ROLE";
    2608          28 :             break;
    2609             : 
    2610             :         case T_DropRoleStmt:
    2611         141 :             tag = "DROP ROLE";
    2612         141 :             break;
    2613             : 
    2614             :         case T_DropOwnedStmt:
    2615          47 :             tag = "DROP OWNED";
    2616          47 :             break;
    2617             : 
    2618             :         case T_ReassignOwnedStmt:
    2619           4 :             tag = "REASSIGN OWNED";
    2620           4 :             break;
    2621             : 
    2622             :         case T_LockStmt:
    2623          40 :             tag = "LOCK TABLE";
    2624          40 :             break;
    2625             : 
    2626             :         case T_ConstraintsSetStmt:
    2627          11 :             tag = "SET CONSTRAINTS";
    2628          11 :             break;
    2629             : 
    2630             :         case T_CheckPointStmt:
    2631           0 :             tag = "CHECKPOINT";
    2632           0 :             break;
    2633             : 
    2634             :         case T_ReindexStmt:
    2635          11 :             tag = "REINDEX";
    2636          11 :             break;
    2637             : 
    2638             :         case T_CreateConversionStmt:
    2639         160 :             tag = "CREATE CONVERSION";
    2640         160 :             break;
    2641             : 
    2642             :         case T_CreateCastStmt:
    2643          32 :             tag = "CREATE CAST";
    2644          32 :             break;
    2645             : 
    2646             :         case T_CreateOpClassStmt:
    2647          18 :             tag = "CREATE OPERATOR CLASS";
    2648          18 :             break;
    2649             : 
    2650             :         case T_CreateOpFamilyStmt:
    2651          60 :             tag = "CREATE OPERATOR FAMILY";
    2652          60 :             break;
    2653             : 
    2654             :         case T_AlterOpFamilyStmt:
    2655          92 :             tag = "ALTER OPERATOR FAMILY";
    2656          92 :             break;
    2657             : 
    2658             :         case T_AlterOperatorStmt:
    2659          32 :             tag = "ALTER OPERATOR";
    2660          32 :             break;
    2661             : 
    2662             :         case T_AlterTSDictionaryStmt:
    2663           0 :             tag = "ALTER TEXT SEARCH DICTIONARY";
    2664           0 :             break;
    2665             : 
    2666             :         case T_AlterTSConfigurationStmt:
    2667          63 :             tag = "ALTER TEXT SEARCH CONFIGURATION";
    2668          63 :             break;
    2669             : 
    2670             :         case T_CreatePolicyStmt:
    2671         243 :             tag = "CREATE POLICY";
    2672         243 :             break;
    2673             : 
    2674             :         case T_AlterPolicyStmt:
    2675          42 :             tag = "ALTER POLICY";
    2676          42 :             break;
    2677             : 
    2678             :         case T_CreateAmStmt:
    2679           3 :             tag = "CREATE ACCESS METHOD";
    2680           3 :             break;
    2681             : 
    2682             :         case T_CreatePublicationStmt:
    2683          34 :             tag = "CREATE PUBLICATION";
    2684          34 :             break;
    2685             : 
    2686             :         case T_AlterPublicationStmt:
    2687          43 :             tag = "ALTER PUBLICATION";
    2688          43 :             break;
    2689             : 
    2690             :         case T_CreateSubscriptionStmt:
    2691          35 :             tag = "CREATE SUBSCRIPTION";
    2692          35 :             break;
    2693             : 
    2694             :         case T_AlterSubscriptionStmt:
    2695          33 :             tag = "ALTER SUBSCRIPTION";
    2696          33 :             break;
    2697             : 
    2698             :         case T_DropSubscriptionStmt:
    2699          16 :             tag = "DROP SUBSCRIPTION";
    2700          16 :             break;
    2701             : 
    2702             :         case T_AlterCollationStmt:
    2703           0 :             tag = "ALTER COLLATION";
    2704           0 :             break;
    2705             : 
    2706             :         case T_PrepareStmt:
    2707          37 :             tag = "PREPARE";
    2708          37 :             break;
    2709             : 
    2710             :         case T_ExecuteStmt:
    2711         135 :             tag = "EXECUTE";
    2712         135 :             break;
    2713             : 
    2714             :         case T_CreateStatsStmt:
    2715          82 :             tag = "CREATE STATISTICS";
    2716          82 :             break;
    2717             : 
    2718             :         case T_DeallocateStmt:
    2719             :             {
    2720           8 :                 DeallocateStmt *stmt = (DeallocateStmt *) parsetree;
    2721             : 
    2722           8 :                 if (stmt->name == NULL)
    2723           1 :                     tag = "DEALLOCATE ALL";
    2724             :                 else
    2725           7 :                     tag = "DEALLOCATE";
    2726             :             }
    2727           8 :             break;
    2728             : 
    2729             :             /* already-planned queries */
    2730             :         case T_PlannedStmt:
    2731             :             {
    2732           4 :                 PlannedStmt *stmt = (PlannedStmt *) parsetree;
    2733             : 
    2734           4 :                 switch (stmt->commandType)
    2735             :                 {
    2736             :                     case CMD_SELECT:
    2737             : 
    2738             :                         /*
    2739             :                          * We take a little extra care here so that the result
    2740             :                          * will be useful for complaints about read-only
    2741             :                          * statements
    2742             :                          */
    2743           0 :                         if (stmt->rowMarks != NIL)
    2744             :                         {
    2745             :                             /* not 100% but probably close enough */
    2746           0 :                             switch (((PlanRowMark *) linitial(stmt->rowMarks))->strength)
    2747             :                             {
    2748             :                                 case LCS_FORKEYSHARE:
    2749           0 :                                     tag = "SELECT FOR KEY SHARE";
    2750           0 :                                     break;
    2751             :                                 case LCS_FORSHARE:
    2752           0 :                                     tag = "SELECT FOR SHARE";
    2753           0 :                                     break;
    2754             :                                 case LCS_FORNOKEYUPDATE:
    2755           0 :                                     tag = "SELECT FOR NO KEY UPDATE";
    2756           0 :                                     break;
    2757             :                                 case LCS_FORUPDATE:
    2758           0 :                                     tag = "SELECT FOR UPDATE";
    2759           0 :                                     break;
    2760             :                                 default:
    2761           0 :                                     tag = "SELECT";
    2762           0 :                                     break;
    2763             :                             }
    2764             :                         }
    2765             :                         else
    2766           0 :                             tag = "SELECT";
    2767           0 :                         break;
    2768             :                     case CMD_UPDATE:
    2769           2 :                         tag = "UPDATE";
    2770           2 :                         break;
    2771             :                     case CMD_INSERT:
    2772           1 :                         tag = "INSERT";
    2773           1 :                         break;
    2774             :                     case CMD_DELETE:
    2775           1 :                         tag = "DELETE";
    2776           1 :                         break;
    2777             :                     case CMD_UTILITY:
    2778           0 :                         tag = CreateCommandTag(stmt->utilityStmt);
    2779           0 :                         break;
    2780             :                     default:
    2781           0 :                         elog(WARNING, "unrecognized commandType: %d",
    2782             :                              (int) stmt->commandType);
    2783           0 :                         tag = "???";
    2784           0 :                         break;
    2785             :                 }
    2786             :             }
    2787           4 :             break;
    2788             : 
    2789             :             /* parsed-and-rewritten-but-not-planned queries */
    2790             :         case T_Query:
    2791             :             {
    2792           0 :                 Query      *stmt = (Query *) parsetree;
    2793             : 
    2794           0 :                 switch (stmt->commandType)
    2795             :                 {
    2796             :                     case CMD_SELECT:
    2797             : 
    2798             :                         /*
    2799             :                          * We take a little extra care here so that the result
    2800             :                          * will be useful for complaints about read-only
    2801             :                          * statements
    2802             :                          */
    2803           0 :                         if (stmt->rowMarks != NIL)
    2804             :                         {
    2805             :                             /* not 100% but probably close enough */
    2806           0 :                             switch (((RowMarkClause *) linitial(stmt->rowMarks))->strength)
    2807             :                             {
    2808             :                                 case LCS_FORKEYSHARE:
    2809           0 :                                     tag = "SELECT FOR KEY SHARE";
    2810           0 :                                     break;
    2811             :                                 case LCS_FORSHARE:
    2812           0 :                                     tag = "SELECT FOR SHARE";
    2813           0 :                                     break;
    2814             :                                 case LCS_FORNOKEYUPDATE:
    2815           0 :                                     tag = "SELECT FOR NO KEY UPDATE";
    2816           0 :                                     break;
    2817             :                                 case LCS_FORUPDATE:
    2818           0 :                                     tag = "SELECT FOR UPDATE";
    2819           0 :                                     break;
    2820             :                                 default:
    2821           0 :                                     tag = "???";
    2822           0 :                                     break;
    2823             :                             }
    2824             :                         }
    2825             :                         else
    2826           0 :                             tag = "SELECT";
    2827           0 :                         break;
    2828             :                     case CMD_UPDATE:
    2829           0 :                         tag = "UPDATE";
    2830           0 :                         break;
    2831             :                     case CMD_INSERT:
    2832           0 :                         tag = "INSERT";
    2833           0 :                         break;
    2834             :                     case CMD_DELETE:
    2835           0 :                         tag = "DELETE";
    2836           0 :                         break;
    2837             :                     case CMD_UTILITY:
    2838           0 :                         tag = CreateCommandTag(stmt->utilityStmt);
    2839           0 :                         break;
    2840             :                     default:
    2841           0 :                         elog(WARNING, "unrecognized commandType: %d",
    2842             :                              (int) stmt->commandType);
    2843           0 :                         tag = "???";
    2844           0 :                         break;
    2845             :                 }
    2846             :             }
    2847           0 :             break;
    2848             : 
    2849             :         default:
    2850           0 :             elog(WARNING, "unrecognized node type: %d",
    2851             :                  (int) nodeTag(parsetree));
    2852           0 :             tag = "???";
    2853           0 :             break;
    2854             :     }
    2855             : 
    2856       43815 :     return tag;
    2857             : }
    2858             : 
    2859             : 
    2860             : /*
    2861             :  * GetCommandLogLevel
    2862             :  *      utility to get the minimum log_statement level for a command,
    2863             :  *      given either a raw (un-analyzed) parsetree, an analyzed Query,
    2864             :  *      or a PlannedStmt.
    2865             :  *
    2866             :  * This must handle all command types, but since the vast majority
    2867             :  * of 'em are utility commands, it seems sensible to keep it here.
    2868             :  */
    2869             : LogStmtLevel
    2870           0 : GetCommandLogLevel(Node *parsetree)
    2871             : {
    2872             :     LogStmtLevel lev;
    2873             : 
    2874           0 :     switch (nodeTag(parsetree))
    2875             :     {
    2876             :             /* recurse if we're given a RawStmt */
    2877             :         case T_RawStmt:
    2878           0 :             lev = GetCommandLogLevel(((RawStmt *) parsetree)->stmt);
    2879           0 :             break;
    2880             : 
    2881             :             /* raw plannable queries */
    2882             :         case T_InsertStmt:
    2883             :         case T_DeleteStmt:
    2884             :         case T_UpdateStmt:
    2885           0 :             lev = LOGSTMT_MOD;
    2886           0 :             break;
    2887             : 
    2888             :         case T_SelectStmt:
    2889           0 :             if (((SelectStmt *) parsetree)->intoClause)
    2890           0 :                 lev = LOGSTMT_DDL;  /* SELECT INTO */
    2891             :             else
    2892           0 :                 lev = LOGSTMT_ALL;
    2893           0 :             break;
    2894             : 
    2895             :             /* utility statements --- same whether raw or cooked */
    2896             :         case T_TransactionStmt:
    2897           0 :             lev = LOGSTMT_ALL;
    2898           0 :             break;
    2899             : 
    2900             :         case T_DeclareCursorStmt:
    2901           0 :             lev = LOGSTMT_ALL;
    2902           0 :             break;
    2903             : 
    2904             :         case T_ClosePortalStmt:
    2905           0 :             lev = LOGSTMT_ALL;
    2906           0 :             break;
    2907             : 
    2908             :         case T_FetchStmt:
    2909           0 :             lev = LOGSTMT_ALL;
    2910           0 :             break;
    2911             : 
    2912             :         case T_CreateSchemaStmt:
    2913           0 :             lev = LOGSTMT_DDL;
    2914           0 :             break;
    2915             : 
    2916             :         case T_CreateStmt:
    2917             :         case T_CreateForeignTableStmt:
    2918           0 :             lev = LOGSTMT_DDL;
    2919           0 :             break;
    2920             : 
    2921             :         case T_CreateTableSpaceStmt:
    2922             :         case T_DropTableSpaceStmt:
    2923             :         case T_AlterTableSpaceOptionsStmt:
    2924           0 :             lev = LOGSTMT_DDL;
    2925           0 :             break;
    2926             : 
    2927             :         case T_CreateExtensionStmt:
    2928             :         case T_AlterExtensionStmt:
    2929             :         case T_AlterExtensionContentsStmt:
    2930           0 :             lev = LOGSTMT_DDL;
    2931           0 :             break;
    2932             : 
    2933             :         case T_CreateFdwStmt:
    2934             :         case T_AlterFdwStmt:
    2935             :         case T_CreateForeignServerStmt:
    2936             :         case T_AlterForeignServerStmt:
    2937             :         case T_CreateUserMappingStmt:
    2938             :         case T_AlterUserMappingStmt:
    2939             :         case T_DropUserMappingStmt:
    2940             :         case T_ImportForeignSchemaStmt:
    2941           0 :             lev = LOGSTMT_DDL;
    2942           0 :             break;
    2943             : 
    2944             :         case T_DropStmt:
    2945           0 :             lev = LOGSTMT_DDL;
    2946           0 :             break;
    2947             : 
    2948             :         case T_TruncateStmt:
    2949           0 :             lev = LOGSTMT_MOD;
    2950           0 :             break;
    2951             : 
    2952             :         case T_CommentStmt:
    2953           0 :             lev = LOGSTMT_DDL;
    2954           0 :             break;
    2955             : 
    2956             :         case T_SecLabelStmt:
    2957           0 :             lev = LOGSTMT_DDL;
    2958           0 :             break;
    2959             : 
    2960             :         case T_CopyStmt:
    2961           0 :             if (((CopyStmt *) parsetree)->is_from)
    2962           0 :                 lev = LOGSTMT_MOD;
    2963             :             else
    2964           0 :                 lev = LOGSTMT_ALL;
    2965           0 :             break;
    2966             : 
    2967             :         case T_PrepareStmt:
    2968             :             {
    2969           0 :                 PrepareStmt *stmt = (PrepareStmt *) parsetree;
    2970             : 
    2971             :                 /* Look through a PREPARE to the contained stmt */
    2972           0 :                 lev = GetCommandLogLevel(stmt->query);
    2973             :             }
    2974           0 :             break;
    2975             : 
    2976             :         case T_ExecuteStmt:
    2977             :             {
    2978           0 :                 ExecuteStmt *stmt = (ExecuteStmt *) parsetree;
    2979             :                 PreparedStatement *ps;
    2980             : 
    2981             :                 /* Look through an EXECUTE to the referenced stmt */
    2982           0 :                 ps = FetchPreparedStatement(stmt->name, false);
    2983           0 :                 if (ps && ps->plansource->raw_parse_tree)
    2984           0 :                     lev = GetCommandLogLevel(ps->plansource->raw_parse_tree->stmt);
    2985             :                 else
    2986           0 :                     lev = LOGSTMT_ALL;
    2987             :             }
    2988           0 :             break;
    2989             : 
    2990             :         case T_DeallocateStmt:
    2991           0 :             lev = LOGSTMT_ALL;
    2992           0 :             break;
    2993             : 
    2994             :         case T_RenameStmt:
    2995           0 :             lev = LOGSTMT_DDL;
    2996           0 :             break;
    2997             : 
    2998             :         case T_AlterObjectDependsStmt:
    2999           0 :             lev = LOGSTMT_DDL;
    3000           0 :             break;
    3001             : 
    3002             :         case T_AlterObjectSchemaStmt:
    3003           0 :             lev = LOGSTMT_DDL;
    3004           0 :             break;
    3005             : 
    3006             :         case T_AlterOwnerStmt:
    3007           0 :             lev = LOGSTMT_DDL;
    3008           0 :             break;
    3009             : 
    3010             :         case T_AlterTableMoveAllStmt:
    3011             :         case T_AlterTableStmt:
    3012           0 :             lev = LOGSTMT_DDL;
    3013           0 :             break;
    3014             : 
    3015             :         case T_AlterDomainStmt:
    3016           0 :             lev = LOGSTMT_DDL;
    3017           0 :             break;
    3018             : 
    3019             :         case T_GrantStmt:
    3020           0 :             lev = LOGSTMT_DDL;
    3021           0 :             break;
    3022             : 
    3023             :         case T_GrantRoleStmt:
    3024           0 :             lev = LOGSTMT_DDL;
    3025           0 :             break;
    3026             : 
    3027             :         case T_AlterDefaultPrivilegesStmt:
    3028           0 :             lev = LOGSTMT_DDL;
    3029           0 :             break;
    3030             : 
    3031             :         case T_DefineStmt:
    3032           0 :             lev = LOGSTMT_DDL;
    3033           0 :             break;
    3034             : 
    3035             :         case T_CompositeTypeStmt:
    3036           0 :             lev = LOGSTMT_DDL;
    3037           0 :             break;
    3038             : 
    3039             :         case T_CreateEnumStmt:
    3040           0 :             lev = LOGSTMT_DDL;
    3041           0 :             break;
    3042             : 
    3043             :         case T_CreateRangeStmt:
    3044           0 :             lev = LOGSTMT_DDL;
    3045           0 :             break;
    3046             : 
    3047             :         case T_AlterEnumStmt:
    3048           0 :             lev = LOGSTMT_DDL;
    3049           0 :             break;
    3050             : 
    3051             :         case T_ViewStmt:
    3052           0 :             lev = LOGSTMT_DDL;
    3053           0 :             break;
    3054             : 
    3055             :         case T_CreateFunctionStmt:
    3056           0 :             lev = LOGSTMT_DDL;
    3057           0 :             break;
    3058             : 
    3059             :         case T_AlterFunctionStmt:
    3060           0 :             lev = LOGSTMT_DDL;
    3061           0 :             break;
    3062             : 
    3063             :         case T_IndexStmt:
    3064           0 :             lev = LOGSTMT_DDL;
    3065           0 :             break;
    3066             : 
    3067             :         case T_RuleStmt:
    3068           0 :             lev = LOGSTMT_DDL;
    3069           0 :             break;
    3070             : 
    3071             :         case T_CreateSeqStmt:
    3072           0 :             lev = LOGSTMT_DDL;
    3073           0 :             break;
    3074             : 
    3075             :         case T_AlterSeqStmt:
    3076           0 :             lev = LOGSTMT_DDL;
    3077           0 :             break;
    3078             : 
    3079             :         case T_DoStmt:
    3080           0 :             lev = LOGSTMT_ALL;
    3081           0 :             break;
    3082             : 
    3083             :         case T_CreatedbStmt:
    3084           0 :             lev = LOGSTMT_DDL;
    3085           0 :             break;
    3086             : 
    3087             :         case T_AlterDatabaseStmt:
    3088           0 :             lev = LOGSTMT_DDL;
    3089           0 :             break;
    3090             : 
    3091             :         case T_AlterDatabaseSetStmt:
    3092           0 :             lev = LOGSTMT_DDL;
    3093           0 :             break;
    3094             : 
    3095             :         case T_DropdbStmt:
    3096           0 :             lev = LOGSTMT_DDL;
    3097           0 :             break;
    3098             : 
    3099             :         case T_NotifyStmt:
    3100           0 :             lev = LOGSTMT_ALL;
    3101           0 :             break;
    3102             : 
    3103             :         case T_ListenStmt:
    3104           0 :             lev = LOGSTMT_ALL;
    3105           0 :             break;
    3106             : 
    3107             :         case T_UnlistenStmt:
    3108           0 :             lev = LOGSTMT_ALL;
    3109           0 :             break;
    3110             : 
    3111             :         case T_LoadStmt:
    3112           0 :             lev = LOGSTMT_ALL;
    3113           0 :             break;
    3114             : 
    3115             :         case T_ClusterStmt:
    3116           0 :             lev = LOGSTMT_DDL;
    3117           0 :             break;
    3118             : 
    3119             :         case T_VacuumStmt:
    3120           0 :             lev = LOGSTMT_ALL;
    3121           0 :             break;
    3122             : 
    3123             :         case T_ExplainStmt:
    3124             :             {
    3125           0 :                 ExplainStmt *stmt = (ExplainStmt *) parsetree;
    3126           0 :                 bool        analyze = false;
    3127             :                 ListCell   *lc;
    3128             : 
    3129             :                 /* Look through an EXPLAIN ANALYZE to the contained stmt */
    3130           0 :                 foreach(lc, stmt->options)
    3131             :                 {
    3132           0 :                     DefElem    *opt = (DefElem *) lfirst(lc);
    3133             : 
    3134           0 :                     if (strcmp(opt->defname, "analyze") == 0)
    3135           0 :                         analyze = defGetBoolean(opt);
    3136             :                     /* don't "break", as explain.c will use the last value */
    3137             :                 }
    3138           0 :                 if (analyze)
    3139           0 :                     return GetCommandLogLevel(stmt->query);
    3140             : 
    3141             :                 /* Plain EXPLAIN isn't so interesting */
    3142           0 :                 lev = LOGSTMT_ALL;
    3143             :             }
    3144           0 :             break;
    3145             : 
    3146             :         case T_CreateTableAsStmt:
    3147           0 :             lev = LOGSTMT_DDL;
    3148           0 :             break;
    3149             : 
    3150             :         case T_RefreshMatViewStmt:
    3151           0 :             lev = LOGSTMT_DDL;
    3152           0 :             break;
    3153             : 
    3154             :         case T_AlterSystemStmt:
    3155           0 :             lev = LOGSTMT_DDL;
    3156           0 :             break;
    3157             : 
    3158             :         case T_VariableSetStmt:
    3159           0 :             lev = LOGSTMT_ALL;
    3160           0 :             break;
    3161             : 
    3162             :         case T_VariableShowStmt:
    3163           0 :             lev = LOGSTMT_ALL;
    3164           0 :             break;
    3165             : 
    3166             :         case T_DiscardStmt:
    3167           0 :             lev = LOGSTMT_ALL;
    3168           0 :             break;
    3169             : 
    3170             :         case T_CreateTrigStmt:
    3171           0 :             lev = LOGSTMT_DDL;
    3172           0 :             break;
    3173             : 
    3174             :         case T_CreateEventTrigStmt:
    3175           0 :             lev = LOGSTMT_DDL;
    3176           0 :             break;
    3177             : 
    3178             :         case T_AlterEventTrigStmt:
    3179           0 :             lev = LOGSTMT_DDL;
    3180           0 :             break;
    3181             : 
    3182             :         case T_CreatePLangStmt:
    3183           0 :             lev = LOGSTMT_DDL;
    3184           0 :             break;
    3185             : 
    3186             :         case T_CreateDomainStmt:
    3187           0 :             lev = LOGSTMT_DDL;
    3188           0 :             break;
    3189             : 
    3190             :         case T_CreateRoleStmt:
    3191           0 :             lev = LOGSTMT_DDL;
    3192           0 :             break;
    3193             : 
    3194             :         case T_AlterRoleStmt:
    3195           0 :             lev = LOGSTMT_DDL;
    3196           0 :             break;
    3197             : 
    3198             :         case T_AlterRoleSetStmt:
    3199           0 :             lev = LOGSTMT_DDL;
    3200           0 :             break;
    3201             : 
    3202             :         case T_DropRoleStmt:
    3203           0 :             lev = LOGSTMT_DDL;
    3204           0 :             break;
    3205             : 
    3206             :         case T_DropOwnedStmt:
    3207           0 :             lev = LOGSTMT_DDL;
    3208           0 :             break;
    3209             : 
    3210             :         case T_ReassignOwnedStmt:
    3211           0 :             lev = LOGSTMT_DDL;
    3212           0 :             break;
    3213             : 
    3214             :         case T_LockStmt:
    3215           0 :             lev = LOGSTMT_ALL;
    3216           0 :             break;
    3217             : 
    3218             :         case T_ConstraintsSetStmt:
    3219           0 :             lev = LOGSTMT_ALL;
    3220           0 :             break;
    3221             : 
    3222             :         case T_CheckPointStmt:
    3223           0 :             lev = LOGSTMT_ALL;
    3224           0 :             break;
    3225             : 
    3226             :         case T_ReindexStmt:
    3227           0 :             lev = LOGSTMT_ALL;  /* should this be DDL? */
    3228           0 :             break;
    3229             : 
    3230             :         case T_CreateConversionStmt:
    3231           0 :             lev = LOGSTMT_DDL;
    3232           0 :             break;
    3233             : 
    3234             :         case T_CreateCastStmt:
    3235           0 :             lev = LOGSTMT_DDL;
    3236           0 :             break;
    3237             : 
    3238             :         case T_CreateOpClassStmt:
    3239           0 :             lev = LOGSTMT_DDL;
    3240           0 :             break;
    3241             : 
    3242             :         case T_CreateOpFamilyStmt:
    3243           0 :             lev = LOGSTMT_DDL;
    3244           0 :             break;
    3245             : 
    3246             :         case T_CreateTransformStmt:
    3247           0 :             lev = LOGSTMT_DDL;
    3248           0 :             break;
    3249             : 
    3250             :         case T_AlterOpFamilyStmt:
    3251           0 :             lev = LOGSTMT_DDL;
    3252           0 :             break;
    3253             : 
    3254             :         case T_CreatePolicyStmt:
    3255           0 :             lev = LOGSTMT_DDL;
    3256           0 :             break;
    3257             : 
    3258             :         case T_AlterPolicyStmt:
    3259           0 :             lev = LOGSTMT_DDL;
    3260           0 :             break;
    3261             : 
    3262             :         case T_AlterTSDictionaryStmt:
    3263           0 :             lev = LOGSTMT_DDL;
    3264           0 :             break;
    3265             : 
    3266             :         case T_AlterTSConfigurationStmt:
    3267           0 :             lev = LOGSTMT_DDL;
    3268           0 :             break;
    3269             : 
    3270             :         case T_CreateAmStmt:
    3271           0 :             lev = LOGSTMT_DDL;
    3272           0 :             break;
    3273             : 
    3274             :         case T_CreatePublicationStmt:
    3275           0 :             lev = LOGSTMT_DDL;
    3276           0 :             break;
    3277             : 
    3278             :         case T_AlterPublicationStmt:
    3279           0 :             lev = LOGSTMT_DDL;
    3280           0 :             break;
    3281             : 
    3282             :         case T_CreateSubscriptionStmt:
    3283           0 :             lev = LOGSTMT_DDL;
    3284           0 :             break;
    3285             : 
    3286             :         case T_AlterSubscriptionStmt:
    3287           0 :             lev = LOGSTMT_DDL;
    3288           0 :             break;
    3289             : 
    3290             :         case T_DropSubscriptionStmt:
    3291           0 :             lev = LOGSTMT_DDL;
    3292           0 :             break;
    3293             : 
    3294             :             /* already-planned queries */
    3295             :         case T_PlannedStmt:
    3296             :             {
    3297           0 :                 PlannedStmt *stmt = (PlannedStmt *) parsetree;
    3298             : 
    3299           0 :                 switch (stmt->commandType)
    3300             :                 {
    3301             :                     case CMD_SELECT:
    3302           0 :                         lev = LOGSTMT_ALL;
    3303           0 :                         break;
    3304             : 
    3305             :                     case CMD_UPDATE:
    3306             :                     case CMD_INSERT:
    3307             :                     case CMD_DELETE:
    3308           0 :                         lev = LOGSTMT_MOD;
    3309           0 :                         break;
    3310             : 
    3311             :                     case CMD_UTILITY:
    3312           0 :                         lev = GetCommandLogLevel(stmt->utilityStmt);
    3313           0 :                         break;
    3314             : 
    3315             :                     default:
    3316           0 :                         elog(WARNING, "unrecognized commandType: %d",
    3317             :                              (int) stmt->commandType);
    3318           0 :                         lev = LOGSTMT_ALL;
    3319           0 :                         break;
    3320             :                 }
    3321             :             }
    3322           0 :             break;
    3323             : 
    3324             :             /* parsed-and-rewritten-but-not-planned queries */
    3325             :         case T_Query:
    3326             :             {
    3327           0 :                 Query      *stmt = (Query *) parsetree;
    3328             : 
    3329           0 :                 switch (stmt->commandType)
    3330             :                 {
    3331             :                     case CMD_SELECT:
    3332           0 :                         lev = LOGSTMT_ALL;
    3333           0 :                         break;
    3334             : 
    3335             :                     case CMD_UPDATE:
    3336             :                     case CMD_INSERT:
    3337             :                     case CMD_DELETE:
    3338           0 :                         lev = LOGSTMT_MOD;
    3339           0 :                         break;
    3340             : 
    3341             :                     case CMD_UTILITY:
    3342           0 :                         lev = GetCommandLogLevel(stmt->utilityStmt);
    3343           0 :                         break;
    3344             : 
    3345             :                     default:
    3346           0 :                         elog(WARNING, "unrecognized commandType: %d",
    3347             :                              (int) stmt->commandType);
    3348           0 :                         lev = LOGSTMT_ALL;
    3349           0 :                         break;
    3350             :                 }
    3351             : 
    3352             :             }
    3353           0 :             break;
    3354             : 
    3355             :         default:
    3356           0 :             elog(WARNING, "unrecognized node type: %d",
    3357             :                  (int) nodeTag(parsetree));
    3358           0 :             lev = LOGSTMT_ALL;
    3359           0 :             break;
    3360             :     }
    3361             : 
    3362           0 :     return lev;
    3363             : }

Generated by: LCOV version 1.11