utility.c 21.9 KB
Newer Older
1 2
/*-------------------------------------------------------------------------
 *
3
 * utility.c
4 5 6
 *	  Contains functions which control the execution of the POSTGRES utility
 *	  commands.  At one time acted as an interface between the Lisp and C
 *	  systems.
7
 *
8
 * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
Bruce Momjian's avatar
Add:  
Bruce Momjian committed
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"
Bruce Momjian's avatar
Bruce Momjian committed
18

19
#include "access/heapam.h"
20
#include "catalog/catalog.h"
21
#include "catalog/pg_shadow.h"
22 23 24
#include "commands/async.h"
#include "commands/cluster.h"
#include "commands/command.h"
Bruce Momjian's avatar
Bruce Momjian committed
25
#include "commands/comment.h"
26 27
#include "commands/copy.h"
#include "commands/creatinh.h"
28
#include "commands/dbcommands.h"
29 30
#include "commands/defrem.h"
#include "commands/explain.h"
31
#include "commands/proclang.h"
Bruce Momjian's avatar
Bruce Momjian committed
32 33 34
#include "commands/rename.h"
#include "commands/sequence.h"
#include "commands/trigger.h"
35
#include "commands/user.h"
Bruce Momjian's avatar
Bruce Momjian committed
36
#include "commands/vacuum.h"
37
#include "commands/variable.h"
Bruce Momjian's avatar
Bruce Momjian committed
38 39
#include "commands/view.h"
#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"
Bruce Momjian's avatar
Bruce Momjian committed
44
#include "rewrite/rewriteRemove.h"
Bruce Momjian's avatar
Bruce Momjian committed
45
#include "tcop/utility.h"
46
#include "utils/acl.h"
Bruce Momjian's avatar
Bruce Momjian committed
47
#include "utils/ps_status.h"
48
#include "utils/syscache.h"
49
#include "utils/temprel.h"
Vadim B. Mikheev's avatar
Vadim B. Mikheev committed
50
#include "access/xlog.h"
51

52
/*
53
 * Error-checking support for DROP commands
54 55
 */

56 57 58 59 60 61
struct kindstrings
{
	char		kind;
	char	   *indef_article;
	char	   *name;
	char	   *command;
62 63 64
};

static struct kindstrings kindstringarray[] = {
65 66 67 68 69
	{RELKIND_RELATION, "a", "table", "TABLE"},
	{RELKIND_SEQUENCE, "a", "sequence", "SEQUENCE"},
	{RELKIND_VIEW, "a", "view", "VIEW"},
	{RELKIND_INDEX, "an", "index", "INDEX"},
	{'\0', "a", "???", "???"}
70 71 72 73
};


static void
74
DropErrorMsg(char *relname, char wrongkind, char rightkind)
75 76 77 78 79 80 81 82 83 84 85 86
{
	struct kindstrings *rentry;
	struct kindstrings *wentry;

	for (rentry = kindstringarray; rentry->kind != '\0'; rentry++)
		if (rentry->kind == rightkind)
			break;
	Assert(rentry->kind != '\0');

	for (wentry = kindstringarray; wentry->kind != '\0'; wentry++)
		if (wentry->kind == wrongkind)
			break;
87 88 89 90 91 92 93 94
	/* wrongkind could be something we don't have in our table... */
	if (wentry->kind != '\0')
		elog(ERROR, "\"%s\" is not %s %s. Use DROP %s to remove %s %s",
			 relname, rentry->indef_article, rentry->name,
			 wentry->command, wentry->indef_article, wentry->name);
	else
		elog(ERROR, "\"%s\" is not %s %s",
			 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 103
	Form_pg_class classform;

104 105 106 107 108
	for (rentry = kindstringarray; rentry->kind != '\0'; rentry++)
		if (rentry->kind == rightkind)
			break;
	Assert(rentry->kind != '\0');

109 110 111
	tuple = SearchSysCache(RELNAME,
						   PointerGetDatum(name),
						   0, 0, 0);
112
	if (!HeapTupleIsValid(tuple))
113
		elog(ERROR, "%s \"%s\" does not exist", rentry->name, name);
114 115 116 117 118

	classform = (Form_pg_class) GETSTRUCT(tuple);

	if (classform->relkind != rightkind)
		DropErrorMsg(name, classform->relkind, rightkind);
119 120 121 122 123

	if (!pg_ownercheck(GetUserId(), name, RELNAME))
		elog(ERROR, "you do not own %s \"%s\"",
			 rentry->name, name);

124 125
	if (!allowSystemTableMods && IsSystemRelationName(name) &&
		!is_temp_relname(name))
126 127
		elog(ERROR, "%s \"%s\" is a system %s",
			 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 142 143
	char	   *commandTag = NULL;
	char	   *relname;
	char	   *relationName;
144 145

	switch (nodeTag(parsetree))
146
	{
147

148 149 150 151 152 153 154
			/*
			 * ******************************** transactions ********************************
			 *
			 */
		case T_TransactionStmt:
			{
				TransactionStmt *stmt = (TransactionStmt *) parsetree;
155

156 157 158
				switch (stmt->command)
				{
					case BEGIN_TRANS:
159
						set_ps_display(commandTag = "BEGIN");
160 161 162
						BeginTransactionBlock();
						break;

163
					case COMMIT:
164
						set_ps_display(commandTag = "COMMIT");
165 166 167
						EndTransactionBlock();
						break;

168
					case ROLLBACK:
169
						set_ps_display(commandTag = "ROLLBACK");
170 171 172 173 174 175 176 177 178 179 180
						UserAbortTransactionBlock();
						break;
				}
			}
			break;

			/*
			 * ******************************** portal manipulation ********************************
			 *
			 */
		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 191 192 193 194 195 196
		case T_FetchStmt:
			{
				FetchStmt  *stmt = (FetchStmt *) parsetree;
				char	   *portalName = stmt->portalname;
				bool		forward;
				int			count;

197
				set_ps_display(commandTag = (stmt->ismove) ? "MOVE" : "FETCH");
198

199 200
				SetQuerySnapshot();

201
				forward = (bool) (stmt->direction == FORWARD);
202

203 204 205
				/*
				 * parser ensures that count is >= 0 and 'fetch ALL' -> 0
				 */
206

207
				count = stmt->howMany;
208 209
				PerformPortalFetch(portalName, forward, count, commandTag,
								   (stmt->ismove) ? None : dest);		/* /dev/null for MOVE */
210 211
			}
			break;
212 213

			/*
214 215 216
			 * ******************************** relation and attribute
			 * manipulation ********************************
			 *
217
			 */
218
		case T_CreateStmt:
219
			set_ps_display(commandTag = "CREATE");
220

221
			DefineRelation((CreateStmt *) parsetree, RELKIND_RELATION);
222 223

			/*
224 225
			 * Let AlterTableCreateToastTable decide if this one needs a
			 * secondary relation too.
226 227
			 */
			CommandCounterIncrement();
228 229
			AlterTableCreateToastTable(((CreateStmt *) parsetree)->relname,
									   true);
230 231
			break;

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 241
				foreach(arg, args)
				{
242
					relname = strVal(lfirst(arg));
243

244
					switch (stmt->removeType)
245 246
					{
						case DROP_TABLE:
247
							CheckDropPermissions(relname, RELKIND_RELATION);
248 249 250 251
							RemoveRelation(relname);
							break;

						case DROP_SEQUENCE:
252
							CheckDropPermissions(relname, RELKIND_SEQUENCE);
253 254 255 256
							RemoveRelation(relname);
							break;

						case DROP_VIEW:
257
							CheckDropPermissions(relname, RELKIND_VIEW);
258 259 260 261
							RemoveView(relname);
							break;

						case DROP_INDEX:
262
							CheckDropPermissions(relname, RELKIND_INDEX);
263 264 265 266 267 268 269 270 271
							RemoveIndex(relname);
							break;

						case DROP_RULE:
							{
								char	   *rulename = relname;
								int			aclcheck_result;

								relationName = RewriteGetRuleEventRel(rulename);
272
								aclcheck_result = pg_aclcheck(relationName, GetUserId(), ACL_RULE);
273
								if (aclcheck_result != ACLCHECK_OK)
274 275
									elog(ERROR, "%s: %s", relationName,
										 aclcheck_error_strings[aclcheck_result]);
276 277 278 279 280
								RemoveRewriteRule(rulename);
							}
							break;

						case DROP_TYPE_P:
281
							/* RemoveType does its own permissions checks */
282 283 284 285
							RemoveType(relname);
							break;
					}

286
					/*
287 288 289
					 * Make sure subsequent loop iterations will see
					 * results of this one; needed if removing multiple
					 * rules for same table, for example.
290 291 292
					 */
					CommandCounterIncrement();
				}
293
			}
294 295
			break;

296 297 298 299
		case T_TruncateStmt:
			{
				Relation	rel;

300
				set_ps_display(commandTag = "TRUNCATE");
301

302
				relname = ((TruncateStmt *) parsetree)->relName;
303 304 305 306 307 308
				if (!allowSystemTableMods && IsSystemRelationName(relname))
					elog(ERROR, "TRUNCATE cannot be used on system tables. '%s' is a system table",
						 relname);

				/* Grab exclusive lock in preparation for truncate... */
				rel = heap_openr(relname, AccessExclusiveLock);
309
				if (rel->rd_rel->relkind == RELKIND_SEQUENCE)
310 311
					elog(ERROR, "TRUNCATE cannot be used on sequences. '%s' is a sequence",
						 relname);
312 313 314
				if (rel->rd_rel->relkind == RELKIND_VIEW)
					elog(ERROR, "TRUNCATE cannot be used on views. '%s' is a sequence",
						 relname);
315
				heap_close(rel, NoLock);
316

317
				if (!pg_ownercheck(GetUserId(), relname, RELNAME))
318 319
					elog(ERROR, "you do not own class \"%s\"", relname);
				TruncateRelation(relname);
320 321 322
			}
			break;

323 324 325 326 327 328
		case T_CommentStmt:
			{
				CommentStmt *statement;

				statement = ((CommentStmt *) parsetree);

329
				set_ps_display(commandTag = "COMMENT");
330

331 332 333 334 335 336
				CommentObject(statement->objtype, statement->objname,
							  statement->objproperty, statement->objlist,
							  statement->comment);
			}
			break;

337 338 339
		case T_CopyStmt:
			{
				CopyStmt   *stmt = (CopyStmt *) parsetree;
340

341
				set_ps_display(commandTag = "COPY");
342

343 344 345
				if (stmt->direction != FROM)
					SetQuerySnapshot();

346 347 348 349 350
				DoCopy(stmt->relname,
					   stmt->binary,
					   stmt->oids,
					   (bool) (stmt->direction == FROM),
					   (bool) (stmt->filename == NULL),
351

352 353 354 355 356
				/*
				 * null filename means copy to/from stdout/stdin, rather
				 * than to/from a file.
				 */
					   stmt->filename,
357
					   stmt->delimiter,
358
					   stmt->null_print);
359 360
			}
			break;
361 362

			/*
363
			 * schema
364
			 */
365 366 367
		case T_RenameStmt:
			{
				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 380 381 382 383
				 *	XXX using len == 3 to tell the difference
				 *		between "rename rel to newrel" and
				 *		"rename att in rel to newatt" will not
				 *		work soon because "rename type/operator/rule"
				 *		stuff is being added. - cim 10/24/90
384
				 * ----------------
385
				 * [another piece of amuzing but useless anecdote -- ay]
386
				 */
387 388
				if (stmt->column == NULL)
				{
389 390 391

					/*
					 * rename relation
392
					 *
393 394
					 * Note: we also rename the "type" tuple corresponding to
					 * the relation.
395 396 397 398 399 400
					 */
					renamerel(relname,	/* old name */
							  stmt->newname);	/* new name */
				}
				else
				{
401 402 403

					/*
					 * rename attribute
404 405 406 407
					 */
					renameatt(relname,	/* relname */
							  stmt->column,		/* old att name */
							  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 418
			{
				AlterTableStmt *stmt = (AlterTableStmt *) parsetree;

419
				set_ps_display(commandTag = "ALTER");
420 421 422 423 424 425 426 427

				/*
				 * Some or all of these functions are recursive to cover
				 * inherited things, so permission checks are done there.
				 */
				switch (stmt->subtype)
				{
					case 'A':	/* ADD COLUMN */
428
						AlterTableAddColumn(stmt->relname,
429
										interpretInhOption(stmt->inhOpt),
430
											(ColumnDef *) stmt->def);
431
						break;
432 433
					case 'T':	/* ALTER COLUMN DEFAULT */
						AlterTableAlterColumnDefault(stmt->relname,
434
										interpretInhOption(stmt->inhOpt),
435 436
													 stmt->name,
													 stmt->def);
437
						break;
438 439 440 441 442 443 444
					case 'S':	/* ALTER COLUMN STATISTICS */
						AlterTableAlterColumnStatistics(stmt->relname,
										interpretInhOption(stmt->inhOpt),
														stmt->name,
														stmt->def);
						break;
					case 'D':	/* DROP COLUMN */
445
						AlterTableDropColumn(stmt->relname,
446
										interpretInhOption(stmt->inhOpt),
447 448
											 stmt->name,
											 stmt->behavior);
449 450
						break;
					case 'C':	/* ADD CONSTRAINT */
451
						AlterTableAddConstraint(stmt->relname,
452
										interpretInhOption(stmt->inhOpt),
453
												stmt->def);
454 455
						break;
					case 'X':	/* DROP CONSTRAINT */
456
						AlterTableDropConstraint(stmt->relname,
457
										interpretInhOption(stmt->inhOpt),
458 459
												 stmt->name,
												 stmt->behavior);
460
						break;
Jan Wieck's avatar
TOAST  
Jan Wieck committed
461
					case 'E':	/* CREATE TOAST TABLE */
462 463
						AlterTableCreateToastTable(stmt->relname,
												   false);
Jan Wieck's avatar
TOAST  
Jan Wieck committed
464
						break;
465
					case 'U':	/* ALTER OWNER */
466 467
						AlterTableOwner(stmt->relname,
										stmt->name);
468
						break;
469 470 471 472 473 474
					default:	/* oops */
						elog(ERROR, "T_AlterTableStmt: unknown subtype");
						break;
				}
			}
			break;
475 476


477
		case T_GrantStmt:
478
			{
479 480 481
				GrantStmt *stmt = (GrantStmt *) parsetree;
				commandTag = stmt->is_grant ? "GRANT" : "REVOKE";
				set_ps_display(commandTag);
482

483
				ExecuteGrantStmt(stmt);
484 485
			}
			break;
486

487 488 489 490 491 492 493 494
			/*
			 * ******************************** object creation /
			 * destruction ********************************
			 *
			 */
		case T_DefineStmt:
			{
				DefineStmt *stmt = (DefineStmt *) parsetree;
495

496
				set_ps_display(commandTag = "CREATE");
497

498
				switch (stmt->defType)
499
				{
500 501 502 503
					case OPERATOR:
						DefineOperator(stmt->defname,	/* operator name */
									   stmt->definition);		/* rest */
						break;
504
					case TYPE_P:
505
						DefineType(stmt->defname, stmt->definition);
506 507 508 509 510
						break;
					case AGGREGATE:
						DefineAggregate(stmt->defname,	/* aggregate name */
										stmt->definition);		/* rest */
						break;
511 512
				}
			}
513 514 515 516 517
			break;

		case T_ViewStmt:		/* CREATE VIEW */
			{
				ViewStmt   *stmt = (ViewStmt *) parsetree;
518

519
				set_ps_display(commandTag = "CREATE");
520

521 522 523
				DefineView(stmt->viewname, stmt->query);		/* retrieve parsetree */
			}
			break;
524

525
		case T_ProcedureStmt:	/* CREATE FUNCTION */
526
			set_ps_display(commandTag = "CREATE");
527

528
			CreateFunction((ProcedureStmt *) parsetree);
529
			break;
530

531 532 533
		case T_IndexStmt:		/* CREATE INDEX */
			{
				IndexStmt  *stmt = (IndexStmt *) parsetree;
534

535
				set_ps_display(commandTag = "CREATE");
536

537 538 539 540 541
				DefineIndex(stmt->relname,		/* relation name */
							stmt->idxname,		/* index name */
							stmt->accessMethod, /* am name */
							stmt->indexParams,	/* parameters */
							stmt->unique,
542
							stmt->primary,
543 544 545 546
							(Expr *) stmt->whereClause,
							stmt->rangetable);
			}
			break;
547

548 549 550 551
		case T_RuleStmt:		/* CREATE RULE */
			{
				RuleStmt   *stmt = (RuleStmt *) parsetree;
				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 560 561 562 563
				DefineQueryRewrite(stmt);
			}
			break;

		case T_CreateSeqStmt:
564
			set_ps_display(commandTag = "CREATE");
565

566 567
			DefineSequence((CreateSeqStmt *) parsetree);
			break;
568

569 570 571
		case T_RemoveAggrStmt:
			{
				RemoveAggrStmt *stmt = (RemoveAggrStmt *) parsetree;
572
				char	   *typename = (char *) NULL;
573

574
				set_ps_display(commandTag = "DROP");
575 576 577 578 579

				if (stmt->aggtype != NULL)
					typename = TypeNameToInternalName((TypeName *) stmt->aggtype);

				RemoveAggregate(stmt->aggname, typename);
580 581
			}
			break;
582

583 584 585
		case T_RemoveFuncStmt:
			{
				RemoveFuncStmt *stmt = (RemoveFuncStmt *) parsetree;
586

587
				set_ps_display(commandTag = "DROP");
588 589

				RemoveFunction(stmt->funcname, stmt->args);
590 591
			}
			break;
592

593 594 595
		case T_RemoveOperStmt:
			{
				RemoveOperStmt *stmt = (RemoveOperStmt *) parsetree;
596 597 598 599
				TypeName   *typenode1 = (TypeName *) lfirst(stmt->args);
				TypeName   *typenode2 = (TypeName *) lsecond(stmt->args);
				char	   *typename1 = (char *) NULL;
				char	   *typename2 = (char *) NULL;
600

601
				set_ps_display(commandTag = "DROP");
602

603 604 605 606 607 608
				if (typenode1 != NULL)
					typename1 = TypeNameToInternalName(typenode1);
				if (typenode2 != NULL)
					typename2 = TypeNameToInternalName(typenode2);

				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 617 618
		case T_CreatedbStmt:
			{
				CreatedbStmt *stmt = (CreatedbStmt *) parsetree;
619

620
				set_ps_display(commandTag = "CREATE DATABASE");
621

622 623
				createdb(stmt->dbname, stmt->dbpath,
						 stmt->dbtemplate, stmt->encoding);
624 625 626
			}
			break;

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 638 639 640
			/* Query-level asynchronous notification */
		case T_NotifyStmt:
			{
				NotifyStmt *stmt = (NotifyStmt *) parsetree;
641

642
				set_ps_display(commandTag = "NOTIFY");
643

644 645 646
				Async_Notify(stmt->relname);
			}
			break;
647

648 649 650
		case T_ListenStmt:
			{
				ListenStmt *stmt = (ListenStmt *) parsetree;
651

652
				set_ps_display(commandTag = "LISTEN");
653

Bruce Momjian's avatar
Bruce Momjian committed
654
				Async_Listen(stmt->relname, MyProcPid);
655 656
			}
			break;
657

658 659 660 661
		case T_UnlistenStmt:
			{
				UnlistenStmt *stmt = (UnlistenStmt *) parsetree;

662
				set_ps_display(commandTag = "UNLISTEN");
663 664 665 666 667

				Async_Unlisten(stmt->relname, MyProcPid);
			}
			break;

668 669 670 671 672 673 674 675
			/*
			 * ******************************** dynamic loader ********************************
			 *
			 */
		case T_LoadStmt:
			{
				LoadStmt   *stmt = (LoadStmt *) parsetree;

676
				set_ps_display(commandTag = "LOAD");
677

Bruce Momjian's avatar
Bruce Momjian committed
678
				closeAllVfds(); /* probably not necessary... */
679
				load_file(stmt->filename);
680 681
			}
			break;
682

683 684 685
		case T_ClusterStmt:
			{
				ClusterStmt *stmt = (ClusterStmt *) parsetree;
686

687
				set_ps_display(commandTag = "CLUSTER");
688

689 690 691 692 693 694 695 696
				relname = stmt->relname;
				if (IsSystemRelationName(relname))
					elog(ERROR, "CLUSTER: relation \"%s\" is a system catalog",
						 relname);
				if (!pg_ownercheck(GetUserId(), relname, RELNAME))
					elog(ERROR, "permission denied");

				cluster(relname, stmt->indexname);
697 698 699 700
			}
			break;

		case T_VacuumStmt:
701 702 703 704 705
			if (((VacuumStmt *) parsetree)->vacuum)
				commandTag = "VACUUM";
			else
				commandTag = "ANALYZE";
			set_ps_display(commandTag);
706

707
			vacuum((VacuumStmt *) parsetree);
708 709 710 711 712 713
			break;

		case T_ExplainStmt:
			{
				ExplainStmt *stmt = (ExplainStmt *) parsetree;

714
				set_ps_display(commandTag = "EXPLAIN");
715

716
				ExplainQuery(stmt->query, stmt->verbose, stmt->analyze, dest);
717 718
			}
			break;
719

720
#ifdef NOT_USED
Bruce Momjian's avatar
Bruce Momjian committed
721

722 723 724 725 726 727
			/*
			 * ******************************** Tioga-related statements *******************************
			 */
		case T_RecipeStmt:
			{
				RecipeStmt *stmt = (RecipeStmt *) parsetree;
728

729
				set_ps_display(commandTag = "EXECUTE RECIPE");
730

731 732 733
				beginRecipe(stmt);
			}
			break;
734
#endif
735 736 737 738 739 740 741 742 743

			/*
			 * ******************************** set variable statements *******************************
			 */
		case T_VariableSetStmt:
			{
				VariableSetStmt *n = (VariableSetStmt *) parsetree;

				SetPGVariable(n->name, n->value);
744
				set_ps_display(commandTag = "SET VARIABLE");
745 746 747 748 749 750 751 752
			}
			break;

		case T_VariableShowStmt:
			{
				VariableShowStmt *n = (VariableShowStmt *) parsetree;

				GetPGVariable(n->name);
753
				set_ps_display(commandTag = "SHOW VARIABLE");
754 755 756 757 758 759 760 761
			}
			break;

		case T_VariableResetStmt:
			{
				VariableResetStmt *n = (VariableResetStmt *) parsetree;

				ResetPGVariable(n->name);
762
				set_ps_display(commandTag = "RESET VARIABLE");
763 764 765 766 767 768 769
			}
			break;

			/*
			 * ******************************** TRIGGER statements *******************************
			 */
		case T_CreateTrigStmt:
770
			set_ps_display(commandTag = "CREATE");
771 772 773 774 775

			CreateTrigger((CreateTrigStmt *) parsetree);
			break;

		case T_DropTrigStmt:
776
			set_ps_display(commandTag = "DROP");
777 778 779 780

			DropTrigger((DropTrigStmt *) parsetree);
			break;

781 782 783 784
			/*
			 * ************* PROCEDURAL LANGUAGE statements *****************
			 */
		case T_CreatePLangStmt:
785
			set_ps_display(commandTag = "CREATE");
786 787 788 789 790

			CreateProceduralLanguage((CreatePLangStmt *) parsetree);
			break;

		case T_DropPLangStmt:
791
			set_ps_display(commandTag = "DROP");
792 793 794 795

			DropProceduralLanguage((DropPLangStmt *) parsetree);
			break;

796 797 798 799 800
			/*
			 * ******************************** USER statements ****
			 *
			 */
		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 822 823

			LockTableCommand((LockStmt *) parsetree);
			break;

824
		case T_ConstraintsSetStmt:
825
			set_ps_display(commandTag = "SET CONSTRAINTS");
826 827 828 829

			DeferredTriggerSetState((ConstraintsSetStmt *) parsetree);
			break;

830
		case T_CreateGroupStmt:
831
			set_ps_display(commandTag = "CREATE GROUP");
832

833 834
			CreateGroup((CreateGroupStmt *) parsetree);
			break;
835

836
		case T_AlterGroupStmt:
837
			set_ps_display(commandTag = "ALTER GROUP");
838

839 840
			AlterGroup((AlterGroupStmt *) parsetree, "ALTER GROUP");
			break;
841

842
		case T_DropGroupStmt:
843
			set_ps_display(commandTag = "DROP GROUP");
844

845 846
			DropGroup((DropGroupStmt *) parsetree);
			break;
847

Vadim B. Mikheev's avatar
Vadim B. Mikheev committed
848 849 850 851
		case T_CheckPointStmt:
			{
				set_ps_display(commandTag = "CHECKPOINT");

852 853
				if (!superuser())
					elog(ERROR, "permission denied");
Vadim B. Mikheev's avatar
Vadim B. Mikheev committed
854 855 856 857
				CreateCheckPoint(false);
			}
			break;

Hiroshi Inoue's avatar
Hiroshi Inoue committed
858 859 860 861
		case T_ReindexStmt:
			{
				ReindexStmt *stmt = (ReindexStmt *) parsetree;

862
				set_ps_display(commandTag = "REINDEX");
Hiroshi Inoue's avatar
Hiroshi Inoue committed
863 864 865 866

				switch (stmt->reindexType)
				{
					case INDEX:
867
						relname = (char *) stmt->name;
Hiroshi Inoue's avatar
Hiroshi Inoue committed
868 869 870
						if (IsSystemRelationName(relname))
						{
							if (!allowSystemTableMods && IsSystemRelationName(relname))
871
								elog(ERROR, "\"%s\" is a system index. call REINDEX under standalone postgres with -O -P options",
872
									 relname);
Hiroshi Inoue's avatar
Hiroshi Inoue committed
873
							if (!IsIgnoringSystemIndexes())
874
								elog(ERROR, "\"%s\" is a system index. call REINDEX under standalone postgres with -P -O options",
875
									 relname);
Hiroshi Inoue's avatar
Hiroshi Inoue committed
876
						}
877
						if (!pg_ownercheck(GetUserId(), relname, RELNAME))
Hiroshi Inoue's avatar
Hiroshi Inoue committed
878 879 880 881
							elog(ERROR, "%s: %s", relname, aclcheck_error_strings[ACLCHECK_NOT_OWNER]);
						ReindexIndex(relname, stmt->force);
						break;
					case TABLE:
882
						relname = (char *) stmt->name;
883
						if (!pg_ownercheck(GetUserId(), relname, RELNAME))
Hiroshi Inoue's avatar
Hiroshi Inoue committed
884 885 886 887
							elog(ERROR, "%s: %s", relname, aclcheck_error_strings[ACLCHECK_NOT_OWNER]);
						ReindexTable(relname, stmt->force);
						break;
					case DATABASE:
888
						relname = (char *) stmt->name;
Hiroshi Inoue's avatar
Hiroshi Inoue committed
889
						if (!allowSystemTableMods)
890
							elog(ERROR, "must be called under standalone postgres with -O -P options");
Hiroshi Inoue's avatar
Hiroshi Inoue committed
891
						if (!IsIgnoringSystemIndexes())
892
							elog(ERROR, "must be called under standalone postgres with -P -O options");
Hiroshi Inoue's avatar
Hiroshi Inoue committed
893 894 895 896 897 898
						ReindexDatabase(relname, stmt->force, false);
						break;
				}
				break;
			}
			break;
899

900 901 902 903 904
			/*
			 * ******************************** default ********************************
			 *
			 */
		default:
905
			elog(ERROR, "ProcessUtility: command #%d unsupported",
906 907
				 nodeTag(parsetree));
			break;
908
	}
909

910 911
	/*
	 * tell fe/be or whatever that we're done.
912
	 */
913
	EndCommand(commandTag, dest);
914
}