OSDN Git Service

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