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