OSDN Git Service

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