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