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