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