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