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