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