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