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