]> granicus.if.org Git - postgresql/blob - src/backend/tcop/utility.c
b48550428f65a44899a7c90cd1081b7f75985894
[postgresql] / 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-2002, 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.192 2003/02/13 05:20:01 momjian 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/conversioncmds.h"
28 #include "commands/dbcommands.h"
29 #include "commands/defrem.h"
30 #include "commands/explain.h"
31 #include "commands/lockcmds.h"
32 #include "commands/portalcmds.h"
33 #include "commands/prepare.h"
34 #include "commands/proclang.h"
35 #include "commands/schemacmds.h"
36 #include "commands/sequence.h"
37 #include "commands/tablecmds.h"
38 #include "commands/trigger.h"
39 #include "commands/typecmds.h"
40 #include "commands/user.h"
41 #include "commands/vacuum.h"
42 #include "commands/view.h"
43 #include "miscadmin.h"
44 #include "nodes/makefuncs.h"
45 #include "parser/parse_clause.h"
46 #include "parser/parse_expr.h"
47 #include "parser/parse_type.h"
48 #include "rewrite/rewriteDefine.h"
49 #include "rewrite/rewriteRemove.h"
50 #include "tcop/utility.h"
51 #include "utils/acl.h"
52 #include "utils/guc.h"
53 #include "utils/lsyscache.h"
54 #include "utils/syscache.h"
55 #include "access/xlog.h"
56
57 /*
58  * Error-checking support for DROP commands
59  */
60
61 struct kindstrings
62 {
63         char            kind;
64         char       *indef_article;
65         char       *name;
66         char       *command;
67 };
68
69 static struct kindstrings kindstringarray[] = {
70         {RELKIND_RELATION, "a", "table", "TABLE"},
71         {RELKIND_SEQUENCE, "a", "sequence", "SEQUENCE"},
72         {RELKIND_VIEW, "a", "view", "VIEW"},
73         {RELKIND_INDEX, "an", "index", "INDEX"},
74         {RELKIND_COMPOSITE_TYPE, "a", "type", "TYPE"},
75         {'\0', "a", "???", "???"}
76 };
77
78
79 static void
80 DropErrorMsg(char *relname, char wrongkind, char rightkind)
81 {
82         struct kindstrings *rentry;
83         struct kindstrings *wentry;
84
85         for (rentry = kindstringarray; rentry->kind != '\0'; rentry++)
86                 if (rentry->kind == rightkind)
87                         break;
88         Assert(rentry->kind != '\0');
89
90         for (wentry = kindstringarray; wentry->kind != '\0'; wentry++)
91                 if (wentry->kind == wrongkind)
92                         break;
93         /* wrongkind could be something we don't have in our table... */
94         if (wentry->kind != '\0')
95                 elog(ERROR, "\"%s\" is not %s %s. Use DROP %s to remove %s %s",
96                          relname, rentry->indef_article, rentry->name,
97                          wentry->command, wentry->indef_article, wentry->name);
98         else
99                 elog(ERROR, "\"%s\" is not %s %s",
100                          relname, rentry->indef_article, rentry->name);
101 }
102
103 static void
104 CheckDropPermissions(RangeVar *rel, char rightkind)
105 {
106         struct kindstrings *rentry;
107         Oid                     relOid;
108         HeapTuple       tuple;
109         Form_pg_class classform;
110
111         for (rentry = kindstringarray; rentry->kind != '\0'; rentry++)
112                 if (rentry->kind == rightkind)
113                         break;
114         Assert(rentry->kind != '\0');
115
116         relOid = RangeVarGetRelid(rel, true);
117         if (!OidIsValid(relOid))
118                 elog(ERROR, "%s \"%s\" does not exist", rentry->name, rel->relname);
119         tuple = SearchSysCache(RELOID,
120                                                    ObjectIdGetDatum(relOid),
121                                                    0, 0, 0);
122         if (!HeapTupleIsValid(tuple))
123                 elog(ERROR, "%s \"%s\" does not exist", rentry->name, rel->relname);
124
125         classform = (Form_pg_class) GETSTRUCT(tuple);
126
127         if (classform->relkind != rightkind)
128                 DropErrorMsg(rel->relname, classform->relkind, rightkind);
129
130         /* Allow DROP to either table owner or schema owner */
131         if (!pg_class_ownercheck(relOid, GetUserId()) &&
132                 !pg_namespace_ownercheck(classform->relnamespace, GetUserId()))
133                 aclcheck_error(ACLCHECK_NOT_OWNER, rel->relname);
134
135         if (!allowSystemTableMods && IsSystemClass(classform))
136                 elog(ERROR, "%s \"%s\" is a system %s",
137                          rentry->name, rel->relname, rentry->name);
138
139         ReleaseSysCache(tuple);
140 }
141
142 static void
143 CheckOwnership(RangeVar *rel, bool noCatalogs)
144 {
145         Oid                     relOid;
146         HeapTuple       tuple;
147
148         relOid = RangeVarGetRelid(rel, false);
149         tuple = SearchSysCache(RELOID,
150                                                    ObjectIdGetDatum(relOid),
151                                                    0, 0, 0);
152         if (!HeapTupleIsValid(tuple))
153                 elog(ERROR, "Relation \"%s\" does not exist", rel->relname);
154
155         if (!pg_class_ownercheck(relOid, GetUserId()))
156                 aclcheck_error(ACLCHECK_NOT_OWNER, rel->relname);
157
158         if (noCatalogs)
159         {
160                 if (!allowSystemTableMods &&
161                         IsSystemClass((Form_pg_class) GETSTRUCT(tuple)))
162                         elog(ERROR, "relation \"%s\" is a system catalog",
163                                  rel->relname);
164         }
165
166         ReleaseSysCache(tuple);
167 }
168
169
170 static void
171 check_xact_readonly(Node *parsetree)
172 {
173         if (!XactReadOnly)
174                 return;
175
176         /*
177          * Note: Commands that need to do more complicated checking are
178          * handled elsewhere.
179          */
180
181         switch (nodeTag(parsetree))
182         {
183                 case T_AlterDatabaseSetStmt:
184                 case T_AlterDomainStmt:
185                 case T_AlterGroupStmt:
186                 case T_AlterTableStmt:
187                 case T_RenameStmt:
188                 case T_AlterUserStmt:
189                 case T_AlterUserSetStmt:
190                 case T_CommentStmt:
191                 case T_DefineStmt:
192                 case T_CreateCastStmt:
193                 case T_CreateConversionStmt:
194                 case T_CreatedbStmt:
195                 case T_CreateDomainStmt:
196                 case T_CreateFunctionStmt:
197                 case T_CreateGroupStmt:
198                 case T_IndexStmt:
199                 case T_CreatePLangStmt:
200                 case T_CreateOpClassStmt:
201                 case T_RuleStmt:
202                 case T_CreateSchemaStmt:
203                 case T_CreateSeqStmt:
204                 case T_CreateStmt:
205                 case T_CreateTrigStmt:
206                 case T_CompositeTypeStmt:
207                 case T_CreateUserStmt:
208                 case T_ViewStmt:
209                 case T_RemoveAggrStmt:
210                 case T_DropCastStmt:
211                 case T_DropStmt:
212                 case T_DropdbStmt:
213                 case T_RemoveFuncStmt:
214                 case T_DropGroupStmt:
215                 case T_DropPLangStmt:
216                 case T_RemoveOperStmt:
217                 case T_RemoveOpClassStmt:
218                 case T_DropPropertyStmt:
219                 case T_DropUserStmt:
220                 case T_GrantStmt:
221                 case T_TruncateStmt:
222                         elog(ERROR, "transaction is read-only");
223                         break;
224                 default:
225                         /*nothing*/;
226         }
227 }
228
229
230 /*
231  * ProcessUtility
232  *              general utility function invoker
233  *
234  *      parsetree: the parse tree for the utility statement
235  *      dest: where to send results
236  *      completionTag: points to a buffer of size COMPLETION_TAG_BUFSIZE
237  *              in which to store a command completion status string.
238  *
239  * completionTag is only set nonempty if we want to return a nondefault
240  * status (currently, only used for MOVE/FETCH).
241  *
242  * completionTag may be NULL if caller doesn't want a status string.
243  */
244 void
245 ProcessUtility(Node *parsetree,
246                            CommandDest dest,
247                            char *completionTag)
248 {
249         check_xact_readonly(parsetree);
250
251         if (completionTag)
252                 completionTag[0] = '\0';
253
254         switch (nodeTag(parsetree))
255         {
256                         /*
257                          * ******************************** transactions ********************************
258                          */
259                 case T_TransactionStmt:
260                         {
261                                 TransactionStmt *stmt = (TransactionStmt *) parsetree;
262
263                                 switch (stmt->kind)
264                                 {
265                                         case TRANS_STMT_BEGIN:
266                                                 BeginTransactionBlock();
267                                                 break;
268
269                                                 /*
270                                                  * START TRANSACTION, as defined by SQL99:
271                                                  * Identical to BEGIN, except that it takes a few
272                                                  * additional options.
273                                                  */
274                                         case TRANS_STMT_START:
275                                                 {
276                                                         BeginTransactionBlock();
277
278                                                         if (stmt->options)
279                                                         {
280                                                                 List *head;
281
282                                                                 foreach(head, stmt->options)
283                                                                 {
284                                                                         DefElem *item = (DefElem *) lfirst(head);
285
286                                                                         if (strcmp(item->defname, "transaction_isolation")==0)
287                                                                                 SetPGVariable("transaction_isolation",
288                                                                                                           makeList1(item->arg), false);
289                                                                         else if (strcmp(item->defname, "transaction_read_only")==0)
290                                                                                 SetPGVariable("transaction_read_only",
291                                                                                                           makeList1(item->arg), false);
292                                                                 }
293                                                         }
294                                                 }
295                                                 break;
296
297                                         case TRANS_STMT_COMMIT:
298                                                 EndTransactionBlock();
299                                                 break;
300
301                                         case TRANS_STMT_ROLLBACK:
302                                                 UserAbortTransactionBlock();
303                                                 break;
304                                 }
305                         }
306                         break;
307
308                         /*
309                          * ************************* portal manipulation ***************************
310                          */
311                 case T_ClosePortalStmt:
312                         {
313                                 ClosePortalStmt *stmt = (ClosePortalStmt *) parsetree;
314
315                                 PerformPortalClose(stmt->portalname, dest);
316                         }
317                         break;
318
319                 case T_FetchStmt:
320                         {
321                                 FetchStmt  *stmt = (FetchStmt *) parsetree;
322
323                                 PerformPortalFetch(stmt->portalname,
324                                                                    stmt->direction == FETCH_FORWARD,
325                                                                    stmt->howMany,
326                                                                    (stmt->ismove) ? None : dest,
327                                                                    completionTag);
328                         }
329                         break;
330
331                         /*
332                          * relation and attribute manipulation
333                          */
334                 case T_CreateSchemaStmt:
335                         CreateSchemaCommand((CreateSchemaStmt *) parsetree);
336                         break;
337
338                 case T_CreateStmt:
339                         {
340                                 Oid                     relOid;
341
342                                 relOid = DefineRelation((CreateStmt *) parsetree,
343                                                                                 RELKIND_RELATION);
344
345                                 /*
346                                  * Let AlterTableCreateToastTable decide if this one needs
347                                  * a secondary relation too.
348                                  */
349                                 CommandCounterIncrement();
350                                 AlterTableCreateToastTable(relOid, true);
351                         }
352                         break;
353
354                 case T_DropStmt:
355                         {
356                                 DropStmt   *stmt = (DropStmt *) parsetree;
357                                 List       *arg;
358
359                                 foreach(arg, stmt->objects)
360                                 {
361                                         List       *names = (List *) lfirst(arg);
362                                         RangeVar   *rel;
363
364                                         switch (stmt->removeType)
365                                         {
366                                                 case DROP_TABLE:
367                                                         rel = makeRangeVarFromNameList(names);
368                                                         CheckDropPermissions(rel, RELKIND_RELATION);
369                                                         RemoveRelation(rel, stmt->behavior);
370                                                         break;
371
372                                                 case DROP_SEQUENCE:
373                                                         rel = makeRangeVarFromNameList(names);
374                                                         CheckDropPermissions(rel, RELKIND_SEQUENCE);
375                                                         RemoveRelation(rel, stmt->behavior);
376                                                         break;
377
378                                                 case DROP_VIEW:
379                                                         rel = makeRangeVarFromNameList(names);
380                                                         CheckDropPermissions(rel, RELKIND_VIEW);
381                                                         RemoveView(rel, stmt->behavior);
382                                                         break;
383
384                                                 case DROP_INDEX:
385                                                         rel = makeRangeVarFromNameList(names);
386                                                         CheckDropPermissions(rel, RELKIND_INDEX);
387                                                         RemoveIndex(rel, stmt->behavior);
388                                                         break;
389
390                                                 case DROP_TYPE:
391                                                         /* RemoveType does its own permissions checks */
392                                                         RemoveType(names, stmt->behavior);
393                                                         break;
394
395                                                 case DROP_DOMAIN:
396
397                                                         /*
398                                                          * RemoveDomain does its own permissions
399                                                          * checks
400                                                          */
401                                                         RemoveDomain(names, stmt->behavior);
402                                                         break;
403
404                                                 case DROP_CONVERSION:
405                                                         DropConversionCommand(names, stmt->behavior);
406                                                         break;
407
408                                                 case DROP_SCHEMA:
409
410                                                         /*
411                                                          * RemoveSchema does its own permissions
412                                                          * checks
413                                                          */
414                                                         RemoveSchema(names, stmt->behavior);
415                                                         break;
416                                         }
417
418                                         /*
419                                          * We used to need to do CommandCounterIncrement()
420                                          * here, but now it's done inside performDeletion().
421                                          */
422                                 }
423                         }
424                         break;
425
426                 case T_TruncateStmt:
427                         {
428                                 TruncateStmt *stmt = (TruncateStmt *) parsetree;
429
430                                 TruncateRelation(stmt->relation);
431                         }
432                         break;
433
434                 case T_CommentStmt:
435                         CommentObject((CommentStmt *) parsetree);
436                         break;
437
438                 case T_CopyStmt:
439                         DoCopy((CopyStmt *) parsetree);
440                         break;
441
442                 case T_PrepareStmt:
443                         PrepareQuery((PrepareStmt *) parsetree);
444                         break;
445
446                 case T_ExecuteStmt:
447                         ExecuteQuery((ExecuteStmt *) parsetree, dest);
448                         break;
449
450                 case T_DeallocateStmt:
451                         DeallocateQuery((DeallocateStmt *) parsetree);
452                         break;
453
454                         /*
455                          * schema
456                          */
457                 case T_RenameStmt:
458                         {
459                                 RenameStmt *stmt = (RenameStmt *) parsetree;
460                                 Oid                     relid;
461
462                                 CheckOwnership(stmt->relation, true);
463
464                                 relid = RangeVarGetRelid(stmt->relation, false);
465
466                                 switch (stmt->renameType)
467                                 {
468                                         case RENAME_TABLE:
469                                                 {
470                                                         /*
471                                                          * RENAME TABLE requires that we (still) hold
472                                                          * CREATE rights on the containing namespace,
473                                                          * as well as ownership of the table.
474                                                          */
475                                                         Oid                     namespaceId = get_rel_namespace(relid);
476                                                         AclResult       aclresult;
477
478                                                         aclresult = pg_namespace_aclcheck(namespaceId,
479                                                                                                                           GetUserId(),
480                                                                                                                           ACL_CREATE);
481                                                         if (aclresult != ACLCHECK_OK)
482                                                                 aclcheck_error(aclresult,
483                                                                                 get_namespace_name(namespaceId));
484
485                                                         renamerel(relid, stmt->newname);
486                                                         break;
487                                                 }
488                                         case RENAME_COLUMN:
489                                                 renameatt(relid,
490                                                                   stmt->oldname,                /* old att name */
491                                                                   stmt->newname,                /* new att name */
492                                                           interpretInhOption(stmt->relation->inhOpt),           /* recursive? */
493                                                                   false);               /* recursing already? */
494                                                 break;
495                                         case RENAME_TRIGGER:
496                                                 renametrig(relid,
497                                                                    stmt->oldname,               /* old att name */
498                                                                    stmt->newname);              /* new att name */
499                                                 break;
500                                         case RENAME_RULE:
501                                                 elog(ERROR, "ProcessUtility: Invalid type for RENAME: %d",
502                                                          stmt->renameType);
503                                                 break;
504                                         default:
505                                                 elog(ERROR, "ProcessUtility: Invalid type for RENAME: %d",
506                                                          stmt->renameType);
507                                 }
508                         }
509                         break;
510
511                         /* various Alter Table forms */
512
513                 case T_AlterTableStmt:
514                         {
515                                 AlterTableStmt *stmt = (AlterTableStmt *) parsetree;
516                                 Oid                     relid;
517
518                                 relid = RangeVarGetRelid(stmt->relation, false);
519
520                                 /*
521                                  * Some or all of these functions are recursive to cover
522                                  * inherited things, so permission checks are done there.
523                                  */
524                                 switch (stmt->subtype)
525                                 {
526                                         case 'A':       /* ADD COLUMN */
527
528                                                 /*
529                                                  * Recursively add column to table and, if
530                                                  * requested, to descendants
531                                                  */
532                                                 AlterTableAddColumn(relid,
533                                                           interpretInhOption(stmt->relation->inhOpt),
534                                                                                         (ColumnDef *) stmt->def);
535                                                 break;
536                                         case 'T':       /* ALTER COLUMN DEFAULT */
537
538                                                 /*
539                                                  * Recursively alter column default for table and,
540                                                  * if requested, for descendants
541                                                  */
542                                                 AlterTableAlterColumnDefault(relid,
543                                                           interpretInhOption(stmt->relation->inhOpt),
544                                                                                                          stmt->name,
545                                                                                                          stmt->def);
546                                                 break;
547                                         case 'N':       /* ALTER COLUMN DROP NOT NULL */
548                                                 AlterTableAlterColumnDropNotNull(relid,
549                                                           interpretInhOption(stmt->relation->inhOpt),
550                                                                                                                  stmt->name);
551                                                 break;
552                                         case 'n':       /* ALTER COLUMN SET NOT NULL */
553                                                 AlterTableAlterColumnSetNotNull(relid,
554                                                           interpretInhOption(stmt->relation->inhOpt),
555                                                                                                                 stmt->name);
556                                                 break;
557                                         case 'S':       /* ALTER COLUMN STATISTICS */
558                                         case 'M':       /* ALTER COLUMN STORAGE */
559
560                                                 /*
561                                                  * Recursively alter column statistics for table
562                                                  * and, if requested, for descendants
563                                                  */
564                                                 AlterTableAlterColumnFlags(relid,
565                                                           interpretInhOption(stmt->relation->inhOpt),
566                                                                                                    stmt->name,
567                                                                                                    stmt->def,
568                                                                                                    &(stmt->subtype));
569                                                 break;
570                                         case 'D':       /* DROP COLUMN */
571
572                                                 /*
573                                                  * Recursively drop column from table and, if
574                                                  * requested, from descendants
575                                                  */
576                                                 AlterTableDropColumn(relid,
577                                                           interpretInhOption(stmt->relation->inhOpt),
578                                                                                          false,
579                                                                                          stmt->name,
580                                                                                          stmt->behavior);
581                                                 break;
582                                         case 'C':       /* ADD CONSTRAINT */
583
584                                                 /*
585                                                  * Recursively add constraint to table and, if
586                                                  * requested, to descendants
587                                                  */
588                                                 AlterTableAddConstraint(relid,
589                                                           interpretInhOption(stmt->relation->inhOpt),
590                                                                                                 (List *) stmt->def);
591                                                 break;
592                                         case 'X':       /* DROP CONSTRAINT */
593
594                                                 /*
595                                                  * Recursively drop constraint from table and, if
596                                                  * requested, from descendants
597                                                  */
598                                                 AlterTableDropConstraint(relid,
599                                                           interpretInhOption(stmt->relation->inhOpt),
600                                                                                                  stmt->name,
601                                                                                                  stmt->behavior);
602                                                 break;
603                                         case 'E':       /* CREATE TOAST TABLE */
604                                                 AlterTableCreateToastTable(relid, false);
605                                                 break;
606                                         case 'U':       /* ALTER OWNER */
607                                                 /* check that we are the superuser */
608                                                 if (!superuser())
609                                                         elog(ERROR, "ALTER TABLE: permission denied");
610                                                 /* get_usesysid raises an error if no such user */
611                                                 AlterTableOwner(relid,
612                                                                                 get_usesysid(stmt->name));
613                                                 break;
614                                         case 'o': /* ADD OIDS */
615                                                 AlterTableAlterOids(relid,
616                                                  interpretInhOption(stmt->relation->inhOpt),
617                                                                                         false);
618                                                 break;
619                                         default:        /* oops */
620                                                 elog(ERROR, "ProcessUtility: Invalid type for AlterTableStmt: %d",
621                                                          stmt->subtype);
622                                                 break;
623                                 }
624                         }
625                         break;
626
627                 case T_AlterDomainStmt:
628                         {
629                                 AlterDomainStmt *stmt = (AlterDomainStmt *) parsetree;
630
631                                 /*
632                                  * Some or all of these functions are recursive to cover
633                                  * inherited things, so permission checks are done there.
634                                  */
635                                 switch (stmt->subtype)
636                                 {
637                                         case 'T':       /* ALTER COLUMN DEFAULT */
638
639                                                 /*
640                                                  * Recursively alter column default for table and,
641                                                  * if requested, for descendants
642                                                  */
643                                                 AlterDomainDefault(stmt->typename,
644                                                                                    stmt->def);
645                                                 break;
646                                         case 'N':       /* ALTER COLUMN DROP NOT NULL */
647                                                 AlterDomainNotNull(stmt->typename,
648                                                                                    false);
649                                                 break;
650                                         case 'O':       /* ALTER COLUMN SET NOT NULL */
651                                                 AlterDomainNotNull(stmt->typename,
652                                                                                    true);
653                                                 break;
654                                         case 'C':       /* ADD CONSTRAINT */
655                                                 AlterDomainAddConstraint(stmt->typename,
656                                                                                                  stmt->def);
657                                                 break;
658                                         case 'X':       /* DROP CONSTRAINT */
659                                                 AlterDomainDropConstraint(stmt->typename,
660                                                                                                   stmt->name,
661                                                                                                   stmt->behavior);
662                                                 break;
663                                         case 'U':       /* OWNER TO */
664                                                 /* check that we are the superuser */
665                                                 if (!superuser())
666                                                         elog(ERROR, "ALTER DOMAIN: permission denied");
667                                                 /* get_usesysid raises an error if no such user */
668                                                 AlterTypeOwner(stmt->typename,
669                                                                            get_usesysid(stmt->name));
670                                                 break;
671                                         default:        /* oops */
672                                                 elog(ERROR, "ProcessUtility: Invalid type for AlterDomainStmt: %d",
673                                                          stmt->subtype);
674                                                 break;
675                                 }
676                         }
677                         break;
678
679
680                 case T_GrantStmt:
681                         ExecuteGrantStmt((GrantStmt *) parsetree);
682                         break;
683
684                         /*
685                          * ******************************** object creation /
686                          * destruction ********************************
687                          *
688                          */
689                 case T_DefineStmt:
690                         {
691                                 DefineStmt *stmt = (DefineStmt *) parsetree;
692
693                                 switch (stmt->kind)
694                                 {
695                                         case DEFINE_STMT_AGGREGATE:
696                                                 DefineAggregate(stmt->defnames, stmt->definition);
697                                                 break;
698                                         case DEFINE_STMT_OPERATOR:
699                                                 DefineOperator(stmt->defnames, stmt->definition);
700                                                 break;
701                                         case DEFINE_STMT_TYPE:
702                                                 DefineType(stmt->defnames, stmt->definition);
703                                                 break;
704                                 }
705                         }
706                         break;
707
708                 case T_CompositeTypeStmt:               /* CREATE TYPE (composite) */
709                         {
710                                 CompositeTypeStmt *stmt = (CompositeTypeStmt *) parsetree;
711
712                                 DefineCompositeType(stmt->typevar, stmt->coldeflist);
713                         }
714                         break;
715
716                 case T_ViewStmt:                /* CREATE VIEW */
717                         {
718                                 ViewStmt   *stmt = (ViewStmt *) parsetree;
719
720                                 DefineView(stmt->view, stmt->query, stmt->replace);
721                         }
722                         break;
723
724                 case T_CreateFunctionStmt:              /* CREATE FUNCTION */
725                         CreateFunction((CreateFunctionStmt *) parsetree);
726                         break;
727
728                 case T_IndexStmt:               /* CREATE INDEX */
729                         {
730                                 IndexStmt  *stmt = (IndexStmt *) parsetree;
731
732                                 CheckOwnership(stmt->relation, true);
733
734                                 DefineIndex(stmt->relation,             /* relation */
735                                                         stmt->idxname,          /* index name */
736                                                         stmt->accessMethod, /* am name */
737                                                         stmt->indexParams,      /* parameters */
738                                                         stmt->unique,
739                                                         stmt->primary,
740                                                         stmt->isconstraint,
741                                                         (Expr *) stmt->whereClause,
742                                                         stmt->rangetable);
743                         }
744                         break;
745
746                 case T_RuleStmt:                /* CREATE RULE */
747                         DefineQueryRewrite((RuleStmt *) parsetree);
748                         break;
749
750                 case T_CreateSeqStmt:
751                         DefineSequence((CreateSeqStmt *) parsetree);
752                         break;
753
754                 case T_RemoveAggrStmt:
755                         RemoveAggregate((RemoveAggrStmt *) parsetree);
756                         break;
757
758                 case T_RemoveFuncStmt:
759                         RemoveFunction((RemoveFuncStmt *) parsetree);
760                         break;
761
762                 case T_RemoveOperStmt:
763                         RemoveOperator((RemoveOperStmt *) parsetree);
764                         break;
765
766                 case T_CreatedbStmt:
767                         createdb((CreatedbStmt *) parsetree);
768                         break;
769
770                 case T_AlterDatabaseSetStmt:
771                         AlterDatabaseSet((AlterDatabaseSetStmt *) parsetree);
772                         break;
773
774                 case T_DropdbStmt:
775                         {
776                                 DropdbStmt *stmt = (DropdbStmt *) parsetree;
777
778                                 dropdb(stmt->dbname);
779                         }
780                         break;
781
782                         /* Query-level asynchronous notification */
783                 case T_NotifyStmt:
784                         {
785                                 NotifyStmt *stmt = (NotifyStmt *) parsetree;
786
787                                 Async_Notify(stmt->relation->relname);
788                         }
789                         break;
790
791                 case T_ListenStmt:
792                         {
793                                 ListenStmt *stmt = (ListenStmt *) parsetree;
794
795                                 Async_Listen(stmt->relation->relname, MyProcPid);
796                         }
797                         break;
798
799                 case T_UnlistenStmt:
800                         {
801                                 UnlistenStmt *stmt = (UnlistenStmt *) parsetree;
802
803                                 Async_Unlisten(stmt->relation->relname, MyProcPid);
804                         }
805                         break;
806
807                 case T_LoadStmt:
808                         {
809                                 LoadStmt   *stmt = (LoadStmt *) parsetree;
810
811                                 closeAllVfds(); /* probably not necessary... */
812                                 load_file(stmt->filename);
813                         }
814                         break;
815
816                 case T_ClusterStmt:
817                         cluster((ClusterStmt *) parsetree);
818                         break;
819
820                 case T_VacuumStmt:
821                         vacuum((VacuumStmt *) parsetree);
822                         break;
823
824                 case T_ExplainStmt:
825                         ExplainQuery((ExplainStmt *) parsetree, dest);
826                         break;
827
828                 case T_VariableSetStmt:
829                         {
830                                 VariableSetStmt *n = (VariableSetStmt *) parsetree;
831
832                                 /*
833                                  * Special cases for special SQL syntax that
834                                  * effectively sets more than one variable per
835                                  * statement.
836                                  */
837                                 if (strcmp(n->name, "TRANSACTION")==0)
838                                 {
839                                         List *head;
840
841                                         foreach(head, n->args)
842                                         {
843                                                 DefElem *item = (DefElem *) lfirst(head);
844
845                                                 if (strcmp(item->defname, "transaction_isolation")==0)
846                                                         SetPGVariable("transaction_isolation",
847                                                                                   makeList1(item->arg), n->is_local);
848                                                 else if (strcmp(item->defname, "transaction_read_only")==0)
849                                                         SetPGVariable("transaction_read_only",
850                                                                                   makeList1(item->arg), n->is_local);
851                                         }
852                                 }
853                                 else if (strcmp(n->name, "SESSION CHARACTERISTICS")==0)
854                                 {
855                                         List *head;
856
857                                         foreach(head, n->args)
858                                         {
859                                                 DefElem *item = (DefElem *) lfirst(head);
860
861                                                 if (strcmp(item->defname, "transaction_isolation")==0)
862                                                         SetPGVariable("default_transaction_isolation",
863                                                                                   makeList1(item->arg), n->is_local);
864                                                 else if (strcmp(item->defname, "transaction_read_only")==0)
865                                                         SetPGVariable("default_transaction_read_only",
866                                                                                   makeList1(item->arg), n->is_local);
867                                         }
868                                 }
869                                 else
870                                         SetPGVariable(n->name, n->args, n->is_local);
871                         }
872                         break;
873
874                 case T_VariableShowStmt:
875                         {
876                                 VariableShowStmt *n = (VariableShowStmt *) parsetree;
877
878                                 GetPGVariable(n->name);
879                         }
880                         break;
881
882                 case T_VariableResetStmt:
883                         {
884                                 VariableResetStmt *n = (VariableResetStmt *) parsetree;
885
886                                 ResetPGVariable(n->name);
887                         }
888                         break;
889
890                 case T_CreateTrigStmt:
891                         CreateTrigger((CreateTrigStmt *) parsetree, false);
892                         break;
893
894                 case T_DropPropertyStmt:
895                         {
896                                 DropPropertyStmt *stmt = (DropPropertyStmt *) parsetree;
897                                 Oid                     relId;
898
899                                 relId = RangeVarGetRelid(stmt->relation, false);
900
901                                 switch (stmt->removeType)
902                                 {
903                                         case DROP_RULE:
904                                                 /* RemoveRewriteRule checks permissions */
905                                                 RemoveRewriteRule(relId, stmt->property,
906                                                                                   stmt->behavior);
907                                                 break;
908                                         case DROP_TRIGGER:
909                                                 /* DropTrigger checks permissions */
910                                                 DropTrigger(relId, stmt->property,
911                                                                         stmt->behavior);
912                                                 break;
913                                 }
914                         }
915                         break;
916
917                 case T_CreatePLangStmt:
918                         CreateProceduralLanguage((CreatePLangStmt *) parsetree);
919                         break;
920
921                 case T_DropPLangStmt:
922                         DropProceduralLanguage((DropPLangStmt *) parsetree);
923                         break;
924
925                         /*
926                          * ******************************** DOMAIN statements ****
927                          */
928                 case T_CreateDomainStmt:
929                         DefineDomain((CreateDomainStmt *) parsetree);
930                         break;
931
932                         /*
933                          * ******************************** USER statements ****
934                          */
935                 case T_CreateUserStmt:
936                         CreateUser((CreateUserStmt *) parsetree);
937                         break;
938
939                 case T_AlterUserStmt:
940                         AlterUser((AlterUserStmt *) parsetree);
941                         break;
942
943                 case T_AlterUserSetStmt:
944                         AlterUserSet((AlterUserSetStmt *) parsetree);
945                         break;
946
947                 case T_DropUserStmt:
948                         DropUser((DropUserStmt *) parsetree);
949                         break;
950
951                 case T_LockStmt:
952                         LockTableCommand((LockStmt *) parsetree);
953                         break;
954
955                 case T_ConstraintsSetStmt:
956                         DeferredTriggerSetState((ConstraintsSetStmt *) parsetree);
957                         break;
958
959                 case T_CreateGroupStmt:
960                         CreateGroup((CreateGroupStmt *) parsetree);
961                         break;
962
963                 case T_AlterGroupStmt:
964                         AlterGroup((AlterGroupStmt *) parsetree, "ALTER GROUP");
965                         break;
966
967                 case T_DropGroupStmt:
968                         DropGroup((DropGroupStmt *) parsetree);
969                         break;
970
971                 case T_CheckPointStmt:
972                         if (!superuser())
973                                 elog(ERROR, "CHECKPOINT: permission denied");
974                         CreateCheckPoint(false, false);
975                         break;
976
977                 case T_ReindexStmt:
978                         {
979                                 ReindexStmt *stmt = (ReindexStmt *) parsetree;
980
981                                 switch (stmt->kind)
982                                 {
983                                         case REINDEX_INDEX:
984                                                 CheckOwnership(stmt->relation, false);
985                                                 ReindexIndex(stmt->relation, stmt->force);
986                                                 break;
987                                         case REINDEX_TABLE:
988                                                 CheckOwnership(stmt->relation, false);
989                                                 ReindexTable(stmt->relation, stmt->force);
990                                                 break;
991                                         case REINDEX_DATABASE:
992                                                 ReindexDatabase(stmt->name, stmt->force, false);
993                                                 break;
994                                 }
995                                 break;
996                         }
997                         break;
998
999                 case T_CreateConversionStmt:
1000                         CreateConversionCommand((CreateConversionStmt *) parsetree);
1001                         break;
1002
1003                 case T_CreateCastStmt:
1004                         CreateCast((CreateCastStmt *) parsetree);
1005                         break;
1006
1007                 case T_DropCastStmt:
1008                         DropCast((DropCastStmt *) parsetree);
1009                         break;
1010
1011                 case T_CreateOpClassStmt:
1012                         DefineOpClass((CreateOpClassStmt *) parsetree);
1013                         break;
1014
1015                 case T_RemoveOpClassStmt:
1016                         RemoveOpClass((RemoveOpClassStmt *) parsetree);
1017                         break;
1018
1019                 default:
1020                         elog(ERROR, "ProcessUtility: command #%d unsupported",
1021                                  nodeTag(parsetree));
1022                         break;
1023         }
1024 }