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