OSDN Git Service

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