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