OSDN Git Service

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