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