OSDN Git Service

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