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