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