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