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