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