OSDN Git Service

Fix CLUSTER ... or at least undo the bit-rot it's suffered since 6.5.
[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.88 2000/05/11 03:54:18 tgl Exp $
14  *
15  *-------------------------------------------------------------------------
16  */
17 #include "postgres.h"
18
19 #include "access/heapam.h"
20 #include "catalog/catalog.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, "current transaction is aborted, " \
60                          "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 COMMIT:
101                                                 PS_SET_STATUS(commandTag = "COMMIT");
102                                                 EndTransactionBlock();
103                                                 break;
104
105                                         case ROLLBACK:
106                                                 PS_SET_STATUS(commandTag = "ROLLBACK");
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                                 SetQuerySnapshot();
139
140                                 forward = (bool) (stmt->direction == FORWARD);
141
142                                 /*
143                                  * parser ensures that count is >= 0 and 'fetch ALL' -> 0
144                                  */
145
146                                 count = stmt->howMany;
147                                 PerformPortalFetch(portalName, forward, count, commandTag,
148                                                                    (stmt->ismove) ? None : dest);               /* /dev/null for MOVE */
149                         }
150                         break;
151
152                         /*
153                          * ******************************** relation and attribute
154                          * manipulation ********************************
155                          *
156                          */
157                 case T_CreateStmt:
158                         PS_SET_STATUS(commandTag = "CREATE");
159                         CHECK_IF_ABORTED();
160
161                         DefineRelation((CreateStmt *) parsetree, RELKIND_RELATION);
162                         break;
163
164                 case T_DropStmt:
165                         {
166                                 DropStmt   *stmt = (DropStmt *) parsetree;
167                                 List       *args = stmt->relNames;
168                                 List       *arg;
169
170                                 PS_SET_STATUS(commandTag = "DROP");
171                                 CHECK_IF_ABORTED();
172
173                                 /* check as much as we can before we start dropping ... */
174                                 foreach(arg, args)
175                                 {
176                                         Relation        rel;
177
178                                         relname = strVal(lfirst(arg));
179                                         if (!allowSystemTableMods && IsSystemRelationName(relname))
180                                                 elog(ERROR, "class \"%s\" is a system catalog",
181                                                          relname);
182                                         rel = heap_openr(relname, AccessExclusiveLock);
183                                         if (stmt->sequence &&
184                                                 rel->rd_rel->relkind != RELKIND_SEQUENCE)
185                                                 elog(ERROR, "Use DROP TABLE to drop table '%s'",
186                                                          relname);
187                                         if (!(stmt->sequence) &&
188                                                 rel->rd_rel->relkind == RELKIND_SEQUENCE)
189                                                 elog(ERROR, "Use DROP SEQUENCE to drop sequence '%s'",
190                                                          relname);
191                                         /* close rel, but keep lock until end of xact */
192                                         heap_close(rel, NoLock);
193 #ifndef NO_SECURITY
194                                         if (!pg_ownercheck(userName, relname, RELNAME))
195                                                 elog(ERROR, "you do not own class \"%s\"",
196                                                          relname);
197 #endif
198                                 }
199                                 /* OK, terminate 'em all */
200                                 foreach(arg, args)
201                                 {
202                                         relname = strVal(lfirst(arg));
203                                         RemoveRelation(relname);
204                                 }
205                         }
206                         break;
207
208                 case T_TruncateStmt:
209                         {
210                                 Relation        rel;
211
212                                 PS_SET_STATUS(commandTag = "TRUNCATE");
213                                 CHECK_IF_ABORTED();
214
215                                 relname = ((TruncateStmt *) parsetree)->relName;
216                                 if (!allowSystemTableMods && IsSystemRelationName(relname))
217                                         elog(ERROR, "TRUNCATE cannot be used on system tables. '%s' is a system table",
218                                                  relname);
219
220                                 /* Grab exclusive lock in preparation for truncate... */
221                                 rel = heap_openr(relname, AccessExclusiveLock);
222                                 if (rel->rd_rel->relkind == RELKIND_SEQUENCE)
223                                         elog(ERROR, "TRUNCATE cannot be used on sequences. '%s' is a sequence",
224                                                  relname);
225                                 heap_close(rel, NoLock);
226
227 #ifndef NO_SECURITY
228                                 if (!pg_ownercheck(userName, relname, RELNAME))
229                                         elog(ERROR, "you do not own class \"%s\"", relname);
230 #endif
231                                 TruncateRelation(relname);
232                         }
233                         break;
234
235                 case T_CommentStmt:
236                         {
237
238                                 CommentStmt *statement;
239
240                                 statement = ((CommentStmt *) parsetree);
241
242                                 PS_SET_STATUS(commandTag = "COMMENT");
243                                 CHECK_IF_ABORTED();
244                                 CommentObject(statement->objtype, statement->objname,
245                                                           statement->objproperty, statement->objlist,
246                                                           statement->comment);
247                         }
248                         break;
249
250
251
252                 case T_CopyStmt:
253                         {
254                                 CopyStmt   *stmt = (CopyStmt *) parsetree;
255
256                                 PS_SET_STATUS(commandTag = "COPY");
257                                 CHECK_IF_ABORTED();
258
259                                 if (stmt->direction != FROM)
260                                         SetQuerySnapshot();
261
262                                 DoCopy(stmt->relname,
263                                            stmt->binary,
264                                            stmt->oids,
265                                            (bool) (stmt->direction == FROM),
266                                            (bool) (stmt->filename == NULL),
267
268                                 /*
269                                  * null filename means copy to/from stdout/stdin, rather
270                                  * than to/from a file.
271                                  */
272                                            stmt->filename,
273                                            stmt->delimiter,
274                                            stmt->null_print);
275                         }
276                         break;
277
278                         /*
279                          * schema
280                          */
281                 case T_RenameStmt:
282                         {
283                                 RenameStmt *stmt = (RenameStmt *) parsetree;
284
285                                 PS_SET_STATUS(commandTag = "ALTER");
286                                 CHECK_IF_ABORTED();
287
288                                 relname = stmt->relname;
289                                 if (!allowSystemTableMods && IsSystemRelationName(relname))
290                                         elog(ERROR, "ALTER TABLE: relation \"%s\" is a system catalog",
291                                                  relname);
292 #ifndef NO_SECURITY
293                                 if (!pg_ownercheck(userName, relname, RELNAME))
294                                         elog(ERROR, "permission denied");
295 #endif
296
297                                 /* ----------------
298                                  *      XXX using len == 3 to tell the difference
299                                  *              between "rename rel to newrel" and
300                                  *              "rename att in rel to newatt" will not
301                                  *              work soon because "rename type/operator/rule"
302                                  *              stuff is being added. - cim 10/24/90
303                                  * ----------------
304                                  * [another piece of amuzing but useless anecdote -- ay]
305                                  */
306                                 if (stmt->column == NULL)
307                                 {
308                                         /* ----------------
309                                          *              rename relation
310                                          *
311                                          *              Note: we also rename the "type" tuple
312                                          *              corresponding to the relation.
313                                          * ----------------
314                                          */
315                                         renamerel(relname,      /* old name */
316                                                           stmt->newname);       /* new name */
317                                 }
318                                 else
319                                 {
320                                         /* ----------------
321                                          *              rename attribute
322                                          * ----------------
323                                          */
324                                         renameatt(relname,      /* relname */
325                                                           stmt->column,         /* old att name */
326                                                           stmt->newname,        /* new att name */
327                                                           userName,
328                                                           stmt->inh);           /* recursive? */
329                                 }
330                         }
331                         break;
332
333                         /* various Alter Table forms */
334
335                 case T_AlterTableStmt:
336                         {
337                                 AlterTableStmt *stmt = (AlterTableStmt *) parsetree;
338
339                                 PS_SET_STATUS(commandTag = "ALTER");
340                                 CHECK_IF_ABORTED();
341
342                                 /*
343                                  * Some or all of these functions are recursive to cover
344                                  * inherited things, so permission checks are done there.
345                                  */
346                                 switch (stmt->subtype)
347                                 {
348                                         case 'A':       /* ADD COLUMN */
349                                                 AlterTableAddColumn(stmt->relname, stmt->inh, (ColumnDef *) stmt->def);
350                                                 break;
351                                         case 'T':       /* ALTER COLUMN */
352                                                 AlterTableAlterColumn(stmt->relname, stmt->inh, stmt->name, stmt->def);
353                                                 break;
354                                         case 'D':       /* ALTER DROP */
355                                                 AlterTableDropColumn(stmt->relname, stmt->inh, stmt->name, stmt->behavior);
356                                                 break;
357                                         case 'C':       /* ADD CONSTRAINT */
358                                                 AlterTableAddConstraint(stmt->relname, stmt->inh, stmt->def);
359                                                 break;
360                                         case 'X':       /* DROP CONSTRAINT */
361                                                 AlterTableDropConstraint(stmt->relname, stmt->inh, stmt->name, stmt->behavior);
362                                                 break;
363                                         default:        /* oops */
364                                                 elog(ERROR, "T_AlterTableStmt: unknown subtype");
365                                                 break;
366                                 }
367                         }
368                         break;
369
370
371                 case T_ChangeACLStmt:
372                         {
373                                 ChangeACLStmt *stmt = (ChangeACLStmt *) parsetree;
374                                 List       *i;
375                                 AclItem    *aip;
376                                 unsigned        modechg;
377
378                                 PS_SET_STATUS(commandTag = "CHANGE");
379                                 CHECK_IF_ABORTED();
380
381                                 aip = stmt->aclitem;
382
383                                 modechg = stmt->modechg;
384                                 foreach(i, stmt->relNames)
385                                 {
386                                         Relation        rel;
387
388                                         relname = strVal(lfirst(i));
389                                         rel = heap_openr(relname, AccessExclusiveLock);
390                                         if (rel && rel->rd_rel->relkind == RELKIND_INDEX)
391                                                 elog(ERROR, "\"%s\" is an index relation",
392                                                          relname);
393                                         /* close rel, but keep lock until end of xact */
394                                         heap_close(rel, NoLock);
395 #ifndef NO_SECURITY
396                                         if (!pg_ownercheck(userName, relname, RELNAME))
397                                                 elog(ERROR, "you do not own class \"%s\"",
398                                                          relname);
399 #endif
400                                         ChangeAcl(relname, aip, modechg);
401                                 }
402                         }
403                         break;
404
405                         /*
406                          * ******************************** object creation /
407                          * destruction ********************************
408                          *
409                          */
410                 case T_DefineStmt:
411                         {
412                                 DefineStmt *stmt = (DefineStmt *) parsetree;
413
414                                 PS_SET_STATUS(commandTag = "CREATE");
415                                 CHECK_IF_ABORTED();
416
417                                 switch (stmt->defType)
418                                 {
419                                         case OPERATOR:
420                                                 DefineOperator(stmt->defname,   /* operator name */
421                                                                            stmt->definition);           /* rest */
422                                                 break;
423                                         case TYPE_P:
424                                                 DefineType(stmt->defname, stmt->definition);
425                                                 break;
426                                         case AGGREGATE:
427                                                 DefineAggregate(stmt->defname,  /* aggregate name */
428                                                                                 stmt->definition);              /* rest */
429                                                 break;
430                                 }
431                         }
432                         break;
433
434                 case T_ViewStmt:                /* CREATE VIEW */
435                         {
436                                 ViewStmt   *stmt = (ViewStmt *) parsetree;
437
438                                 PS_SET_STATUS(commandTag = "CREATE");
439                                 CHECK_IF_ABORTED();
440                                 DefineView(stmt->viewname, stmt->query);                /* retrieve parsetree */
441                         }
442                         break;
443
444                 case T_ProcedureStmt:   /* CREATE FUNCTION */
445                         PS_SET_STATUS(commandTag = "CREATE");
446                         CHECK_IF_ABORTED();
447                         CreateFunction((ProcedureStmt *) parsetree, dest);      /* everything */
448                         break;
449
450                 case T_IndexStmt:               /* CREATE INDEX */
451                         {
452                                 IndexStmt  *stmt = (IndexStmt *) parsetree;
453
454                                 PS_SET_STATUS(commandTag = "CREATE");
455                                 CHECK_IF_ABORTED();
456                                 DefineIndex(stmt->relname,              /* relation name */
457                                                         stmt->idxname,          /* index name */
458                                                         stmt->accessMethod, /* am name */
459                                                         stmt->indexParams,      /* parameters */
460                                                         stmt->withClause,
461                                                         stmt->unique,
462                                                         stmt->primary,
463                                                         (Expr *) stmt->whereClause,
464                                                         stmt->rangetable);
465                         }
466                         break;
467
468                 case T_RuleStmt:                /* CREATE RULE */
469                         {
470                                 RuleStmt   *stmt = (RuleStmt *) parsetree;
471                                 int                     aclcheck_result;
472
473 #ifndef NO_SECURITY
474                                 relname = stmt->object->relname;
475                                 aclcheck_result = pg_aclcheck(relname, userName, ACL_RU);
476                                 if (aclcheck_result != ACLCHECK_OK)
477                                         elog(ERROR, "%s: %s", relname, aclcheck_error_strings[aclcheck_result]);
478 #endif
479                                 PS_SET_STATUS(commandTag = "CREATE");
480                                 CHECK_IF_ABORTED();
481                                 DefineQueryRewrite(stmt);
482                         }
483                         break;
484
485                 case T_CreateSeqStmt:
486                         PS_SET_STATUS(commandTag = "CREATE");
487                         CHECK_IF_ABORTED();
488
489                         DefineSequence((CreateSeqStmt *) parsetree);
490                         break;
491
492                 case T_ExtendStmt:
493                         {
494                                 ExtendStmt *stmt = (ExtendStmt *) parsetree;
495
496                                 PS_SET_STATUS(commandTag = "EXTEND");
497                                 CHECK_IF_ABORTED();
498
499                                 ExtendIndex(stmt->idxname,              /* index name */
500                                                         (Expr *) stmt->whereClause, /* where */
501                                                         stmt->rangetable);
502                         }
503                         break;
504
505                 case T_RemoveStmt:
506                         {
507                                 RemoveStmt *stmt = (RemoveStmt *) parsetree;
508
509                                 PS_SET_STATUS(commandTag = "DROP");
510                                 CHECK_IF_ABORTED();
511
512                                 switch (stmt->removeType)
513                                 {
514                                         case INDEX:
515                                                 relname = stmt->name;
516                                                 if (!allowSystemTableMods && IsSystemRelationName(relname))
517                                                         elog(ERROR, "class \"%s\" is a system catalog index",
518                                                                  relname);
519 #ifndef NO_SECURITY
520                                                 if (!pg_ownercheck(userName, relname, RELNAME))
521                                                         elog(ERROR, "%s: %s", relname, aclcheck_error_strings[ACLCHECK_NOT_OWNER]);
522 #endif
523                                                 RemoveIndex(relname);
524                                                 break;
525                                         case RULE:
526                                                 {
527                                                         char       *rulename = stmt->name;
528                                                         int                     aclcheck_result;
529
530 #ifndef NO_SECURITY
531
532                                                         relationName = RewriteGetRuleEventRel(rulename);
533                                                         aclcheck_result = pg_aclcheck(relationName, userName, ACL_RU);
534                                                         if (aclcheck_result != ACLCHECK_OK)
535                                                                 elog(ERROR, "%s: %s", relationName, aclcheck_error_strings[aclcheck_result]);
536 #endif
537                                                         RemoveRewriteRule(rulename);
538                                                 }
539                                                 break;
540                                         case TYPE_P:
541 #ifndef NO_SECURITY
542                                                 /* XXX moved to remove.c */
543 #endif
544                                                 RemoveType(stmt->name);
545                                                 break;
546                                         case VIEW:
547                                                 {
548                                                         char       *viewName = stmt->name;
549                                                         char       *ruleName;
550
551 #ifndef NO_SECURITY
552
553                                                         ruleName = MakeRetrieveViewRuleName(viewName);
554                                                         relationName = RewriteGetRuleEventRel(ruleName);
555                                                         if (!pg_ownercheck(userName, relationName, RELNAME))
556                                                                 elog(ERROR, "%s: %s", relationName, aclcheck_error_strings[ACLCHECK_NOT_OWNER]);
557                                                         pfree(ruleName);
558 #endif
559                                                         RemoveView(viewName);
560                                                 }
561                                                 break;
562                                 }
563                                 break;
564                         }
565                         break;
566
567                 case T_RemoveAggrStmt:
568                         {
569                                 RemoveAggrStmt *stmt = (RemoveAggrStmt *) parsetree;
570
571                                 PS_SET_STATUS(commandTag = "DROP");
572                                 CHECK_IF_ABORTED();
573                                 RemoveAggregate(stmt->aggname, stmt->aggtype);
574                         }
575                         break;
576
577                 case T_RemoveFuncStmt:
578                         {
579                                 RemoveFuncStmt *stmt = (RemoveFuncStmt *) parsetree;
580
581                                 PS_SET_STATUS(commandTag = "DROP");
582                                 CHECK_IF_ABORTED();
583                                 RemoveFunction(stmt->funcname,
584                                                            length(stmt->args),
585                                                            stmt->args);
586                         }
587                         break;
588
589                 case T_RemoveOperStmt:
590                         {
591                                 RemoveOperStmt *stmt = (RemoveOperStmt *) parsetree;
592                                 char       *type1 = (char *) NULL;
593                                 char       *type2 = (char *) NULL;
594
595                                 PS_SET_STATUS(commandTag = "DROP");
596                                 CHECK_IF_ABORTED();
597
598                                 if (lfirst(stmt->args) != NULL)
599                                         type1 = strVal(lfirst(stmt->args));
600                                 if (lsecond(stmt->args) != NULL)
601                                         type2 = strVal(lsecond(stmt->args));
602                                 RemoveOperator(stmt->opname, type1, type2);
603                         }
604                         break;
605
606                 case T_VersionStmt:
607                         elog(ERROR, "CREATE VERSION is not currently implemented");
608                         break;
609
610                 case T_CreatedbStmt:
611                         {
612                                 CreatedbStmt *stmt = (CreatedbStmt *) parsetree;
613
614                                 PS_SET_STATUS(commandTag = "CREATE DATABASE");
615                                 CHECK_IF_ABORTED();
616                                 createdb(stmt->dbname, stmt->dbpath, stmt->encoding);
617                         }
618                         break;
619
620                 case T_DropdbStmt:
621                         {
622                                 DropdbStmt *stmt = (DropdbStmt *) parsetree;
623
624                                 PS_SET_STATUS(commandTag = "DROP DATABASE");
625                                 CHECK_IF_ABORTED();
626                                 dropdb(stmt->dbname);
627                         }
628                         break;
629
630                         /* Query-level asynchronous notification */
631                 case T_NotifyStmt:
632                         {
633                                 NotifyStmt *stmt = (NotifyStmt *) parsetree;
634
635                                 PS_SET_STATUS(commandTag = "NOTIFY");
636                                 CHECK_IF_ABORTED();
637
638                                 Async_Notify(stmt->relname);
639                         }
640                         break;
641
642                 case T_ListenStmt:
643                         {
644                                 ListenStmt *stmt = (ListenStmt *) parsetree;
645
646                                 PS_SET_STATUS(commandTag = "LISTEN");
647                                 CHECK_IF_ABORTED();
648
649                                 Async_Listen(stmt->relname, MyProcPid);
650                         }
651                         break;
652
653                 case T_UnlistenStmt:
654                         {
655                                 UnlistenStmt *stmt = (UnlistenStmt *) parsetree;
656
657                                 PS_SET_STATUS(commandTag = "UNLISTEN");
658                                 CHECK_IF_ABORTED();
659
660                                 Async_Unlisten(stmt->relname, MyProcPid);
661                         }
662                         break;
663
664                         /*
665                          * ******************************** dynamic loader ********************************
666                          *
667                          */
668                 case T_LoadStmt:
669                         {
670                                 LoadStmt   *stmt = (LoadStmt *) parsetree;
671
672                                 PS_SET_STATUS(commandTag = "LOAD");
673                                 CHECK_IF_ABORTED();
674
675                                 closeAllVfds(); /* probably not necessary... */
676                                 load_file(stmt->filename);
677                         }
678                         break;
679
680                 case T_ClusterStmt:
681                         {
682                                 ClusterStmt *stmt = (ClusterStmt *) parsetree;
683
684                                 PS_SET_STATUS(commandTag = "CLUSTER");
685                                 CHECK_IF_ABORTED();
686
687                                 cluster(stmt->relname, stmt->indexname);
688                         }
689                         break;
690
691                 case T_VacuumStmt:
692                         PS_SET_STATUS(commandTag = "VACUUM");
693                         CHECK_IF_ABORTED();
694                         vacuum(((VacuumStmt *) parsetree)->vacrel,
695                                    ((VacuumStmt *) parsetree)->verbose,
696                                    ((VacuumStmt *) parsetree)->analyze,
697                                    ((VacuumStmt *) parsetree)->va_spec);
698                         break;
699
700                 case T_ExplainStmt:
701                         {
702                                 ExplainStmt *stmt = (ExplainStmt *) parsetree;
703
704                                 PS_SET_STATUS(commandTag = "EXPLAIN");
705                                 CHECK_IF_ABORTED();
706
707                                 ExplainQuery(stmt->query, stmt->verbose, dest);
708                         }
709                         break;
710
711 #ifdef NOT_USED
712
713                         /*
714                          * ******************************** Tioga-related statements *******************************
715                          */
716                 case T_RecipeStmt:
717                         {
718                                 RecipeStmt *stmt = (RecipeStmt *) parsetree;
719
720                                 PS_SET_STATUS(commandTag = "EXECUTE RECIPE");
721                                 CHECK_IF_ABORTED();
722                                 beginRecipe(stmt);
723                         }
724                         break;
725 #endif
726
727                         /*
728                          * ******************************** set variable statements *******************************
729                          */
730                 case T_VariableSetStmt:
731                         {
732                                 VariableSetStmt *n = (VariableSetStmt *) parsetree;
733
734                                 SetPGVariable(n->name, n->value);
735                                 PS_SET_STATUS(commandTag = "SET VARIABLE");
736                         }
737                         break;
738
739                 case T_VariableShowStmt:
740                         {
741                                 VariableShowStmt *n = (VariableShowStmt *) parsetree;
742
743                                 GetPGVariable(n->name);
744                                 PS_SET_STATUS(commandTag = "SHOW VARIABLE");
745                         }
746                         break;
747
748                 case T_VariableResetStmt:
749                         {
750                                 VariableResetStmt *n = (VariableResetStmt *) parsetree;
751
752                                 ResetPGVariable(n->name);
753                                 PS_SET_STATUS(commandTag = "RESET VARIABLE");
754                         }
755                         break;
756
757                         /*
758                          * ******************************** TRIGGER statements *******************************
759                          */
760                 case T_CreateTrigStmt:
761                         PS_SET_STATUS(commandTag = "CREATE");
762                         CHECK_IF_ABORTED();
763
764                         CreateTrigger((CreateTrigStmt *) parsetree);
765                         break;
766
767                 case T_DropTrigStmt:
768                         PS_SET_STATUS(commandTag = "DROP");
769                         CHECK_IF_ABORTED();
770
771                         DropTrigger((DropTrigStmt *) parsetree);
772                         break;
773
774                         /*
775                          * ************* PROCEDURAL LANGUAGE statements *****************
776                          */
777                 case T_CreatePLangStmt:
778                         PS_SET_STATUS(commandTag = "CREATE");
779                         CHECK_IF_ABORTED();
780
781                         CreateProceduralLanguage((CreatePLangStmt *) parsetree);
782                         break;
783
784                 case T_DropPLangStmt:
785                         PS_SET_STATUS(commandTag = "DROP");
786                         CHECK_IF_ABORTED();
787
788                         DropProceduralLanguage((DropPLangStmt *) parsetree);
789                         break;
790
791                         /*
792                          * ******************************** USER statements ****
793                          *
794                          */
795                 case T_CreateUserStmt:
796                         PS_SET_STATUS(commandTag = "CREATE USER");
797                         CHECK_IF_ABORTED();
798
799                         CreateUser((CreateUserStmt *) parsetree);
800                         break;
801
802                 case T_AlterUserStmt:
803                         PS_SET_STATUS(commandTag = "ALTER USER");
804                         CHECK_IF_ABORTED();
805
806                         AlterUser((AlterUserStmt *) parsetree);
807                         break;
808
809                 case T_DropUserStmt:
810                         PS_SET_STATUS(commandTag = "DROP USER");
811                         CHECK_IF_ABORTED();
812
813                         DropUser((DropUserStmt *) parsetree);
814                         break;
815
816                 case T_LockStmt:
817                         PS_SET_STATUS(commandTag = "LOCK TABLE");
818                         CHECK_IF_ABORTED();
819
820                         LockTableCommand((LockStmt *) parsetree);
821                         break;
822
823                 case T_ConstraintsSetStmt:
824                         PS_SET_STATUS(commandTag = "SET CONSTRAINTS");
825                         CHECK_IF_ABORTED();
826
827                         DeferredTriggerSetState((ConstraintsSetStmt *) parsetree);
828                         break;
829
830                 case T_CreateGroupStmt:
831                         PS_SET_STATUS(commandTag = "CREATE GROUP");
832                         CHECK_IF_ABORTED();
833
834                         CreateGroup((CreateGroupStmt *) parsetree);
835                         break;
836
837                 case T_AlterGroupStmt:
838                         PS_SET_STATUS(commandTag = "ALTER GROUP");
839                         CHECK_IF_ABORTED();
840
841                         AlterGroup((AlterGroupStmt *) parsetree, "ALTER GROUP");
842                         break;
843
844                 case T_DropGroupStmt:
845                         PS_SET_STATUS(commandTag = "DROP GROUP");
846                         CHECK_IF_ABORTED();
847
848                         DropGroup((DropGroupStmt *) parsetree);
849                         break;
850
851                 case T_ReindexStmt:
852                         {
853                                 ReindexStmt *stmt = (ReindexStmt *) parsetree;
854
855                                 PS_SET_STATUS(commandTag = "REINDEX");
856                                 CHECK_IF_ABORTED();
857
858                                 switch (stmt->reindexType)
859                                 {
860                                         case INDEX:
861                                                 relname = (char *) stmt->name;
862                                                 if (IsSystemRelationName(relname))
863                                                 {
864                                                         if (!allowSystemTableMods && IsSystemRelationName(relname))
865                                                                 elog(ERROR, "\"%s\" is a system index. call REINDEX under standalone postgres with -O -P options",
866                                                                  relname);
867                                                         if (!IsIgnoringSystemIndexes())
868                                                                 elog(ERROR, "\"%s\" is a system index. call REINDEX under standalone postgres with -P -O options",
869                                                                  relname);
870                                                 }
871 #ifndef NO_SECURITY
872                                                 if (!pg_ownercheck(userName, relname, RELNAME))
873                                                         elog(ERROR, "%s: %s", relname, aclcheck_error_strings[ACLCHECK_NOT_OWNER]);
874 #endif
875                                                 ReindexIndex(relname, stmt->force);
876                                                 break;
877                                         case TABLE:
878                                                 relname = (char *) stmt->name;
879                                                 if (IsSystemRelationName(relname))
880                                                 {
881                                                         if (!allowSystemTableMods && IsSystemRelationName(relname))
882                                                                 elog(ERROR, "\"%s\" is a system table. call REINDEX under standalone postgres with -O -P options",
883                                                                  relname);
884                                                         if (!IsIgnoringSystemIndexes())
885                                                                 elog(ERROR, "\"%s\" is a system table. call REINDEX under standalone postgres with -P -O options",
886
887                                                                  relname);
888                                                 }
889 #ifndef NO_SECURITY
890                                                 if (!pg_ownercheck(userName, relname, RELNAME))
891                                                         elog(ERROR, "%s: %s", relname, aclcheck_error_strings[ACLCHECK_NOT_OWNER]);
892 #endif
893                                                 ReindexTable(relname, stmt->force);
894                                                 break;
895                                         case DATABASE:
896                                                 relname = (char *) stmt->name;
897                                                 if (!allowSystemTableMods)
898                                                         elog(ERROR, "must be called under standalone postgres with -O -P options");
899                                                 if (!IsIgnoringSystemIndexes())
900                                                         elog(ERROR, "must be called under standalone postgres with -P -O options");
901                                                 ReindexDatabase(relname, stmt->force, false);
902                                                 break;
903                                 }
904                                 break;
905                         }
906                         break;
907
908                         /*
909                          * ******************************** default ********************************
910                          *
911                          */
912                 default:
913                         elog(ERROR, "ProcessUtility: command #%d unsupported",
914                                  nodeTag(parsetree));
915                         break;
916         }
917
918         /* ----------------
919          *      tell fe/be or whatever that we're done.
920          * ----------------
921          */
922         EndCommand(commandTag, dest);
923 }