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