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