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