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