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