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