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