OSDN Git Service

Pgindent run for 8.0.
[pg-rex/syncrep.git] / 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-2004, PostgreSQL Global Development Group
9  * Portions Copyright (c) 1994, Regents of the University of California
10  *
11  *
12  * IDENTIFICATION
13  *        $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.228 2004/08/29 05:06:49 momjian Exp $
14  *
15  *-------------------------------------------------------------------------
16  */
17 #include "postgres.h"
18
19 #include "access/heapam.h"
20 #include "catalog/catalog.h"
21 #include "catalog/namespace.h"
22 #include "catalog/pg_shadow.h"
23 #include "commands/alter.h"
24 #include "commands/async.h"
25 #include "commands/cluster.h"
26 #include "commands/comment.h"
27 #include "commands/copy.h"
28 #include "commands/conversioncmds.h"
29 #include "commands/dbcommands.h"
30 #include "commands/defrem.h"
31 #include "commands/explain.h"
32 #include "commands/lockcmds.h"
33 #include "commands/portalcmds.h"
34 #include "commands/prepare.h"
35 #include "commands/proclang.h"
36 #include "commands/schemacmds.h"
37 #include "commands/sequence.h"
38 #include "commands/tablecmds.h"
39 #include "commands/tablespace.h"
40 #include "commands/trigger.h"
41 #include "commands/typecmds.h"
42 #include "commands/user.h"
43 #include "commands/vacuum.h"
44 #include "commands/view.h"
45 #include "miscadmin.h"
46 #include "nodes/makefuncs.h"
47 #include "parser/parse_expr.h"
48 #include "parser/parse_type.h"
49 #include "postmaster/bgwriter.h"
50 #include "rewrite/rewriteDefine.h"
51 #include "rewrite/rewriteRemove.h"
52 #include "storage/fd.h"
53 #include "tcop/pquery.h"
54 #include "tcop/utility.h"
55 #include "utils/acl.h"
56 #include "utils/guc.h"
57 #include "utils/lsyscache.h"
58 #include "utils/syscache.h"
59
60
61 /*
62  * Error-checking support for DROP commands
63  */
64
65 struct msgstrings
66 {
67         char            kind;
68         int                     nonexistent_code;
69         const char *nonexistent_msg;
70         const char *nota_msg;
71         const char *drophint_msg;
72 };
73
74 static const struct msgstrings msgstringarray[] = {
75         {RELKIND_RELATION,
76                 ERRCODE_UNDEFINED_TABLE,
77                 gettext_noop("table \"%s\" does not exist"),
78                 gettext_noop("\"%s\" is not a table"),
79         gettext_noop("Use DROP TABLE to remove a table.")},
80         {RELKIND_SEQUENCE,
81                 ERRCODE_UNDEFINED_TABLE,
82                 gettext_noop("sequence \"%s\" does not exist"),
83                 gettext_noop("\"%s\" is not a sequence"),
84         gettext_noop("Use DROP SEQUENCE to remove a sequence.")},
85         {RELKIND_VIEW,
86                 ERRCODE_UNDEFINED_TABLE,
87                 gettext_noop("view \"%s\" does not exist"),
88                 gettext_noop("\"%s\" is not a view"),
89         gettext_noop("Use DROP VIEW to remove a view.")},
90         {RELKIND_INDEX,
91                 ERRCODE_UNDEFINED_OBJECT,
92                 gettext_noop("index \"%s\" does not exist"),
93                 gettext_noop("\"%s\" is not an index"),
94         gettext_noop("Use DROP INDEX to remove an index.")},
95         {RELKIND_COMPOSITE_TYPE,
96                 ERRCODE_UNDEFINED_OBJECT,
97                 gettext_noop("type \"%s\" does not exist"),
98                 gettext_noop("\"%s\" is not a type"),
99         gettext_noop("Use DROP TYPE to remove a type.")},
100         {'\0', 0, NULL, NULL, NULL}
101 };
102
103
104 /*
105  * Emit the right error message for a "DROP" command issued on a
106  * relation of the wrong type
107  */
108 static void
109 DropErrorMsgWrongType(char *relname, char wrongkind, char rightkind)
110 {
111         const struct msgstrings *rentry;
112         const struct msgstrings *wentry;
113
114         for (rentry = msgstringarray; rentry->kind != '\0'; rentry++)
115                 if (rentry->kind == rightkind)
116                         break;
117         Assert(rentry->kind != '\0');
118
119         for (wentry = msgstringarray; wentry->kind != '\0'; wentry++)
120                 if (wentry->kind == wrongkind)
121                         break;
122         /* wrongkind could be something we don't have in our table... */
123
124         ereport(ERROR,
125                         (errcode(ERRCODE_WRONG_OBJECT_TYPE),
126                          errmsg(rentry->nota_msg, relname),
127                          (wentry->kind != '\0') ? errhint(wentry->drophint_msg) : 0));
128 }
129
130 /*
131  * Emit the right error message for a "DROP" command issued on a
132  * non-existent relation
133  */
134 static void
135 DropErrorMsgNonExistent(RangeVar *rel, char rightkind)
136 {
137         const struct msgstrings *rentry;
138
139         for (rentry = msgstringarray; rentry->kind != '\0'; rentry++)
140         {
141                 if (rentry->kind == rightkind)
142                         ereport(ERROR,
143                                         (errcode(rentry->nonexistent_code),
144                                          errmsg(rentry->nonexistent_msg, rel->relname)));
145         }
146
147         Assert(false);                          /* Should be impossible */
148 }
149
150 static void
151 CheckDropPermissions(RangeVar *rel, char rightkind)
152 {
153         Oid                     relOid;
154         HeapTuple       tuple;
155         Form_pg_class classform;
156
157         relOid = RangeVarGetRelid(rel, true);
158         if (!OidIsValid(relOid))
159                 DropErrorMsgNonExistent(rel, rightkind);
160
161         tuple = SearchSysCache(RELOID,
162                                                    ObjectIdGetDatum(relOid),
163                                                    0, 0, 0);
164         if (!HeapTupleIsValid(tuple))
165                 elog(ERROR, "cache lookup failed for relation %u", relOid);
166
167         classform = (Form_pg_class) GETSTRUCT(tuple);
168
169         if (classform->relkind != rightkind)
170                 DropErrorMsgWrongType(rel->relname, classform->relkind,
171                                                           rightkind);
172
173         /* Allow DROP to either table owner or schema owner */
174         if (!pg_class_ownercheck(relOid, GetUserId()) &&
175                 !pg_namespace_ownercheck(classform->relnamespace, GetUserId()))
176                 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
177                                            rel->relname);
178
179         if (!allowSystemTableMods && IsSystemClass(classform))
180                 ereport(ERROR,
181                                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
182                                  errmsg("permission denied: \"%s\" is a system catalog",
183                                                 rel->relname)));
184
185         ReleaseSysCache(tuple);
186 }
187
188 /*
189  * Verify user has ownership of specified relation, else ereport.
190  *
191  * If noCatalogs is true then we also deny access to system catalogs,
192  * except when allowSystemTableMods is true.
193  */
194 void
195 CheckRelationOwnership(RangeVar *rel, bool noCatalogs)
196 {
197         Oid                     relOid;
198         HeapTuple       tuple;
199
200         relOid = RangeVarGetRelid(rel, false);
201         tuple = SearchSysCache(RELOID,
202                                                    ObjectIdGetDatum(relOid),
203                                                    0, 0, 0);
204         if (!HeapTupleIsValid(tuple))           /* should not happen */
205                 elog(ERROR, "cache lookup failed for relation %u", relOid);
206
207         if (!pg_class_ownercheck(relOid, GetUserId()))
208                 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
209                                            rel->relname);
210
211         if (noCatalogs)
212         {
213                 if (!allowSystemTableMods &&
214                         IsSystemClass((Form_pg_class) GETSTRUCT(tuple)))
215                         ereport(ERROR,
216                                         (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
217                                   errmsg("permission denied: \"%s\" is a system catalog",
218                                                  rel->relname)));
219         }
220
221         ReleaseSysCache(tuple);
222 }
223
224
225 static void
226 check_xact_readonly(Node *parsetree)
227 {
228         if (!XactReadOnly)
229                 return;
230
231         /*
232          * Note: Commands that need to do more complicated checking are
233          * handled elsewhere.
234          */
235
236         switch (nodeTag(parsetree))
237         {
238                 case T_AlterDatabaseSetStmt:
239                 case T_AlterDomainStmt:
240                 case T_AlterGroupStmt:
241                 case T_AlterOwnerStmt:
242                 case T_AlterSeqStmt:
243                 case T_AlterTableStmt:
244                 case T_AlterUserStmt:
245                 case T_AlterUserSetStmt:
246                 case T_RenameStmt:
247                 case T_CommentStmt:
248                 case T_DefineStmt:
249                 case T_CreateCastStmt:
250                 case T_CreateConversionStmt:
251                 case T_CreatedbStmt:
252                 case T_CreateDomainStmt:
253                 case T_CreateFunctionStmt:
254                 case T_CreateGroupStmt:
255                 case T_IndexStmt:
256                 case T_CreatePLangStmt:
257                 case T_CreateOpClassStmt:
258                 case T_RuleStmt:
259                 case T_CreateSchemaStmt:
260                 case T_CreateSeqStmt:
261                 case T_CreateStmt:
262                 case T_CreateTableSpaceStmt:
263                 case T_CreateTrigStmt:
264                 case T_CompositeTypeStmt:
265                 case T_CreateUserStmt:
266                 case T_ViewStmt:
267                 case T_RemoveAggrStmt:
268                 case T_DropCastStmt:
269                 case T_DropStmt:
270                 case T_DropdbStmt:
271                 case T_DropTableSpaceStmt:
272                 case T_RemoveFuncStmt:
273                 case T_DropGroupStmt:
274                 case T_DropPLangStmt:
275                 case T_RemoveOperStmt:
276                 case T_RemoveOpClassStmt:
277                 case T_DropPropertyStmt:
278                 case T_DropUserStmt:
279                 case T_GrantStmt:
280                 case T_TruncateStmt:
281                         ereport(ERROR,
282                                         (errcode(ERRCODE_READ_ONLY_SQL_TRANSACTION),
283                                          errmsg("transaction is read-only")));
284                         break;
285                 default:
286                         /* do nothing */
287                         break;
288         }
289 }
290
291
292 /*
293  * ProcessUtility
294  *              general utility function invoker
295  *
296  *      parsetree: the parse tree for the utility statement
297  *      params: parameters to use during execution (currently only used by DECLARE)
298  *      dest: where to send results
299  *      completionTag: points to a buffer of size COMPLETION_TAG_BUFSIZE
300  *              in which to store a command completion status string.
301  *
302  * completionTag is only set nonempty if we want to return a nondefault
303  * status (currently, only used for MOVE/FETCH).
304  *
305  * completionTag may be NULL if caller doesn't want a status string.
306  */
307 void
308 ProcessUtility(Node *parsetree,
309                            ParamListInfo params,
310                            DestReceiver *dest,
311                            char *completionTag)
312 {
313         check_xact_readonly(parsetree);
314
315         if (completionTag)
316                 completionTag[0] = '\0';
317
318         switch (nodeTag(parsetree))
319         {
320                         /*
321                          * ******************** transactions ********************
322                          */
323                 case T_TransactionStmt:
324                         {
325                                 TransactionStmt *stmt = (TransactionStmt *) parsetree;
326
327                                 switch (stmt->kind)
328                                 {
329                                                 /*
330                                                  * START TRANSACTION, as defined by SQL99:
331                                                  * Identical to BEGIN.  Same code for both.
332                                                  */
333                                         case TRANS_STMT_BEGIN:
334                                         case TRANS_STMT_START:
335                                                 {
336                                                         ListCell   *lc;
337
338                                                         BeginTransactionBlock();
339                                                         foreach(lc, stmt->options)
340                                                         {
341                                                                 DefElem    *item = (DefElem *) lfirst(lc);
342
343                                                                 if (strcmp(item->defname, "transaction_isolation") == 0)
344                                                                         SetPGVariable("transaction_isolation",
345                                                                                                   list_make1(item->arg),
346                                                                                                   false);
347                                                                 else if (strcmp(item->defname, "transaction_read_only") == 0)
348                                                                         SetPGVariable("transaction_read_only",
349                                                                                                   list_make1(item->arg),
350                                                                                                   false);
351                                                         }
352                                                 }
353                                                 break;
354
355                                         case TRANS_STMT_COMMIT:
356                                                 if (!EndTransactionBlock())
357                                                 {
358                                                         /* report unsuccessful commit in completionTag */
359                                                         if (completionTag)
360                                                                 strcpy(completionTag, "ROLLBACK");
361                                                 }
362                                                 break;
363
364                                         case TRANS_STMT_ROLLBACK:
365                                                 UserAbortTransactionBlock();
366                                                 break;
367
368                                         case TRANS_STMT_SAVEPOINT:
369                                                 {
370                                                         ListCell   *cell;
371                                                         char       *name = NULL;
372
373                                                         RequireTransactionChain((void *) stmt, "SAVEPOINT");
374
375                                                         foreach(cell, stmt->options)
376                                                         {
377                                                                 DefElem    *elem = lfirst(cell);
378
379                                                                 if (strcmp(elem->defname, "savepoint_name") == 0)
380                                                                         name = strVal(elem->arg);
381                                                         }
382
383                                                         Assert(PointerIsValid(name));
384
385                                                         DefineSavepoint(name);
386                                                 }
387                                                 break;
388
389                                         case TRANS_STMT_RELEASE:
390                                                 RequireTransactionChain((void *) stmt, "RELEASE SAVEPOINT");
391                                                 ReleaseSavepoint(stmt->options);
392                                                 break;
393
394                                         case TRANS_STMT_ROLLBACK_TO:
395                                                 RequireTransactionChain((void *) stmt, "ROLLBACK TO SAVEPOINT");
396                                                 RollbackToSavepoint(stmt->options);
397
398                                                 /*
399                                                  * CommitTransactionCommand is in charge of
400                                                  * re-defining the savepoint again
401                                                  */
402                                                 break;
403                                 }
404                         }
405                         break;
406
407                         /*
408                          * Portal (cursor) manipulation
409                          */
410                 case T_DeclareCursorStmt:
411                         PerformCursorOpen((DeclareCursorStmt *) parsetree, params);
412                         break;
413
414                 case T_ClosePortalStmt:
415                         {
416                                 ClosePortalStmt *stmt = (ClosePortalStmt *) parsetree;
417
418                                 PerformPortalClose(stmt->portalname);
419                         }
420                         break;
421
422                 case T_FetchStmt:
423                         PerformPortalFetch((FetchStmt *) parsetree, dest,
424                                                            completionTag);
425                         break;
426
427                         /*
428                          * relation and attribute manipulation
429                          */
430                 case T_CreateSchemaStmt:
431                         CreateSchemaCommand((CreateSchemaStmt *) parsetree);
432                         break;
433
434                 case T_CreateStmt:
435                         {
436                                 Oid                     relOid;
437
438                                 relOid = DefineRelation((CreateStmt *) parsetree,
439                                                                                 RELKIND_RELATION);
440
441                                 /*
442                                  * Let AlterTableCreateToastTable decide if this one needs
443                                  * a secondary relation too.
444                                  */
445                                 CommandCounterIncrement();
446                                 AlterTableCreateToastTable(relOid, true);
447                         }
448                         break;
449
450                 case T_CreateTableSpaceStmt:
451                         CreateTableSpace((CreateTableSpaceStmt *) parsetree);
452                         break;
453
454                 case T_DropTableSpaceStmt:
455                         DropTableSpace((DropTableSpaceStmt *) parsetree);
456                         break;
457
458                 case T_DropStmt:
459                         {
460                                 DropStmt   *stmt = (DropStmt *) parsetree;
461                                 ListCell   *arg;
462
463                                 foreach(arg, stmt->objects)
464                                 {
465                                         List       *names = (List *) lfirst(arg);
466                                         RangeVar   *rel;
467
468                                         switch (stmt->removeType)
469                                         {
470                                                 case OBJECT_TABLE:
471                                                         rel = makeRangeVarFromNameList(names);
472                                                         CheckDropPermissions(rel, RELKIND_RELATION);
473                                                         RemoveRelation(rel, stmt->behavior);
474                                                         break;
475
476                                                 case OBJECT_SEQUENCE:
477                                                         rel = makeRangeVarFromNameList(names);
478                                                         CheckDropPermissions(rel, RELKIND_SEQUENCE);
479                                                         RemoveRelation(rel, stmt->behavior);
480                                                         break;
481
482                                                 case OBJECT_VIEW:
483                                                         rel = makeRangeVarFromNameList(names);
484                                                         CheckDropPermissions(rel, RELKIND_VIEW);
485                                                         RemoveView(rel, stmt->behavior);
486                                                         break;
487
488                                                 case OBJECT_INDEX:
489                                                         rel = makeRangeVarFromNameList(names);
490                                                         CheckDropPermissions(rel, RELKIND_INDEX);
491                                                         RemoveIndex(rel, stmt->behavior);
492                                                         break;
493
494                                                 case OBJECT_TYPE:
495                                                         /* RemoveType does its own permissions checks */
496                                                         RemoveType(names, stmt->behavior);
497                                                         break;
498
499                                                 case OBJECT_DOMAIN:
500
501                                                         /*
502                                                          * RemoveDomain does its own permissions
503                                                          * checks
504                                                          */
505                                                         RemoveDomain(names, stmt->behavior);
506                                                         break;
507
508                                                 case OBJECT_CONVERSION:
509                                                         DropConversionCommand(names, stmt->behavior);
510                                                         break;
511
512                                                 case OBJECT_SCHEMA:
513
514                                                         /*
515                                                          * RemoveSchema does its own permissions
516                                                          * checks
517                                                          */
518                                                         RemoveSchema(names, stmt->behavior);
519                                                         break;
520
521                                                 default:
522                                                         elog(ERROR, "unrecognized drop object type: %d",
523                                                                  (int) stmt->removeType);
524                                                         break;
525                                         }
526
527                                         /*
528                                          * We used to need to do CommandCounterIncrement()
529                                          * here, but now it's done inside performDeletion().
530                                          */
531                                 }
532                         }
533                         break;
534
535                 case T_TruncateStmt:
536                         {
537                                 TruncateStmt *stmt = (TruncateStmt *) parsetree;
538
539                                 TruncateRelation(stmt->relation);
540                         }
541                         break;
542
543                 case T_CommentStmt:
544                         CommentObject((CommentStmt *) parsetree);
545                         break;
546
547                 case T_CopyStmt:
548                         DoCopy((CopyStmt *) parsetree);
549                         break;
550
551                 case T_PrepareStmt:
552                         PrepareQuery((PrepareStmt *) parsetree);
553                         break;
554
555                 case T_ExecuteStmt:
556                         ExecuteQuery((ExecuteStmt *) parsetree, dest, completionTag);
557                         break;
558
559                 case T_DeallocateStmt:
560                         DeallocateQuery((DeallocateStmt *) parsetree);
561                         break;
562
563                         /*
564                          * schema
565                          */
566                 case T_RenameStmt:
567                         ExecRenameStmt((RenameStmt *) parsetree);
568                         break;
569
570                 case T_AlterOwnerStmt:
571                         ExecAlterOwnerStmt((AlterOwnerStmt *) parsetree);
572                         break;
573
574                 case T_AlterTableStmt:
575                         AlterTable((AlterTableStmt *) parsetree);
576                         break;
577
578                 case T_AlterDomainStmt:
579                         {
580                                 AlterDomainStmt *stmt = (AlterDomainStmt *) parsetree;
581
582                                 /*
583                                  * Some or all of these functions are recursive to cover
584                                  * inherited things, so permission checks are done there.
585                                  */
586                                 switch (stmt->subtype)
587                                 {
588                                         case 'T':       /* ALTER DOMAIN DEFAULT */
589
590                                                 /*
591                                                  * Recursively alter column default for table and,
592                                                  * if requested, for descendants
593                                                  */
594                                                 AlterDomainDefault(stmt->typename,
595                                                                                    stmt->def);
596                                                 break;
597                                         case 'N':       /* ALTER DOMAIN DROP NOT NULL */
598                                                 AlterDomainNotNull(stmt->typename,
599                                                                                    false);
600                                                 break;
601                                         case 'O':       /* ALTER DOMAIN SET NOT NULL */
602                                                 AlterDomainNotNull(stmt->typename,
603                                                                                    true);
604                                                 break;
605                                         case 'C':       /* ADD CONSTRAINT */
606                                                 AlterDomainAddConstraint(stmt->typename,
607                                                                                                  stmt->def);
608                                                 break;
609                                         case 'X':       /* DROP CONSTRAINT */
610                                                 AlterDomainDropConstraint(stmt->typename,
611                                                                                                   stmt->name,
612                                                                                                   stmt->behavior);
613                                                 break;
614                                         default:        /* oops */
615                                                 elog(ERROR, "unrecognized alter domain type: %d",
616                                                          (int) stmt->subtype);
617                                                 break;
618                                 }
619                         }
620                         break;
621
622
623                 case T_GrantStmt:
624                         ExecuteGrantStmt((GrantStmt *) parsetree);
625                         break;
626
627                         /*
628                          * ******************************** object creation /
629                          * destruction ********************************
630                          *
631                          */
632                 case T_DefineStmt:
633                         {
634                                 DefineStmt *stmt = (DefineStmt *) parsetree;
635
636                                 switch (stmt->kind)
637                                 {
638                                         case OBJECT_AGGREGATE:
639                                                 DefineAggregate(stmt->defnames, stmt->definition);
640                                                 break;
641                                         case OBJECT_OPERATOR:
642                                                 DefineOperator(stmt->defnames, stmt->definition);
643                                                 break;
644                                         case OBJECT_TYPE:
645                                                 DefineType(stmt->defnames, stmt->definition);
646                                                 break;
647                                         default:
648                                                 elog(ERROR, "unrecognized define stmt type: %d",
649                                                          (int) stmt->kind);
650                                                 break;
651                                 }
652                         }
653                         break;
654
655                 case T_CompositeTypeStmt:               /* CREATE TYPE (composite) */
656                         {
657                                 CompositeTypeStmt *stmt = (CompositeTypeStmt *) parsetree;
658
659                                 DefineCompositeType(stmt->typevar, stmt->coldeflist);
660                         }
661                         break;
662
663                 case T_ViewStmt:                /* CREATE VIEW */
664                         {
665                                 ViewStmt   *stmt = (ViewStmt *) parsetree;
666
667                                 DefineView(stmt->view, stmt->query, stmt->replace);
668                         }
669                         break;
670
671                 case T_CreateFunctionStmt:              /* CREATE FUNCTION */
672                         CreateFunction((CreateFunctionStmt *) parsetree);
673                         break;
674
675                 case T_IndexStmt:               /* CREATE INDEX */
676                         {
677                                 IndexStmt  *stmt = (IndexStmt *) parsetree;
678
679                                 CheckRelationOwnership(stmt->relation, true);
680
681                                 DefineIndex(stmt->relation,             /* relation */
682                                                         stmt->idxname,          /* index name */
683                                                         stmt->accessMethod, /* am name */
684                                                         stmt->tableSpace,
685                                                         stmt->indexParams,      /* parameters */
686                                                         (Expr *) stmt->whereClause,
687                                                         stmt->rangetable,
688                                                         stmt->unique,
689                                                         stmt->primary,
690                                                         stmt->isconstraint,
691                                                         false,          /* is_alter_table */
692                                                         true,           /* check_rights */
693                                                         false,          /* skip_build */
694                                                         false);         /* quiet */
695                         }
696                         break;
697
698                 case T_RuleStmt:                /* CREATE RULE */
699                         DefineQueryRewrite((RuleStmt *) parsetree);
700                         break;
701
702                 case T_CreateSeqStmt:
703                         DefineSequence((CreateSeqStmt *) parsetree);
704                         break;
705
706                 case T_AlterSeqStmt:
707                         AlterSequence((AlterSeqStmt *) parsetree);
708                         break;
709
710                 case T_RemoveAggrStmt:
711                         RemoveAggregate((RemoveAggrStmt *) parsetree);
712                         break;
713
714                 case T_RemoveFuncStmt:
715                         RemoveFunction((RemoveFuncStmt *) parsetree);
716                         break;
717
718                 case T_RemoveOperStmt:
719                         RemoveOperator((RemoveOperStmt *) parsetree);
720                         break;
721
722                 case T_CreatedbStmt:
723                         createdb((CreatedbStmt *) parsetree);
724                         break;
725
726                 case T_AlterDatabaseSetStmt:
727                         AlterDatabaseSet((AlterDatabaseSetStmt *) parsetree);
728                         break;
729
730                 case T_DropdbStmt:
731                         {
732                                 DropdbStmt *stmt = (DropdbStmt *) parsetree;
733
734                                 dropdb(stmt->dbname);
735                         }
736                         break;
737
738                         /* Query-level asynchronous notification */
739                 case T_NotifyStmt:
740                         {
741                                 NotifyStmt *stmt = (NotifyStmt *) parsetree;
742
743                                 Async_Notify(stmt->relation->relname);
744                         }
745                         break;
746
747                 case T_ListenStmt:
748                         {
749                                 ListenStmt *stmt = (ListenStmt *) parsetree;
750
751                                 Async_Listen(stmt->relation->relname, MyProcPid);
752                         }
753                         break;
754
755                 case T_UnlistenStmt:
756                         {
757                                 UnlistenStmt *stmt = (UnlistenStmt *) parsetree;
758
759                                 Async_Unlisten(stmt->relation->relname, MyProcPid);
760                         }
761                         break;
762
763                 case T_LoadStmt:
764                         {
765                                 LoadStmt   *stmt = (LoadStmt *) parsetree;
766
767                                 closeAllVfds(); /* probably not necessary... */
768                                 load_file(stmt->filename);
769                         }
770                         break;
771
772                 case T_ClusterStmt:
773                         cluster((ClusterStmt *) parsetree);
774                         break;
775
776                 case T_VacuumStmt:
777                         vacuum((VacuumStmt *) parsetree);
778                         break;
779
780                 case T_ExplainStmt:
781                         ExplainQuery((ExplainStmt *) parsetree, dest);
782                         break;
783
784                 case T_VariableSetStmt:
785                         {
786                                 VariableSetStmt *n = (VariableSetStmt *) parsetree;
787
788                                 /*
789                                  * Special cases for special SQL syntax that effectively
790                                  * sets more than one variable per statement.
791                                  */
792                                 if (strcmp(n->name, "TRANSACTION") == 0)
793                                 {
794                                         ListCell   *head;
795
796                                         foreach(head, n->args)
797                                         {
798                                                 DefElem    *item = (DefElem *) lfirst(head);
799
800                                                 if (strcmp(item->defname, "transaction_isolation") == 0)
801                                                         SetPGVariable("transaction_isolation",
802                                                                          list_make1(item->arg), n->is_local);
803                                                 else if (strcmp(item->defname, "transaction_read_only") == 0)
804                                                         SetPGVariable("transaction_read_only",
805                                                                          list_make1(item->arg), n->is_local);
806                                         }
807                                 }
808                                 else if (strcmp(n->name, "SESSION CHARACTERISTICS") == 0)
809                                 {
810                                         ListCell   *head;
811
812                                         foreach(head, n->args)
813                                         {
814                                                 DefElem    *item = (DefElem *) lfirst(head);
815
816                                                 if (strcmp(item->defname, "transaction_isolation") == 0)
817                                                         SetPGVariable("default_transaction_isolation",
818                                                                          list_make1(item->arg), n->is_local);
819                                                 else if (strcmp(item->defname, "transaction_read_only") == 0)
820                                                         SetPGVariable("default_transaction_read_only",
821                                                                          list_make1(item->arg), n->is_local);
822                                         }
823                                 }
824                                 else
825                                         SetPGVariable(n->name, n->args, n->is_local);
826                         }
827                         break;
828
829                 case T_VariableShowStmt:
830                         {
831                                 VariableShowStmt *n = (VariableShowStmt *) parsetree;
832
833                                 GetPGVariable(n->name, dest);
834                         }
835                         break;
836
837                 case T_VariableResetStmt:
838                         {
839                                 VariableResetStmt *n = (VariableResetStmt *) parsetree;
840
841                                 ResetPGVariable(n->name);
842                         }
843                         break;
844
845                 case T_CreateTrigStmt:
846                         CreateTrigger((CreateTrigStmt *) parsetree, false);
847                         break;
848
849                 case T_DropPropertyStmt:
850                         {
851                                 DropPropertyStmt *stmt = (DropPropertyStmt *) parsetree;
852                                 Oid                     relId;
853
854                                 relId = RangeVarGetRelid(stmt->relation, false);
855
856                                 switch (stmt->removeType)
857                                 {
858                                         case OBJECT_RULE:
859                                                 /* RemoveRewriteRule checks permissions */
860                                                 RemoveRewriteRule(relId, stmt->property,
861                                                                                   stmt->behavior);
862                                                 break;
863                                         case OBJECT_TRIGGER:
864                                                 /* DropTrigger checks permissions */
865                                                 DropTrigger(relId, stmt->property,
866                                                                         stmt->behavior);
867                                                 break;
868                                         default:
869                                                 elog(ERROR, "unrecognized object type: %d",
870                                                          (int) stmt->removeType);
871                                                 break;
872                                 }
873                         }
874                         break;
875
876                 case T_CreatePLangStmt:
877                         CreateProceduralLanguage((CreatePLangStmt *) parsetree);
878                         break;
879
880                 case T_DropPLangStmt:
881                         DropProceduralLanguage((DropPLangStmt *) parsetree);
882                         break;
883
884                         /*
885                          * ******************************** DOMAIN statements ****
886                          */
887                 case T_CreateDomainStmt:
888                         DefineDomain((CreateDomainStmt *) parsetree);
889                         break;
890
891                         /*
892                          * ******************************** USER statements ****
893                          */
894                 case T_CreateUserStmt:
895                         CreateUser((CreateUserStmt *) parsetree);
896                         break;
897
898                 case T_AlterUserStmt:
899                         AlterUser((AlterUserStmt *) parsetree);
900                         break;
901
902                 case T_AlterUserSetStmt:
903                         AlterUserSet((AlterUserSetStmt *) parsetree);
904                         break;
905
906                 case T_DropUserStmt:
907                         DropUser((DropUserStmt *) parsetree);
908                         break;
909
910                 case T_LockStmt:
911                         LockTableCommand((LockStmt *) parsetree);
912                         break;
913
914                 case T_ConstraintsSetStmt:
915                         DeferredTriggerSetState((ConstraintsSetStmt *) parsetree);
916                         break;
917
918                 case T_CreateGroupStmt:
919                         CreateGroup((CreateGroupStmt *) parsetree);
920                         break;
921
922                 case T_AlterGroupStmt:
923                         AlterGroup((AlterGroupStmt *) parsetree, "ALTER GROUP");
924                         break;
925
926                 case T_DropGroupStmt:
927                         DropGroup((DropGroupStmt *) parsetree);
928                         break;
929
930                 case T_CheckPointStmt:
931                         if (!superuser())
932                                 ereport(ERROR,
933                                                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
934                                                  errmsg("must be superuser to do CHECKPOINT")));
935                         RequestCheckpoint(true);
936                         break;
937
938                 case T_ReindexStmt:
939                         {
940                                 ReindexStmt *stmt = (ReindexStmt *) parsetree;
941
942                                 switch (stmt->kind)
943                                 {
944                                         case OBJECT_INDEX:
945                                                 ReindexIndex(stmt->relation, stmt->force);
946                                                 break;
947                                         case OBJECT_TABLE:
948                                                 ReindexTable(stmt->relation, stmt->force);
949                                                 break;
950                                         case OBJECT_DATABASE:
951                                                 ReindexDatabase(stmt->name, stmt->force, false);
952                                                 break;
953                                         default:
954                                                 elog(ERROR, "unrecognized object type: %d",
955                                                          (int) stmt->kind);
956                                                 break;
957                                 }
958                                 break;
959                         }
960                         break;
961
962                 case T_CreateConversionStmt:
963                         CreateConversionCommand((CreateConversionStmt *) parsetree);
964                         break;
965
966                 case T_CreateCastStmt:
967                         CreateCast((CreateCastStmt *) parsetree);
968                         break;
969
970                 case T_DropCastStmt:
971                         DropCast((DropCastStmt *) parsetree);
972                         break;
973
974                 case T_CreateOpClassStmt:
975                         DefineOpClass((CreateOpClassStmt *) parsetree);
976                         break;
977
978                 case T_RemoveOpClassStmt:
979                         RemoveOpClass((RemoveOpClassStmt *) parsetree);
980                         break;
981
982                 default:
983                         elog(ERROR, "unrecognized node type: %d",
984                                  (int) nodeTag(parsetree));
985                         break;
986         }
987 }
988
989 /*
990  * UtilityReturnsTuples
991  *              Return "true" if this utility statement will send output to the
992  *              destination.
993  *
994  * Generally, there should be a case here for each case in ProcessUtility
995  * where "dest" is passed on.
996  */
997 bool
998 UtilityReturnsTuples(Node *parsetree)
999 {
1000         switch (nodeTag(parsetree))
1001         {
1002                 case T_FetchStmt:
1003                         {
1004                                 FetchStmt  *stmt = (FetchStmt *) parsetree;
1005                                 Portal          portal;
1006
1007                                 if (stmt->ismove)
1008                                         return false;
1009                                 portal = GetPortalByName(stmt->portalname);
1010                                 if (!PortalIsValid(portal))
1011                                         return false;           /* not our business to raise error */
1012                                 return portal->tupDesc ? true : false;
1013                         }
1014
1015                 case T_ExecuteStmt:
1016                         {
1017                                 ExecuteStmt *stmt = (ExecuteStmt *) parsetree;
1018                                 PreparedStatement *entry;
1019
1020                                 if (stmt->into)
1021                                         return false;
1022                                 entry = FetchPreparedStatement(stmt->name, false);
1023                                 if (!entry)
1024                                         return false;           /* not our business to raise error */
1025                                 switch (ChoosePortalStrategy(entry->query_list))
1026                                 {
1027                                         case PORTAL_ONE_SELECT:
1028                                                 return true;
1029                                         case PORTAL_UTIL_SELECT:
1030                                                 return true;
1031                                         case PORTAL_MULTI_QUERY:
1032                                                 /* will not return tuples */
1033                                                 break;
1034                                 }
1035                                 return false;
1036                         }
1037
1038                 case T_ExplainStmt:
1039                         return true;
1040
1041                 case T_VariableShowStmt:
1042                         return true;
1043
1044                 default:
1045                         return false;
1046         }
1047 }
1048
1049 /*
1050  * UtilityTupleDescriptor
1051  *              Fetch the actual output tuple descriptor for a utility statement
1052  *              for which UtilityReturnsTuples() previously returned "true".
1053  *
1054  * The returned descriptor is created in (or copied into) the current memory
1055  * context.
1056  */
1057 TupleDesc
1058 UtilityTupleDescriptor(Node *parsetree)
1059 {
1060         switch (nodeTag(parsetree))
1061         {
1062                 case T_FetchStmt:
1063                         {
1064                                 FetchStmt  *stmt = (FetchStmt *) parsetree;
1065                                 Portal          portal;
1066
1067                                 if (stmt->ismove)
1068                                         return NULL;
1069                                 portal = GetPortalByName(stmt->portalname);
1070                                 if (!PortalIsValid(portal))
1071                                         return NULL;    /* not our business to raise error */
1072                                 return CreateTupleDescCopy(portal->tupDesc);
1073                         }
1074
1075                 case T_ExecuteStmt:
1076                         {
1077                                 ExecuteStmt *stmt = (ExecuteStmt *) parsetree;
1078                                 PreparedStatement *entry;
1079
1080                                 if (stmt->into)
1081                                         return NULL;
1082                                 entry = FetchPreparedStatement(stmt->name, false);
1083                                 if (!entry)
1084                                         return NULL;    /* not our business to raise error */
1085                                 return FetchPreparedStatementResultDesc(entry);
1086                         }
1087
1088                 case T_ExplainStmt:
1089                         return ExplainResultDesc((ExplainStmt *) parsetree);
1090
1091                 case T_VariableShowStmt:
1092                         {
1093                                 VariableShowStmt *n = (VariableShowStmt *) parsetree;
1094
1095                                 return GetPGVariableResultDesc(n->name);
1096                         }
1097
1098                 default:
1099                         return NULL;
1100         }
1101 }
1102
1103
1104 /*
1105  * CreateCommandTag
1106  *              utility to get a string representation of the
1107  *              command operation, given a raw (un-analyzed) parsetree.
1108  *
1109  * This must handle all raw command types, but since the vast majority
1110  * of 'em are utility commands, it seems sensible to keep it here.
1111  *
1112  * NB: all result strings must be shorter than COMPLETION_TAG_BUFSIZE.
1113  * Also, the result must point at a true constant (permanent storage).
1114  */
1115 const char *
1116 CreateCommandTag(Node *parsetree)
1117 {
1118         const char *tag;
1119
1120         switch (nodeTag(parsetree))
1121         {
1122                 case T_InsertStmt:
1123                         tag = "INSERT";
1124                         break;
1125
1126                 case T_DeleteStmt:
1127                         tag = "DELETE";
1128                         break;
1129
1130                 case T_UpdateStmt:
1131                         tag = "UPDATE";
1132                         break;
1133
1134                 case T_SelectStmt:
1135                         tag = "SELECT";
1136                         break;
1137
1138                 case T_TransactionStmt:
1139                         {
1140                                 TransactionStmt *stmt = (TransactionStmt *) parsetree;
1141
1142                                 switch (stmt->kind)
1143                                 {
1144                                         case TRANS_STMT_BEGIN:
1145                                                 tag = "BEGIN";
1146                                                 break;
1147
1148                                         case TRANS_STMT_START:
1149                                                 tag = "START TRANSACTION";
1150                                                 break;
1151
1152                                         case TRANS_STMT_COMMIT:
1153                                                 tag = "COMMIT";
1154                                                 break;
1155
1156                                         case TRANS_STMT_ROLLBACK:
1157                                         case TRANS_STMT_ROLLBACK_TO:
1158                                                 tag = "ROLLBACK";
1159                                                 break;
1160
1161                                         case TRANS_STMT_SAVEPOINT:
1162                                                 tag = "SAVEPOINT";
1163                                                 break;
1164
1165                                         case TRANS_STMT_RELEASE:
1166                                                 tag = "RELEASE";
1167                                                 break;
1168
1169                                         default:
1170                                                 tag = "???";
1171                                                 break;
1172                                 }
1173                         }
1174                         break;
1175
1176                 case T_DeclareCursorStmt:
1177                         tag = "DECLARE CURSOR";
1178                         break;
1179
1180                 case T_ClosePortalStmt:
1181                         tag = "CLOSE CURSOR";
1182                         break;
1183
1184                 case T_FetchStmt:
1185                         {
1186                                 FetchStmt  *stmt = (FetchStmt *) parsetree;
1187
1188                                 tag = (stmt->ismove) ? "MOVE" : "FETCH";
1189                         }
1190                         break;
1191
1192                 case T_CreateDomainStmt:
1193                         tag = "CREATE DOMAIN";
1194                         break;
1195
1196                 case T_CreateSchemaStmt:
1197                         tag = "CREATE SCHEMA";
1198                         break;
1199
1200                 case T_CreateStmt:
1201                         tag = "CREATE TABLE";
1202                         break;
1203
1204                 case T_CreateTableSpaceStmt:
1205                         tag = "CREATE TABLESPACE";
1206                         break;
1207
1208                 case T_DropTableSpaceStmt:
1209                         tag = "DROP TABLESPACE";
1210                         break;
1211
1212                 case T_DropStmt:
1213                         switch (((DropStmt *) parsetree)->removeType)
1214                         {
1215                                 case OBJECT_TABLE:
1216                                         tag = "DROP TABLE";
1217                                         break;
1218                                 case OBJECT_SEQUENCE:
1219                                         tag = "DROP SEQUENCE";
1220                                         break;
1221                                 case OBJECT_VIEW:
1222                                         tag = "DROP VIEW";
1223                                         break;
1224                                 case OBJECT_INDEX:
1225                                         tag = "DROP INDEX";
1226                                         break;
1227                                 case OBJECT_TYPE:
1228                                         tag = "DROP TYPE";
1229                                         break;
1230                                 case OBJECT_DOMAIN:
1231                                         tag = "DROP DOMAIN";
1232                                         break;
1233                                 case OBJECT_CONVERSION:
1234                                         tag = "DROP CONVERSION";
1235                                         break;
1236                                 case OBJECT_SCHEMA:
1237                                         tag = "DROP SCHEMA";
1238                                         break;
1239                                 default:
1240                                         tag = "???";
1241                         }
1242                         break;
1243
1244                 case T_TruncateStmt:
1245                         tag = "TRUNCATE TABLE";
1246                         break;
1247
1248                 case T_CommentStmt:
1249                         tag = "COMMENT";
1250                         break;
1251
1252                 case T_CopyStmt:
1253                         tag = "COPY";
1254                         break;
1255
1256                 case T_RenameStmt:
1257                         switch (((RenameStmt *) parsetree)->renameType)
1258                         {
1259                                 case OBJECT_AGGREGATE:
1260                                         tag = "ALTER AGGREGATE";
1261                                         break;
1262                                 case OBJECT_CONVERSION:
1263                                         tag = "ALTER CONVERSION";
1264                                         break;
1265                                 case OBJECT_DATABASE:
1266                                         tag = "ALTER DATABASE";
1267                                         break;
1268                                 case OBJECT_FUNCTION:
1269                                         tag = "ALTER FUNCTION";
1270                                         break;
1271                                 case OBJECT_GROUP:
1272                                         tag = "ALTER GROUP";
1273                                         break;
1274                                 case OBJECT_INDEX:
1275                                         tag = "ALTER INDEX";
1276                                         break;
1277                                 case OBJECT_LANGUAGE:
1278                                         tag = "ALTER LANGUAGE";
1279                                         break;
1280                                 case OBJECT_OPCLASS:
1281                                         tag = "ALTER OPERATOR CLASS";
1282                                         break;
1283                                 case OBJECT_SCHEMA:
1284                                         tag = "ALTER SCHEMA";
1285                                         break;
1286                                 case OBJECT_TABLESPACE:
1287                                         tag = "ALTER TABLESPACE";
1288                                         break;
1289                                 case OBJECT_TRIGGER:
1290                                         tag = "ALTER TRIGGER";
1291                                         break;
1292                                 case OBJECT_USER:
1293                                         tag = "ALTER USER";
1294                                         break;
1295                                 default:
1296                                         tag = "ALTER TABLE";
1297                         }
1298                         break;
1299
1300                 case T_AlterOwnerStmt:
1301                         switch (((AlterOwnerStmt *) parsetree)->objectType)
1302                         {
1303                                 case OBJECT_AGGREGATE:
1304                                         tag = "ALTER AGGREGATE";
1305                                         break;
1306                                 case OBJECT_CONVERSION:
1307                                         tag = "ALTER CONVERSION";
1308                                         break;
1309                                 case OBJECT_DATABASE:
1310                                         tag = "ALTER DATABASE";
1311                                         break;
1312                                 case OBJECT_DOMAIN:
1313                                         tag = "ALTER DOMAIN";
1314                                         break;
1315                                 case OBJECT_FUNCTION:
1316                                         tag = "ALTER FUNCTION";
1317                                         break;
1318                                 case OBJECT_OPERATOR:
1319                                         tag = "ALTER OPERATOR";
1320                                         break;
1321                                 case OBJECT_OPCLASS:
1322                                         tag = "ALTER OPERATOR CLASS";
1323                                         break;
1324                                 case OBJECT_SCHEMA:
1325                                         tag = "ALTER SCHEMA";
1326                                         break;
1327                                 case OBJECT_TABLESPACE:
1328                                         tag = "ALTER TABLESPACE";
1329                                         break;
1330                                 case OBJECT_TYPE:
1331                                         tag = "ALTER TYPE";
1332                                         break;
1333                                 default:
1334                                         tag = "ALTER TABLE";
1335                         }
1336                         break;
1337
1338                 case T_AlterTableStmt:
1339                         {
1340                                 AlterTableStmt *stmt = (AlterTableStmt *) parsetree;
1341
1342                                 /*
1343                                  * We might be supporting ALTER INDEX here, so set the
1344                                  * completion table appropriately. Catch all other
1345                                  * possibilities with ALTER TABLE
1346                                  */
1347
1348                                 if (stmt->relkind == OBJECT_INDEX)
1349                                         tag = "ALTER INDEX";
1350                                 else
1351                                         tag = "ALTER TABLE";
1352                         }
1353                         break;
1354                 case T_AlterDomainStmt:
1355                         tag = "ALTER DOMAIN";
1356                         break;
1357
1358                 case T_GrantStmt:
1359                         {
1360                                 GrantStmt  *stmt = (GrantStmt *) parsetree;
1361
1362                                 tag = (stmt->is_grant) ? "GRANT" : "REVOKE";
1363                         }
1364                         break;
1365
1366                 case T_DefineStmt:
1367                         switch (((DefineStmt *) parsetree)->kind)
1368                         {
1369                                 case OBJECT_AGGREGATE:
1370                                         tag = "CREATE AGGREGATE";
1371                                         break;
1372                                 case OBJECT_OPERATOR:
1373                                         tag = "CREATE OPERATOR";
1374                                         break;
1375                                 case OBJECT_TYPE:
1376                                         tag = "CREATE TYPE";
1377                                         break;
1378                                 default:
1379                                         tag = "???";
1380                         }
1381                         break;
1382
1383                 case T_CompositeTypeStmt:
1384                         tag = "CREATE TYPE";
1385                         break;
1386
1387                 case T_ViewStmt:
1388                         tag = "CREATE VIEW";
1389                         break;
1390
1391                 case T_CreateFunctionStmt:
1392                         tag = "CREATE FUNCTION";
1393                         break;
1394
1395                 case T_IndexStmt:
1396                         tag = "CREATE INDEX";
1397                         break;
1398
1399                 case T_RuleStmt:
1400                         tag = "CREATE RULE";
1401                         break;
1402
1403                 case T_CreateSeqStmt:
1404                         tag = "CREATE SEQUENCE";
1405                         break;
1406
1407                 case T_AlterSeqStmt:
1408                         tag = "ALTER SEQUENCE";
1409                         break;
1410
1411                 case T_RemoveAggrStmt:
1412                         tag = "DROP AGGREGATE";
1413                         break;
1414
1415                 case T_RemoveFuncStmt:
1416                         tag = "DROP FUNCTION";
1417                         break;
1418
1419                 case T_RemoveOperStmt:
1420                         tag = "DROP OPERATOR";
1421                         break;
1422
1423                 case T_CreatedbStmt:
1424                         tag = "CREATE DATABASE";
1425                         break;
1426
1427                 case T_AlterDatabaseSetStmt:
1428                         tag = "ALTER DATABASE";
1429                         break;
1430
1431                 case T_DropdbStmt:
1432                         tag = "DROP DATABASE";
1433                         break;
1434
1435                 case T_NotifyStmt:
1436                         tag = "NOTIFY";
1437                         break;
1438
1439                 case T_ListenStmt:
1440                         tag = "LISTEN";
1441                         break;
1442
1443                 case T_UnlistenStmt:
1444                         tag = "UNLISTEN";
1445                         break;
1446
1447                 case T_LoadStmt:
1448                         tag = "LOAD";
1449                         break;
1450
1451                 case T_ClusterStmt:
1452                         tag = "CLUSTER";
1453                         break;
1454
1455                 case T_VacuumStmt:
1456                         if (((VacuumStmt *) parsetree)->vacuum)
1457                                 tag = "VACUUM";
1458                         else
1459                                 tag = "ANALYZE";
1460                         break;
1461
1462                 case T_ExplainStmt:
1463                         tag = "EXPLAIN";
1464                         break;
1465
1466                 case T_VariableSetStmt:
1467                         tag = "SET";
1468                         break;
1469
1470                 case T_VariableShowStmt:
1471                         tag = "SHOW";
1472                         break;
1473
1474                 case T_VariableResetStmt:
1475                         tag = "RESET";
1476                         break;
1477
1478                 case T_CreateTrigStmt:
1479                         tag = "CREATE TRIGGER";
1480                         break;
1481
1482                 case T_DropPropertyStmt:
1483                         switch (((DropPropertyStmt *) parsetree)->removeType)
1484                         {
1485                                 case OBJECT_TRIGGER:
1486                                         tag = "DROP TRIGGER";
1487                                         break;
1488                                 case OBJECT_RULE:
1489                                         tag = "DROP RULE";
1490                                         break;
1491                                 default:
1492                                         tag = "???";
1493                         }
1494                         break;
1495
1496                 case T_CreatePLangStmt:
1497                         tag = "CREATE LANGUAGE";
1498                         break;
1499
1500                 case T_DropPLangStmt:
1501                         tag = "DROP LANGUAGE";
1502                         break;
1503
1504                 case T_CreateUserStmt:
1505                         tag = "CREATE USER";
1506                         break;
1507
1508                 case T_AlterUserStmt:
1509                         tag = "ALTER USER";
1510                         break;
1511
1512                 case T_AlterUserSetStmt:
1513                         tag = "ALTER USER";
1514                         break;
1515
1516                 case T_DropUserStmt:
1517                         tag = "DROP USER";
1518                         break;
1519
1520                 case T_LockStmt:
1521                         tag = "LOCK TABLE";
1522                         break;
1523
1524                 case T_ConstraintsSetStmt:
1525                         tag = "SET CONSTRAINTS";
1526                         break;
1527
1528                 case T_CreateGroupStmt:
1529                         tag = "CREATE GROUP";
1530                         break;
1531
1532                 case T_AlterGroupStmt:
1533                         tag = "ALTER GROUP";
1534                         break;
1535
1536                 case T_DropGroupStmt:
1537                         tag = "DROP GROUP";
1538                         break;
1539
1540                 case T_CheckPointStmt:
1541                         tag = "CHECKPOINT";
1542                         break;
1543
1544                 case T_ReindexStmt:
1545                         tag = "REINDEX";
1546                         break;
1547
1548                 case T_CreateConversionStmt:
1549                         tag = "CREATE CONVERSION";
1550                         break;
1551
1552                 case T_CreateCastStmt:
1553                         tag = "CREATE CAST";
1554                         break;
1555
1556                 case T_DropCastStmt:
1557                         tag = "DROP CAST";
1558                         break;
1559
1560                 case T_CreateOpClassStmt:
1561                         tag = "CREATE OPERATOR CLASS";
1562                         break;
1563
1564                 case T_RemoveOpClassStmt:
1565                         tag = "DROP OPERATOR CLASS";
1566                         break;
1567
1568                 case T_PrepareStmt:
1569                         tag = "PREPARE";
1570                         break;
1571
1572                 case T_ExecuteStmt:
1573                         tag = "EXECUTE";
1574                         break;
1575
1576                 case T_DeallocateStmt:
1577                         tag = "DEALLOCATE";
1578                         break;
1579
1580                 default:
1581                         elog(WARNING, "unrecognized node type: %d",
1582                                  (int) nodeTag(parsetree));
1583                         tag = "???";
1584                         break;
1585         }
1586
1587         return tag;
1588 }