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