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