utility.c 22.2 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.114 2001/06/18 16:13:21 momjian 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 529
			CreateFunction((ProcedureStmt *) parsetree, dest);	/* everything */
			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 542
				DefineIndex(stmt->relname,		/* relation name */
							stmt->idxname,		/* index name */
							stmt->accessMethod, /* am name */
							stmt->indexParams,	/* parameters */
							stmt->withClause,
							stmt->unique,
543
							stmt->primary,
544 545 546 547
							(Expr *) stmt->whereClause,
							stmt->rangetable);
			}
			break;
548

549 550 551 552
		case T_RuleStmt:		/* CREATE RULE */
			{
				RuleStmt   *stmt = (RuleStmt *) parsetree;
				int			aclcheck_result;
553

554
				relname = stmt->object->relname;
555
				aclcheck_result = pg_aclcheck(relname, GetUserId(), ACL_RULE);
556
				if (aclcheck_result != ACLCHECK_OK)
557
					elog(ERROR, "%s: %s", relname, aclcheck_error_strings[aclcheck_result]);
558
				set_ps_display(commandTag = "CREATE");
559

560 561 562 563 564
				DefineQueryRewrite(stmt);
			}
			break;

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

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

570 571 572
		case T_ExtendStmt:
			{
				ExtendStmt *stmt = (ExtendStmt *) parsetree;
573

574
				set_ps_display(commandTag = "EXTEND");
575

576 577 578 579 580
				ExtendIndex(stmt->idxname,		/* index name */
							(Expr *) stmt->whereClause, /* where */
							stmt->rangetable);
			}
			break;
581

582 583 584
		case T_RemoveAggrStmt:
			{
				RemoveAggrStmt *stmt = (RemoveAggrStmt *) parsetree;
585
				char	   *typename = (char *) NULL;
586

587
				set_ps_display(commandTag = "DROP");
588 589 590 591 592

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

				RemoveAggregate(stmt->aggname, typename);
593 594
			}
			break;
595

596 597 598
		case T_RemoveFuncStmt:
			{
				RemoveFuncStmt *stmt = (RemoveFuncStmt *) parsetree;
599

600
				set_ps_display(commandTag = "DROP");
601 602

				RemoveFunction(stmt->funcname, stmt->args);
603 604
			}
			break;
605

606 607 608
		case T_RemoveOperStmt:
			{
				RemoveOperStmt *stmt = (RemoveOperStmt *) parsetree;
609 610 611 612
				TypeName   *typenode1 = (TypeName *) lfirst(stmt->args);
				TypeName   *typenode2 = (TypeName *) lsecond(stmt->args);
				char	   *typename1 = (char *) NULL;
				char	   *typename2 = (char *) NULL;
613

614
				set_ps_display(commandTag = "DROP");
615

616 617 618 619 620 621
				if (typenode1 != NULL)
					typename1 = TypeNameToInternalName(typenode1);
				if (typenode2 != NULL)
					typename2 = TypeNameToInternalName(typenode2);

				RemoveOperator(stmt->opname, typename1, typename2);
622 623
			}
			break;
624

625
		case T_VersionStmt:
626
			elog(ERROR, "CREATE VERSION is not currently implemented");
627
			break;
628

629 630 631
		case T_CreatedbStmt:
			{
				CreatedbStmt *stmt = (CreatedbStmt *) parsetree;
632

633
				set_ps_display(commandTag = "CREATE DATABASE");
634

635 636
				createdb(stmt->dbname, stmt->dbpath,
						 stmt->dbtemplate, stmt->encoding);
637 638 639
			}
			break;

640
		case T_DropdbStmt:
641
			{
642
				DropdbStmt *stmt = (DropdbStmt *) parsetree;
643

644
				set_ps_display(commandTag = "DROP DATABASE");
645

646
				dropdb(stmt->dbname);
647 648
			}
			break;
649

650 651 652 653
			/* Query-level asynchronous notification */
		case T_NotifyStmt:
			{
				NotifyStmt *stmt = (NotifyStmt *) parsetree;
654

655
				set_ps_display(commandTag = "NOTIFY");
656

657 658 659
				Async_Notify(stmt->relname);
			}
			break;
660

661 662 663
		case T_ListenStmt:
			{
				ListenStmt *stmt = (ListenStmt *) parsetree;
664

665
				set_ps_display(commandTag = "LISTEN");
666

Bruce Momjian's avatar
Bruce Momjian committed
667
				Async_Listen(stmt->relname, MyProcPid);
668 669
			}
			break;
670

671 672 673 674
		case T_UnlistenStmt:
			{
				UnlistenStmt *stmt = (UnlistenStmt *) parsetree;

675
				set_ps_display(commandTag = "UNLISTEN");
676 677 678 679 680

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

681 682 683 684 685 686 687 688
			/*
			 * ******************************** dynamic loader ********************************
			 *
			 */
		case T_LoadStmt:
			{
				LoadStmt   *stmt = (LoadStmt *) parsetree;

689
				set_ps_display(commandTag = "LOAD");
690

Bruce Momjian's avatar
Bruce Momjian committed
691
				closeAllVfds(); /* probably not necessary... */
692
				load_file(stmt->filename);
693 694
			}
			break;
695

696 697 698
		case T_ClusterStmt:
			{
				ClusterStmt *stmt = (ClusterStmt *) parsetree;
699

700
				set_ps_display(commandTag = "CLUSTER");
701

702 703 704 705 706 707 708 709
				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);
710 711 712 713
			}
			break;

		case T_VacuumStmt:
714 715 716 717 718
			if (((VacuumStmt *) parsetree)->vacuum)
				commandTag = "VACUUM";
			else
				commandTag = "ANALYZE";
			set_ps_display(commandTag);
719

720
			vacuum((VacuumStmt *) parsetree);
721 722 723 724 725 726
			break;

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

727
				set_ps_display(commandTag = "EXPLAIN");
728

729 730 731
				ExplainQuery(stmt->query, stmt->verbose, dest);
			}
			break;
732

733
#ifdef NOT_USED
Bruce Momjian's avatar
Bruce Momjian committed
734

735 736 737 738 739 740
			/*
			 * ******************************** Tioga-related statements *******************************
			 */
		case T_RecipeStmt:
			{
				RecipeStmt *stmt = (RecipeStmt *) parsetree;
741

742
				set_ps_display(commandTag = "EXECUTE RECIPE");
743

744 745 746
				beginRecipe(stmt);
			}
			break;
747
#endif
748 749 750 751 752 753 754 755 756

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

				SetPGVariable(n->name, n->value);
757
				set_ps_display(commandTag = "SET VARIABLE");
758 759 760 761 762 763 764 765
			}
			break;

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

				GetPGVariable(n->name);
766
				set_ps_display(commandTag = "SHOW VARIABLE");
767 768 769 770 771 772 773 774
			}
			break;

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

				ResetPGVariable(n->name);
775
				set_ps_display(commandTag = "RESET VARIABLE");
776 777 778 779 780 781 782
			}
			break;

			/*
			 * ******************************** TRIGGER statements *******************************
			 */
		case T_CreateTrigStmt:
783
			set_ps_display(commandTag = "CREATE");
784 785 786 787 788

			CreateTrigger((CreateTrigStmt *) parsetree);
			break;

		case T_DropTrigStmt:
789
			set_ps_display(commandTag = "DROP");
790 791 792 793

			DropTrigger((DropTrigStmt *) parsetree);
			break;

794 795 796 797
			/*
			 * ************* PROCEDURAL LANGUAGE statements *****************
			 */
		case T_CreatePLangStmt:
798
			set_ps_display(commandTag = "CREATE");
799 800 801 802 803

			CreateProceduralLanguage((CreatePLangStmt *) parsetree);
			break;

		case T_DropPLangStmt:
804
			set_ps_display(commandTag = "DROP");
805 806 807 808

			DropProceduralLanguage((DropPLangStmt *) parsetree);
			break;

809 810 811 812 813
			/*
			 * ******************************** USER statements ****
			 *
			 */
		case T_CreateUserStmt:
814
			set_ps_display(commandTag = "CREATE USER");
815

816
			CreateUser((CreateUserStmt *) parsetree);
817
			break;
818

819
		case T_AlterUserStmt:
820
			set_ps_display(commandTag = "ALTER USER");
821

822
			AlterUser((AlterUserStmt *) parsetree);
823
			break;
824

825
		case T_DropUserStmt:
826
			set_ps_display(commandTag = "DROP USER");
827

828
			DropUser((DropUserStmt *) parsetree);
829
			break;
830

831
		case T_LockStmt:
832
			set_ps_display(commandTag = "LOCK TABLE");
833 834 835 836

			LockTableCommand((LockStmt *) parsetree);
			break;

837
		case T_ConstraintsSetStmt:
838
			set_ps_display(commandTag = "SET CONSTRAINTS");
839 840 841 842

			DeferredTriggerSetState((ConstraintsSetStmt *) parsetree);
			break;

843
		case T_CreateGroupStmt:
844
			set_ps_display(commandTag = "CREATE GROUP");
845

846 847
			CreateGroup((CreateGroupStmt *) parsetree);
			break;
848

849
		case T_AlterGroupStmt:
850
			set_ps_display(commandTag = "ALTER GROUP");
851

852 853
			AlterGroup((AlterGroupStmt *) parsetree, "ALTER GROUP");
			break;
854

855
		case T_DropGroupStmt:
856
			set_ps_display(commandTag = "DROP GROUP");
857

858 859
			DropGroup((DropGroupStmt *) parsetree);
			break;
860

Vadim B. Mikheev's avatar
Vadim B. Mikheev committed
861 862 863 864
		case T_CheckPointStmt:
			{
				set_ps_display(commandTag = "CHECKPOINT");

865 866
				if (!superuser())
					elog(ERROR, "permission denied");
Vadim B. Mikheev's avatar
Vadim B. Mikheev committed
867 868 869 870
				CreateCheckPoint(false);
			}
			break;

Hiroshi Inoue's avatar
Hiroshi Inoue committed
871 872 873 874
		case T_ReindexStmt:
			{
				ReindexStmt *stmt = (ReindexStmt *) parsetree;

875
				set_ps_display(commandTag = "REINDEX");
Hiroshi Inoue's avatar
Hiroshi Inoue committed
876 877 878 879

				switch (stmt->reindexType)
				{
					case INDEX:
880
						relname = (char *) stmt->name;
Hiroshi Inoue's avatar
Hiroshi Inoue committed
881 882 883
						if (IsSystemRelationName(relname))
						{
							if (!allowSystemTableMods && IsSystemRelationName(relname))
884
								elog(ERROR, "\"%s\" is a system index. call REINDEX under standalone postgres with -O -P options",
885
									 relname);
Hiroshi Inoue's avatar
Hiroshi Inoue committed
886
							if (!IsIgnoringSystemIndexes())
887
								elog(ERROR, "\"%s\" is a system index. call REINDEX under standalone postgres with -P -O options",
888
									 relname);
Hiroshi Inoue's avatar
Hiroshi Inoue committed
889
						}
890
						if (!pg_ownercheck(GetUserId(), relname, RELNAME))
Hiroshi Inoue's avatar
Hiroshi Inoue committed
891 892 893 894
							elog(ERROR, "%s: %s", relname, aclcheck_error_strings[ACLCHECK_NOT_OWNER]);
						ReindexIndex(relname, stmt->force);
						break;
					case TABLE:
895
						relname = (char *) stmt->name;
896
						if (!pg_ownercheck(GetUserId(), relname, RELNAME))
Hiroshi Inoue's avatar
Hiroshi Inoue committed
897 898 899 900
							elog(ERROR, "%s: %s", relname, aclcheck_error_strings[ACLCHECK_NOT_OWNER]);
						ReindexTable(relname, stmt->force);
						break;
					case DATABASE:
901
						relname = (char *) stmt->name;
Hiroshi Inoue's avatar
Hiroshi Inoue committed
902
						if (!allowSystemTableMods)
903
							elog(ERROR, "must be called under standalone postgres with -O -P options");
Hiroshi Inoue's avatar
Hiroshi Inoue committed
904
						if (!IsIgnoringSystemIndexes())
905
							elog(ERROR, "must be called under standalone postgres with -P -O options");
Hiroshi Inoue's avatar
Hiroshi Inoue committed
906 907 908 909 910 911
						ReindexDatabase(relname, stmt->force, false);
						break;
				}
				break;
			}
			break;
912

913 914 915 916 917
			/*
			 * ******************************** default ********************************
			 *
			 */
		default:
918
			elog(ERROR, "ProcessUtility: command #%d unsupported",
919 920
				 nodeTag(parsetree));
			break;
921
	}
922

923 924
	/*
	 * tell fe/be or whatever that we're done.
925
	 */
926
	EndCommand(commandTag, dest);
927
}