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