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