OSDN Git Service

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