OSDN Git Service

User and database-specific session defaults for run-time configuration
[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.128 2002/03/01 22:45:14 petere 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                                                 AlterTableAlterColumnStatistics(stmt->relname,
429                                                                                 interpretInhOption(stmt->inhOpt),
430                                                                                                                 stmt->name,
431                                                                                                                 stmt->def);
432                                                 break;
433                                         case 'D':       /* DROP COLUMN */
434                                                 AlterTableDropColumn(stmt->relname,
435                                                                                 interpretInhOption(stmt->inhOpt),
436                                                                                          stmt->name,
437                                                                                          stmt->behavior);
438                                                 break;
439                                         case 'C':       /* ADD CONSTRAINT */
440                                                 AlterTableAddConstraint(stmt->relname,
441                                                                                 interpretInhOption(stmt->inhOpt),
442                                                                                                 (List *) stmt->def);
443                                                 break;
444                                         case 'X':       /* DROP CONSTRAINT */
445                                                 AlterTableDropConstraint(stmt->relname,
446                                                                                 interpretInhOption(stmt->inhOpt),
447                                                                                                  stmt->name,
448                                                                                                  stmt->behavior);
449                                                 break;
450                                         case 'E':       /* CREATE TOAST TABLE */
451                                                 AlterTableCreateToastTable(stmt->relname,
452                                                                                                    false);
453                                                 break;
454                                         case 'U':       /* ALTER OWNER */
455                                                 AlterTableOwner(stmt->relname,
456                                                                                 stmt->name);
457                                                 break;
458                                         default:        /* oops */
459                                                 elog(ERROR, "T_AlterTableStmt: unknown subtype");
460                                                 break;
461                                 }
462                         }
463                         break;
464
465
466                 case T_GrantStmt:
467                         {
468                                 GrantStmt  *stmt = (GrantStmt *) parsetree;
469
470                                 ExecuteGrantStmt(stmt);
471                         }
472                         break;
473
474                         /*
475                          * ******************************** object creation /
476                          * destruction ********************************
477                          *
478                          */
479                 case T_DefineStmt:
480                         {
481                                 DefineStmt *stmt = (DefineStmt *) parsetree;
482
483                                 switch (stmt->defType)
484                                 {
485                                         case OPERATOR:
486                                                 DefineOperator(stmt->defname,   /* operator name */
487                                                                            stmt->definition);           /* rest */
488                                                 break;
489                                         case TYPE_P:
490                                                 DefineType(stmt->defname, stmt->definition);
491                                                 break;
492                                         case AGGREGATE:
493                                                 DefineAggregate(stmt->defname,  /* aggregate name */
494                                                                                 stmt->definition);              /* rest */
495                                                 break;
496                                 }
497                         }
498                         break;
499
500                 case T_ViewStmt:                /* CREATE VIEW */
501                         {
502                                 ViewStmt   *stmt = (ViewStmt *) parsetree;
503
504                                 DefineView(stmt->viewname, stmt->query);                /* retrieve parsetree */
505                         }
506                         break;
507
508                 case T_ProcedureStmt:   /* CREATE FUNCTION */
509                         CreateFunction((ProcedureStmt *) parsetree);
510                         break;
511
512                 case T_IndexStmt:               /* CREATE INDEX */
513                         {
514                                 IndexStmt  *stmt = (IndexStmt *) parsetree;
515
516                                 relname = stmt->relname;
517                                 if (!allowSystemTableMods && IsSystemRelationName(relname))
518                                         elog(ERROR, "CREATE INDEX: relation \"%s\" is a system catalog",
519                                                  relname);
520                                 if (!pg_ownercheck(GetUserId(), relname, RELNAME))
521                                         elog(ERROR, "permission denied");
522
523                                 DefineIndex(stmt->relname,              /* relation name */
524                                                         stmt->idxname,          /* index name */
525                                                         stmt->accessMethod, /* am name */
526                                                         stmt->indexParams,      /* parameters */
527                                                         stmt->unique,
528                                                         stmt->primary,
529                                                         (Expr *) stmt->whereClause,
530                                                         stmt->rangetable);
531                         }
532                         break;
533
534                 case T_RuleStmt:                /* CREATE RULE */
535                         {
536                                 RuleStmt   *stmt = (RuleStmt *) parsetree;
537                                 int                     aclcheck_result;
538
539                                 relname = stmt->object->relname;
540                                 aclcheck_result = pg_aclcheck(relname, GetUserId(), ACL_RULE);
541                                 if (aclcheck_result != ACLCHECK_OK)
542                                         elog(ERROR, "%s: %s", relname, aclcheck_error_strings[aclcheck_result]);
543
544                                 DefineQueryRewrite(stmt);
545                         }
546                         break;
547
548                 case T_CreateSeqStmt:
549                         DefineSequence((CreateSeqStmt *) parsetree);
550                         break;
551
552                 case T_RemoveAggrStmt:
553                         {
554                                 RemoveAggrStmt *stmt = (RemoveAggrStmt *) parsetree;
555                                 char       *typename = (char *) NULL;
556
557                                 if (stmt->aggtype != NULL)
558                                         typename = TypeNameToInternalName((TypeName *) stmt->aggtype);
559
560                                 RemoveAggregate(stmt->aggname, typename);
561                         }
562                         break;
563
564                 case T_RemoveFuncStmt:
565                         {
566                                 RemoveFuncStmt *stmt = (RemoveFuncStmt *) parsetree;
567
568                                 RemoveFunction(stmt->funcname, stmt->args);
569                         }
570                         break;
571
572                 case T_RemoveOperStmt:
573                         {
574                                 RemoveOperStmt *stmt = (RemoveOperStmt *) parsetree;
575                                 TypeName   *typenode1 = (TypeName *) lfirst(stmt->args);
576                                 TypeName   *typenode2 = (TypeName *) lsecond(stmt->args);
577                                 char       *typename1 = (char *) NULL;
578                                 char       *typename2 = (char *) NULL;
579
580                                 if (typenode1 != NULL)
581                                         typename1 = TypeNameToInternalName(typenode1);
582                                 if (typenode2 != NULL)
583                                         typename2 = TypeNameToInternalName(typenode2);
584
585                                 RemoveOperator(stmt->opname, typename1, typename2);
586                         }
587                         break;
588
589                 case T_VersionStmt:
590                         elog(ERROR, "CREATE VERSION is not currently implemented");
591                         break;
592
593                 case T_CreatedbStmt:
594                         {
595                                 CreatedbStmt *stmt = (CreatedbStmt *) parsetree;
596
597                                 createdb(stmt->dbname, stmt->dbowner,
598                                                  stmt->dbpath, stmt->dbtemplate,
599                                                  stmt->encoding);
600                         }
601                         break;
602
603                 case T_AlterDatabaseSetStmt:
604                         AlterDatabaseSet((AlterDatabaseSetStmt *)parsetree);
605                         break;
606
607                 case T_DropdbStmt:
608                         {
609                                 DropdbStmt *stmt = (DropdbStmt *) parsetree;
610
611                                 dropdb(stmt->dbname);
612                         }
613                         break;
614
615                         /* Query-level asynchronous notification */
616                 case T_NotifyStmt:
617                         {
618                                 NotifyStmt *stmt = (NotifyStmt *) parsetree;
619
620                                 Async_Notify(stmt->relname);
621                         }
622                         break;
623
624                 case T_ListenStmt:
625                         {
626                                 ListenStmt *stmt = (ListenStmt *) parsetree;
627
628                                 Async_Listen(stmt->relname, MyProcPid);
629                         }
630                         break;
631
632                 case T_UnlistenStmt:
633                         {
634                                 UnlistenStmt *stmt = (UnlistenStmt *) parsetree;
635
636                                 Async_Unlisten(stmt->relname, MyProcPid);
637                         }
638                         break;
639
640                         /*
641                          * ******************************** dynamic loader ********************************
642                          *
643                          */
644                 case T_LoadStmt:
645                         {
646                                 LoadStmt   *stmt = (LoadStmt *) parsetree;
647
648                                 closeAllVfds(); /* probably not necessary... */
649                                 load_file(stmt->filename);
650                         }
651                         break;
652
653                 case T_ClusterStmt:
654                         {
655                                 ClusterStmt *stmt = (ClusterStmt *) parsetree;
656
657                                 relname = stmt->relname;
658                                 if (IsSystemRelationName(relname))
659                                         elog(ERROR, "CLUSTER: relation \"%s\" is a system catalog",
660                                                  relname);
661                                 if (!pg_ownercheck(GetUserId(), relname, RELNAME))
662                                         elog(ERROR, "permission denied");
663
664                                 cluster(relname, stmt->indexname);
665                         }
666                         break;
667
668                 case T_VacuumStmt:
669                         vacuum((VacuumStmt *) parsetree);
670                         break;
671
672                 case T_ExplainStmt:
673                         {
674                                 ExplainStmt *stmt = (ExplainStmt *) parsetree;
675
676                                 ExplainQuery(stmt->query, stmt->verbose, stmt->analyze, dest);
677                         }
678                         break;
679
680 #ifdef NOT_USED
681
682                         /*
683                          * ******************************** Tioga-related statements *******************************
684                          */
685                 case T_RecipeStmt:
686                         {
687                                 RecipeStmt *stmt = (RecipeStmt *) parsetree;
688
689                                 beginRecipe(stmt);
690                         }
691                         break;
692 #endif
693
694                         /*
695                          * ******************************** set variable statements *******************************
696                          */
697                 case T_VariableSetStmt:
698                         {
699                                 VariableSetStmt *n = (VariableSetStmt *) parsetree;
700
701                                 SetPGVariable(n->name, n->args);
702                         }
703                         break;
704
705                 case T_VariableShowStmt:
706                         {
707                                 VariableShowStmt *n = (VariableShowStmt *) parsetree;
708
709                                 GetPGVariable(n->name);
710                         }
711                         break;
712
713                 case T_VariableResetStmt:
714                         {
715                                 VariableResetStmt *n = (VariableResetStmt *) parsetree;
716
717                                 ResetPGVariable(n->name);
718                         }
719                         break;
720
721                         /*
722                          * ******************************** TRIGGER statements *******************************
723                          */
724                 case T_CreateTrigStmt:
725                         CreateTrigger((CreateTrigStmt *) parsetree);
726                         break;
727
728                 case T_DropTrigStmt:
729                         DropTrigger((DropTrigStmt *) parsetree);
730                         break;
731
732                         /*
733                          * ************* PROCEDURAL LANGUAGE statements *****************
734                          */
735                 case T_CreatePLangStmt:
736                         CreateProceduralLanguage((CreatePLangStmt *) parsetree);
737                         break;
738
739                 case T_DropPLangStmt:
740                         DropProceduralLanguage((DropPLangStmt *) parsetree);
741                         break;
742
743                         /*
744                          * ******************************** USER statements ****
745                          *
746                          */
747                 case T_CreateUserStmt:
748                         CreateUser((CreateUserStmt *) parsetree);
749                         break;
750
751                 case T_AlterUserStmt:
752                         AlterUser((AlterUserStmt *) parsetree);
753                         break;
754
755                 case T_AlterUserSetStmt:
756                         AlterUserSet((AlterUserSetStmt *) parsetree);
757                         break;
758
759                 case T_DropUserStmt:
760                         DropUser((DropUserStmt *) parsetree);
761                         break;
762
763                 case T_LockStmt:
764                         LockTableCommand((LockStmt *) parsetree);
765                         break;
766
767                 case T_ConstraintsSetStmt:
768                         DeferredTriggerSetState((ConstraintsSetStmt *) parsetree);
769                         break;
770
771                 case T_CreateGroupStmt:
772                         CreateGroup((CreateGroupStmt *) parsetree);
773                         break;
774
775                 case T_AlterGroupStmt:
776                         AlterGroup((AlterGroupStmt *) parsetree, "ALTER GROUP");
777                         break;
778
779                 case T_DropGroupStmt:
780                         DropGroup((DropGroupStmt *) parsetree);
781                         break;
782
783                 case T_CheckPointStmt:
784                         {
785                                 if (!superuser())
786                                         elog(ERROR, "permission denied");
787                                 CreateCheckPoint(false);
788                         }
789                         break;
790
791                 case T_ReindexStmt:
792                         {
793                                 ReindexStmt *stmt = (ReindexStmt *) parsetree;
794
795                                 switch (stmt->reindexType)
796                                 {
797                                         case INDEX:
798                                                 relname = (char *) stmt->name;
799                                                 if (IsSystemRelationName(relname))
800                                                 {
801                                                         if (!allowSystemTableMods)
802                                                                 elog(ERROR, "\"%s\" is a system index. call REINDEX under standalone postgres with -O -P options",
803                                                                          relname);
804                                                         if (!IsIgnoringSystemIndexes())
805                                                                 elog(ERROR, "\"%s\" is a system index. call REINDEX under standalone postgres with -P -O options",
806                                                                          relname);
807                                                 }
808                                                 if (!pg_ownercheck(GetUserId(), relname, RELNAME))
809                                                         elog(ERROR, "%s: %s", relname, aclcheck_error_strings[ACLCHECK_NOT_OWNER]);
810                                                 ReindexIndex(relname, stmt->force);
811                                                 break;
812                                         case TABLE:
813                                                 relname = (char *) stmt->name;
814                                                 if (!pg_ownercheck(GetUserId(), relname, RELNAME))
815                                                         elog(ERROR, "%s: %s", relname, aclcheck_error_strings[ACLCHECK_NOT_OWNER]);
816                                                 ReindexTable(relname, stmt->force);
817                                                 break;
818                                         case DATABASE:
819                                                 relname = (char *) stmt->name;
820                                                 if (!allowSystemTableMods)
821                                                         elog(ERROR, "must be called under standalone postgres with -O -P options");
822                                                 if (!IsIgnoringSystemIndexes())
823                                                         elog(ERROR, "must be called under standalone postgres with -P -O options");
824                                                 ReindexDatabase(relname, stmt->force, false);
825                                                 break;
826                                 }
827                                 break;
828                         }
829                         break;
830
831                         /*
832                          * ******************************** default ********************************
833                          *
834                          */
835                 default:
836                         elog(ERROR, "ProcessUtility: command #%d unsupported",
837                                  nodeTag(parsetree));
838                         break;
839         }
840 }