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