]> granicus.if.org Git - postgresql/blob - src/backend/tcop/utility.c
From: t-ishii@sra.co.jp
[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  * Copyright (c) 1994, Regents of the University of California
9  *
10  *
11  * IDENTIFICATION
12  *        $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.44 1998/07/26 04:30:48 scrappy Exp $
13  *
14  *-------------------------------------------------------------------------
15  */
16 #include "postgres.h"
17 #include "access/xact.h"
18 #include "access/heapam.h"
19 #include "catalog/catalog.h"
20 #include "catalog/pg_type.h"
21
22 #include "commands/async.h"
23 #include "commands/cluster.h"
24 #include "commands/command.h"
25 #include "commands/copy.h"
26 #include "commands/creatinh.h"
27 #include "commands/dbcommands.h"
28 #include "commands/sequence.h"
29 #include "commands/defrem.h"
30 #include "commands/rename.h"
31 #include "commands/view.h"
32 #include "commands/version.h"
33 #include "commands/vacuum.h"
34 #include "commands/recipe.h"
35 #include "commands/explain.h"
36 #include "commands/trigger.h"
37 #include "commands/proclang.h"
38 #include "commands/variable.h"
39
40 #include "nodes/parsenodes.h"
41 #include "../backend/parser/parse.h"
42 #include "utils/builtins.h"
43 #include "utils/acl.h"
44 #include "utils/palloc.h"
45 #include "rewrite/rewriteRemove.h"
46 #include "rewrite/rewriteDefine.h"
47 #include "tcop/tcopdebug.h"
48 #include "tcop/dest.h"
49 #include "tcop/utility.h"
50 #include "fmgr.h"                               /* For load_file() */
51 #include "storage/fd.h"
52
53 #ifndef NO_SECURITY
54 #include "miscadmin.h"
55 #include "utils/acl.h"
56 #include "utils/syscache.h"
57 #endif
58
59 void            DefineUser(CreateUserStmt *stmt);
60 void            AlterUser(AlterUserStmt *stmt);
61 void            RemoveUser(char *username);
62
63 extern const char **ps_status;  /* from postgres.c */
64
65 /* ----------------
66  *              CHECK_IF_ABORTED() is used to avoid doing unnecessary
67  *              processing within an aborted transaction block.
68  * ----------------
69  */
70  /* we have to use IF because of the 'break' */
71 #define CHECK_IF_ABORTED() \
72 if (1) \
73 { \
74         if (IsAbortedTransactionBlockState()) \
75         { \
76                 elog(NOTICE, "(transaction aborted): %s", \
77                          "all queries ignored until end of transaction block"); \
78                 commandTag = "*ABORT STATE*"; \
79                 break; \
80         } \
81 } else
82
83 /* ----------------
84  *              general utility function invoker
85  * ----------------
86  */
87 void
88 ProcessUtility(Node *parsetree,
89                            CommandDest dest)
90 {
91         char       *commandTag = NULL;
92         char       *relname;
93         char       *relationName;
94         char       *userName;
95
96         userName = GetPgUserName();
97
98         switch (nodeTag(parsetree))
99         {
100
101                         /*
102                          * ******************************** transactions ********************************
103                          *
104                          */
105                 case T_TransactionStmt:
106                         {
107                                 TransactionStmt *stmt = (TransactionStmt *) parsetree;
108
109                                 switch (stmt->command)
110                                 {
111                                         case BEGIN_TRANS:
112                                                 *ps_status = commandTag = "BEGIN";
113                                                 CHECK_IF_ABORTED();
114                                                 BeginTransactionBlock();
115                                                 break;
116
117                                         case END_TRANS:
118                                                 *ps_status = commandTag = "END";
119                                                 EndTransactionBlock();
120                                                 break;
121
122                                         case ABORT_TRANS:
123                                                 *ps_status = commandTag = "ABORT";
124                                                 UserAbortTransactionBlock();
125                                                 break;
126                                 }
127                         }
128                         break;
129
130                         /*
131                          * ******************************** portal manipulation ********************************
132                          *
133                          */
134                 case T_ClosePortalStmt:
135                         {
136                                 ClosePortalStmt *stmt = (ClosePortalStmt *) parsetree;
137
138                                 *ps_status = commandTag = "CLOSE";
139                                 CHECK_IF_ABORTED();
140
141                                 PerformPortalClose(stmt->portalname, dest);
142                         }
143                         break;
144
145                 case T_FetchStmt:
146                         {
147                                 FetchStmt  *stmt = (FetchStmt *) parsetree;
148                                 char       *portalName = stmt->portalname;
149                                 bool            forward;
150                                 int                     count;
151
152                                 *ps_status = commandTag = (stmt->ismove) ? "MOVE" : "FETCH";
153                                 CHECK_IF_ABORTED();
154
155                                 forward = (bool) (stmt->direction == FORWARD);
156
157                                 /*
158                                  * parser ensures that count is >= 0 and 'fetch ALL' -> 0
159                                  */
160
161                                 count = stmt->howMany;
162                                 PerformPortalFetch(portalName, forward, count, commandTag,
163                                                                    (stmt->ismove) ? None : dest);               /* /dev/null for MOVE */
164                         }
165                         break;
166
167                         /*
168                          * ******************************** relation and attribute
169                          * manipulation ********************************
170                          *
171                          */
172                 case T_CreateStmt:
173                         *ps_status = commandTag = "CREATE";
174                         CHECK_IF_ABORTED();
175
176                         DefineRelation((CreateStmt *) parsetree);
177                         break;
178
179                 case T_DestroyStmt:
180                         {
181                                 DestroyStmt *stmt = (DestroyStmt *) parsetree;
182                                 List       *arg;
183                                 List       *args = stmt->relNames;
184                                 Relation        rel;
185
186                                 *ps_status = commandTag = "DROP";
187                                 CHECK_IF_ABORTED();
188
189                                 foreach(arg, args)
190                                 {
191                                         relname = strVal(lfirst(arg));
192                                         if (IsSystemRelationName(relname))
193                                                 elog(ERROR, "class \"%s\" is a system catalog",
194                                                          relname);
195                                         rel = heap_openr(relname);
196                                         if (RelationIsValid(rel))
197                                         {
198                                                 if (stmt->sequence &&
199                                                         rel->rd_rel->relkind != RELKIND_SEQUENCE)
200                                                         elog(ERROR, "Use DROP TABLE to drop table '%s'",
201                                                                  relname);
202                                                 if (!(stmt->sequence) &&
203                                                         rel->rd_rel->relkind == RELKIND_SEQUENCE)
204                                                         elog(ERROR, "Use DROP SEQUENCE to drop sequence '%s'",
205                                                                  relname);
206                                                 heap_close(rel);
207                                         }
208 #ifndef NO_SECURITY
209                                         if (!pg_ownercheck(userName, relname, RELNAME))
210                                                 elog(ERROR, "you do not own class \"%s\"",
211                                                          relname);
212 #endif
213                                 }
214                                 foreach(arg, args)
215                                 {
216                                         relname = strVal(lfirst(arg));
217                                         RemoveRelation(relname);
218                                 }
219                         }
220                         break;
221
222                 case T_CopyStmt:
223                         {
224                                 CopyStmt   *stmt = (CopyStmt *) parsetree;
225
226                                 *ps_status = commandTag = "COPY";
227                                 CHECK_IF_ABORTED();
228
229                                 DoCopy(stmt->relname,
230                                            stmt->binary,
231                                            stmt->oids,
232                                            (bool) (stmt->direction == FROM),
233                                            (bool) (stmt->filename == NULL),
234
235                                 /*
236                                  * null filename means copy to/from stdout/stdin, rather
237                                  * than to/from a file.
238                                  */
239                                            stmt->filename,
240                                            stmt->delimiter);
241                         }
242                         break;
243
244                 case T_AddAttrStmt:
245                         {
246                                 AddAttrStmt *stmt = (AddAttrStmt *) parsetree;
247
248                                 *ps_status = commandTag = "ADD";
249                                 CHECK_IF_ABORTED();
250
251                                 /*
252                                  * owner checking done in PerformAddAttribute (now
253                                  * recursive)
254                                  */
255                                 PerformAddAttribute(stmt->relname,
256                                                                         userName,
257                                                                         stmt->inh,
258                                                                         (ColumnDef *) stmt->colDef);
259                         }
260                         break;
261
262                         /*
263                          * schema
264                          */
265                 case T_RenameStmt:
266                         {
267                                 RenameStmt *stmt = (RenameStmt *) parsetree;
268
269                                 *ps_status = commandTag = "RENAME";
270                                 CHECK_IF_ABORTED();
271
272                                 relname = stmt->relname;
273                                 if (IsSystemRelationName(relname))
274                                         elog(ERROR, "class \"%s\" is a system catalog",
275                                                  relname);
276 #ifndef NO_SECURITY
277                                 if (!pg_ownercheck(userName, relname, RELNAME))
278                                         elog(ERROR, "you do not own class \"%s\"",
279                                                  relname);
280 #endif
281
282                                 /* ----------------
283                                  *      XXX using len == 3 to tell the difference
284                                  *              between "rename rel to newrel" and
285                                  *              "rename att in rel to newatt" will not
286                                  *              work soon because "rename type/operator/rule"
287                                  *              stuff is being added. - cim 10/24/90
288                                  * ----------------
289                                  * [another piece of amuzing but useless anecdote -- ay]
290                                  */
291                                 if (stmt->column == NULL)
292                                 {
293                                         /* ----------------
294                                          *              rename relation
295                                          *
296                                          *              Note: we also rename the "type" tuple
297                                          *              corresponding to the relation.
298                                          * ----------------
299                                          */
300                                         renamerel(relname,      /* old name */
301                                                           stmt->newname);       /* new name */
302                                         TypeRename(relname, /* old name */
303                                                            stmt->newname);      /* new name */
304                                 }
305                                 else
306                                 {
307                                         /* ----------------
308                                          *              rename attribute
309                                          * ----------------
310                                          */
311                                         renameatt(relname,      /* relname */
312                                                           stmt->column,         /* old att name */
313                                                           stmt->newname,        /* new att name */
314                                                           userName,
315                                                           stmt->inh);           /* recursive? */
316                                 }
317                         }
318                         break;
319
320                 case T_ChangeACLStmt:
321                         {
322                                 ChangeACLStmt *stmt = (ChangeACLStmt *) parsetree;
323                                 List       *i;
324                                 AclItem    *aip;
325                                 unsigned        modechg;
326
327                                 *ps_status = commandTag = "CHANGE";
328                                 CHECK_IF_ABORTED();
329
330                                 aip = stmt->aclitem;
331
332                                 modechg = stmt->modechg;
333 #ifndef NO_SECURITY
334                                 foreach(i, stmt->relNames)
335                                 {
336                                         relname = strVal(lfirst(i));
337                                         if (!pg_ownercheck(userName, relname, RELNAME))
338                                                 elog(ERROR, "you do not own class \"%s\"",
339                                                          relname);
340                                 }
341 #endif
342                                 foreach(i, stmt->relNames)
343                                 {
344                                         relname = strVal(lfirst(i));
345                                         ChangeAcl(relname, aip, modechg);
346                                 }
347
348                         }
349                         break;
350
351                         /*
352                          * ******************************** object creation /
353                          * destruction ********************************
354                          *
355                          */
356                 case T_DefineStmt:
357                         {
358                                 DefineStmt *stmt = (DefineStmt *) parsetree;
359
360                                 *ps_status = commandTag = "CREATE";
361                                 CHECK_IF_ABORTED();
362
363                                 switch (stmt->defType)
364                                 {
365                                         case OPERATOR:
366                                                 DefineOperator(stmt->defname,   /* operator name */
367                                                                            stmt->definition);           /* rest */
368                                                 break;
369                                         case TYPE_P:
370                                                         DefineType(stmt->defname, stmt->definition);
371                                                 break;
372                                         case AGGREGATE:
373                                                 DefineAggregate(stmt->defname,  /* aggregate name */
374                                                                                 stmt->definition);              /* rest */
375                                                 break;
376                                 }
377                         }
378                         break;
379
380                 case T_ViewStmt:                /* CREATE VIEW */
381                         {
382                                 ViewStmt   *stmt = (ViewStmt *) parsetree;
383
384                                 *ps_status = commandTag = "CREATE";
385                                 CHECK_IF_ABORTED();
386                                 DefineView(stmt->viewname, stmt->query);                /* retrieve parsetree */
387                         }
388                         break;
389
390                 case T_ProcedureStmt:   /* CREATE FUNCTION */
391                         *ps_status = commandTag = "CREATE";
392                         CHECK_IF_ABORTED();
393                         CreateFunction((ProcedureStmt *) parsetree, dest);      /* everything */
394                         break;
395
396                 case T_IndexStmt:               /* CREATE INDEX */
397                         {
398                                 IndexStmt  *stmt = (IndexStmt *) parsetree;
399
400                                 *ps_status = commandTag = "CREATE";
401                                 CHECK_IF_ABORTED();
402                                 DefineIndex(stmt->relname,              /* relation name */
403                                                         stmt->idxname,          /* index name */
404                                                         stmt->accessMethod, /* am name */
405                                                         stmt->indexParams,      /* parameters */
406                                                         stmt->withClause,
407                                                         stmt->unique,
408                                                         (Expr *) stmt->whereClause,
409                                                         stmt->rangetable);
410                         }
411                         break;
412
413                 case T_RuleStmt:                /* CREATE RULE */
414                         {
415                                 RuleStmt   *stmt = (RuleStmt *) parsetree;
416                                 int                     aclcheck_result;
417
418 #ifndef NO_SECURITY
419                                 relname = stmt->object->relname;
420                                 aclcheck_result = pg_aclcheck(relname, userName, ACL_RU);
421                                 if (aclcheck_result != ACLCHECK_OK)
422                                         elog(ERROR, "%s: %s", relname, aclcheck_error_strings[aclcheck_result]);
423 #endif
424                                 *ps_status = commandTag = "CREATE";
425                                 CHECK_IF_ABORTED();
426                                 DefineQueryRewrite(stmt);
427                         }
428                         break;
429
430                 case T_CreateSeqStmt:
431                         *ps_status = commandTag = "CREATE";
432                         CHECK_IF_ABORTED();
433
434                         DefineSequence((CreateSeqStmt *) parsetree);
435                         break;
436
437                 case T_ExtendStmt:
438                         {
439                                 ExtendStmt *stmt = (ExtendStmt *) parsetree;
440
441                                 *ps_status = commandTag = "EXTEND";
442                                 CHECK_IF_ABORTED();
443
444                                 ExtendIndex(stmt->idxname,              /* index name */
445                                                         (Expr *) stmt->whereClause, /* where */
446                                                         stmt->rangetable);
447                         }
448                         break;
449
450                 case T_RemoveStmt:
451                         {
452                                 RemoveStmt *stmt = (RemoveStmt *) parsetree;
453
454                                 *ps_status = commandTag = "DROP";
455                                 CHECK_IF_ABORTED();
456
457                                 switch (stmt->removeType)
458                                 {
459                                         case INDEX:
460                                                 relname = stmt->name;
461                                                 if (IsSystemRelationName(relname))
462                                                         elog(ERROR, "class \"%s\" is a system catalog index",
463                                                                  relname);
464 #ifndef NO_SECURITY
465                                                 if (!pg_ownercheck(userName, relname, RELNAME))
466                                                         elog(ERROR, "%s: %s", relname, aclcheck_error_strings[ACLCHECK_NOT_OWNER]);
467 #endif
468                                                 RemoveIndex(relname);
469                                                 break;
470                                         case RULE:
471                                                 {
472                                                         char       *rulename = stmt->name;
473                                                         int                     aclcheck_result;
474
475 #ifndef NO_SECURITY
476
477                                                         relationName = RewriteGetRuleEventRel(rulename);
478                                                         aclcheck_result = pg_aclcheck(relationName, userName, ACL_RU);
479                                                         if (aclcheck_result != ACLCHECK_OK)
480                                                                 elog(ERROR, "%s: %s", relationName, aclcheck_error_strings[aclcheck_result]);
481 #endif
482                                                         RemoveRewriteRule(rulename);
483                                                 }
484                                                 break;
485                                         case TYPE_P:
486 #ifndef NO_SECURITY
487                                                 /* XXX moved to remove.c */
488 #endif
489                                                 RemoveType(stmt->name);
490                                                 break;
491                                         case VIEW:
492                                                 {
493                                                         char       *viewName = stmt->name;
494                                                         char       *ruleName;
495
496 #ifndef NO_SECURITY
497
498                                                         ruleName = MakeRetrieveViewRuleName(viewName);
499                                                         relationName = RewriteGetRuleEventRel(ruleName);
500                                                         if (!pg_ownercheck(userName, relationName, RELNAME))
501                                                                 elog(ERROR, "%s: %s", relationName, aclcheck_error_strings[ACLCHECK_NOT_OWNER]);
502                                                         pfree(ruleName);
503 #endif
504                                                         RemoveView(viewName);
505                                                 }
506                                                 break;
507                                 }
508                                 break;
509                         }
510                         break;
511
512                 case T_RemoveAggrStmt:
513                         {
514                                 RemoveAggrStmt *stmt = (RemoveAggrStmt *) parsetree;
515
516                                 *ps_status = commandTag = "DROP";
517                                 CHECK_IF_ABORTED();
518                                 RemoveAggregate(stmt->aggname, stmt->aggtype);
519                         }
520                         break;
521
522                 case T_RemoveFuncStmt:
523                         {
524                                 RemoveFuncStmt *stmt = (RemoveFuncStmt *) parsetree;
525
526                                 *ps_status = commandTag = "DROP";
527                                 CHECK_IF_ABORTED();
528                                 RemoveFunction(stmt->funcname,
529                                                            length(stmt->args),
530                                                            stmt->args);
531                         }
532                         break;
533
534                 case T_RemoveOperStmt:
535                         {
536                                 RemoveOperStmt *stmt = (RemoveOperStmt *) parsetree;
537                                 char       *type1 = (char *) NULL;
538                                 char       *type2 = (char *) NULL;
539
540                                 *ps_status = commandTag = "DROP";
541                                 CHECK_IF_ABORTED();
542
543                                 if (lfirst(stmt->args) != NULL)
544                                         type1 = strVal(lfirst(stmt->args));
545                                 if (lsecond(stmt->args) != NULL)
546                                         type2 = strVal(lsecond(stmt->args));
547                                 RemoveOperator(stmt->opname, type1, type2);
548                         }
549                         break;
550
551                 case T_VersionStmt:
552                                 elog(ERROR, "CREATE VERSION is not currently implemented");
553                         break;
554
555                 case T_CreatedbStmt:
556                         {
557                                 CreatedbStmt *stmt = (CreatedbStmt *) parsetree;
558
559                                 *ps_status = commandTag = "CREATEDB";
560                                 CHECK_IF_ABORTED();
561 #ifdef MULTIBYTE
562                                 createdb(stmt->dbname, stmt->dbpath, stmt->encoding);
563 #else
564                                 createdb(stmt->dbname, stmt->dbpath);
565 #endif
566                         }
567                         break;
568
569                 case T_DestroydbStmt:
570                         {
571                                 DestroydbStmt *stmt = (DestroydbStmt *) parsetree;
572
573                                 *ps_status = commandTag = "DESTROYDB";
574                                 CHECK_IF_ABORTED();
575                                 destroydb(stmt->dbname);
576                         }
577                         break;
578
579                         /* Query-level asynchronous notification */
580                 case T_NotifyStmt:
581                         {
582                                 NotifyStmt *stmt = (NotifyStmt *) parsetree;
583
584                                 *ps_status = commandTag = "NOTIFY";
585                                 CHECK_IF_ABORTED();
586
587                                 Async_Notify(stmt->relname);
588                         }
589                         break;
590
591                 case T_ListenStmt:
592                         {
593                                 ListenStmt *stmt = (ListenStmt *) parsetree;
594
595                                 *ps_status = commandTag = "LISTEN";
596                                 CHECK_IF_ABORTED();
597
598                                 Async_Listen(stmt->relname, MyProcPid);
599                         }
600                         break;
601
602                         /*
603                          * ******************************** dynamic loader ********************************
604                          *
605                          */
606                 case T_LoadStmt:
607                         {
608                                 LoadStmt   *stmt = (LoadStmt *) parsetree;
609                                 FILE       *fp;
610                                 char       *filename;
611
612                                 *ps_status = commandTag = "LOAD";
613                                 CHECK_IF_ABORTED();
614
615                                 filename = stmt->filename;
616                                 closeAllVfds();
617                                 if ((fp = AllocateFile(filename, "r")) == NULL)
618                                         elog(ERROR, "LOAD: could not open file %s", filename);
619                                 FreeFile(fp);
620                                 load_file(filename);
621                         }
622                         break;
623
624                 case T_ClusterStmt:
625                         {
626                                 ClusterStmt *stmt = (ClusterStmt *) parsetree;
627
628                                 *ps_status = commandTag = "CLUSTER";
629                                 CHECK_IF_ABORTED();
630
631                                 cluster(stmt->relname, stmt->indexname);
632                         }
633                         break;
634
635                 case T_VacuumStmt:
636                         *ps_status = commandTag = "VACUUM";
637                         CHECK_IF_ABORTED();
638                         vacuum(((VacuumStmt *) parsetree)->vacrel,
639                                    ((VacuumStmt *) parsetree)->verbose,
640                                    ((VacuumStmt *) parsetree)->analyze,
641                                    ((VacuumStmt *) parsetree)->va_spec);
642                         break;
643
644                 case T_ExplainStmt:
645                         {
646                                 ExplainStmt *stmt = (ExplainStmt *) parsetree;
647
648                                 *ps_status = commandTag = "EXPLAIN";
649                                 CHECK_IF_ABORTED();
650
651                                 ExplainQuery(stmt->query, stmt->verbose, dest);
652                         }
653                         break;
654
655                         /*
656                          * ******************************** Tioga-related statements *******************************
657                          */
658                 case T_RecipeStmt:
659                         {
660                                 RecipeStmt *stmt = (RecipeStmt *) parsetree;
661
662                                 *ps_status = commandTag = "EXECUTE RECIPE";
663                                 CHECK_IF_ABORTED();
664                                 beginRecipe(stmt);
665                         }
666                         break;
667
668                         /*
669                          * ******************************** set variable statements *******************************
670                          */
671                 case T_VariableSetStmt:
672                         {
673                                 VariableSetStmt *n = (VariableSetStmt *) parsetree;
674
675                                 SetPGVariable(n->name, n->value);
676                                 *ps_status = commandTag = "SET VARIABLE";
677                         }
678                         break;
679
680                 case T_VariableShowStmt:
681                         {
682                                 VariableShowStmt *n = (VariableShowStmt *) parsetree;
683
684                                 GetPGVariable(n->name);
685                                 *ps_status = commandTag = "SHOW VARIABLE";
686                         }
687                         break;
688
689                 case T_VariableResetStmt:
690                         {
691                                 VariableResetStmt *n = (VariableResetStmt *) parsetree;
692
693                                 ResetPGVariable(n->name);
694                                 *ps_status = commandTag = "RESET VARIABLE";
695                         }
696                         break;
697
698                         /*
699                          * ******************************** TRIGGER statements *******************************
700                          */
701                 case T_CreateTrigStmt:
702                         *ps_status = commandTag = "CREATE";
703                         CHECK_IF_ABORTED();
704
705                         CreateTrigger((CreateTrigStmt *) parsetree);
706                         break;
707
708                 case T_DropTrigStmt:
709                         *ps_status = commandTag = "DROP";
710                         CHECK_IF_ABORTED();
711
712                         DropTrigger((DropTrigStmt *) parsetree);
713                         break;
714
715                         /*
716                          * ************* PROCEDURAL LANGUAGE statements *****************
717                          */
718                 case T_CreatePLangStmt:
719                         *ps_status = commandTag = "CREATE";
720                         CHECK_IF_ABORTED();
721
722                         CreateProceduralLanguage((CreatePLangStmt *) parsetree);
723                         break;
724
725                 case T_DropPLangStmt:
726                         *ps_status = commandTag = "DROP";
727                         CHECK_IF_ABORTED();
728
729                         DropProceduralLanguage((DropPLangStmt *) parsetree);
730                         break;
731
732                         /*
733                          * ******************************** USER statements ****
734                          *
735                          */
736                 case T_CreateUserStmt:
737                         *ps_status = commandTag = "CREATE USER";
738                         CHECK_IF_ABORTED();
739
740                         DefineUser((CreateUserStmt *) parsetree);
741                         break;
742
743                 case T_AlterUserStmt:
744                         *ps_status = commandTag = "ALTER USER";
745                         CHECK_IF_ABORTED();
746
747                         AlterUser((AlterUserStmt *) parsetree);
748                         break;
749
750                 case T_DropUserStmt:
751                         *ps_status = commandTag = "DROP USER";
752                         CHECK_IF_ABORTED();
753
754                         RemoveUser(((DropUserStmt *) parsetree)->user);
755                         break;
756
757
758                         /*
759                          * ******************************** default ********************************
760                          *
761                          */
762                 default:
763                         elog(ERROR, "ProcessUtility: command #%d unsupported",
764                                  nodeTag(parsetree));
765                         break;
766         }
767
768         /* ----------------
769          *      tell fe/be or whatever that we're done.
770          * ----------------
771          */
772         EndCommand(commandTag, dest);
773 }