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