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