]> granicus.if.org Git - postgresql/blob - src/backend/tcop/utility.c
Change error message and remove non-functional update message, from
[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.42 1998/06/16 02:53:26 momjian 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                                 createdb(stmt->dbname, stmt->dbpath);
562                         }
563                         break;
564
565                 case T_DestroydbStmt:
566                         {
567                                 DestroydbStmt *stmt = (DestroydbStmt *) parsetree;
568
569                                 *ps_status = commandTag = "DESTROYDB";
570                                 CHECK_IF_ABORTED();
571                                 destroydb(stmt->dbname);
572                         }
573                         break;
574
575                         /* Query-level asynchronous notification */
576                 case T_NotifyStmt:
577                         {
578                                 NotifyStmt *stmt = (NotifyStmt *) parsetree;
579
580                                 *ps_status = commandTag = "NOTIFY";
581                                 CHECK_IF_ABORTED();
582
583                                 Async_Notify(stmt->relname);
584                         }
585                         break;
586
587                 case T_ListenStmt:
588                         {
589                                 ListenStmt *stmt = (ListenStmt *) parsetree;
590
591                                 *ps_status = commandTag = "LISTEN";
592                                 CHECK_IF_ABORTED();
593
594                                 Async_Listen(stmt->relname, MyProcPid);
595                         }
596                         break;
597
598                         /*
599                          * ******************************** dynamic loader ********************************
600                          *
601                          */
602                 case T_LoadStmt:
603                         {
604                                 LoadStmt   *stmt = (LoadStmt *) parsetree;
605                                 FILE       *fp;
606                                 char       *filename;
607
608                                 *ps_status = commandTag = "LOAD";
609                                 CHECK_IF_ABORTED();
610
611                                 filename = stmt->filename;
612                                 closeAllVfds();
613                                 if ((fp = AllocateFile(filename, "r")) == NULL)
614                                         elog(ERROR, "LOAD: could not open file %s", filename);
615                                 FreeFile(fp);
616                                 load_file(filename);
617                         }
618                         break;
619
620                 case T_ClusterStmt:
621                         {
622                                 ClusterStmt *stmt = (ClusterStmt *) parsetree;
623
624                                 *ps_status = commandTag = "CLUSTER";
625                                 CHECK_IF_ABORTED();
626
627                                 cluster(stmt->relname, stmt->indexname);
628                         }
629                         break;
630
631                 case T_VacuumStmt:
632                         *ps_status = commandTag = "VACUUM";
633                         CHECK_IF_ABORTED();
634                         vacuum(((VacuumStmt *) parsetree)->vacrel,
635                                    ((VacuumStmt *) parsetree)->verbose,
636                                    ((VacuumStmt *) parsetree)->analyze,
637                                    ((VacuumStmt *) parsetree)->va_spec);
638                         break;
639
640                 case T_ExplainStmt:
641                         {
642                                 ExplainStmt *stmt = (ExplainStmt *) parsetree;
643
644                                 *ps_status = commandTag = "EXPLAIN";
645                                 CHECK_IF_ABORTED();
646
647                                 ExplainQuery(stmt->query, stmt->verbose, dest);
648                         }
649                         break;
650
651                         /*
652                          * ******************************** Tioga-related statements *******************************
653                          */
654                 case T_RecipeStmt:
655                         {
656                                 RecipeStmt *stmt = (RecipeStmt *) parsetree;
657
658                                 *ps_status = commandTag = "EXECUTE RECIPE";
659                                 CHECK_IF_ABORTED();
660                                 beginRecipe(stmt);
661                         }
662                         break;
663
664                         /*
665                          * ******************************** set variable statements *******************************
666                          */
667                 case T_VariableSetStmt:
668                         {
669                                 VariableSetStmt *n = (VariableSetStmt *) parsetree;
670
671                                 SetPGVariable(n->name, n->value);
672                                 *ps_status = commandTag = "SET VARIABLE";
673                         }
674                         break;
675
676                 case T_VariableShowStmt:
677                         {
678                                 VariableShowStmt *n = (VariableShowStmt *) parsetree;
679
680                                 GetPGVariable(n->name);
681                                 *ps_status = commandTag = "SHOW VARIABLE";
682                         }
683                         break;
684
685                 case T_VariableResetStmt:
686                         {
687                                 VariableResetStmt *n = (VariableResetStmt *) parsetree;
688
689                                 ResetPGVariable(n->name);
690                                 *ps_status = commandTag = "RESET VARIABLE";
691                         }
692                         break;
693
694                         /*
695                          * ******************************** TRIGGER statements *******************************
696                          */
697                 case T_CreateTrigStmt:
698                         *ps_status = commandTag = "CREATE";
699                         CHECK_IF_ABORTED();
700
701                         CreateTrigger((CreateTrigStmt *) parsetree);
702                         break;
703
704                 case T_DropTrigStmt:
705                         *ps_status = commandTag = "DROP";
706                         CHECK_IF_ABORTED();
707
708                         DropTrigger((DropTrigStmt *) parsetree);
709                         break;
710
711                         /*
712                          * ************* PROCEDURAL LANGUAGE statements *****************
713                          */
714                 case T_CreatePLangStmt:
715                         *ps_status = commandTag = "CREATE";
716                         CHECK_IF_ABORTED();
717
718                         CreateProceduralLanguage((CreatePLangStmt *) parsetree);
719                         break;
720
721                 case T_DropPLangStmt:
722                         *ps_status = commandTag = "DROP";
723                         CHECK_IF_ABORTED();
724
725                         DropProceduralLanguage((DropPLangStmt *) parsetree);
726                         break;
727
728                         /*
729                          * ******************************** USER statements ****
730                          *
731                          */
732                 case T_CreateUserStmt:
733                         *ps_status = commandTag = "CREATE USER";
734                         CHECK_IF_ABORTED();
735
736                         DefineUser((CreateUserStmt *) parsetree);
737                         break;
738
739                 case T_AlterUserStmt:
740                         *ps_status = commandTag = "ALTER USER";
741                         CHECK_IF_ABORTED();
742
743                         AlterUser((AlterUserStmt *) parsetree);
744                         break;
745
746                 case T_DropUserStmt:
747                         *ps_status = commandTag = "DROP USER";
748                         CHECK_IF_ABORTED();
749
750                         RemoveUser(((DropUserStmt *) parsetree)->user);
751                         break;
752
753
754                         /*
755                          * ******************************** default ********************************
756                          *
757                          */
758                 default:
759                         elog(ERROR, "ProcessUtility: command #%d unsupported",
760                                  nodeTag(parsetree));
761                         break;
762         }
763
764         /* ----------------
765          *      tell fe/be or whatever that we're done.
766          * ----------------
767          */
768         EndCommand(commandTag, dest);
769 }