OSDN Git Service

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