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