PostgreSQL Source Code  git master
utility.c
Go to the documentation of this file.
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-2021, 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/index.h"
26 #include "catalog/namespace.h"
27 #include "catalog/pg_inherits.h"
28 #include "catalog/toasting.h"
29 #include "commands/alter.h"
30 #include "commands/async.h"
31 #include "commands/cluster.h"
32 #include "commands/collationcmds.h"
33 #include "commands/comment.h"
35 #include "commands/copy.h"
36 #include "commands/createas.h"
37 #include "commands/dbcommands.h"
38 #include "commands/defrem.h"
39 #include "commands/discard.h"
40 #include "commands/event_trigger.h"
41 #include "commands/explain.h"
42 #include "commands/extension.h"
43 #include "commands/lockcmds.h"
44 #include "commands/matview.h"
45 #include "commands/policy.h"
46 #include "commands/portalcmds.h"
47 #include "commands/prepare.h"
48 #include "commands/proclang.h"
50 #include "commands/schemacmds.h"
51 #include "commands/seclabel.h"
52 #include "commands/sequence.h"
54 #include "commands/tablecmds.h"
55 #include "commands/tablespace.h"
56 #include "commands/trigger.h"
57 #include "commands/typecmds.h"
58 #include "commands/user.h"
59 #include "commands/vacuum.h"
60 #include "commands/view.h"
61 #include "miscadmin.h"
62 #include "parser/parse_utilcmd.h"
63 #include "postmaster/bgwriter.h"
64 #include "rewrite/rewriteDefine.h"
65 #include "rewrite/rewriteRemove.h"
66 #include "storage/fd.h"
67 #include "tcop/pquery.h"
68 #include "tcop/utility.h"
69 #include "utils/acl.h"
70 #include "utils/guc.h"
71 #include "utils/lsyscache.h"
72 #include "utils/rel.h"
73 #include "utils/syscache.h"
74 
75 /* Hook for plugins to get control in ProcessUtility() */
77 
78 /* local function declarations */
79 static int ClassifyUtilityCommandAsReadOnly(Node *parsetree);
80 static void ProcessUtilitySlow(ParseState *pstate,
81  PlannedStmt *pstmt,
82  const char *queryString,
83  ProcessUtilityContext context,
84  ParamListInfo params,
85  QueryEnvironment *queryEnv,
87  QueryCompletion *qc);
88 static void ExecDropStmt(DropStmt *stmt, bool isTopLevel);
89 
90 /*
91  * CommandIsReadOnly: is an executable query read-only?
92  *
93  * This is a much stricter test than we apply for XactReadOnly mode;
94  * the query must be *in truth* read-only, because the caller wishes
95  * not to do CommandCounterIncrement for it.
96  *
97  * Note: currently no need to support raw or analyzed queries here
98  */
99 bool
101 {
102  Assert(IsA(pstmt, PlannedStmt));
103  switch (pstmt->commandType)
104  {
105  case CMD_SELECT:
106  if (pstmt->rowMarks != NIL)
107  return false; /* SELECT FOR [KEY] UPDATE/SHARE */
108  else if (pstmt->hasModifyingCTE)
109  return false; /* data-modifying CTE */
110  else
111  return true;
112  case CMD_UPDATE:
113  case CMD_INSERT:
114  case CMD_DELETE:
115  return false;
116  case CMD_UTILITY:
117  /* For now, treat all utility commands as read/write */
118  return false;
119  default:
120  elog(WARNING, "unrecognized commandType: %d",
121  (int) pstmt->commandType);
122  break;
123  }
124  return false;
125 }
126 
127 /*
128  * Determine the degree to which a utility command is read only.
129  *
130  * Note the definitions of the relevant flags in src/include/utility/tcop.h.
131  */
132 static int
134 {
135  switch (nodeTag(parsetree))
136  {
139  case T_AlterDatabaseStmt:
141  case T_AlterDomainStmt:
142  case T_AlterEnumStmt:
146  case T_AlterFdwStmt:
148  case T_AlterFunctionStmt:
151  case T_AlterOpFamilyStmt:
152  case T_AlterOperatorStmt:
153  case T_AlterOwnerStmt:
154  case T_AlterPolicyStmt:
156  case T_AlterRoleSetStmt:
157  case T_AlterRoleStmt:
158  case T_AlterSeqStmt:
159  case T_AlterStatsStmt:
165  case T_AlterTableStmt:
166  case T_AlterTypeStmt:
168  case T_CommentStmt:
169  case T_CompositeTypeStmt:
170  case T_CreateAmStmt:
171  case T_CreateCastStmt:
173  case T_CreateDomainStmt:
174  case T_CreateEnumStmt:
177  case T_CreateFdwStmt:
181  case T_CreateOpClassStmt:
183  case T_CreatePLangStmt:
184  case T_CreatePolicyStmt:
186  case T_CreateRangeStmt:
187  case T_CreateRoleStmt:
188  case T_CreateSchemaStmt:
189  case T_CreateSeqStmt:
190  case T_CreateStatsStmt:
191  case T_CreateStmt:
193  case T_CreateTableAsStmt:
196  case T_CreateTrigStmt:
198  case T_CreatedbStmt:
199  case T_DefineStmt:
200  case T_DropOwnedStmt:
201  case T_DropRoleStmt:
202  case T_DropStmt:
206  case T_DropdbStmt:
207  case T_GrantRoleStmt:
208  case T_GrantStmt:
210  case T_IndexStmt:
211  case T_ReassignOwnedStmt:
213  case T_RenameStmt:
214  case T_RuleStmt:
215  case T_SecLabelStmt:
216  case T_TruncateStmt:
217  case T_ViewStmt:
218  {
219  /* DDL is not read-only, and neither is TRUNCATE. */
221  }
222 
223  case T_AlterSystemStmt:
224  {
225  /*
226  * Surprisingly, ALTER SYSTEM meets all our definitions of
227  * read-only: it changes nothing that affects the output of
228  * pg_dump, it doesn't write WAL or imperil the application of
229  * future WAL, and it doesn't depend on any state that needs
230  * to be synchronized with parallel workers.
231  *
232  * So, despite the fact that it writes to a file, it's read
233  * only!
234  */
236  }
237 
238  case T_CallStmt:
239  case T_DoStmt:
240  {
241  /*
242  * Commands inside the DO block or the called procedure might
243  * not be read only, but they'll be checked separately when we
244  * try to execute them. Here we only need to worry about the
245  * DO or CALL command itself.
246  */
248  }
249 
250  case T_CheckPointStmt:
251  {
252  /*
253  * You might think that this should not be permitted in
254  * recovery, but we interpret a CHECKPOINT command during
255  * recovery as a request for a restartpoint instead. We allow
256  * this since it can be a useful way of reducing switchover
257  * time when using various forms of replication.
258  */
260  }
261 
262  case T_ClosePortalStmt:
264  case T_DeallocateStmt:
265  case T_DeclareCursorStmt:
266  case T_DiscardStmt:
267  case T_ExecuteStmt:
268  case T_FetchStmt:
269  case T_LoadStmt:
270  case T_PrepareStmt:
271  case T_UnlistenStmt:
272  case T_VariableSetStmt:
273  {
274  /*
275  * These modify only backend-local state, so they're OK to run
276  * in a read-only transaction or on a standby. However, they
277  * are disallowed in parallel mode, because they either rely
278  * upon or modify backend-local state that might not be
279  * synchronized among cooperating backends.
280  */
282  }
283 
284  case T_ClusterStmt:
285  case T_ReindexStmt:
286  case T_VacuumStmt:
287  {
288  /*
289  * These commands write WAL, so they're not strictly
290  * read-only, and running them in parallel workers isn't
291  * supported.
292  *
293  * However, they don't change the database state in a way that
294  * would affect pg_dump output, so it's fine to run them in a
295  * read-only transaction. (CLUSTER might change the order of
296  * rows on disk, which could affect the ordering of pg_dump
297  * output, but that's not semantically significant.)
298  */
300  }
301 
302  case T_CopyStmt:
303  {
304  CopyStmt *stmt = (CopyStmt *) parsetree;
305 
306  /*
307  * You might think that COPY FROM is not at all read only, but
308  * it's OK to copy into a temporary table, because that
309  * wouldn't change the output of pg_dump. If the target table
310  * turns out to be non-temporary, DoCopy itself will call
311  * PreventCommandIfReadOnly.
312  */
313  if (stmt->is_from)
315  else
317  }
318 
319  case T_ExplainStmt:
320  case T_VariableShowStmt:
321  {
322  /*
323  * These commands don't modify any data and are safe to run in
324  * a parallel worker.
325  */
327  }
328 
329  case T_ListenStmt:
330  case T_NotifyStmt:
331  {
332  /*
333  * NOTIFY requires an XID assignment, so it can't be permitted
334  * on a standby. Perhaps LISTEN could, since without NOTIFY it
335  * would be OK to just do nothing, at least until promotion,
336  * but we currently prohibit it lest the user get the wrong
337  * idea.
338  *
339  * (We do allow T_UnlistenStmt on a standby, though, because
340  * it's a no-op.)
341  */
343  }
344 
345  case T_LockStmt:
346  {
347  LockStmt *stmt = (LockStmt *) parsetree;
348 
349  /*
350  * Only weaker locker modes are allowed during recovery. The
351  * restrictions here must match those in
352  * LockAcquireExtended().
353  */
354  if (stmt->mode > RowExclusiveLock)
356  else
358  }
359 
360  case T_TransactionStmt:
361  {
362  TransactionStmt *stmt = (TransactionStmt *) parsetree;
363 
364  /*
365  * PREPARE, COMMIT PREPARED, and ROLLBACK PREPARED all write
366  * WAL, so they're not read-only in the strict sense; but the
367  * first and third do not change pg_dump output, so they're OK
368  * in a read-only transactions.
369  *
370  * We also consider COMMIT PREPARED to be OK in a read-only
371  * transaction environment, by way of exception.
372  */
373  switch (stmt->kind)
374  {
375  case TRANS_STMT_BEGIN:
376  case TRANS_STMT_START:
377  case TRANS_STMT_COMMIT:
378  case TRANS_STMT_ROLLBACK:
380  case TRANS_STMT_RELEASE:
383 
384  case TRANS_STMT_PREPARE:
388  }
389  elog(ERROR, "unrecognized TransactionStmtKind: %d",
390  (int) stmt->kind);
391  return 0; /* silence stupider compilers */
392  }
393 
394  default:
395  elog(ERROR, "unrecognized node type: %d",
396  (int) nodeTag(parsetree));
397  return 0; /* silence stupider compilers */
398  }
399 }
400 
401 /*
402  * PreventCommandIfReadOnly: throw error if XactReadOnly
403  *
404  * This is useful partly to ensure consistency of the error message wording;
405  * some callers have checked XactReadOnly for themselves.
406  */
407 void
408 PreventCommandIfReadOnly(const char *cmdname)
409 {
410  if (XactReadOnly)
411  ereport(ERROR,
412  (errcode(ERRCODE_READ_ONLY_SQL_TRANSACTION),
413  /* translator: %s is name of a SQL command, eg CREATE */
414  errmsg("cannot execute %s in a read-only transaction",
415  cmdname)));
416 }
417 
418 /*
419  * PreventCommandIfParallelMode: throw error if current (sub)transaction is
420  * in parallel mode.
421  *
422  * This is useful partly to ensure consistency of the error message wording;
423  * some callers have checked IsInParallelMode() for themselves.
424  */
425 void
426 PreventCommandIfParallelMode(const char *cmdname)
427 {
428  if (IsInParallelMode())
429  ereport(ERROR,
430  (errcode(ERRCODE_INVALID_TRANSACTION_STATE),
431  /* translator: %s is name of a SQL command, eg CREATE */
432  errmsg("cannot execute %s during a parallel operation",
433  cmdname)));
434 }
435 
436 /*
437  * PreventCommandDuringRecovery: throw error if RecoveryInProgress
438  *
439  * The majority of operations that are unsafe in a Hot Standby
440  * will be rejected by XactReadOnly tests. However there are a few
441  * commands that are allowed in "read-only" xacts but cannot be allowed
442  * in Hot Standby mode. Those commands should call this function.
443  */
444 void
445 PreventCommandDuringRecovery(const char *cmdname)
446 {
447  if (RecoveryInProgress())
448  ereport(ERROR,
449  (errcode(ERRCODE_READ_ONLY_SQL_TRANSACTION),
450  /* translator: %s is name of a SQL command, eg CREATE */
451  errmsg("cannot execute %s during recovery",
452  cmdname)));
453 }
454 
455 /*
456  * CheckRestrictedOperation: throw error for hazardous command if we're
457  * inside a security restriction context.
458  *
459  * This is needed to protect session-local state for which there is not any
460  * better-defined protection mechanism, such as ownership.
461  */
462 static void
463 CheckRestrictedOperation(const char *cmdname)
464 {
466  ereport(ERROR,
467  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
468  /* translator: %s is name of a SQL command, eg PREPARE */
469  errmsg("cannot execute %s within security-restricted operation",
470  cmdname)));
471 }
472 
473 /*
474  * ProcessUtility
475  * general utility function invoker
476  *
477  * pstmt: PlannedStmt wrapper for the utility statement
478  * queryString: original source text of command
479  * readOnlyTree: if true, pstmt's node tree must not be modified
480  * context: identifies source of statement (toplevel client command,
481  * non-toplevel client command, subcommand of a larger utility command)
482  * params: parameters to use during execution
483  * queryEnv: environment for parse through execution (e.g., ephemeral named
484  * tables like trigger transition tables). May be NULL.
485  * dest: where to send results
486  * qc: where to store command completion status data. May be NULL,
487  * but if not, then caller must have initialized it.
488  *
489  * Caller MUST supply a queryString; it is not allowed (anymore) to pass NULL.
490  * If you really don't have source text, you can pass a constant string,
491  * perhaps "(query not available)".
492  *
493  * Note for users of ProcessUtility_hook: the same queryString may be passed
494  * to multiple invocations of ProcessUtility when processing a query string
495  * containing multiple semicolon-separated statements. One should use
496  * pstmt->stmt_location and pstmt->stmt_len to identify the substring
497  * containing the current statement. Keep in mind also that some utility
498  * statements (e.g., CREATE SCHEMA) will recurse to ProcessUtility to process
499  * sub-statements, often passing down the same queryString, stmt_location,
500  * and stmt_len that were given for the whole statement.
501  */
502 void
504  const char *queryString,
505  bool readOnlyTree,
506  ProcessUtilityContext context,
507  ParamListInfo params,
508  QueryEnvironment *queryEnv,
510  QueryCompletion *qc)
511 {
512  Assert(IsA(pstmt, PlannedStmt));
513  Assert(pstmt->commandType == CMD_UTILITY);
514  Assert(queryString != NULL); /* required as of 8.4 */
515  Assert(qc == NULL || qc->commandTag == CMDTAG_UNKNOWN);
516 
517  /*
518  * We provide a function hook variable that lets loadable plugins get
519  * control when ProcessUtility is called. Such a plugin would normally
520  * call standard_ProcessUtility().
521  */
523  (*ProcessUtility_hook) (pstmt, queryString, readOnlyTree,
524  context, params, queryEnv,
525  dest, qc);
526  else
527  standard_ProcessUtility(pstmt, queryString, readOnlyTree,
528  context, params, queryEnv,
529  dest, qc);
530 }
531 
532 /*
533  * standard_ProcessUtility itself deals only with utility commands for
534  * which we do not provide event trigger support. Commands that do have
535  * such support are passed down to ProcessUtilitySlow, which contains the
536  * necessary infrastructure for such triggers.
537  *
538  * This division is not just for performance: it's critical that the
539  * event trigger code not be invoked when doing START TRANSACTION for
540  * example, because we might need to refresh the event trigger cache,
541  * which requires being in a valid transaction.
542  */
543 void
545  const char *queryString,
546  bool readOnlyTree,
547  ProcessUtilityContext context,
548  ParamListInfo params,
549  QueryEnvironment *queryEnv,
551  QueryCompletion *qc)
552 {
553  Node *parsetree;
554  bool isTopLevel = (context == PROCESS_UTILITY_TOPLEVEL);
555  bool isAtomicContext = (!(context == PROCESS_UTILITY_TOPLEVEL || context == PROCESS_UTILITY_QUERY_NONATOMIC) || IsTransactionBlock());
556  ParseState *pstate;
557  int readonly_flags;
558 
559  /* This can recurse, so check for excessive recursion */
561 
562  /*
563  * If the given node tree is read-only, make a copy to ensure that parse
564  * transformations don't damage the original tree. This could be
565  * refactored to avoid making unnecessary copies in more cases, but it's
566  * not clear that it's worth a great deal of trouble over. Statements
567  * that are complex enough to be expensive to copy are exactly the ones
568  * we'd need to copy, so that only marginal savings seem possible.
569  */
570  if (readOnlyTree)
571  pstmt = copyObject(pstmt);
572  parsetree = pstmt->utilityStmt;
573 
574  /* Prohibit read/write commands in read-only states. */
575  readonly_flags = ClassifyUtilityCommandAsReadOnly(parsetree);
576  if (readonly_flags != COMMAND_IS_STRICTLY_READ_ONLY &&
578  {
579  CommandTag commandtag = CreateCommandTag(parsetree);
580 
581  if ((readonly_flags & COMMAND_OK_IN_READ_ONLY_TXN) == 0)
583  if ((readonly_flags & COMMAND_OK_IN_PARALLEL_MODE) == 0)
585  if ((readonly_flags & COMMAND_OK_IN_RECOVERY) == 0)
587  }
588 
589  pstate = make_parsestate(NULL);
590  pstate->p_sourcetext = queryString;
591  pstate->p_queryEnv = queryEnv;
592 
593  switch (nodeTag(parsetree))
594  {
595  /*
596  * ******************** transactions ********************
597  */
598  case T_TransactionStmt:
599  {
600  TransactionStmt *stmt = (TransactionStmt *) parsetree;
601 
602  switch (stmt->kind)
603  {
604  /*
605  * START TRANSACTION, as defined by SQL99: Identical
606  * to BEGIN. Same code for both.
607  */
608  case TRANS_STMT_BEGIN:
609  case TRANS_STMT_START:
610  {
611  ListCell *lc;
612 
614  foreach(lc, stmt->options)
615  {
616  DefElem *item = (DefElem *) lfirst(lc);
617 
618  if (strcmp(item->defname, "transaction_isolation") == 0)
619  SetPGVariable("transaction_isolation",
620  list_make1(item->arg),
621  true);
622  else if (strcmp(item->defname, "transaction_read_only") == 0)
623  SetPGVariable("transaction_read_only",
624  list_make1(item->arg),
625  true);
626  else if (strcmp(item->defname, "transaction_deferrable") == 0)
627  SetPGVariable("transaction_deferrable",
628  list_make1(item->arg),
629  true);
630  }
631  }
632  break;
633 
634  case TRANS_STMT_COMMIT:
635  if (!EndTransactionBlock(stmt->chain))
636  {
637  /* report unsuccessful commit in qc */
638  if (qc)
639  SetQueryCompletion(qc, CMDTAG_ROLLBACK, 0);
640  }
641  break;
642 
643  case TRANS_STMT_PREPARE:
644  if (!PrepareTransactionBlock(stmt->gid))
645  {
646  /* report unsuccessful commit in qc */
647  if (qc)
648  SetQueryCompletion(qc, CMDTAG_ROLLBACK, 0);
649  }
650  break;
651 
653  PreventInTransactionBlock(isTopLevel, "COMMIT PREPARED");
654  FinishPreparedTransaction(stmt->gid, true);
655  break;
656 
658  PreventInTransactionBlock(isTopLevel, "ROLLBACK PREPARED");
659  FinishPreparedTransaction(stmt->gid, false);
660  break;
661 
662  case TRANS_STMT_ROLLBACK:
664  break;
665 
667  RequireTransactionBlock(isTopLevel, "SAVEPOINT");
669  break;
670 
671  case TRANS_STMT_RELEASE:
672  RequireTransactionBlock(isTopLevel, "RELEASE SAVEPOINT");
674  break;
675 
677  RequireTransactionBlock(isTopLevel, "ROLLBACK TO SAVEPOINT");
679 
680  /*
681  * CommitTransactionCommand is in charge of
682  * re-defining the savepoint again
683  */
684  break;
685  }
686  }
687  break;
688 
689  /*
690  * Portal (cursor) manipulation
691  */
692  case T_DeclareCursorStmt:
693  PerformCursorOpen(pstate, (DeclareCursorStmt *) parsetree, params,
694  isTopLevel);
695  break;
696 
697  case T_ClosePortalStmt:
698  {
699  ClosePortalStmt *stmt = (ClosePortalStmt *) parsetree;
700 
701  CheckRestrictedOperation("CLOSE");
703  }
704  break;
705 
706  case T_FetchStmt:
707  PerformPortalFetch((FetchStmt *) parsetree, dest, qc);
708  break;
709 
710  case T_DoStmt:
711  ExecuteDoStmt(pstate, (DoStmt *) parsetree, isAtomicContext);
712  break;
713 
715  /* no event triggers for global objects */
716  PreventInTransactionBlock(isTopLevel, "CREATE TABLESPACE");
717  CreateTableSpace((CreateTableSpaceStmt *) parsetree);
718  break;
719 
721  /* no event triggers for global objects */
722  PreventInTransactionBlock(isTopLevel, "DROP TABLESPACE");
723  DropTableSpace((DropTableSpaceStmt *) parsetree);
724  break;
725 
727  /* no event triggers for global objects */
729  break;
730 
731  case T_TruncateStmt:
732  ExecuteTruncate((TruncateStmt *) parsetree);
733  break;
734 
735  case T_CopyStmt:
736  {
737  uint64 processed;
738 
739  DoCopy(pstate, (CopyStmt *) parsetree,
740  pstmt->stmt_location, pstmt->stmt_len,
741  &processed);
742  if (qc)
743  SetQueryCompletion(qc, CMDTAG_COPY, processed);
744  }
745  break;
746 
747  case T_PrepareStmt:
748  CheckRestrictedOperation("PREPARE");
749  PrepareQuery(pstate, (PrepareStmt *) parsetree,
750  pstmt->stmt_location, pstmt->stmt_len);
751  break;
752 
753  case T_ExecuteStmt:
754  ExecuteQuery(pstate,
755  (ExecuteStmt *) parsetree, NULL,
756  params,
757  dest, qc);
758  break;
759 
760  case T_DeallocateStmt:
761  CheckRestrictedOperation("DEALLOCATE");
762  DeallocateQuery((DeallocateStmt *) parsetree);
763  break;
764 
765  case T_GrantRoleStmt:
766  /* no event triggers for global objects */
767  GrantRole((GrantRoleStmt *) parsetree);
768  break;
769 
770  case T_CreatedbStmt:
771  /* no event triggers for global objects */
772  PreventInTransactionBlock(isTopLevel, "CREATE DATABASE");
773  createdb(pstate, (CreatedbStmt *) parsetree);
774  break;
775 
776  case T_AlterDatabaseStmt:
777  /* no event triggers for global objects */
778  AlterDatabase(pstate, (AlterDatabaseStmt *) parsetree, isTopLevel);
779  break;
780 
782  /* no event triggers for global objects */
783  AlterDatabaseSet((AlterDatabaseSetStmt *) parsetree);
784  break;
785 
786  case T_DropdbStmt:
787  /* no event triggers for global objects */
788  PreventInTransactionBlock(isTopLevel, "DROP DATABASE");
789  DropDatabase(pstate, (DropdbStmt *) parsetree);
790  break;
791 
792  /* Query-level asynchronous notification */
793  case T_NotifyStmt:
794  {
795  NotifyStmt *stmt = (NotifyStmt *) parsetree;
796 
797  Async_Notify(stmt->conditionname, stmt->payload);
798  }
799  break;
800 
801  case T_ListenStmt:
802  {
803  ListenStmt *stmt = (ListenStmt *) parsetree;
804 
805  CheckRestrictedOperation("LISTEN");
806 
807  /*
808  * We don't allow LISTEN in background processes, as there is
809  * no mechanism for them to collect NOTIFY messages, so they'd
810  * just block cleanout of the async SLRU indefinitely.
811  * (Authors of custom background workers could bypass this
812  * restriction by calling Async_Listen directly, but then it's
813  * on them to provide some mechanism to process the message
814  * queue.) Note there seems no reason to forbid UNLISTEN.
815  */
816  if (MyBackendType != B_BACKEND)
817  ereport(ERROR,
818  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
819  /* translator: %s is name of a SQL command, eg LISTEN */
820  errmsg("cannot execute %s within a background process",
821  "LISTEN")));
822 
824  }
825  break;
826 
827  case T_UnlistenStmt:
828  {
829  UnlistenStmt *stmt = (UnlistenStmt *) parsetree;
830 
831  CheckRestrictedOperation("UNLISTEN");
832  if (stmt->conditionname)
834  else
836  }
837  break;
838 
839  case T_LoadStmt:
840  {
841  LoadStmt *stmt = (LoadStmt *) parsetree;
842 
843  closeAllVfds(); /* probably not necessary... */
844  /* Allowed names are restricted if you're not superuser */
845  load_file(stmt->filename, !superuser());
846  }
847  break;
848 
849  case T_CallStmt:
850  ExecuteCallStmt(castNode(CallStmt, parsetree), params, isAtomicContext, dest);
851  break;
852 
853  case T_ClusterStmt:
854  cluster(pstate, (ClusterStmt *) parsetree, isTopLevel);
855  break;
856 
857  case T_VacuumStmt:
858  ExecVacuum(pstate, (VacuumStmt *) parsetree, isTopLevel);
859  break;
860 
861  case T_ExplainStmt:
862  ExplainQuery(pstate, (ExplainStmt *) parsetree, params, dest);
863  break;
864 
865  case T_AlterSystemStmt:
866  PreventInTransactionBlock(isTopLevel, "ALTER SYSTEM");
868  break;
869 
870  case T_VariableSetStmt:
871  ExecSetVariableStmt((VariableSetStmt *) parsetree, isTopLevel);
872  break;
873 
874  case T_VariableShowStmt:
875  {
876  VariableShowStmt *n = (VariableShowStmt *) parsetree;
877 
878  GetPGVariable(n->name, dest);
879  }
880  break;
881 
882  case T_DiscardStmt:
883  /* should we allow DISCARD PLANS? */
884  CheckRestrictedOperation("DISCARD");
885  DiscardCommand((DiscardStmt *) parsetree, isTopLevel);
886  break;
887 
889  /* no event triggers on event triggers */
891  break;
892 
894  /* no event triggers on event triggers */
895  AlterEventTrigger((AlterEventTrigStmt *) parsetree);
896  break;
897 
898  /*
899  * ******************************** ROLE statements ****
900  */
901  case T_CreateRoleStmt:
902  /* no event triggers for global objects */
903  CreateRole(pstate, (CreateRoleStmt *) parsetree);
904  break;
905 
906  case T_AlterRoleStmt:
907  /* no event triggers for global objects */
908  AlterRole(pstate, (AlterRoleStmt *) parsetree);
909  break;
910 
911  case T_AlterRoleSetStmt:
912  /* no event triggers for global objects */
913  AlterRoleSet((AlterRoleSetStmt *) parsetree);
914  break;
915 
916  case T_DropRoleStmt:
917  /* no event triggers for global objects */
918  DropRole((DropRoleStmt *) parsetree);
919  break;
920 
921  case T_ReassignOwnedStmt:
922  /* no event triggers for global objects */
924  break;
925 
926  case T_LockStmt:
927 
928  /*
929  * Since the lock would just get dropped immediately, LOCK TABLE
930  * outside a transaction block is presumed to be user error.
931  */
932  RequireTransactionBlock(isTopLevel, "LOCK TABLE");
933  LockTableCommand((LockStmt *) parsetree);
934  break;
935 
937  WarnNoTransactionBlock(isTopLevel, "SET CONSTRAINTS");
939  break;
940 
941  case T_CheckPointStmt:
942  if (!superuser())
943  ereport(ERROR,
944  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
945  errmsg("must be superuser to do CHECKPOINT")));
946 
949  break;
950 
951  case T_ReindexStmt:
952  ExecReindex(pstate, (ReindexStmt *) parsetree, isTopLevel);
953  break;
954 
955  /*
956  * The following statements are supported by Event Triggers only
957  * in some cases, so we "fast path" them in the other cases.
958  */
959 
960  case T_GrantStmt:
961  {
962  GrantStmt *stmt = (GrantStmt *) parsetree;
963 
965  ProcessUtilitySlow(pstate, pstmt, queryString,
966  context, params, queryEnv,
967  dest, qc);
968  else
969  ExecuteGrantStmt(stmt);
970  }
971  break;
972 
973  case T_DropStmt:
974  {
975  DropStmt *stmt = (DropStmt *) parsetree;
976 
978  ProcessUtilitySlow(pstate, pstmt, queryString,
979  context, params, queryEnv,
980  dest, qc);
981  else
982  ExecDropStmt(stmt, isTopLevel);
983  }
984  break;
985 
986  case T_RenameStmt:
987  {
988  RenameStmt *stmt = (RenameStmt *) parsetree;
989 
991  ProcessUtilitySlow(pstate, pstmt, queryString,
992  context, params, queryEnv,
993  dest, qc);
994  else
995  ExecRenameStmt(stmt);
996  }
997  break;
998 
1000  {
1001  AlterObjectDependsStmt *stmt = (AlterObjectDependsStmt *) parsetree;
1002 
1004  ProcessUtilitySlow(pstate, pstmt, queryString,
1005  context, params, queryEnv,
1006  dest, qc);
1007  else
1008  ExecAlterObjectDependsStmt(stmt, NULL);
1009  }
1010  break;
1011 
1013  {
1014  AlterObjectSchemaStmt *stmt = (AlterObjectSchemaStmt *) parsetree;
1015 
1017  ProcessUtilitySlow(pstate, pstmt, queryString,
1018  context, params, queryEnv,
1019  dest, qc);
1020  else
1021  ExecAlterObjectSchemaStmt(stmt, NULL);
1022  }
1023  break;
1024 
1025  case T_AlterOwnerStmt:
1026  {
1027  AlterOwnerStmt *stmt = (AlterOwnerStmt *) parsetree;
1028 
1030  ProcessUtilitySlow(pstate, pstmt, queryString,
1031  context, params, queryEnv,
1032  dest, qc);
1033  else
1034  ExecAlterOwnerStmt(stmt);
1035  }
1036  break;
1037 
1038  case T_CommentStmt:
1039  {
1040  CommentStmt *stmt = (CommentStmt *) parsetree;
1041 
1043  ProcessUtilitySlow(pstate, pstmt, queryString,
1044  context, params, queryEnv,
1045  dest, qc);
1046  else
1047  CommentObject(stmt);
1048  break;
1049  }
1050 
1051  case T_SecLabelStmt:
1052  {
1053  SecLabelStmt *stmt = (SecLabelStmt *) parsetree;
1054 
1056  ProcessUtilitySlow(pstate, pstmt, queryString,
1057  context, params, queryEnv,
1058  dest, qc);
1059  else
1060  ExecSecLabelStmt(stmt);
1061  break;
1062  }
1063 
1064  default:
1065  /* All other statement types have event trigger support */
1066  ProcessUtilitySlow(pstate, pstmt, queryString,
1067  context, params, queryEnv,
1068  dest, qc);
1069  break;
1070  }
1071 
1072  free_parsestate(pstate);
1073 
1074  /*
1075  * Make effects of commands visible, for instance so that
1076  * PreCommit_on_commit_actions() can see them (see for example bug
1077  * #15631).
1078  */
1080 }
1081 
1082 /*
1083  * The "Slow" variant of ProcessUtility should only receive statements
1084  * supported by the event triggers facility. Therefore, we always
1085  * perform the trigger support calls if the context allows it.
1086  */
1087 static void
1089  PlannedStmt *pstmt,
1090  const char *queryString,
1091  ProcessUtilityContext context,
1092  ParamListInfo params,
1093  QueryEnvironment *queryEnv,
1094  DestReceiver *dest,
1095  QueryCompletion *qc)
1096 {
1097  Node *parsetree = pstmt->utilityStmt;
1098  bool isTopLevel = (context == PROCESS_UTILITY_TOPLEVEL);
1099  bool isCompleteQuery = (context != PROCESS_UTILITY_SUBCOMMAND);
1100  bool needCleanup;
1101  bool commandCollected = false;
1102  ObjectAddress address;
1103  ObjectAddress secondaryObject = InvalidObjectAddress;
1104 
1105  /* All event trigger calls are done only when isCompleteQuery is true */
1106  needCleanup = isCompleteQuery && EventTriggerBeginCompleteQuery();
1107 
1108  /* PG_TRY block is to ensure we call EventTriggerEndCompleteQuery */
1109  PG_TRY();
1110  {
1111  if (isCompleteQuery)
1112  EventTriggerDDLCommandStart(parsetree);
1113 
1114  switch (nodeTag(parsetree))
1115  {
1116  /*
1117  * relation and attribute manipulation
1118  */
1119  case T_CreateSchemaStmt:
1120  CreateSchemaCommand((CreateSchemaStmt *) parsetree,
1121  queryString,
1122  pstmt->stmt_location,
1123  pstmt->stmt_len);
1124 
1125  /*
1126  * EventTriggerCollectSimpleCommand called by
1127  * CreateSchemaCommand
1128  */
1129  commandCollected = true;
1130  break;
1131 
1132  case T_CreateStmt:
1134  {
1135  List *stmts;
1136  RangeVar *table_rv = NULL;
1137 
1138  /* Run parse analysis ... */
1139  stmts = transformCreateStmt((CreateStmt *) parsetree,
1140  queryString);
1141 
1142  /*
1143  * ... and do it. We can't use foreach() because we may
1144  * modify the list midway through, so pick off the
1145  * elements one at a time, the hard way.
1146  */
1147  while (stmts != NIL)
1148  {
1149  Node *stmt = (Node *) linitial(stmts);
1150 
1151  stmts = list_delete_first(stmts);
1152 
1153  if (IsA(stmt, CreateStmt))
1154  {
1155  CreateStmt *cstmt = (CreateStmt *) stmt;
1156  Datum toast_options;
1157  static char *validnsps[] = HEAP_RELOPT_NAMESPACES;
1158 
1159  /* Remember transformed RangeVar for LIKE */
1160  table_rv = cstmt->relation;
1161 
1162  /* Create the table itself */
1163  address = DefineRelation(cstmt,
1164  RELKIND_RELATION,
1165  InvalidOid, NULL,
1166  queryString);
1168  secondaryObject,
1169  stmt);
1170 
1171  /*
1172  * Let NewRelationCreateToastTable decide if this
1173  * one needs a secondary relation too.
1174  */
1176 
1177  /*
1178  * parse and validate reloptions for the toast
1179  * table
1180  */
1181  toast_options = transformRelOptions((Datum) 0,
1182  cstmt->options,
1183  "toast",
1184  validnsps,
1185  true,
1186  false);
1187  (void) heap_reloptions(RELKIND_TOASTVALUE,
1188  toast_options,
1189  true);
1190 
1192  toast_options);
1193  }
1194  else if (IsA(stmt, CreateForeignTableStmt))
1195  {
1197 
1198  /* Remember transformed RangeVar for LIKE */
1199  table_rv = cstmt->base.relation;
1200 
1201  /* Create the table itself */
1202  address = DefineRelation(&cstmt->base,
1203  RELKIND_FOREIGN_TABLE,
1204  InvalidOid, NULL,
1205  queryString);
1206  CreateForeignTable(cstmt,
1207  address.objectId);
1209  secondaryObject,
1210  stmt);
1211  }
1212  else if (IsA(stmt, TableLikeClause))
1213  {
1214  /*
1215  * Do delayed processing of LIKE options. This
1216  * will result in additional sub-statements for us
1217  * to process. Those should get done before any
1218  * remaining actions, so prepend them to "stmts".
1219  */
1220  TableLikeClause *like = (TableLikeClause *) stmt;
1221  List *morestmts;
1222 
1223  Assert(table_rv != NULL);
1224 
1225  morestmts = expandTableLikeClause(table_rv, like);
1226  stmts = list_concat(morestmts, stmts);
1227  }
1228  else
1229  {
1230  /*
1231  * Recurse for anything else. Note the recursive
1232  * call will stash the objects so created into our
1233  * event trigger context.
1234  */
1235  PlannedStmt *wrapper;
1236 
1237  wrapper = makeNode(PlannedStmt);
1238  wrapper->commandType = CMD_UTILITY;
1239  wrapper->canSetTag = false;
1240  wrapper->utilityStmt = stmt;
1241  wrapper->stmt_location = pstmt->stmt_location;
1242  wrapper->stmt_len = pstmt->stmt_len;
1243 
1244  ProcessUtility(wrapper,
1245  queryString,
1246  false,
1248  params,
1249  NULL,
1250  None_Receiver,
1251  NULL);
1252  }
1253 
1254  /* Need CCI between commands */
1255  if (stmts != NIL)
1257  }
1258 
1259  /*
1260  * The multiple commands generated here are stashed
1261  * individually, so disable collection below.
1262  */
1263  commandCollected = true;
1264  }
1265  break;
1266 
1267  case T_AlterTableStmt:
1268  {
1269  AlterTableStmt *atstmt = (AlterTableStmt *) parsetree;
1270  Oid relid;
1271  LOCKMODE lockmode;
1272  ListCell *cell;
1273 
1274  /*
1275  * Disallow ALTER TABLE .. DETACH CONCURRENTLY in a
1276  * transaction block or function. (Perhaps it could be
1277  * allowed in a procedure, but don't hold your breath.)
1278  */
1279  foreach(cell, atstmt->cmds)
1280  {
1281  AlterTableCmd *cmd = (AlterTableCmd *) lfirst(cell);
1282 
1283  /* Disallow DETACH CONCURRENTLY in a transaction block */
1284  if (cmd->subtype == AT_DetachPartition)
1285  {
1286  if (((PartitionCmd *) cmd->def)->concurrent)
1287  PreventInTransactionBlock(isTopLevel,
1288  "ALTER TABLE ... DETACH CONCURRENTLY");
1289  }
1290  }
1291 
1292  /*
1293  * Figure out lock mode, and acquire lock. This also does
1294  * basic permissions checks, so that we won't wait for a
1295  * lock on (for example) a relation on which we have no
1296  * permissions.
1297  */
1298  lockmode = AlterTableGetLockLevel(atstmt->cmds);
1299  relid = AlterTableLookupRelation(atstmt, lockmode);
1300 
1301  if (OidIsValid(relid))
1302  {
1303  AlterTableUtilityContext atcontext;
1304 
1305  /* Set up info needed for recursive callbacks ... */
1306  atcontext.pstmt = pstmt;
1307  atcontext.queryString = queryString;
1308  atcontext.relid = relid;
1309  atcontext.params = params;
1310  atcontext.queryEnv = queryEnv;
1311 
1312  /* ... ensure we have an event trigger context ... */
1313  EventTriggerAlterTableStart(parsetree);
1315 
1316  /* ... and do it */
1317  AlterTable(atstmt, lockmode, &atcontext);
1318 
1319  /* done */
1321  }
1322  else
1323  ereport(NOTICE,
1324  (errmsg("relation \"%s\" does not exist, skipping",
1325  atstmt->relation->relname)));
1326  }
1327 
1328  /* ALTER TABLE stashes commands internally */
1329  commandCollected = true;
1330  break;
1331 
1332  case T_AlterDomainStmt:
1333  {
1334  AlterDomainStmt *stmt = (AlterDomainStmt *) parsetree;
1335 
1336  /*
1337  * Some or all of these functions are recursive to cover
1338  * inherited things, so permission checks are done there.
1339  */
1340  switch (stmt->subtype)
1341  {
1342  case 'T': /* ALTER DOMAIN DEFAULT */
1343 
1344  /*
1345  * Recursively alter column default for table and,
1346  * if requested, for descendants
1347  */
1348  address =
1350  stmt->def);
1351  break;
1352  case 'N': /* ALTER DOMAIN DROP NOT NULL */
1353  address =
1355  false);
1356  break;
1357  case 'O': /* ALTER DOMAIN SET NOT NULL */
1358  address =
1360  true);
1361  break;
1362  case 'C': /* ADD CONSTRAINT */
1363  address =
1365  stmt->def,
1366  &secondaryObject);
1367  break;
1368  case 'X': /* DROP CONSTRAINT */
1369  address =
1371  stmt->name,
1372  stmt->behavior,
1373  stmt->missing_ok);
1374  break;
1375  case 'V': /* VALIDATE CONSTRAINT */
1376  address =
1378  stmt->name);
1379  break;
1380  default: /* oops */
1381  elog(ERROR, "unrecognized alter domain type: %d",
1382  (int) stmt->subtype);
1383  break;
1384  }
1385  }
1386  break;
1387 
1388  /*
1389  * ************* object creation / destruction **************
1390  */
1391  case T_DefineStmt:
1392  {
1393  DefineStmt *stmt = (DefineStmt *) parsetree;
1394 
1395  switch (stmt->kind)
1396  {
1397  case OBJECT_AGGREGATE:
1398  address =
1399  DefineAggregate(pstate, stmt->defnames, stmt->args,
1400  stmt->oldstyle,
1401  stmt->definition,
1402  stmt->replace);
1403  break;
1404  case OBJECT_OPERATOR:
1405  Assert(stmt->args == NIL);
1406  address = DefineOperator(stmt->defnames,
1407  stmt->definition);
1408  break;
1409  case OBJECT_TYPE:
1410  Assert(stmt->args == NIL);
1411  address = DefineType(pstate,
1412  stmt->defnames,
1413  stmt->definition);
1414  break;
1415  case OBJECT_TSPARSER:
1416  Assert(stmt->args == NIL);
1417  address = DefineTSParser(stmt->defnames,
1418  stmt->definition);
1419  break;
1420  case OBJECT_TSDICTIONARY:
1421  Assert(stmt->args == NIL);
1422  address = DefineTSDictionary(stmt->defnames,
1423  stmt->definition);
1424  break;
1425  case OBJECT_TSTEMPLATE:
1426  Assert(stmt->args == NIL);
1427  address = DefineTSTemplate(stmt->defnames,
1428  stmt->definition);
1429  break;
1431  Assert(stmt->args == NIL);
1432  address = DefineTSConfiguration(stmt->defnames,
1433  stmt->definition,
1434  &secondaryObject);
1435  break;
1436  case OBJECT_COLLATION:
1437  Assert(stmt->args == NIL);
1438  address = DefineCollation(pstate,
1439  stmt->defnames,
1440  stmt->definition,
1441  stmt->if_not_exists);
1442  break;
1443  default:
1444  elog(ERROR, "unrecognized define stmt type: %d",
1445  (int) stmt->kind);
1446  break;
1447  }
1448  }
1449  break;
1450 
1451  case T_IndexStmt: /* CREATE INDEX */
1452  {
1453  IndexStmt *stmt = (IndexStmt *) parsetree;
1454  Oid relid;
1455  LOCKMODE lockmode;
1456  bool is_alter_table;
1457 
1458  if (stmt->concurrent)
1459  PreventInTransactionBlock(isTopLevel,
1460  "CREATE INDEX CONCURRENTLY");
1461 
1462  /*
1463  * Look up the relation OID just once, right here at the
1464  * beginning, so that we don't end up repeating the name
1465  * lookup later and latching onto a different relation
1466  * partway through. To avoid lock upgrade hazards, it's
1467  * important that we take the strongest lock that will
1468  * eventually be needed here, so the lockmode calculation
1469  * needs to match what DefineIndex() does.
1470  */
1471  lockmode = stmt->concurrent ? ShareUpdateExclusiveLock
1472  : ShareLock;
1473  relid =
1474  RangeVarGetRelidExtended(stmt->relation, lockmode,
1475  0,
1477  NULL);
1478 
1479  /*
1480  * CREATE INDEX on partitioned tables (but not regular
1481  * inherited tables) recurses to partitions, so we must
1482  * acquire locks early to avoid deadlocks.
1483  *
1484  * We also take the opportunity to verify that all
1485  * partitions are something we can put an index on, to
1486  * avoid building some indexes only to fail later.
1487  */
1488  if (stmt->relation->inh &&
1489  get_rel_relkind(relid) == RELKIND_PARTITIONED_TABLE)
1490  {
1491  ListCell *lc;
1492  List *inheritors = NIL;
1493 
1494  inheritors = find_all_inheritors(relid, lockmode, NULL);
1495  foreach(lc, inheritors)
1496  {
1497  char relkind = get_rel_relkind(lfirst_oid(lc));
1498 
1499  if (relkind != RELKIND_RELATION &&
1500  relkind != RELKIND_MATVIEW &&
1501  relkind != RELKIND_PARTITIONED_TABLE &&
1502  relkind != RELKIND_FOREIGN_TABLE)
1503  elog(ERROR, "unexpected relkind \"%c\" on partition \"%s\"",
1504  relkind, stmt->relation->relname);
1505 
1506  if (relkind == RELKIND_FOREIGN_TABLE &&
1507  (stmt->unique || stmt->primary))
1508  ereport(ERROR,
1509  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1510  errmsg("cannot create unique index on partitioned table \"%s\"",
1511  stmt->relation->relname),
1512  errdetail("Table \"%s\" contains partitions that are foreign tables.",
1513  stmt->relation->relname)));
1514  }
1515  list_free(inheritors);
1516  }
1517 
1518  /*
1519  * If the IndexStmt is already transformed, it must have
1520  * come from generateClonedIndexStmt, which in current
1521  * usage means it came from expandTableLikeClause rather
1522  * than from original parse analysis. And that means we
1523  * must treat it like ALTER TABLE ADD INDEX, not CREATE.
1524  * (This is a bit grotty, but currently it doesn't seem
1525  * worth adding a separate bool field for the purpose.)
1526  */
1527  is_alter_table = stmt->transformed;
1528 
1529  /* Run parse analysis ... */
1530  stmt = transformIndexStmt(relid, stmt, queryString);
1531 
1532  /* ... and do it */
1533  EventTriggerAlterTableStart(parsetree);
1534  address =
1535  DefineIndex(relid, /* OID of heap relation */
1536  stmt,
1537  InvalidOid, /* no predefined OID */
1538  InvalidOid, /* no parent index */
1539  InvalidOid, /* no parent constraint */
1540  is_alter_table,
1541  true, /* check_rights */
1542  true, /* check_not_in_use */
1543  false, /* skip_build */
1544  false); /* quiet */
1545 
1546  /*
1547  * Add the CREATE INDEX node itself to stash right away;
1548  * if there were any commands stashed in the ALTER TABLE
1549  * code, we need them to appear after this one.
1550  */
1551  EventTriggerCollectSimpleCommand(address, secondaryObject,
1552  parsetree);
1553  commandCollected = true;
1555  }
1556  break;
1557 
1558  case T_CreateExtensionStmt:
1559  address = CreateExtension(pstate, (CreateExtensionStmt *) parsetree);
1560  break;
1561 
1562  case T_AlterExtensionStmt:
1563  address = ExecAlterExtensionStmt(pstate, (AlterExtensionStmt *) parsetree);
1564  break;
1565 
1568  &secondaryObject);
1569  break;
1570 
1571  case T_CreateFdwStmt:
1572  address = CreateForeignDataWrapper(pstate, (CreateFdwStmt *) parsetree);
1573  break;
1574 
1575  case T_AlterFdwStmt:
1576  address = AlterForeignDataWrapper(pstate, (AlterFdwStmt *) parsetree);
1577  break;
1578 
1580  address = CreateForeignServer((CreateForeignServerStmt *) parsetree);
1581  break;
1582 
1584  address = AlterForeignServer((AlterForeignServerStmt *) parsetree);
1585  break;
1586 
1588  address = CreateUserMapping((CreateUserMappingStmt *) parsetree);
1589  break;
1590 
1592  address = AlterUserMapping((AlterUserMappingStmt *) parsetree);
1593  break;
1594 
1595  case T_DropUserMappingStmt:
1596  RemoveUserMapping((DropUserMappingStmt *) parsetree);
1597  /* no commands stashed for DROP */
1598  commandCollected = true;
1599  break;
1600 
1603  /* commands are stashed inside ImportForeignSchema */
1604  commandCollected = true;
1605  break;
1606 
1607  case T_CompositeTypeStmt: /* CREATE TYPE (composite) */
1608  {
1609  CompositeTypeStmt *stmt = (CompositeTypeStmt *) parsetree;
1610 
1611  address = DefineCompositeType(stmt->typevar,
1612  stmt->coldeflist);
1613  }
1614  break;
1615 
1616  case T_CreateEnumStmt: /* CREATE TYPE AS ENUM */
1617  address = DefineEnum((CreateEnumStmt *) parsetree);
1618  break;
1619 
1620  case T_CreateRangeStmt: /* CREATE TYPE AS RANGE */
1621  address = DefineRange(pstate, (CreateRangeStmt *) parsetree);
1622  break;
1623 
1624  case T_AlterEnumStmt: /* ALTER TYPE (enum) */
1625  address = AlterEnum((AlterEnumStmt *) parsetree);
1626  break;
1627 
1628  case T_ViewStmt: /* CREATE VIEW */
1629  EventTriggerAlterTableStart(parsetree);
1630  address = DefineView((ViewStmt *) parsetree, queryString,
1631  pstmt->stmt_location, pstmt->stmt_len);
1632  EventTriggerCollectSimpleCommand(address, secondaryObject,
1633  parsetree);
1634  /* stashed internally */
1635  commandCollected = true;
1637  break;
1638 
1639  case T_CreateFunctionStmt: /* CREATE FUNCTION */
1640  address = CreateFunction(pstate, (CreateFunctionStmt *) parsetree);
1641  break;
1642 
1643  case T_AlterFunctionStmt: /* ALTER FUNCTION */
1644  address = AlterFunction(pstate, (AlterFunctionStmt *) parsetree);
1645  break;
1646 
1647  case T_RuleStmt: /* CREATE RULE */
1648  address = DefineRule((RuleStmt *) parsetree, queryString);
1649  break;
1650 
1651  case T_CreateSeqStmt:
1652  address = DefineSequence(pstate, (CreateSeqStmt *) parsetree);
1653  break;
1654 
1655  case T_AlterSeqStmt:
1656  address = AlterSequence(pstate, (AlterSeqStmt *) parsetree);
1657  break;
1658 
1659  case T_CreateTableAsStmt:
1660  address = ExecCreateTableAs(pstate, (CreateTableAsStmt *) parsetree,
1661  params, queryEnv, qc);
1662  break;
1663 
1664  case T_RefreshMatViewStmt:
1665 
1666  /*
1667  * REFRESH CONCURRENTLY executes some DDL commands internally.
1668  * Inhibit DDL command collection here to avoid those commands
1669  * from showing up in the deparsed command queue. The refresh
1670  * command itself is queued, which is enough.
1671  */
1673  PG_TRY();
1674  {
1675  address = ExecRefreshMatView((RefreshMatViewStmt *) parsetree,
1676  queryString, params, qc);
1677  }
1678  PG_FINALLY();
1679  {
1681  }
1682  PG_END_TRY();
1683  break;
1684 
1685  case T_CreateTrigStmt:
1686  address = CreateTrigger((CreateTrigStmt *) parsetree,
1687  queryString, InvalidOid, InvalidOid,
1689  InvalidOid, NULL, false, false);
1690  break;
1691 
1692  case T_CreatePLangStmt:
1693  address = CreateProceduralLanguage((CreatePLangStmt *) parsetree);
1694  break;
1695 
1696  case T_CreateDomainStmt:
1697  address = DefineDomain((CreateDomainStmt *) parsetree);
1698  break;
1699 
1701  address = CreateConversionCommand((CreateConversionStmt *) parsetree);
1702  break;
1703 
1704  case T_CreateCastStmt:
1705  address = CreateCast((CreateCastStmt *) parsetree);
1706  break;
1707 
1708  case T_CreateOpClassStmt:
1709  DefineOpClass((CreateOpClassStmt *) parsetree);
1710  /* command is stashed in DefineOpClass */
1711  commandCollected = true;
1712  break;
1713 
1714  case T_CreateOpFamilyStmt:
1715  address = DefineOpFamily((CreateOpFamilyStmt *) parsetree);
1716  break;
1717 
1718  case T_CreateTransformStmt:
1719  address = CreateTransform((CreateTransformStmt *) parsetree);
1720  break;
1721 
1722  case T_AlterOpFamilyStmt:
1723  AlterOpFamily((AlterOpFamilyStmt *) parsetree);
1724  /* commands are stashed in AlterOpFamily */
1725  commandCollected = true;
1726  break;
1727 
1729  address = AlterTSDictionary((AlterTSDictionaryStmt *) parsetree);
1730  break;
1731 
1734 
1735  /*
1736  * Commands are stashed in MakeConfigurationMapping and
1737  * DropConfigurationMapping, which are called from
1738  * AlterTSConfiguration
1739  */
1740  commandCollected = true;
1741  break;
1742 
1745  /* commands are stashed in AlterTableMoveAll */
1746  commandCollected = true;
1747  break;
1748 
1749  case T_DropStmt:
1750  ExecDropStmt((DropStmt *) parsetree, isTopLevel);
1751  /* no commands stashed for DROP */
1752  commandCollected = true;
1753  break;
1754 
1755  case T_RenameStmt:
1756  address = ExecRenameStmt((RenameStmt *) parsetree);
1757  break;
1758 
1760  address =
1762  &secondaryObject);
1763  break;
1764 
1766  address =
1768  &secondaryObject);
1769  break;
1770 
1771  case T_AlterOwnerStmt:
1772  address = ExecAlterOwnerStmt((AlterOwnerStmt *) parsetree);
1773  break;
1774 
1775  case T_AlterOperatorStmt:
1776  address = AlterOperator((AlterOperatorStmt *) parsetree);
1777  break;
1778 
1779  case T_AlterTypeStmt:
1780  address = AlterType((AlterTypeStmt *) parsetree);
1781  break;
1782 
1783  case T_CommentStmt:
1784  address = CommentObject((CommentStmt *) parsetree);
1785  break;
1786 
1787  case T_GrantStmt:
1788  ExecuteGrantStmt((GrantStmt *) parsetree);
1789  /* commands are stashed in ExecGrantStmt_oids */
1790  commandCollected = true;
1791  break;
1792 
1793  case T_DropOwnedStmt:
1794  DropOwnedObjects((DropOwnedStmt *) parsetree);
1795  /* no commands stashed for DROP */
1796  commandCollected = true;
1797  break;
1798 
1802  commandCollected = true;
1803  break;
1804 
1805  case T_CreatePolicyStmt: /* CREATE POLICY */
1806  address = CreatePolicy((CreatePolicyStmt *) parsetree);
1807  break;
1808 
1809  case T_AlterPolicyStmt: /* ALTER POLICY */
1810  address = AlterPolicy((AlterPolicyStmt *) parsetree);
1811  break;
1812 
1813  case T_SecLabelStmt:
1814  address = ExecSecLabelStmt((SecLabelStmt *) parsetree);
1815  break;
1816 
1817  case T_CreateAmStmt:
1818  address = CreateAccessMethod((CreateAmStmt *) parsetree);
1819  break;
1820 
1822  address = CreatePublication(pstate, (CreatePublicationStmt *) parsetree);
1823  break;
1824 
1826  AlterPublication(pstate, (AlterPublicationStmt *) parsetree);
1827 
1828  /*
1829  * AlterPublication calls EventTriggerCollectSimpleCommand
1830  * directly
1831  */
1832  commandCollected = true;
1833  break;
1834 
1836  address = CreateSubscription(pstate,
1837  (CreateSubscriptionStmt *) parsetree,
1838  isTopLevel);
1839  break;
1840 
1842  address = AlterSubscription(pstate,
1843  (AlterSubscriptionStmt *) parsetree,
1844  isTopLevel);
1845  break;
1846 
1848  DropSubscription((DropSubscriptionStmt *) parsetree, isTopLevel);
1849  /* no commands stashed for DROP */
1850  commandCollected = true;
1851  break;
1852 
1853  case T_CreateStatsStmt:
1854  {
1855  Oid relid;
1856  CreateStatsStmt *stmt = (CreateStatsStmt *) parsetree;
1857  RangeVar *rel = (RangeVar *) linitial(stmt->relations);
1858 
1859  if (!IsA(rel, RangeVar))
1860  ereport(ERROR,
1861  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1862  errmsg("only a single relation is allowed in CREATE STATISTICS")));
1863 
1864  /*
1865  * CREATE STATISTICS will influence future execution plans
1866  * but does not interfere with currently executing plans.
1867  * So it should be enough to take ShareUpdateExclusiveLock
1868  * on relation, conflicting with ANALYZE and other DDL
1869  * that sets statistical information, but not with normal
1870  * queries.
1871  *
1872  * XXX RangeVarCallbackOwnsRelation not needed here, to
1873  * keep the same behavior as before.
1874  */
1875  relid = RangeVarGetRelid(rel, ShareUpdateExclusiveLock, false);
1876 
1877  /* Run parse analysis ... */
1878  stmt = transformStatsStmt(relid, stmt, queryString);
1879 
1880  address = CreateStatistics(stmt);
1881  }
1882  break;
1883 
1884  case T_AlterStatsStmt:
1885  address = AlterStatistics((AlterStatsStmt *) parsetree);
1886  break;
1887 
1888  case T_AlterCollationStmt:
1889  address = AlterCollation((AlterCollationStmt *) parsetree);
1890  break;
1891 
1892  default:
1893  elog(ERROR, "unrecognized node type: %d",
1894  (int) nodeTag(parsetree));
1895  break;
1896  }
1897 
1898  /*
1899  * Remember the object so that ddl_command_end event triggers have
1900  * access to it.
1901  */
1902  if (!commandCollected)
1903  EventTriggerCollectSimpleCommand(address, secondaryObject,
1904  parsetree);
1905 
1906  if (isCompleteQuery)
1907  {
1908  EventTriggerSQLDrop(parsetree);
1909  EventTriggerDDLCommandEnd(parsetree);
1910  }
1911  }
1912  PG_FINALLY();
1913  {
1914  if (needCleanup)
1916  }
1917  PG_END_TRY();
1918 }
1919 
1920 /*
1921  * ProcessUtilityForAlterTable
1922  * Recursive entry from ALTER TABLE
1923  *
1924  * ALTER TABLE sometimes generates subcommands such as CREATE INDEX.
1925  * It calls this, not the main entry point ProcessUtility, to execute
1926  * such subcommands.
1927  *
1928  * stmt: the utility command to execute
1929  * context: opaque passthrough struct with the info we need
1930  *
1931  * It's caller's responsibility to do CommandCounterIncrement after
1932  * calling this, if needed.
1933  */
1934 void
1936 {
1937  PlannedStmt *wrapper;
1938 
1939  /*
1940  * For event triggers, we must "close" the current complex-command set,
1941  * and start a new one afterwards; this is needed to ensure the ordering
1942  * of command events is consistent with the way they were executed.
1943  */
1945 
1946  /* Create a suitable wrapper */
1947  wrapper = makeNode(PlannedStmt);
1948  wrapper->commandType = CMD_UTILITY;
1949  wrapper->canSetTag = false;
1950  wrapper->utilityStmt = stmt;
1951  wrapper->stmt_location = context->pstmt->stmt_location;
1952  wrapper->stmt_len = context->pstmt->stmt_len;
1953 
1954  ProcessUtility(wrapper,
1955  context->queryString,
1956  false,
1958  context->params,
1959  context->queryEnv,
1960  None_Receiver,
1961  NULL);
1962 
1965 }
1966 
1967 /*
1968  * Dispatch function for DropStmt
1969  */
1970 static void
1971 ExecDropStmt(DropStmt *stmt, bool isTopLevel)
1972 {
1973  switch (stmt->removeType)
1974  {
1975  case OBJECT_INDEX:
1976  if (stmt->concurrent)
1977  PreventInTransactionBlock(isTopLevel,
1978  "DROP INDEX CONCURRENTLY");
1979  /* fall through */
1980 
1981  case OBJECT_TABLE:
1982  case OBJECT_SEQUENCE:
1983  case OBJECT_VIEW:
1984  case OBJECT_MATVIEW:
1985  case OBJECT_FOREIGN_TABLE:
1986  RemoveRelations(stmt);
1987  break;
1988  default:
1989  RemoveObjects(stmt);
1990  break;
1991  }
1992 }
1993 
1994 
1995 /*
1996  * UtilityReturnsTuples
1997  * Return "true" if this utility statement will send output to the
1998  * destination.
1999  *
2000  * Generally, there should be a case here for each case in ProcessUtility
2001  * where "dest" is passed on.
2002  */
2003 bool
2005 {
2006  switch (nodeTag(parsetree))
2007  {
2008  case T_CallStmt:
2009  {
2010  CallStmt *stmt = (CallStmt *) parsetree;
2011 
2012  return (stmt->funcexpr->funcresulttype == RECORDOID);
2013  }
2014  case T_FetchStmt:
2015  {
2016  FetchStmt *stmt = (FetchStmt *) parsetree;
2017  Portal portal;
2018 
2019  if (stmt->ismove)
2020  return false;
2021  portal = GetPortalByName(stmt->portalname);
2022  if (!PortalIsValid(portal))
2023  return false; /* not our business to raise error */
2024  return portal->tupDesc ? true : false;
2025  }
2026 
2027  case T_ExecuteStmt:
2028  {
2029  ExecuteStmt *stmt = (ExecuteStmt *) parsetree;
2030  PreparedStatement *entry;
2031 
2032  entry = FetchPreparedStatement(stmt->name, false);
2033  if (!entry)
2034  return false; /* not our business to raise error */
2035  if (entry->plansource->resultDesc)
2036  return true;
2037  return false;
2038  }
2039 
2040  case T_ExplainStmt:
2041  return true;
2042 
2043  case T_VariableShowStmt:
2044  return true;
2045 
2046  default:
2047  return false;
2048  }
2049 }
2050 
2051 /*
2052  * UtilityTupleDescriptor
2053  * Fetch the actual output tuple descriptor for a utility statement
2054  * for which UtilityReturnsTuples() previously returned "true".
2055  *
2056  * The returned descriptor is created in (or copied into) the current memory
2057  * context.
2058  */
2059 TupleDesc
2061 {
2062  switch (nodeTag(parsetree))
2063  {
2064  case T_CallStmt:
2065  return CallStmtResultDesc((CallStmt *) parsetree);
2066 
2067  case T_FetchStmt:
2068  {
2069  FetchStmt *stmt = (FetchStmt *) parsetree;
2070  Portal portal;
2071 
2072  if (stmt->ismove)
2073  return NULL;
2074  portal = GetPortalByName(stmt->portalname);
2075  if (!PortalIsValid(portal))
2076  return NULL; /* not our business to raise error */
2077  return CreateTupleDescCopy(portal->tupDesc);
2078  }
2079 
2080  case T_ExecuteStmt:
2081  {
2082  ExecuteStmt *stmt = (ExecuteStmt *) parsetree;
2083  PreparedStatement *entry;
2084 
2085  entry = FetchPreparedStatement(stmt->name, false);
2086  if (!entry)
2087  return NULL; /* not our business to raise error */
2088  return FetchPreparedStatementResultDesc(entry);
2089  }
2090 
2091  case T_ExplainStmt:
2092  return ExplainResultDesc((ExplainStmt *) parsetree);
2093 
2094  case T_VariableShowStmt:
2095  {
2096  VariableShowStmt *n = (VariableShowStmt *) parsetree;
2097 
2098  return GetPGVariableResultDesc(n->name);
2099  }
2100 
2101  default:
2102  return NULL;
2103  }
2104 }
2105 
2106 
2107 /*
2108  * QueryReturnsTuples
2109  * Return "true" if this Query will send output to the destination.
2110  */
2111 #ifdef NOT_USED
2112 bool
2113 QueryReturnsTuples(Query *parsetree)
2114 {
2115  switch (parsetree->commandType)
2116  {
2117  case CMD_SELECT:
2118  /* returns tuples */
2119  return true;
2120  case CMD_INSERT:
2121  case CMD_UPDATE:
2122  case CMD_DELETE:
2123  /* the forms with RETURNING return tuples */
2124  if (parsetree->returningList)
2125  return true;
2126  break;
2127  case CMD_UTILITY:
2128  return UtilityReturnsTuples(parsetree->utilityStmt);
2129  case CMD_UNKNOWN:
2130  case CMD_NOTHING:
2131  /* probably shouldn't get here */
2132  break;
2133  }
2134  return false; /* default */
2135 }
2136 #endif
2137 
2138 
2139 /*
2140  * UtilityContainsQuery
2141  * Return the contained Query, or NULL if there is none
2142  *
2143  * Certain utility statements, such as EXPLAIN, contain a plannable Query.
2144  * This function encapsulates knowledge of exactly which ones do.
2145  * We assume it is invoked only on already-parse-analyzed statements
2146  * (else the contained parsetree isn't a Query yet).
2147  *
2148  * In some cases (currently, only EXPLAIN of CREATE TABLE AS/SELECT INTO and
2149  * CREATE MATERIALIZED VIEW), potentially Query-containing utility statements
2150  * can be nested. This function will drill down to a non-utility Query, or
2151  * return NULL if none.
2152  */
2153 Query *
2155 {
2156  Query *qry;
2157 
2158  switch (nodeTag(parsetree))
2159  {
2160  case T_DeclareCursorStmt:
2161  qry = castNode(Query, ((DeclareCursorStmt *) parsetree)->query);
2162  if (qry->commandType == CMD_UTILITY)
2163  return UtilityContainsQuery(qry->utilityStmt);
2164  return qry;
2165 
2166  case T_ExplainStmt:
2167  qry = castNode(Query, ((ExplainStmt *) parsetree)->query);
2168  if (qry->commandType == CMD_UTILITY)
2169  return UtilityContainsQuery(qry->utilityStmt);
2170  return qry;
2171 
2172  case T_CreateTableAsStmt:
2173  qry = castNode(Query, ((CreateTableAsStmt *) parsetree)->query);
2174  if (qry->commandType == CMD_UTILITY)
2175  return UtilityContainsQuery(qry->utilityStmt);
2176  return qry;
2177 
2178  default:
2179  return NULL;
2180  }
2181 }
2182 
2183 
2184 /*
2185  * AlterObjectTypeCommandTag
2186  * helper function for CreateCommandTag
2187  *
2188  * This covers most cases where ALTER is used with an ObjectType enum.
2189  */
2190 static CommandTag
2192 {
2193  CommandTag tag;
2194 
2195  switch (objtype)
2196  {
2197  case OBJECT_AGGREGATE:
2198  tag = CMDTAG_ALTER_AGGREGATE;
2199  break;
2200  case OBJECT_ATTRIBUTE:
2201  tag = CMDTAG_ALTER_TYPE;
2202  break;
2203  case OBJECT_CAST:
2204  tag = CMDTAG_ALTER_CAST;
2205  break;
2206  case OBJECT_COLLATION:
2207  tag = CMDTAG_ALTER_COLLATION;
2208  break;
2209  case OBJECT_COLUMN:
2210  tag = CMDTAG_ALTER_TABLE;
2211  break;
2212  case OBJECT_CONVERSION:
2213  tag = CMDTAG_ALTER_CONVERSION;
2214  break;
2215  case OBJECT_DATABASE:
2216  tag = CMDTAG_ALTER_DATABASE;
2217  break;
2218  case OBJECT_DOMAIN:
2219  case OBJECT_DOMCONSTRAINT:
2220  tag = CMDTAG_ALTER_DOMAIN;
2221  break;
2222  case OBJECT_EXTENSION:
2223  tag = CMDTAG_ALTER_EXTENSION;
2224  break;
2225  case OBJECT_FDW:
2226  tag = CMDTAG_ALTER_FOREIGN_DATA_WRAPPER;
2227  break;
2228  case OBJECT_FOREIGN_SERVER:
2229  tag = CMDTAG_ALTER_SERVER;
2230  break;
2231  case OBJECT_FOREIGN_TABLE:
2232  tag = CMDTAG_ALTER_FOREIGN_TABLE;
2233  break;
2234  case OBJECT_FUNCTION:
2235  tag = CMDTAG_ALTER_FUNCTION;
2236  break;
2237  case OBJECT_INDEX:
2238  tag = CMDTAG_ALTER_INDEX;
2239  break;
2240  case OBJECT_LANGUAGE:
2241  tag = CMDTAG_ALTER_LANGUAGE;
2242  break;
2243  case OBJECT_LARGEOBJECT:
2244  tag = CMDTAG_ALTER_LARGE_OBJECT;
2245  break;
2246  case OBJECT_OPCLASS:
2247  tag = CMDTAG_ALTER_OPERATOR_CLASS;
2248  break;
2249  case OBJECT_OPERATOR:
2250  tag = CMDTAG_ALTER_OPERATOR;
2251  break;
2252  case OBJECT_OPFAMILY:
2253  tag = CMDTAG_ALTER_OPERATOR_FAMILY;
2254  break;
2255  case OBJECT_POLICY:
2256  tag = CMDTAG_ALTER_POLICY;
2257  break;
2258  case OBJECT_PROCEDURE:
2259  tag = CMDTAG_ALTER_PROCEDURE;
2260  break;
2261  case OBJECT_ROLE:
2262  tag = CMDTAG_ALTER_ROLE;
2263  break;
2264  case OBJECT_ROUTINE:
2265  tag = CMDTAG_ALTER_ROUTINE;
2266  break;
2267  case OBJECT_RULE:
2268  tag = CMDTAG_ALTER_RULE;
2269  break;
2270  case OBJECT_SCHEMA:
2271  tag = CMDTAG_ALTER_SCHEMA;
2272  break;
2273  case OBJECT_SEQUENCE:
2274  tag = CMDTAG_ALTER_SEQUENCE;
2275  break;
2276  case OBJECT_TABLE:
2277  case OBJECT_TABCONSTRAINT:
2278  tag = CMDTAG_ALTER_TABLE;
2279  break;
2280  case OBJECT_TABLESPACE:
2281  tag = CMDTAG_ALTER_TABLESPACE;
2282  break;
2283  case OBJECT_TRIGGER:
2284  tag = CMDTAG_ALTER_TRIGGER;
2285  break;
2286  case OBJECT_EVENT_TRIGGER:
2287  tag = CMDTAG_ALTER_EVENT_TRIGGER;
2288  break;
2290  tag = CMDTAG_ALTER_TEXT_SEARCH_CONFIGURATION;
2291  break;
2292  case OBJECT_TSDICTIONARY:
2293  tag = CMDTAG_ALTER_TEXT_SEARCH_DICTIONARY;
2294  break;
2295  case OBJECT_TSPARSER:
2296  tag = CMDTAG_ALTER_TEXT_SEARCH_PARSER;
2297  break;
2298  case OBJECT_TSTEMPLATE:
2299  tag = CMDTAG_ALTER_TEXT_SEARCH_TEMPLATE;
2300  break;
2301  case OBJECT_TYPE:
2302  tag = CMDTAG_ALTER_TYPE;
2303  break;
2304  case OBJECT_VIEW:
2305  tag = CMDTAG_ALTER_VIEW;
2306  break;
2307  case OBJECT_MATVIEW:
2308  tag = CMDTAG_ALTER_MATERIALIZED_VIEW;
2309  break;
2310  case OBJECT_PUBLICATION:
2311  tag = CMDTAG_ALTER_PUBLICATION;
2312  break;
2313  case OBJECT_SUBSCRIPTION:
2314  tag = CMDTAG_ALTER_SUBSCRIPTION;
2315  break;
2316  case OBJECT_STATISTIC_EXT:
2317  tag = CMDTAG_ALTER_STATISTICS;
2318  break;
2319  default:
2320  tag = CMDTAG_UNKNOWN;
2321  break;
2322  }
2323 
2324  return tag;
2325 }
2326 
2327 /*
2328  * CreateCommandTag
2329  * utility to get a CommandTag for the command operation,
2330  * given either a raw (un-analyzed) parsetree, an analyzed Query,
2331  * or a PlannedStmt.
2332  *
2333  * This must handle all command types, but since the vast majority
2334  * of 'em are utility commands, it seems sensible to keep it here.
2335  */
2336 CommandTag
2338 {
2339  CommandTag tag;
2340 
2341  switch (nodeTag(parsetree))
2342  {
2343  /* recurse if we're given a RawStmt */
2344  case T_RawStmt:
2345  tag = CreateCommandTag(((RawStmt *) parsetree)->stmt);
2346  break;
2347 
2348  /* raw plannable queries */
2349  case T_InsertStmt:
2350  tag = CMDTAG_INSERT;
2351  break;
2352 
2353  case T_DeleteStmt:
2354  tag = CMDTAG_DELETE;
2355  break;
2356 
2357  case T_UpdateStmt:
2358  tag = CMDTAG_UPDATE;
2359  break;
2360 
2361  case T_SelectStmt:
2362  tag = CMDTAG_SELECT;
2363  break;
2364 
2365  case T_PLAssignStmt:
2366  tag = CMDTAG_SELECT;
2367  break;
2368 
2369  /* utility statements --- same whether raw or cooked */
2370  case T_TransactionStmt:
2371  {
2372  TransactionStmt *stmt = (TransactionStmt *) parsetree;
2373 
2374  switch (stmt->kind)
2375  {
2376  case TRANS_STMT_BEGIN:
2377  tag = CMDTAG_BEGIN;
2378  break;
2379 
2380  case TRANS_STMT_START:
2381  tag = CMDTAG_START_TRANSACTION;
2382  break;
2383 
2384  case TRANS_STMT_COMMIT:
2385  tag = CMDTAG_COMMIT;
2386  break;
2387 
2388  case TRANS_STMT_ROLLBACK:
2390  tag = CMDTAG_ROLLBACK;
2391  break;
2392 
2393  case TRANS_STMT_SAVEPOINT:
2394  tag = CMDTAG_SAVEPOINT;
2395  break;
2396 
2397  case TRANS_STMT_RELEASE:
2398  tag = CMDTAG_RELEASE;
2399  break;
2400 
2401  case TRANS_STMT_PREPARE:
2402  tag = CMDTAG_PREPARE_TRANSACTION;
2403  break;
2404 
2406  tag = CMDTAG_COMMIT_PREPARED;
2407  break;
2408 
2410  tag = CMDTAG_ROLLBACK_PREPARED;
2411  break;
2412 
2413  default:
2414  tag = CMDTAG_UNKNOWN;
2415  break;
2416  }
2417  }
2418  break;
2419 
2420  case T_DeclareCursorStmt:
2421  tag = CMDTAG_DECLARE_CURSOR;
2422  break;
2423 
2424  case T_ClosePortalStmt:
2425  {
2426  ClosePortalStmt *stmt = (ClosePortalStmt *) parsetree;
2427 
2428  if (stmt->portalname == NULL)
2429  tag = CMDTAG_CLOSE_CURSOR_ALL;
2430  else
2431  tag = CMDTAG_CLOSE_CURSOR;
2432  }
2433  break;
2434 
2435  case T_FetchStmt:
2436  {
2437  FetchStmt *stmt = (FetchStmt *) parsetree;
2438 
2439  tag = (stmt->ismove) ? CMDTAG_MOVE : CMDTAG_FETCH;
2440  }
2441  break;
2442 
2443  case T_CreateDomainStmt:
2444  tag = CMDTAG_CREATE_DOMAIN;
2445  break;
2446 
2447  case T_CreateSchemaStmt:
2448  tag = CMDTAG_CREATE_SCHEMA;
2449  break;
2450 
2451  case T_CreateStmt:
2452  tag = CMDTAG_CREATE_TABLE;
2453  break;
2454 
2456  tag = CMDTAG_CREATE_TABLESPACE;
2457  break;
2458 
2459  case T_DropTableSpaceStmt:
2460  tag = CMDTAG_DROP_TABLESPACE;
2461  break;
2462 
2464  tag = CMDTAG_ALTER_TABLESPACE;
2465  break;
2466 
2467  case T_CreateExtensionStmt:
2468  tag = CMDTAG_CREATE_EXTENSION;
2469  break;
2470 
2471  case T_AlterExtensionStmt:
2472  tag = CMDTAG_ALTER_EXTENSION;
2473  break;
2474 
2476  tag = CMDTAG_ALTER_EXTENSION;
2477  break;
2478 
2479  case T_CreateFdwStmt:
2480  tag = CMDTAG_CREATE_FOREIGN_DATA_WRAPPER;
2481  break;
2482 
2483  case T_AlterFdwStmt:
2484  tag = CMDTAG_ALTER_FOREIGN_DATA_WRAPPER;
2485  break;
2486 
2488  tag = CMDTAG_CREATE_SERVER;
2489  break;
2490 
2492  tag = CMDTAG_ALTER_SERVER;
2493  break;
2494 
2496  tag = CMDTAG_CREATE_USER_MAPPING;
2497  break;
2498 
2500  tag = CMDTAG_ALTER_USER_MAPPING;
2501  break;
2502 
2503  case T_DropUserMappingStmt:
2504  tag = CMDTAG_DROP_USER_MAPPING;
2505  break;
2506 
2508  tag = CMDTAG_CREATE_FOREIGN_TABLE;
2509  break;
2510 
2512  tag = CMDTAG_IMPORT_FOREIGN_SCHEMA;
2513  break;
2514 
2515  case T_DropStmt:
2516  switch (((DropStmt *) parsetree)->removeType)
2517  {
2518  case OBJECT_TABLE:
2519  tag = CMDTAG_DROP_TABLE;
2520  break;
2521  case OBJECT_SEQUENCE:
2522  tag = CMDTAG_DROP_SEQUENCE;
2523  break;
2524  case OBJECT_VIEW:
2525  tag = CMDTAG_DROP_VIEW;
2526  break;
2527  case OBJECT_MATVIEW:
2528  tag = CMDTAG_DROP_MATERIALIZED_VIEW;
2529  break;
2530  case OBJECT_INDEX:
2531  tag = CMDTAG_DROP_INDEX;
2532  break;
2533  case OBJECT_TYPE:
2534  tag = CMDTAG_DROP_TYPE;
2535  break;
2536  case OBJECT_DOMAIN:
2537  tag = CMDTAG_DROP_DOMAIN;
2538  break;
2539  case OBJECT_COLLATION:
2540  tag = CMDTAG_DROP_COLLATION;
2541  break;
2542  case OBJECT_CONVERSION:
2543  tag = CMDTAG_DROP_CONVERSION;
2544  break;
2545  case OBJECT_SCHEMA:
2546  tag = CMDTAG_DROP_SCHEMA;
2547  break;
2548  case OBJECT_TSPARSER:
2549  tag = CMDTAG_DROP_TEXT_SEARCH_PARSER;
2550  break;
2551  case OBJECT_TSDICTIONARY:
2552  tag = CMDTAG_DROP_TEXT_SEARCH_DICTIONARY;
2553  break;
2554  case OBJECT_TSTEMPLATE:
2555  tag = CMDTAG_DROP_TEXT_SEARCH_TEMPLATE;
2556  break;
2558  tag = CMDTAG_DROP_TEXT_SEARCH_CONFIGURATION;
2559  break;
2560  case OBJECT_FOREIGN_TABLE:
2561  tag = CMDTAG_DROP_FOREIGN_TABLE;
2562  break;
2563  case OBJECT_EXTENSION:
2564  tag = CMDTAG_DROP_EXTENSION;
2565  break;
2566  case OBJECT_FUNCTION:
2567  tag = CMDTAG_DROP_FUNCTION;
2568  break;
2569  case OBJECT_PROCEDURE:
2570  tag = CMDTAG_DROP_PROCEDURE;
2571  break;
2572  case OBJECT_ROUTINE:
2573  tag = CMDTAG_DROP_ROUTINE;
2574  break;
2575  case OBJECT_AGGREGATE:
2576  tag = CMDTAG_DROP_AGGREGATE;
2577  break;
2578  case OBJECT_OPERATOR:
2579  tag = CMDTAG_DROP_OPERATOR;
2580  break;
2581  case OBJECT_LANGUAGE:
2582  tag = CMDTAG_DROP_LANGUAGE;
2583  break;
2584  case OBJECT_CAST:
2585  tag = CMDTAG_DROP_CAST;
2586  break;
2587  case OBJECT_TRIGGER:
2588  tag = CMDTAG_DROP_TRIGGER;
2589  break;
2590  case OBJECT_EVENT_TRIGGER:
2591  tag = CMDTAG_DROP_EVENT_TRIGGER;
2592  break;
2593  case OBJECT_RULE:
2594  tag = CMDTAG_DROP_RULE;
2595  break;
2596  case OBJECT_FDW:
2597  tag = CMDTAG_DROP_FOREIGN_DATA_WRAPPER;
2598  break;
2599  case OBJECT_FOREIGN_SERVER:
2600  tag = CMDTAG_DROP_SERVER;
2601  break;
2602  case OBJECT_OPCLASS:
2603  tag = CMDTAG_DROP_OPERATOR_CLASS;
2604  break;
2605  case OBJECT_OPFAMILY:
2606  tag = CMDTAG_DROP_OPERATOR_FAMILY;
2607  break;
2608  case OBJECT_POLICY:
2609  tag = CMDTAG_DROP_POLICY;
2610  break;
2611  case OBJECT_TRANSFORM:
2612  tag = CMDTAG_DROP_TRANSFORM;
2613  break;
2614  case OBJECT_ACCESS_METHOD:
2615  tag = CMDTAG_DROP_ACCESS_METHOD;
2616  break;
2617  case OBJECT_PUBLICATION:
2618  tag = CMDTAG_DROP_PUBLICATION;
2619  break;
2620  case OBJECT_STATISTIC_EXT:
2621  tag = CMDTAG_DROP_STATISTICS;
2622  break;
2623  default:
2624  tag = CMDTAG_UNKNOWN;
2625  }
2626  break;
2627 
2628  case T_TruncateStmt:
2629  tag = CMDTAG_TRUNCATE_TABLE;
2630  break;
2631 
2632  case T_CommentStmt:
2633  tag = CMDTAG_COMMENT;
2634  break;
2635 
2636  case T_SecLabelStmt:
2637  tag = CMDTAG_SECURITY_LABEL;
2638  break;
2639 
2640  case T_CopyStmt:
2641  tag = CMDTAG_COPY;
2642  break;
2643 
2644  case T_RenameStmt:
2645 
2646  /*
2647  * When the column is renamed, the command tag is created from its
2648  * relation type
2649  */
2650  tag = AlterObjectTypeCommandTag(((RenameStmt *) parsetree)->renameType == OBJECT_COLUMN ?
2651  ((RenameStmt *) parsetree)->relationType :
2652  ((RenameStmt *) parsetree)->renameType);
2653  break;
2654 
2656  tag = AlterObjectTypeCommandTag(((AlterObjectDependsStmt *) parsetree)->objectType);
2657  break;
2658 
2660  tag = AlterObjectTypeCommandTag(((AlterObjectSchemaStmt *) parsetree)->objectType);
2661  break;
2662 
2663  case T_AlterOwnerStmt:
2664  tag = AlterObjectTypeCommandTag(((AlterOwnerStmt *) parsetree)->objectType);
2665  break;
2666 
2668  tag = AlterObjectTypeCommandTag(((AlterTableMoveAllStmt *) parsetree)->objtype);
2669  break;
2670 
2671  case T_AlterTableStmt:
2672  tag = AlterObjectTypeCommandTag(((AlterTableStmt *) parsetree)->objtype);
2673  break;
2674 
2675  case T_AlterDomainStmt:
2676  tag = CMDTAG_ALTER_DOMAIN;
2677  break;
2678 
2679  case T_AlterFunctionStmt:
2680  switch (((AlterFunctionStmt *) parsetree)->objtype)
2681  {
2682  case OBJECT_FUNCTION:
2683  tag = CMDTAG_ALTER_FUNCTION;
2684  break;
2685  case OBJECT_PROCEDURE:
2686  tag = CMDTAG_ALTER_PROCEDURE;
2687  break;
2688  case OBJECT_ROUTINE:
2689  tag = CMDTAG_ALTER_ROUTINE;
2690  break;
2691  default:
2692  tag = CMDTAG_UNKNOWN;
2693  }
2694  break;
2695 
2696  case T_GrantStmt:
2697  {
2698  GrantStmt *stmt = (GrantStmt *) parsetree;
2699 
2700  tag = (stmt->is_grant) ? CMDTAG_GRANT : CMDTAG_REVOKE;
2701  }
2702  break;
2703 
2704  case T_GrantRoleStmt:
2705  {
2706  GrantRoleStmt *stmt = (GrantRoleStmt *) parsetree;
2707 
2708  tag = (stmt->is_grant) ? CMDTAG_GRANT_ROLE : CMDTAG_REVOKE_ROLE;
2709  }
2710  break;
2711 
2713  tag = CMDTAG_ALTER_DEFAULT_PRIVILEGES;
2714  break;
2715 
2716  case T_DefineStmt:
2717  switch (((DefineStmt *) parsetree)->kind)
2718  {
2719  case OBJECT_AGGREGATE:
2720  tag = CMDTAG_CREATE_AGGREGATE;
2721  break;
2722  case OBJECT_OPERATOR:
2723  tag = CMDTAG_CREATE_OPERATOR;
2724  break;
2725  case OBJECT_TYPE:
2726  tag = CMDTAG_CREATE_TYPE;
2727  break;
2728  case OBJECT_TSPARSER:
2729  tag = CMDTAG_CREATE_TEXT_SEARCH_PARSER;
2730  break;
2731  case OBJECT_TSDICTIONARY:
2732  tag = CMDTAG_CREATE_TEXT_SEARCH_DICTIONARY;
2733  break;
2734  case OBJECT_TSTEMPLATE:
2735  tag = CMDTAG_CREATE_TEXT_SEARCH_TEMPLATE;
2736  break;
2738  tag = CMDTAG_CREATE_TEXT_SEARCH_CONFIGURATION;
2739  break;
2740  case OBJECT_COLLATION:
2741  tag = CMDTAG_CREATE_COLLATION;
2742  break;
2743  case OBJECT_ACCESS_METHOD:
2744  tag = CMDTAG_CREATE_ACCESS_METHOD;
2745  break;
2746  default:
2747  tag = CMDTAG_UNKNOWN;
2748  }
2749  break;
2750 
2751  case T_CompositeTypeStmt:
2752  tag = CMDTAG_CREATE_TYPE;
2753  break;
2754 
2755  case T_CreateEnumStmt:
2756  tag = CMDTAG_CREATE_TYPE;
2757  break;
2758 
2759  case T_CreateRangeStmt:
2760  tag = CMDTAG_CREATE_TYPE;
2761  break;
2762 
2763  case T_AlterEnumStmt:
2764  tag = CMDTAG_ALTER_TYPE;
2765  break;
2766 
2767  case T_ViewStmt:
2768  tag = CMDTAG_CREATE_VIEW;
2769  break;
2770 
2771  case T_CreateFunctionStmt:
2772  if (((CreateFunctionStmt *) parsetree)->is_procedure)
2773  tag = CMDTAG_CREATE_PROCEDURE;
2774  else
2775  tag = CMDTAG_CREATE_FUNCTION;
2776  break;
2777 
2778  case T_IndexStmt:
2779  tag = CMDTAG_CREATE_INDEX;
2780  break;
2781 
2782  case T_RuleStmt:
2783  tag = CMDTAG_CREATE_RULE;
2784  break;
2785 
2786  case T_CreateSeqStmt:
2787  tag = CMDTAG_CREATE_SEQUENCE;
2788  break;
2789 
2790  case T_AlterSeqStmt:
2791  tag = CMDTAG_ALTER_SEQUENCE;
2792  break;
2793 
2794  case T_DoStmt:
2795  tag = CMDTAG_DO;
2796  break;
2797 
2798  case T_CreatedbStmt:
2799  tag = CMDTAG_CREATE_DATABASE;
2800  break;
2801 
2802  case T_AlterDatabaseStmt:
2803  tag = CMDTAG_ALTER_DATABASE;
2804  break;
2805 
2807  tag = CMDTAG_ALTER_DATABASE;
2808  break;
2809 
2810  case T_DropdbStmt:
2811  tag = CMDTAG_DROP_DATABASE;
2812  break;
2813 
2814  case T_NotifyStmt:
2815  tag = CMDTAG_NOTIFY;
2816  break;
2817 
2818  case T_ListenStmt:
2819  tag = CMDTAG_LISTEN;
2820  break;
2821 
2822  case T_UnlistenStmt:
2823  tag = CMDTAG_UNLISTEN;
2824  break;
2825 
2826  case T_LoadStmt:
2827  tag = CMDTAG_LOAD;
2828  break;
2829 
2830  case T_CallStmt:
2831  tag = CMDTAG_CALL;
2832  break;
2833 
2834  case T_ClusterStmt:
2835  tag = CMDTAG_CLUSTER;
2836  break;
2837 
2838  case T_VacuumStmt:
2839  if (((VacuumStmt *) parsetree)->is_vacuumcmd)
2840  tag = CMDTAG_VACUUM;
2841  else
2842  tag = CMDTAG_ANALYZE;
2843  break;
2844 
2845  case T_ExplainStmt:
2846  tag = CMDTAG_EXPLAIN;
2847  break;
2848 
2849  case T_CreateTableAsStmt:
2850  switch (((CreateTableAsStmt *) parsetree)->objtype)
2851  {
2852  case OBJECT_TABLE:
2853  if (((CreateTableAsStmt *) parsetree)->is_select_into)
2854  tag = CMDTAG_SELECT_INTO;
2855  else
2856  tag = CMDTAG_CREATE_TABLE_AS;
2857  break;
2858  case OBJECT_MATVIEW:
2859  tag = CMDTAG_CREATE_MATERIALIZED_VIEW;
2860  break;
2861  default:
2862  tag = CMDTAG_UNKNOWN;
2863  }
2864  break;
2865 
2866  case T_RefreshMatViewStmt:
2867  tag = CMDTAG_REFRESH_MATERIALIZED_VIEW;
2868  break;
2869 
2870  case T_AlterSystemStmt:
2871  tag = CMDTAG_ALTER_SYSTEM;
2872  break;
2873 
2874  case T_VariableSetStmt:
2875  switch (((VariableSetStmt *) parsetree)->kind)
2876  {
2877  case VAR_SET_VALUE:
2878  case VAR_SET_CURRENT:
2879  case VAR_SET_DEFAULT:
2880  case VAR_SET_MULTI:
2881  tag = CMDTAG_SET;
2882  break;
2883  case VAR_RESET:
2884  case VAR_RESET_ALL:
2885  tag = CMDTAG_RESET;
2886  break;
2887  default:
2888  tag = CMDTAG_UNKNOWN;
2889  }
2890  break;
2891 
2892  case T_VariableShowStmt:
2893  tag = CMDTAG_SHOW;
2894  break;
2895 
2896  case T_DiscardStmt:
2897  switch (((DiscardStmt *) parsetree)->target)
2898  {
2899  case DISCARD_ALL:
2900  tag = CMDTAG_DISCARD_ALL;
2901  break;
2902  case DISCARD_PLANS:
2903  tag = CMDTAG_DISCARD_PLANS;
2904  break;
2905  case DISCARD_TEMP:
2906  tag = CMDTAG_DISCARD_TEMP;
2907  break;
2908  case DISCARD_SEQUENCES:
2909  tag = CMDTAG_DISCARD_SEQUENCES;
2910  break;
2911  default:
2912  tag = CMDTAG_UNKNOWN;
2913  }
2914  break;
2915 
2916  case T_CreateTransformStmt:
2917  tag = CMDTAG_CREATE_TRANSFORM;
2918  break;
2919 
2920  case T_CreateTrigStmt:
2921  tag = CMDTAG_CREATE_TRIGGER;
2922  break;
2923 
2924  case T_CreateEventTrigStmt:
2925  tag = CMDTAG_CREATE_EVENT_TRIGGER;
2926  break;
2927 
2928  case T_AlterEventTrigStmt:
2929  tag = CMDTAG_ALTER_EVENT_TRIGGER;
2930  break;
2931 
2932  case T_CreatePLangStmt:
2933  tag = CMDTAG_CREATE_LANGUAGE;
2934  break;
2935 
2936  case T_CreateRoleStmt:
2937  tag = CMDTAG_CREATE_ROLE;
2938  break;
2939 
2940  case T_AlterRoleStmt:
2941  tag = CMDTAG_ALTER_ROLE;
2942  break;
2943 
2944  case T_AlterRoleSetStmt:
2945  tag = CMDTAG_ALTER_ROLE;
2946  break;
2947 
2948  case T_DropRoleStmt:
2949  tag = CMDTAG_DROP_ROLE;
2950  break;
2951 
2952  case T_DropOwnedStmt:
2953  tag = CMDTAG_DROP_OWNED;
2954  break;
2955 
2956  case T_ReassignOwnedStmt:
2957  tag = CMDTAG_REASSIGN_OWNED;
2958  break;
2959 
2960  case T_LockStmt:
2961  tag = CMDTAG_LOCK_TABLE;
2962  break;
2963 
2964  case T_ConstraintsSetStmt:
2965  tag = CMDTAG_SET_CONSTRAINTS;
2966  break;
2967 
2968  case T_CheckPointStmt:
2969  tag = CMDTAG_CHECKPOINT;
2970  break;
2971 
2972  case T_ReindexStmt:
2973  tag = CMDTAG_REINDEX;
2974  break;
2975 
2977  tag = CMDTAG_CREATE_CONVERSION;
2978  break;
2979 
2980  case T_CreateCastStmt:
2981  tag = CMDTAG_CREATE_CAST;
2982  break;
2983 
2984  case T_CreateOpClassStmt:
2985  tag = CMDTAG_CREATE_OPERATOR_CLASS;
2986  break;
2987 
2988  case T_CreateOpFamilyStmt:
2989  tag = CMDTAG_CREATE_OPERATOR_FAMILY;
2990  break;
2991 
2992  case T_AlterOpFamilyStmt:
2993  tag = CMDTAG_ALTER_OPERATOR_FAMILY;
2994  break;
2995 
2996  case T_AlterOperatorStmt:
2997  tag = CMDTAG_ALTER_OPERATOR;
2998  break;
2999 
3000  case T_AlterTypeStmt:
3001  tag = CMDTAG_ALTER_TYPE;
3002  break;
3003 
3005  tag = CMDTAG_ALTER_TEXT_SEARCH_DICTIONARY;
3006  break;
3007 
3009  tag = CMDTAG_ALTER_TEXT_SEARCH_CONFIGURATION;
3010  break;
3011 
3012  case T_CreatePolicyStmt:
3013  tag = CMDTAG_CREATE_POLICY;
3014  break;
3015 
3016  case T_AlterPolicyStmt:
3017  tag = CMDTAG_ALTER_POLICY;
3018  break;
3019 
3020  case T_CreateAmStmt:
3021  tag = CMDTAG_CREATE_ACCESS_METHOD;
3022  break;
3023 
3025  tag = CMDTAG_CREATE_PUBLICATION;
3026  break;
3027 
3029  tag = CMDTAG_ALTER_PUBLICATION;
3030  break;
3031 
3033  tag = CMDTAG_CREATE_SUBSCRIPTION;
3034  break;
3035 
3037  tag = CMDTAG_ALTER_SUBSCRIPTION;
3038  break;
3039 
3041  tag = CMDTAG_DROP_SUBSCRIPTION;
3042  break;
3043 
3044  case T_AlterCollationStmt:
3045  tag = CMDTAG_ALTER_COLLATION;
3046  break;
3047 
3048  case T_PrepareStmt:
3049  tag = CMDTAG_PREPARE;
3050  break;
3051 
3052  case T_ExecuteStmt:
3053  tag = CMDTAG_EXECUTE;
3054  break;
3055 
3056  case T_CreateStatsStmt:
3057  tag = CMDTAG_CREATE_STATISTICS;
3058  break;
3059 
3060  case T_AlterStatsStmt:
3061  tag = CMDTAG_ALTER_STATISTICS;
3062  break;
3063 
3064  case T_DeallocateStmt:
3065  {
3066  DeallocateStmt *stmt = (DeallocateStmt *) parsetree;
3067 
3068  if (stmt->name == NULL)
3069  tag = CMDTAG_DEALLOCATE_ALL;
3070  else
3071  tag = CMDTAG_DEALLOCATE;
3072  }
3073  break;
3074 
3075  /* already-planned queries */
3076  case T_PlannedStmt:
3077  {
3078  PlannedStmt *stmt = (PlannedStmt *) parsetree;
3079 
3080  switch (stmt->commandType)
3081  {
3082  case CMD_SELECT:
3083 
3084  /*
3085  * We take a little extra care here so that the result
3086  * will be useful for complaints about read-only
3087  * statements
3088  */
3089  if (stmt->rowMarks != NIL)
3090  {
3091  /* not 100% but probably close enough */
3092  switch (((PlanRowMark *) linitial(stmt->rowMarks))->strength)
3093  {
3094  case LCS_FORKEYSHARE:
3095  tag = CMDTAG_SELECT_FOR_KEY_SHARE;
3096  break;
3097  case LCS_FORSHARE:
3098  tag = CMDTAG_SELECT_FOR_SHARE;
3099  break;
3100  case LCS_FORNOKEYUPDATE:
3101  tag = CMDTAG_SELECT_FOR_NO_KEY_UPDATE;
3102  break;
3103  case LCS_FORUPDATE:
3104  tag = CMDTAG_SELECT_FOR_UPDATE;
3105  break;
3106  default:
3107  tag = CMDTAG_SELECT;
3108  break;
3109  }
3110  }
3111  else
3112  tag = CMDTAG_SELECT;
3113  break;
3114  case CMD_UPDATE:
3115  tag = CMDTAG_UPDATE;
3116  break;
3117  case CMD_INSERT:
3118  tag = CMDTAG_INSERT;
3119  break;
3120  case CMD_DELETE:
3121  tag = CMDTAG_DELETE;
3122  break;
3123  case CMD_UTILITY:
3124  tag = CreateCommandTag(stmt->utilityStmt);
3125  break;
3126  default:
3127  elog(WARNING, "unrecognized commandType: %d",
3128  (int) stmt->commandType);
3129  tag = CMDTAG_UNKNOWN;
3130  break;
3131  }
3132  }
3133  break;
3134 
3135  /* parsed-and-rewritten-but-not-planned queries */
3136  case T_Query:
3137  {
3138  Query *stmt = (Query *) parsetree;
3139 
3140  switch (stmt->commandType)
3141  {
3142  case CMD_SELECT:
3143 
3144  /*
3145  * We take a little extra care here so that the result
3146  * will be useful for complaints about read-only
3147  * statements
3148  */
3149  if (stmt->rowMarks != NIL)
3150  {
3151  /* not 100% but probably close enough */
3152  switch (((RowMarkClause *) linitial(stmt->rowMarks))->strength)
3153  {
3154  case LCS_FORKEYSHARE:
3155  tag = CMDTAG_SELECT_FOR_KEY_SHARE;
3156  break;
3157  case LCS_FORSHARE:
3158  tag = CMDTAG_SELECT_FOR_SHARE;
3159  break;
3160  case LCS_FORNOKEYUPDATE:
3161  tag = CMDTAG_SELECT_FOR_NO_KEY_UPDATE;
3162  break;
3163  case LCS_FORUPDATE:
3164  tag = CMDTAG_SELECT_FOR_UPDATE;
3165  break;
3166  default:
3167  tag = CMDTAG_UNKNOWN;
3168  break;
3169  }
3170  }
3171  else
3172  tag = CMDTAG_SELECT;
3173  break;
3174  case CMD_UPDATE:
3175  tag = CMDTAG_UPDATE;
3176  break;
3177  case CMD_INSERT:
3178  tag = CMDTAG_INSERT;
3179  break;
3180  case CMD_DELETE:
3181  tag = CMDTAG_DELETE;
3182  break;
3183  case CMD_UTILITY:
3184  tag = CreateCommandTag(stmt->utilityStmt);
3185  break;
3186  default:
3187  elog(WARNING, "unrecognized commandType: %d",
3188  (int) stmt->commandType);
3189  tag = CMDTAG_UNKNOWN;
3190  break;
3191  }
3192  }
3193  break;
3194 
3195  default:
3196  elog(WARNING, "unrecognized node type: %d",
3197  (int) nodeTag(parsetree));
3198  tag = CMDTAG_UNKNOWN;
3199  break;
3200  }
3201 
3202  return tag;
3203 }
3204 
3205 
3206 /*
3207  * GetCommandLogLevel
3208  * utility to get the minimum log_statement level for a command,
3209  * given either a raw (un-analyzed) parsetree, an analyzed Query,
3210  * or a PlannedStmt.
3211  *
3212  * This must handle all command types, but since the vast majority
3213  * of 'em are utility commands, it seems sensible to keep it here.
3214  */
3217 {
3218  LogStmtLevel lev;
3219 
3220  switch (nodeTag(parsetree))
3221  {
3222  /* recurse if we're given a RawStmt */
3223  case T_RawStmt:
3224  lev = GetCommandLogLevel(((RawStmt *) parsetree)->stmt);
3225  break;
3226 
3227  /* raw plannable queries */
3228  case T_InsertStmt:
3229  case T_DeleteStmt:
3230  case T_UpdateStmt:
3231  lev = LOGSTMT_MOD;
3232  break;
3233 
3234  case T_SelectStmt:
3235  if (((SelectStmt *) parsetree)->intoClause)
3236  lev = LOGSTMT_DDL; /* SELECT INTO */
3237  else
3238  lev = LOGSTMT_ALL;
3239  break;
3240 
3241  case T_PLAssignStmt:
3242  lev = LOGSTMT_ALL;
3243  break;
3244 
3245  /* utility statements --- same whether raw or cooked */
3246  case T_TransactionStmt:
3247  lev = LOGSTMT_ALL;
3248  break;
3249 
3250  case T_DeclareCursorStmt:
3251  lev = LOGSTMT_ALL;
3252  break;
3253 
3254  case T_ClosePortalStmt:
3255  lev = LOGSTMT_ALL;
3256  break;
3257 
3258  case T_FetchStmt:
3259  lev = LOGSTMT_ALL;
3260  break;
3261 
3262  case T_CreateSchemaStmt:
3263  lev = LOGSTMT_DDL;
3264  break;
3265 
3266  case T_CreateStmt:
3268  lev = LOGSTMT_DDL;
3269  break;
3270 
3272  case T_DropTableSpaceStmt:
3274  lev = LOGSTMT_DDL;
3275  break;
3276 
3277  case T_CreateExtensionStmt:
3278  case T_AlterExtensionStmt:
3280  lev = LOGSTMT_DDL;
3281  break;
3282 
3283  case T_CreateFdwStmt:
3284  case T_AlterFdwStmt:
3289  case T_DropUserMappingStmt:
3291  lev = LOGSTMT_DDL;
3292  break;
3293 
3294  case T_DropStmt:
3295  lev = LOGSTMT_DDL;
3296  break;
3297 
3298  case T_TruncateStmt:
3299  lev = LOGSTMT_MOD;
3300  break;
3301 
3302  case T_CommentStmt:
3303  lev = LOGSTMT_DDL;
3304  break;
3305 
3306  case T_SecLabelStmt:
3307  lev = LOGSTMT_DDL;
3308  break;
3309 
3310  case T_CopyStmt:
3311  if (((CopyStmt *) parsetree)->is_from)
3312  lev = LOGSTMT_MOD;
3313  else
3314  lev = LOGSTMT_ALL;
3315  break;
3316 
3317  case T_PrepareStmt:
3318  {
3319  PrepareStmt *stmt = (PrepareStmt *) parsetree;
3320 
3321  /* Look through a PREPARE to the contained stmt */
3322  lev = GetCommandLogLevel(stmt->query);
3323  }
3324  break;
3325 
3326  case T_ExecuteStmt:
3327  {
3328  ExecuteStmt *stmt = (ExecuteStmt *) parsetree;
3329  PreparedStatement *ps;
3330 
3331  /* Look through an EXECUTE to the referenced stmt */
3332  ps = FetchPreparedStatement(stmt->name, false);
3333  if (ps && ps->plansource->raw_parse_tree)
3335  else
3336  lev = LOGSTMT_ALL;
3337  }
3338  break;
3339 
3340  case T_DeallocateStmt:
3341  lev = LOGSTMT_ALL;
3342  break;
3343 
3344  case T_RenameStmt:
3345  lev = LOGSTMT_DDL;
3346  break;
3347 
3349  lev = LOGSTMT_DDL;
3350  break;
3351 
3353  lev = LOGSTMT_DDL;
3354  break;
3355 
3356  case T_AlterOwnerStmt:
3357  lev = LOGSTMT_DDL;
3358  break;
3359 
3360  case T_AlterOperatorStmt:
3361  lev = LOGSTMT_DDL;
3362  break;
3363 
3364  case T_AlterTypeStmt:
3365  lev = LOGSTMT_DDL;
3366  break;
3367 
3369  case T_AlterTableStmt:
3370  lev = LOGSTMT_DDL;
3371  break;
3372 
3373  case T_AlterDomainStmt:
3374  lev = LOGSTMT_DDL;
3375  break;
3376 
3377  case T_GrantStmt:
3378  lev = LOGSTMT_DDL;
3379  break;
3380 
3381  case T_GrantRoleStmt:
3382  lev = LOGSTMT_DDL;
3383  break;
3384 
3386  lev = LOGSTMT_DDL;
3387  break;
3388 
3389  case T_DefineStmt:
3390  lev = LOGSTMT_DDL;
3391  break;
3392 
3393  case T_CompositeTypeStmt:
3394  lev = LOGSTMT_DDL;
3395  break;
3396 
3397  case T_CreateEnumStmt:
3398  lev = LOGSTMT_DDL;
3399  break;
3400 
3401  case T_CreateRangeStmt:
3402  lev = LOGSTMT_DDL;
3403  break;
3404 
3405  case T_AlterEnumStmt:
3406  lev = LOGSTMT_DDL;
3407  break;
3408 
3409  case T_ViewStmt:
3410  lev = LOGSTMT_DDL;
3411  break;
3412 
3413  case T_CreateFunctionStmt:
3414  lev = LOGSTMT_DDL;
3415  break;
3416 
3417  case T_AlterFunctionStmt:
3418  lev = LOGSTMT_DDL;
3419  break;
3420 
3421  case T_IndexStmt:
3422  lev = LOGSTMT_DDL;
3423  break;
3424 
3425  case T_RuleStmt:
3426  lev = LOGSTMT_DDL;
3427  break;
3428 
3429  case T_CreateSeqStmt:
3430  lev = LOGSTMT_DDL;
3431  break;
3432 
3433  case T_AlterSeqStmt:
3434  lev = LOGSTMT_DDL;
3435  break;
3436 
3437  case T_DoStmt:
3438  lev = LOGSTMT_ALL;
3439  break;
3440 
3441  case T_CreatedbStmt:
3442  lev = LOGSTMT_DDL;
3443  break;
3444 
3445  case T_AlterDatabaseStmt:
3446  lev = LOGSTMT_DDL;
3447  break;
3448 
3450  lev = LOGSTMT_DDL;
3451  break;
3452 
3453  case T_DropdbStmt:
3454  lev = LOGSTMT_DDL;
3455  break;
3456 
3457  case T_NotifyStmt:
3458  lev = LOGSTMT_ALL;
3459  break;
3460 
3461  case T_ListenStmt:
3462  lev = LOGSTMT_ALL;
3463  break;
3464 
3465  case T_UnlistenStmt:
3466  lev = LOGSTMT_ALL;
3467  break;
3468 
3469  case T_LoadStmt:
3470  lev = LOGSTMT_ALL;
3471  break;
3472 
3473  case T_CallStmt:
3474  lev = LOGSTMT_ALL;
3475  break;
3476 
3477  case T_ClusterStmt:
3478  lev = LOGSTMT_DDL;
3479  break;
3480 
3481  case T_VacuumStmt:
3482  lev = LOGSTMT_ALL;
3483  break;
3484 
3485  case T_ExplainStmt:
3486  {
3487  ExplainStmt *stmt = (ExplainStmt *) parsetree;
3488  bool analyze = false;
3489  ListCell *lc;
3490 
3491  /* Look through an EXPLAIN ANALYZE to the contained stmt */
3492  foreach(lc, stmt->options)
3493  {
3494  DefElem *opt = (DefElem *) lfirst(lc);
3495 
3496  if (strcmp(opt->defname, "analyze") == 0)
3497  analyze = defGetBoolean(opt);
3498  /* don't "break", as explain.c will use the last value */
3499  }
3500  if (analyze)
3501  return GetCommandLogLevel(stmt->query);
3502 
3503  /* Plain EXPLAIN isn't so interesting */
3504  lev = LOGSTMT_ALL;
3505  }
3506  break;
3507 
3508  case T_CreateTableAsStmt:
3509  lev = LOGSTMT_DDL;
3510  break;
3511 
3512  case T_RefreshMatViewStmt:
3513  lev = LOGSTMT_DDL;
3514  break;
3515 
3516  case T_AlterSystemStmt:
3517  lev = LOGSTMT_DDL;
3518  break;
3519 
3520  case T_VariableSetStmt:
3521  lev = LOGSTMT_ALL;
3522  break;
3523 
3524  case T_VariableShowStmt:
3525  lev = LOGSTMT_ALL;
3526  break;
3527 
3528  case T_DiscardStmt:
3529  lev = LOGSTMT_ALL;
3530  break;
3531 
3532  case T_CreateTrigStmt:
3533  lev = LOGSTMT_DDL;
3534  break;
3535 
3536  case T_CreateEventTrigStmt:
3537  lev = LOGSTMT_DDL;
3538  break;
3539 
3540  case T_AlterEventTrigStmt:
3541  lev = LOGSTMT_DDL;
3542  break;
3543 
3544  case T_CreatePLangStmt:
3545  lev = LOGSTMT_DDL;
3546  break;
3547 
3548  case T_CreateDomainStmt:
3549  lev = LOGSTMT_DDL;
3550  break;
3551 
3552  case T_CreateRoleStmt:
3553  lev = LOGSTMT_DDL;
3554  break;
3555 
3556  case T_AlterRoleStmt:
3557  lev = LOGSTMT_DDL;
3558  break;
3559 
3560  case T_AlterRoleSetStmt:
3561  lev = LOGSTMT_DDL;
3562  break;
3563 
3564  case T_DropRoleStmt:
3565  lev = LOGSTMT_DDL;
3566  break;
3567 
3568  case T_DropOwnedStmt:
3569  lev = LOGSTMT_DDL;
3570  break;
3571 
3572  case T_ReassignOwnedStmt:
3573  lev = LOGSTMT_DDL;
3574  break;
3575 
3576  case T_LockStmt:
3577  lev = LOGSTMT_ALL;
3578  break;
3579 
3580  case T_ConstraintsSetStmt:
3581  lev = LOGSTMT_ALL;
3582  break;
3583 
3584  case T_CheckPointStmt:
3585  lev = LOGSTMT_ALL;
3586  break;
3587 
3588  case T_ReindexStmt:
3589  lev = LOGSTMT_ALL; /* should this be DDL? */
3590  break;
3591 
3593  lev = LOGSTMT_DDL;
3594  break;
3595 
3596  case T_CreateCastStmt:
3597  lev = LOGSTMT_DDL;
3598  break;
3599 
3600  case T_CreateOpClassStmt:
3601  lev = LOGSTMT_DDL;
3602  break;
3603 
3604  case T_CreateOpFamilyStmt:
3605  lev = LOGSTMT_DDL;
3606  break;
3607 
3608  case T_CreateTransformStmt:
3609  lev = LOGSTMT_DDL;
3610  break;
3611 
3612  case T_AlterOpFamilyStmt:
3613  lev = LOGSTMT_DDL;
3614  break;
3615 
3616  case T_CreatePolicyStmt:
3617  lev = LOGSTMT_DDL;
3618  break;
3619 
3620  case T_AlterPolicyStmt:
3621  lev = LOGSTMT_DDL;
3622  break;
3623 
3625  lev = LOGSTMT_DDL;
3626  break;
3627 
3629  lev = LOGSTMT_DDL;
3630  break;
3631 
3632  case T_CreateAmStmt:
3633  lev = LOGSTMT_DDL;
3634  break;
3635 
3637  lev = LOGSTMT_DDL;
3638  break;
3639 
3641  lev = LOGSTMT_DDL;
3642  break;
3643 
3645  lev = LOGSTMT_DDL;
3646  break;
3647 
3649  lev = LOGSTMT_DDL;
3650  break;
3651 
3653  lev = LOGSTMT_DDL;
3654  break;
3655 
3656  case T_CreateStatsStmt:
3657  lev = LOGSTMT_DDL;
3658  break;
3659 
3660  case T_AlterStatsStmt:
3661  lev = LOGSTMT_DDL;
3662  break;
3663 
3664  case T_AlterCollationStmt:
3665  lev = LOGSTMT_DDL;
3666  break;
3667 
3668  /* already-planned queries */
3669  case T_PlannedStmt:
3670  {
3671  PlannedStmt *stmt = (PlannedStmt *) parsetree;
3672 
3673  switch (stmt->commandType)
3674  {
3675  case CMD_SELECT:
3676  lev = LOGSTMT_ALL;
3677  break;
3678 
3679  case CMD_UPDATE:
3680  case CMD_INSERT:
3681  case CMD_DELETE:
3682  lev = LOGSTMT_MOD;
3683  break;
3684 
3685  case CMD_UTILITY:
3686  lev = GetCommandLogLevel(stmt->utilityStmt);
3687  break;
3688 
3689  default:
3690  elog(WARNING, "unrecognized commandType: %d",
3691  (int) stmt->commandType);
3692  lev = LOGSTMT_ALL;
3693  break;
3694  }
3695  }
3696  break;
3697 
3698  /* parsed-and-rewritten-but-not-planned queries */
3699  case T_Query:
3700  {
3701  Query *stmt = (Query *) parsetree;
3702 
3703  switch (stmt->commandType)
3704  {
3705  case CMD_SELECT:
3706  lev = LOGSTMT_ALL;
3707  break;
3708 
3709  case CMD_UPDATE:
3710  case CMD_INSERT:
3711  case CMD_DELETE:
3712  lev = LOGSTMT_MOD;
3713  break;
3714 
3715  case CMD_UTILITY:
3716  lev = GetCommandLogLevel(stmt->utilityStmt);
3717  break;
3718 
3719  default:
3720  elog(WARNING, "unrecognized commandType: %d",
3721  (int) stmt->commandType);
3722  lev = LOGSTMT_ALL;
3723  break;
3724  }
3725 
3726  }
3727  break;
3728 
3729  default:
3730  elog(WARNING, "unrecognized node type: %d",
3731  (int) nodeTag(parsetree));
3732  lev = LOGSTMT_ALL;
3733  break;
3734  }
3735 
3736  return lev;
3737 }
TupleDesc GetPGVariableResultDesc(const char *name)
Definition: guc.c:9348
RangeVar * relation
Definition: parsenodes.h:2183
ObjectType objtype
Definition: parsenodes.h:2792
ObjectAddress AlterSequence(ParseState *pstate, AlterSeqStmt *stmt)
Definition: sequence.c:422
ObjectAddress DefineTSParser(List *names, List *parameters)
Definition: tsearchcmds.c:178
void ExplainQuery(ParseState *pstate, ExplainStmt *stmt, ParamListInfo params, DestReceiver *dest)
Definition: explain.c:164
bytea * heap_reloptions(char relkind, Datum reloptions, bool validate)
Definition: reloptions.c:2013
Oid funcresulttype
Definition: primnodes.h:496
#define NIL
Definition: pg_list.h:65
CommandTag
Definition: cmdtag.h:20
bool primary
Definition: parsenodes.h:2905
void closeAllVfds(void)
Definition: fd.c:2897
bool CommandIsReadOnly(PlannedStmt *pstmt)
Definition: utility.c:100
ObjectAddress AlterForeignServer(AlterForeignServerStmt *stmt)
Definition: foreigncmds.c:965
void CreateForeignTable(CreateForeignTableStmt *stmt, Oid relid)
Definition: foreigncmds.c:1391
void DropSubscription(DropSubscriptionStmt *stmt, bool isTopLevel)
ObjectAddress DefineOperator(List *names, List *parameters)
Definition: operatorcmds.c:65
TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)
Definition: tupdesc.c:111
ObjectType objtype
Definition: parsenodes.h:2804
#define IsA(nodeptr, _type_)
Definition: nodes.h:587
ObjectAddress DefineTSConfiguration(List *names, List *parameters, ObjectAddress *copied)
Definition: tsearchcmds.c:893
ObjectAddress CreateTransform(CreateTransformStmt *stmt)
static void ExecDropStmt(DropStmt *stmt, bool isTopLevel)
Definition: utility.c:1971
ObjectAddress DefineIndex(Oid relationId, IndexStmt *stmt, Oid indexRelationId, Oid parentIndexId, Oid parentConstraintId, bool is_alter_table, bool check_rights, bool check_not_in_use, bool skip_build, bool quiet)
Definition: indexcmds.c:506
ObjectAddress CreateForeignDataWrapper(ParseState *pstate, CreateFdwStmt *stmt)
Definition: foreigncmds.c:558
void PerformPortalClose(const char *name)
Definition: portalcmds.c:214
ObjectAddress AlterDomainAddConstraint(List *names, Node *newConstraint, ObjectAddress *constrAddr)
Definition: typecmds.c:2919
bool EndTransactionBlock(bool chain)
Definition: xact.c:3767
Datum transformRelOptions(Datum oldOptions, List *defList, const char *namspace, char *validnsps[], bool acceptOidsOff, bool isReset)
Definition: reloptions.c:1149
void PreventCommandIfParallelMode(const char *cmdname)
Definition: utility.c:426
void cluster(ParseState *pstate, ClusterStmt *stmt, bool isTopLevel)
Definition: cluster.c:103
DropBehavior behavior
Definition: parsenodes.h:2007
ObjectAddress CommentObject(CommentStmt *stmt)
Definition: comment.c:40
ObjectAddress CreateFunction(ParseState *pstate, CreateFunctionStmt *stmt)
FuncExpr * funcexpr
Definition: parsenodes.h:3038
static CommandTag AlterObjectTypeCommandTag(ObjectType objtype)
Definition: utility.c:2191
ObjectType renameType
Definition: parsenodes.h:3055
int LOCKMODE
Definition: lockdefs.h:26
ObjectAddress ExecSecLabelStmt(SecLabelStmt *stmt)
Definition: seclabel.c:113
void WarnNoTransactionBlock(bool isTopLevel, const char *stmtType)
Definition: xact.c:3449
ObjectAddress CreatePublication(ParseState *pstate, CreatePublicationStmt *stmt)
#define castNode(_type_, nodeptr)
Definition: nodes.h:605
BackendType MyBackendType
Definition: miscinit.c:62
QueryEnvironment * p_queryEnv
Definition: parse_node.h:205
void ExecReindex(ParseState *pstate, ReindexStmt *stmt, bool isTopLevel)
Definition: indexcmds.c:2470
CachedPlanSource * plansource
Definition: prepare.h:31
LogStmtLevel
Definition: tcopprot.h:36
PlannedStmt * pstmt
Definition: utility.h:32
#define RangeVarGetRelid(relation, lockmode, missing_ok)
Definition: namespace.h:79
Oid AlterTableLookupRelation(AlterTableStmt *stmt, LOCKMODE lockmode)
Definition: tablecmds.c:3937
Portal GetPortalByName(const char *name)
Definition: portalmem.c:130
ObjectAddress AlterDomainValidateConstraint(List *names, const char *constrName)
Definition: typecmds.c:3035
ObjectAddress DefineAggregate(ParseState *pstate, List *name, List *args, bool oldstyle, List *parameters, bool replace)
Definition: aggregatecmds.c:56
char get_rel_relkind(Oid relid)
Definition: lsyscache.c:1974
ObjectAddress AlterEnum(AlterEnumStmt *stmt)
Definition: typecmds.c:1261
void DropOwnedObjects(DropOwnedStmt *stmt)
Definition: user.c:1313
Oid AlterDatabaseSet(AlterDatabaseSetStmt *stmt)
Definition: dbcommands.c:1608
ObjectType objectType
Definition: parsenodes.h:3101
void DefineSavepoint(const char *name)
Definition: xact.c:4096
RangeVar * typevar
Definition: parsenodes.h:3211
void AfterTriggerSetState(ConstraintsSetStmt *stmt)
Definition: trigger.c:5212
TupleDesc CallStmtResultDesc(CallStmt *stmt)
void EventTriggerDDLCommandEnd(Node *parsetree)
void ExecuteCallStmt(CallStmt *stmt, ParamListInfo params, bool atomic, DestReceiver *dest)
static void CheckRestrictedOperation(const char *cmdname)
Definition: utility.c:463
ProcessUtility_hook_type ProcessUtility_hook
Definition: utility.c:76
Definition: nodes.h:536
ObjectAddress ExecAlterExtensionContentsStmt(AlterExtensionContentsStmt *stmt, ObjectAddress *objAddr)
Definition: extension.c:3266
bool PrepareTransactionBlock(const char *gid)
Definition: xact.c:3715
List * list_concat(List *list1, const List *list2)
Definition: list.c:530
int errcode(int sqlerrcode)
Definition: elog.c:698
ObjectAddress CreateProceduralLanguage(CreatePLangStmt *stmt)
Definition: proclang.c:39
ProcessUtilityContext
Definition: utility.h:20
bool superuser(void)
Definition: superuser.c:46
AlterTableType subtype
Definition: parsenodes.h:1962
char * filename
Definition: parsenodes.h:3281
void EventTriggerInhibitCommandCollection(void)
ObjectAddress DefineDomain(CreateDomainStmt *stmt)
Definition: typecmds.c:693
void PrepareQuery(ParseState *pstate, PrepareStmt *stmt, int stmt_location, int stmt_len)
Definition: prepare.c:58
List * options
Definition: parsenodes.h:3389
void Async_Listen(const char *channel)
Definition: async.c:772
ObjectAddress DefineCompositeType(RangeVar *typevar, List *coldeflist)
Definition: typecmds.c:2510
Oid CreateTableSpace(CreateTableSpaceStmt *stmt)
Definition: tablespace.c:233
unsigned int Oid
Definition: postgres_ext.h:31
bool RecoveryInProgress(void)
Definition: xlog.c:8220
static int ClassifyUtilityCommandAsReadOnly(Node *parsetree)
Definition: utility.c:133
List * rowMarks
Definition: parsenodes.h:175
void ExecuteTruncate(TruncateStmt *stmt)
Definition: tablecmds.c:1611
void RemoveObjects(DropStmt *stmt)
Definition: dropcmds.c:57
Node * utilityStmt
Definition: parsenodes.h:128
ObjectAddress DefineOpClass(CreateOpClassStmt *stmt)
Definition: opclasscmds.c:328
DestReceiver * None_Receiver
Definition: dest.c:96
void NewRelationCreateToastTable(Oid relOid, Datum reloptions)
Definition: toasting.c:73
#define OidIsValid(objectId)
Definition: c.h:710
int stmt_len
Definition: plannodes.h:90
Oid CreateRole(ParseState *pstate, CreateRoleStmt *stmt)
Definition: user.c:72
ObjectType removeType
Definition: parsenodes.h:2767
void RollbackToSavepoint(const char *name)
Definition: xact.c:4290
void GetPGVariable(const char *name, DestReceiver *dest)
Definition: guc.c:9339
ParseState * make_parsestate(ParseState *parentParseState)
Definition: parse_node.c:44
TupleDesc resultDesc
Definition: plancache.h:108
Query * UtilityContainsQuery(Node *parsetree)
Definition: utility.c:2154
void EventTriggerAlterTableStart(Node *parsetree)
#define list_make1(x1)
Definition: pg_list.h:206
bool IsTransactionBlock(void)
Definition: xact.c:4693
char * relname
Definition: primnodes.h:68
Node * query
Definition: parsenodes.h:3388
static void ProcessUtilitySlow(ParseState *pstate, PlannedStmt *pstmt, const char *queryString, ProcessUtilityContext context, ParamListInfo params, QueryEnvironment *queryEnv, DestReceiver *dest, QueryCompletion *qc)
Definition: utility.c:1088
void AlterTable(AlterTableStmt *stmt, LOCKMODE lockmode, AlterTableUtilityContext *context)
Definition: tablecmds.c:3993
void DeallocateQuery(DeallocateStmt *stmt)
Definition: prepare.c:539
#define true
Definition: c.h:395
RangeVar * relation
Definition: parsenodes.h:2889
bool defGetBoolean(DefElem *def)
Definition: define.c:106
ObjectAddress AlterPolicy(AlterPolicyStmt *stmt)
Definition: policy.c:773
void RemoveRelations(DropStmt *drop)
Definition: tablecmds.c:1307
ObjectAddress AlterStatistics(AlterStatsStmt *stmt)
Definition: statscmds.c:619
#define COMMAND_OK_IN_RECOVERY
Definition: utility.h:58
bool IsInParallelMode(void)
Definition: xact.c:1012
#define linitial(l)
Definition: pg_list.h:174
void RangeVarCallbackOwnsRelation(const RangeVar *relation, Oid relId, Oid oldRelId, void *arg)
Definition: tablecmds.c:16508
List * args
Definition: parsenodes.h:2683
void ProcessUtility(PlannedStmt *pstmt, const char *queryString, bool readOnlyTree, ProcessUtilityContext context, ParamListInfo params, QueryEnvironment *queryEnv, DestReceiver *dest, QueryCompletion *qc)
Definition: utility.c:503
#define ERROR
Definition: elog.h:46
ObjectAddress AlterDomainDefault(List *names, Node *defaultRaw)
Definition: typecmds.c:2568
void PreventCommandDuringRecovery(const char *cmdname)
Definition: utility.c:445
char * savepoint_name
Definition: parsenodes.h:3199
bool concurrent
Definition: parsenodes.h:2770
void GrantRole(GrantRoleStmt *stmt)
Definition: user.c:1254
ObjectAddress AlterOperator(AlterOperatorStmt *stmt)
Definition: operatorcmds.c:409
TupleDesc ExplainResultDesc(ExplainStmt *stmt)
Definition: explain.c:328
void EventTriggerDDLCommandStart(Node *parsetree)
void standard_ProcessUtility(PlannedStmt *pstmt, const char *queryString, bool readOnlyTree, ProcessUtilityContext context, ParamListInfo params, QueryEnvironment *queryEnv, DestReceiver *dest, QueryCompletion *qc)
Definition: utility.c:544
void PerformCursorOpen(ParseState *pstate, DeclareCursorStmt *cstmt, ParamListInfo params, bool isTopLevel)
Definition: portalcmds.c:43
ObjectAddress CreatePolicy(CreatePolicyStmt *stmt)
Definition: policy.c:573
void EventTriggerSQLDrop(Node *parsetree)
void PerformPortalFetch(FetchStmt *stmt, DestReceiver *dest, QueryCompletion *qc)
Definition: portalcmds.c:167
ObjectAddress AlterTSConfiguration(AlterTSConfigurationStmt *stmt)
Definition: tsearchcmds.c:1109
ObjectAddress AlterType(AlterTypeStmt *stmt)
Definition: typecmds.c:4099
ObjectAddress AlterDomainNotNull(List *names, bool notNull)
Definition: typecmds.c:2700
Oid RemoveUserMapping(DropUserMappingStmt *stmt)
Definition: foreigncmds.c:1311
ObjectAddress CreateUserMapping(CreateUserMappingStmt *stmt)
Definition: foreigncmds.c:1091
void ExecSetVariableStmt(VariableSetStmt *stmt, bool isTopLevel)
Definition: guc.c:8722
int stmt_location
Definition: plannodes.h:89
Node * stmt
Definition: parsenodes.h:1572
ObjectAddress AlterTSDictionary(AlterTSDictionaryStmt *stmt)
Definition: tsearchcmds.c:487
void check_stack_depth(void)
Definition: postgres.c:3469
bool transformed
Definition: parsenodes.h:2909
#define RowExclusiveLock
Definition: lockdefs.h:38
int errdetail(const char *fmt,...)
Definition: elog.c:1042
void ExecuteQuery(ParseState *pstate, ExecuteStmt *stmt, IntoClause *intoClause, ParamListInfo params, DestReceiver *dest, QueryCompletion *qc)
Definition: prepare.c:184
Node * utilityStmt
Definition: plannodes.h:86
void PreventInTransactionBlock(bool isTopLevel, const char *stmtType)
Definition: xact.c:3389
const char * queryString
Definition: utility.h:33
List * options
Definition: parsenodes.h:2191
Oid RangeVarGetRelidExtended(const RangeVar *relation, LOCKMODE lockmode, uint32 flags, RangeVarGetRelidCallback callback, void *callback_arg)
Definition: namespace.c:237
ObjectAddress DefineEnum(CreateEnumStmt *stmt)
Definition: typecmds.c:1137
bool UtilityReturnsTuples(Node *parsetree)
Definition: utility.c:2004
ObjectAddress DefineView(ViewStmt *stmt, const char *queryString, int stmt_location, int stmt_len)
Definition: view.c:407
Oid CreateSchemaCommand(CreateSchemaStmt *stmt, const char *queryString, int stmt_location, int stmt_len)
Definition: schemacmds.c:50
#define HEAP_RELOPT_NAMESPACES
Definition: reloptions.h:61
const char * p_sourcetext
Definition: parse_node.h:181
void DropTableSpace(DropTableSpaceStmt *stmt)
Definition: tablespace.c:413
ObjectAddress AlterUserMapping(AlterUserMappingStmt *stmt)
Definition: foreigncmds.c:1213
List * returningList
Definition: parsenodes.h:156
char * conditionname
Definition: parsenodes.h:3163
ObjectAddress ExecRenameStmt(RenameStmt *stmt)
Definition: alter.c:331
char * portalname
Definition: parsenodes.h:2870
#define CHECKPOINT_FORCE
Definition: xlog.h:200
ObjectAddress DefineSequence(ParseState *pstate, CreateSeqStmt *seq)
Definition: sequence.c:118
ObjectAddress DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId, ObjectAddress *typaddress, const char *queryString)
Definition: tablecmds.c:627
QueryEnvironment * queryEnv
Definition: utility.h:36
Oid AlterRole(ParseState *pstate, AlterRoleStmt *stmt)
Definition: user.c:493
void ExecAlterDefaultPrivilegesStmt(ParseState *pstate, AlterDefaultPrivilegesStmt *stmt)
Definition: aclchk.c:905
ObjectAddress DefineType(ParseState *pstate, List *names, List *parameters)
Definition: typecmds.c:148
Oid AlterEventTrigger(AlterEventTrigStmt *stmt)
bool inh
Definition: primnodes.h:69
Node * arg
Definition: parsenodes.h:759
ObjectType
Definition: parsenodes.h:1787
ObjectAddress AlterForeignDataWrapper(ParseState *pstate, AlterFdwStmt *stmt)
Definition: foreigncmds.c:674
ObjectAddress CreateExtension(ParseState *pstate, CreateExtensionStmt *stmt)
Definition: extension.c:1681
void BeginTransactionBlock(void)
Definition: xact.c:3647
void EventTriggerEndCompleteQuery(void)
bool is_grant
Definition: parsenodes.h:2026
#define WARNING
Definition: elog.h:40
ObjectAddress AlterSubscription(ParseState *pstate, AlterSubscriptionStmt *stmt, bool isTopLevel)
LOCKMODE AlterTableGetLockLevel(List *cmds)
Definition: tablecmds.c:4067
ObjectAddress CreateForeignServer(CreateForeignServerStmt *stmt)
Definition: foreigncmds.c:838
bool replace
Definition: parsenodes.h:2686
#define PortalIsValid(p)
Definition: portal.h:211
void AlterSystemSetConfigFile(AlterSystemStmt *altersysstmt)
Definition: guc.c:8512
#define PG_FINALLY()
Definition: elog.h:330
Definition: nodes.h:314
bool canSetTag
Definition: plannodes.h:54
bool ismove
Definition: parsenodes.h:2871
void EventTriggerUndoInhibitCommandCollection(void)
uintptr_t Datum
Definition: postgres.h:411
void CommandCounterIncrement(void)
Definition: xact.c:1021
CmdType commandType
Definition: plannodes.h:46
ObjectAddress DefineRange(ParseState *pstate, CreateRangeStmt *stmt)
Definition: typecmds.c:1336
void ReleaseSavepoint(const char *name)
Definition: xact.c:4181
Oid AlterRoleSet(AlterRoleSetStmt *stmt)
Definition: user.c:855
Oid CreateEventTrigger(CreateEventTrigStmt *stmt)
TupleDesc FetchPreparedStatementResultDesc(PreparedStatement *stmt)
Definition: prepare.c:500
bool unique
Definition: parsenodes.h:2904
ObjectType kind
Definition: parsenodes.h:2680
char * conditionname
Definition: parsenodes.h:3152
ObjectAddress ExecAlterObjectDependsStmt(AlterObjectDependsStmt *stmt, ObjectAddress *refAddress)
Definition: alter.c:431
void EventTriggerCollectAlterDefPrivs(AlterDefaultPrivilegesStmt *stmt)
List * rowMarks
Definition: plannodes.h:78
List * expandTableLikeClause(RangeVar *heapRel, TableLikeClause *table_like_clause)
TupleDesc tupDesc
Definition: portal.h:159
#define InvalidOid
Definition: postgres_ext.h:36
ObjectAddress DefineCollation(ParseState *pstate, List *names, List *parameters, bool if_not_exists)
Definition: collationcmds.c:53
CommandTag commandTag
Definition: cmdtag.h:30
List * defnames
Definition: parsenodes.h:2682
#define ereport(elevel,...)
Definition: elog.h:157
bool EventTriggerSupportsObjectType(ObjectType obtype)
bool XactReadOnly
Definition: xact.c:78
#define NOTICE
Definition: elog.h:37
Oid AlterDatabase(ParseState *pstate, AlterDatabaseStmt *stmt, bool isTopLevel)
Definition: dbcommands.c:1441
CmdType commandType
Definition: parsenodes.h:120
ObjectAddress CreateCast(CreateCastStmt *stmt)
void FinishPreparedTransaction(const char *gid, bool isCommit)
Definition: twophase.c:1409
#define CHECKPOINT_WAIT
Definition: xlog.h:204
ObjectAddress ExecAlterExtensionStmt(ParseState *pstate, AlterExtensionStmt *stmt)
Definition: extension.c:2961
ObjectAddress ExecAlterObjectSchemaStmt(AlterObjectSchemaStmt *stmt, ObjectAddress *oldSchemaAddr)
Definition: alter.c:495
#define makeNode(_type_)
Definition: nodes.h:584
#define ShareUpdateExclusiveLock
Definition: lockdefs.h:39
ObjectAddress DefineTSDictionary(List *names, List *parameters)
Definition: tsearchcmds.c:391
void ExecVacuum(ParseState *pstate, VacuumStmt *vacstmt, bool isTopLevel)
Definition: vacuum.c:100
void DoCopy(ParseState *pstate, const CopyStmt *stmt, int stmt_location, int stmt_len, uint64 *processed)
Definition: copy.c:64
#define Assert(condition)
Definition: c.h:804
#define lfirst(lc)
Definition: pg_list.h:169
CommandTag CreateCommandTag(Node *parsetree)
Definition: utility.c:2337
bool InSecurityRestrictedOperation(void)
Definition: miscinit.c:627
static void SetQueryCompletion(QueryCompletion *qc, CommandTag commandTag, uint64 nprocessed)
Definition: cmdtag.h:36
bool hasModifyingCTE
Definition: plannodes.h:52
ObjectAddress CreateSubscription(ParseState *pstate, CreateSubscriptionStmt *stmt, bool isTopLevel)
ObjectAddress ExecRefreshMatView(RefreshMatViewStmt *stmt, const char *queryString, ParamListInfo params, QueryCompletion *qc)
Definition: matview.c:138
void load_file(const char *filename, bool restricted)
Definition: dfmgr.c:146
Node * query
Definition: parsenodes.h:3552
ObjectAddress CreateConversionCommand(CreateConversionStmt *stmt)
void Async_UnlistenAll(void)
Definition: async.c:804
Oid AlterTableMoveAll(AlterTableMoveAllStmt *stmt)
Definition: tablecmds.c:14031
List * transformCreateStmt(CreateStmt *stmt, const char *queryString)
ObjectAddress ExecAlterOwnerStmt(AlterOwnerStmt *stmt)
Definition: alter.c:833
ObjectAddress ExecCreateTableAs(ParseState *pstate, CreateTableAsStmt *stmt, ParamListInfo params, QueryEnvironment *queryEnv, QueryCompletion *qc)
Definition: createas.c:226
struct RawStmt * raw_parse_tree
Definition: plancache.h:99
void PreventCommandIfReadOnly(const char *cmdname)
Definition: utility.c:408
#define nodeTag(nodeptr)
Definition: nodes.h:541
void EventTriggerAlterTableRelid(Oid objectId)
void Async_Notify(const char *channel, const char *payload)
Definition: async.c:625
Oid AlterOpFamily(AlterOpFamilyStmt *stmt)
Definition: opclasscmds.c:808
#define COMMAND_IS_NOT_READ_ONLY
Definition: utility.h:68
ObjectAddress DefineOpFamily(CreateOpFamilyStmt *stmt)
Definition: opclasscmds.c:763
const char * GetCommandTagName(CommandTag commandTag)
Definition: cmdtag.c:45
ObjectAddress AlterDomainDropConstraint(List *names, const char *constrName, DropBehavior behavior, bool missing_ok)
Definition: typecmds.c:2820
bool concurrent
Definition: parsenodes.h:2910
ObjectAddress DefineRule(RuleStmt *stmt, const char *queryString)
List * find_all_inheritors(Oid parentrelId, LOCKMODE lockmode, List **numparents)
Definition: pg_inherits.c:256
void LockTableCommand(LockStmt *lockstmt)
Definition: lockcmds.c:42
Oid createdb(ParseState *pstate, const CreatedbStmt *stmt)
Definition: dbcommands.c:100
bool is_from
Definition: parsenodes.h:2126
CreateStatsStmt * transformStatsStmt(Oid relid, CreateStatsStmt *stmt, const char *queryString)
const ObjectAddress InvalidObjectAddress
void ImportForeignSchema(ImportForeignSchemaStmt *stmt)
Definition: foreigncmds.c:1471
int errmsg(const char *fmt,...)
Definition: elog.c:909
RangeVar * relation
Definition: parsenodes.h:1871
void list_free(List *list)
Definition: list.c:1391
#define elog(elevel,...)
Definition: elog.h:232
void ReassignOwnedObjects(ReassignOwnedStmt *stmt)
Definition: user.c:1339
ObjectAddress AlterCollation(AlterCollationStmt *stmt)
#define ShareLock
Definition: lockdefs.h:41
#define COMMAND_IS_STRICTLY_READ_ONLY
Definition: utility.h:65
#define COMMAND_OK_IN_READ_ONLY_TXN
Definition: utility.h:56
ObjectType objtype
Definition: parsenodes.h:2028
ObjectAddress DefineTSTemplate(List *names, List *parameters)
Definition: tsearchcmds.c:684
char * name
Definition: parsenodes.h:3564
bool if_not_exists
Definition: parsenodes.h:2685
#define CHECKPOINT_IMMEDIATE
Definition: xlog.h:199
ObjectAddress CreateTrigger(CreateTrigStmt *stmt, const char *queryString, Oid relOid, Oid refRelOid, Oid constraintOid, Oid indexOid, Oid funcoid, Oid parentTriggerOid, Node *whenClause, bool isInternal, bool in_partition)
Definition: trigger.c:156
void(* ProcessUtility_hook_type)(PlannedStmt *pstmt, const char *queryString, bool readOnlyTree, ProcessUtilityContext context, ParamListInfo params, QueryEnvironment *queryEnv, DestReceiver *dest, QueryCompletion *qc)
Definition: utility.h:71
void DropRole(DropRoleStmt *stmt)
Definition: user.c:936
char * defname
Definition: parsenodes.h:758
ObjectAddress CreateAccessMethod(CreateAmStmt *stmt)
Definition: amcmds.c:43
List * definition
Definition: parsenodes.h:2684
void ProcessUtilityForAlterTable(Node *stmt, AlterTableUtilityContext *context)
Definition: utility.c:1935
void EventTriggerCollectSimpleCommand(ObjectAddress address, ObjectAddress secondaryObject, Node *parsetree)
void UserAbortTransactionBlock(bool chain)
Definition: xact.c:3927
#define copyObject(obj)
Definition: nodes.h:652
#define PG_TRY()
Definition: elog.h:313
#define COMMAND_OK_IN_PARALLEL_MODE
Definition: utility.h:57
void free_parsestate(ParseState *pstate)
Definition: parse_node.c:77
IndexStmt * transformIndexStmt(Oid relid, IndexStmt *stmt, const char *queryString)
PreparedStatement * FetchPreparedStatement(const char *stmt_name, bool throwError)
Definition: prepare.c:468
Definition: pg_list.h:50
ObjectAddress AlterFunction(ParseState *pstate, AlterFunctionStmt *stmt)
TupleDesc UtilityTupleDescriptor(Node *parsetree)
Definition: utility.c:2060
ParamListInfo params
Definition: utility.h:35
void AlterPublication(ParseState *pstate, AlterPublicationStmt *stmt)
void DropDatabase(ParseState *pstate, DropdbStmt *stmt)
Definition: dbcommands.c:1416
static long analyze(struct nfa *nfa)
Definition: regc_nfa.c:3044
bool oldstyle
Definition: parsenodes.h:2681
#define PG_END_TRY()
Definition: elog.h:338
void DiscardCommand(DiscardStmt *stmt, bool isTopLevel)
Definition: discard.c:31
void RequireTransactionBlock(bool isTopLevel, const char *stmtType)
Definition: xact.c:3455
void Async_Unlisten(const char *channel)
Definition: async.c:786
#define lfirst_oid(lc)
Definition: pg_list.h:171
void SetPGVariable(const char *name, List *args, bool is_local)
Definition: guc.c:8865
LogStmtLevel GetCommandLogLevel(Node *parsetree)
Definition: utility.c:3216
List * list_delete_first(List *list)
Definition: list.c:875
bool EventTriggerBeginCompleteQuery(void)
void RequestCheckpoint(int flags)
Definition: checkpointer.c:920
char * payload
Definition: parsenodes.h:3153
TransactionStmtKind kind
Definition: parsenodes.h:3197
void ExecuteDoStmt(ParseState *pstate, DoStmt *stmt, bool atomic)
void ExecuteGrantStmt(GrantStmt *stmt)
Definition: aclchk.c:360
void EventTriggerAlterTableEnd(void)
ObjectAddress CreateStatistics(CreateStatsStmt *stmt)
Definition: statscmds.c:65
char * conditionname
Definition: parsenodes.h:3173
Oid AlterTableSpaceOptions(AlterTableSpaceOptionsStmt *stmt)
Definition: tablespace.c:1016