utility.c 18.8 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 9 10 11
 *
 * Copyright (c) 1994, Regents of the University of California
 *
 *
 * IDENTIFICATION
12
 *	  $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.69 1999/09/30 01:12:36 tgl Exp $
13 14 15 16
 *
 *-------------------------------------------------------------------------
 */
#include "postgres.h"
Bruce Momjian's avatar
Bruce Momjian committed
17

18
#include "access/heapam.h"
19 20 21 22 23 24 25
#include "catalog/catalog.h"
#include "catalog/pg_type.h"
#include "commands/async.h"
#include "commands/cluster.h"
#include "commands/command.h"
#include "commands/copy.h"
#include "commands/creatinh.h"
26
#include "commands/dbcommands.h"
27 28
#include "commands/defrem.h"
#include "commands/explain.h"
29
#include "commands/proclang.h"
Bruce Momjian's avatar
Bruce Momjian committed
30 31 32 33
#include "commands/rename.h"
#include "commands/sequence.h"
#include "commands/trigger.h"
#include "commands/vacuum.h"
34
#include "commands/variable.h"
Bruce Momjian's avatar
Bruce Momjian committed
35 36
#include "commands/view.h"
#include "miscadmin.h"
37
#include "rewrite/rewriteDefine.h"
Bruce Momjian's avatar
Bruce Momjian committed
38
#include "rewrite/rewriteRemove.h"
Bruce Momjian's avatar
Bruce Momjian committed
39
#include "tcop/utility.h"
40
#include "utils/acl.h"
Bruce Momjian's avatar
Bruce Momjian committed
41 42
#include "utils/acl.h"
#include "utils/ps_status.h"
43
#include "utils/syscache.h"
Bruce Momjian's avatar
Bruce Momjian committed
44 45

#include "../backend/parser/parse.h"
46

Bruce Momjian's avatar
Bruce Momjian committed
47 48 49
void		DefineUser(CreateUserStmt *stmt, CommandDest);
void		AlterUser(AlterUserStmt *stmt, CommandDest);
void		RemoveUser(char *username, CommandDest);
50 51

/* ----------------
52 53
 *		CHECK_IF_ABORTED() is used to avoid doing unnecessary
 *		processing within an aborted transaction block.
54 55
 * ----------------
 */
56
 /* we have to use IF because of the 'break' */
57
#define CHECK_IF_ABORTED() \
58 59 60 61
if (1) \
{ \
	if (IsAbortedTransactionBlockState()) \
	{ \
62
		elog(NOTICE, "(transaction aborted): %s", \
63
			 "all queries ignored until end of transaction block"); \
64 65 66
		commandTag = "*ABORT STATE*"; \
		break; \
	} \
67
} else
68

69
/* ----------------
70
 *		general utility function invoker
71 72 73
 * ----------------
 */
void
74
ProcessUtility(Node *parsetree,
75
			   CommandDest dest)
76
{
77 78 79 80
	char	   *commandTag = NULL;
	char	   *relname;
	char	   *relationName;
	char	   *userName;
81 82 83 84

	userName = GetPgUserName();

	switch (nodeTag(parsetree))
85
	{
86

87 88 89 90 91 92 93
			/*
			 * ******************************** transactions ********************************
			 *
			 */
		case T_TransactionStmt:
			{
				TransactionStmt *stmt = (TransactionStmt *) parsetree;
94

95 96 97
				switch (stmt->command)
				{
					case BEGIN_TRANS:
98
						PS_SET_STATUS(commandTag = "BEGIN");
99 100 101 102 103
						CHECK_IF_ABORTED();
						BeginTransactionBlock();
						break;

					case END_TRANS:
104
						PS_SET_STATUS(commandTag = "END");
105 106 107 108
						EndTransactionBlock();
						break;

					case ABORT_TRANS:
109
						PS_SET_STATUS(commandTag = "ABORT");
110 111 112 113 114 115 116 117 118 119 120
						UserAbortTransactionBlock();
						break;
				}
			}
			break;

			/*
			 * ******************************** portal manipulation ********************************
			 *
			 */
		case T_ClosePortalStmt:
121
			{
122
				ClosePortalStmt *stmt = (ClosePortalStmt *) parsetree;
123

124
				PS_SET_STATUS(commandTag = "CLOSE");
125
				CHECK_IF_ABORTED();
126

127
				PerformPortalClose(stmt->portalname, dest);
128
			}
129
			break;
130

131 132 133 134 135 136 137
		case T_FetchStmt:
			{
				FetchStmt  *stmt = (FetchStmt *) parsetree;
				char	   *portalName = stmt->portalname;
				bool		forward;
				int			count;

138
				PS_SET_STATUS(commandTag = (stmt->ismove) ? "MOVE" : "FETCH");
139
				CHECK_IF_ABORTED();
140

141
				forward = (bool) (stmt->direction == FORWARD);
142

143 144 145
				/*
				 * parser ensures that count is >= 0 and 'fetch ALL' -> 0
				 */
146

147
				count = stmt->howMany;
148 149
				PerformPortalFetch(portalName, forward, count, commandTag,
								   (stmt->ismove) ? None : dest);		/* /dev/null for MOVE */
150 151
			}
			break;
152 153

			/*
154 155 156
			 * ******************************** relation and attribute
			 * manipulation ********************************
			 *
157
			 */
158
		case T_CreateStmt:
159
			PS_SET_STATUS(commandTag = "CREATE");
160 161
			CHECK_IF_ABORTED();

162
			DefineRelation((CreateStmt *) parsetree, RELKIND_RELATION);
163 164 165
			break;

		case T_DestroyStmt:
166
			{
167 168
				DestroyStmt *stmt = (DestroyStmt *) parsetree;
				List	   *args = stmt->relNames;
169
				List	   *arg;
170

171
				PS_SET_STATUS(commandTag = "DROP");
172 173
				CHECK_IF_ABORTED();

174
				/* check as much as we can before we start dropping ... */
175
				foreach(arg, args)
176
				{
177 178
					Relation	rel;

179
					relname = strVal(lfirst(arg));
180
					if (!allowSystemTableMods && IsSystemRelationName(relname))
181
						elog(ERROR, "class \"%s\" is a system catalog",
182
							 relname);
183 184 185 186 187 188 189 190 191 192 193
					rel = heap_openr(relname, AccessExclusiveLock);
					if (stmt->sequence &&
						rel->rd_rel->relkind != RELKIND_SEQUENCE)
						elog(ERROR, "Use DROP TABLE to drop table '%s'",
							 relname);
					if (!(stmt->sequence) &&
						rel->rd_rel->relkind == RELKIND_SEQUENCE)
						elog(ERROR, "Use DROP SEQUENCE to drop sequence '%s'",
							 relname);
					/* close rel, but keep lock until end of xact */
					heap_close(rel, NoLock);
194
#ifndef NO_SECURITY
195
					if (!pg_ownercheck(userName, relname, RELNAME))
196
						elog(ERROR, "you do not own class \"%s\"",
197
							 relname);
198
#endif
199
				}
200
				/* OK, terminate 'em all */
201 202 203 204 205
				foreach(arg, args)
				{
					relname = strVal(lfirst(arg));
					RemoveRelation(relname);
				}
206
			}
207 208
			break;

209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225
		case T_TruncateStmt:
			{
				Relation	rel;

				PS_SET_STATUS(commandTag = "TRUNCATE");
				CHECK_IF_ABORTED();

				relname = ((TruncateStmt *) parsetree)->relName;			
				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);
			    if (rel->rd_rel->relkind == RELKIND_SEQUENCE)
					elog(ERROR, "TRUNCATE cannot be used on sequences. '%s' is a sequence",
						 relname);
226
			    heap_close(rel, NoLock);
227

228
#ifndef NO_SECURITY
229 230
				if (!pg_ownercheck(userName, relname, RELNAME))
					elog(ERROR, "you do not own class \"%s\"", relname);
231
#endif
232
				TruncateRelation(relname);
233 234 235
			}
			break;

236 237 238
		case T_CopyStmt:
			{
				CopyStmt   *stmt = (CopyStmt *) parsetree;
239

240
				PS_SET_STATUS(commandTag = "COPY");
241
				CHECK_IF_ABORTED();
242

243 244 245 246 247
				DoCopy(stmt->relname,
					   stmt->binary,
					   stmt->oids,
					   (bool) (stmt->direction == FROM),
					   (bool) (stmt->filename == NULL),
248

249 250 251 252 253 254 255 256
				/*
				 * null filename means copy to/from stdout/stdin, rather
				 * than to/from a file.
				 */
					   stmt->filename,
					   stmt->delimiter);
			}
			break;
257

258 259 260
		case T_AddAttrStmt:
			{
				AddAttrStmt *stmt = (AddAttrStmt *) parsetree;
261

262
				PS_SET_STATUS(commandTag = "ADD");
263
				CHECK_IF_ABORTED();
264

265
				/*
266 267
				 * owner checking done in PerformAddAttribute (now
				 * recursive)
268 269 270 271
				 */
				PerformAddAttribute(stmt->relname,
									userName,
									stmt->inh,
272
									(ColumnDef *) stmt->colDef);
273 274
			}
			break;
275 276

			/*
277
			 * schema
278
			 */
279 280 281
		case T_RenameStmt:
			{
				RenameStmt *stmt = (RenameStmt *) parsetree;
282

283
				PS_SET_STATUS(commandTag = "RENAME");
284
				CHECK_IF_ABORTED();
285

286
				relname = stmt->relname;
287
				if (!allowSystemTableMods && IsSystemRelationName(relname))
288
					elog(ERROR, "class \"%s\" is a system catalog",
289
						 relname);
290
#ifndef NO_SECURITY
291
				if (!pg_ownercheck(userName, relname, RELNAME))
292
					elog(ERROR, "you do not own class \"%s\"",
293
						 relname);
294
#endif
295 296

				/* ----------------
297 298 299 300 301
				 *	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
302
				 * ----------------
303
				 * [another piece of amuzing but useless anecdote -- ay]
304
				 */
305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330
				if (stmt->column == NULL)
				{
					/* ----------------
					 *		rename relation
					 *
					 *		Note: we also rename the "type" tuple
					 *		corresponding to the relation.
					 * ----------------
					 */
					renamerel(relname,	/* old name */
							  stmt->newname);	/* new name */
					TypeRename(relname, /* old name */
							   stmt->newname);	/* new name */
				}
				else
				{
					/* ----------------
					 *		rename attribute
					 * ----------------
					 */
					renameatt(relname,	/* relname */
							  stmt->column,		/* old att name */
							  stmt->newname,	/* new att name */
							  userName,
							  stmt->inh);		/* recursive? */
				}
331
			}
332
			break;
333

334 335 336 337 338 339
		case T_ChangeACLStmt:
			{
				ChangeACLStmt *stmt = (ChangeACLStmt *) parsetree;
				List	   *i;
				AclItem    *aip;
				unsigned	modechg;
340

341
				PS_SET_STATUS(commandTag = "CHANGE");
342
				CHECK_IF_ABORTED();
343

344
				aip = stmt->aclitem;
345

346
				modechg = stmt->modechg;
347
#ifndef NO_SECURITY
348 349 350 351
				foreach(i, stmt->relNames)
				{
					relname = strVal(lfirst(i));
					if (!pg_ownercheck(userName, relname, RELNAME))
352
						elog(ERROR, "you do not own class \"%s\"",
353 354
							 relname);
				}
355
#endif
356 357 358 359 360
				foreach(i, stmt->relNames)
				{
					relname = strVal(lfirst(i));
					ChangeAcl(relname, aip, modechg);
				}
361

362 363
			}
			break;
364

365 366 367 368 369 370 371 372
			/*
			 * ******************************** object creation /
			 * destruction ********************************
			 *
			 */
		case T_DefineStmt:
			{
				DefineStmt *stmt = (DefineStmt *) parsetree;
373

374
				PS_SET_STATUS(commandTag = "CREATE");
375
				CHECK_IF_ABORTED();
376

377
				switch (stmt->defType)
378
				{
379 380 381 382
					case OPERATOR:
						DefineOperator(stmt->defname,	/* operator name */
									   stmt->definition);		/* rest */
						break;
383
					case TYPE_P:
384
						DefineType(stmt->defname, stmt->definition);
385 386 387 388 389
						break;
					case AGGREGATE:
						DefineAggregate(stmt->defname,	/* aggregate name */
										stmt->definition);		/* rest */
						break;
390 391
				}
			}
392 393 394 395 396
			break;

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

398
				PS_SET_STATUS(commandTag = "CREATE");
399 400 401 402
				CHECK_IF_ABORTED();
				DefineView(stmt->viewname, stmt->query);		/* retrieve parsetree */
			}
			break;
403

404
		case T_ProcedureStmt:	/* CREATE FUNCTION */
405
			PS_SET_STATUS(commandTag = "CREATE");
406
			CHECK_IF_ABORTED();
407 408
			CreateFunction((ProcedureStmt *) parsetree, dest);	/* everything */
			break;
409

410 411 412
		case T_IndexStmt:		/* CREATE INDEX */
			{
				IndexStmt  *stmt = (IndexStmt *) parsetree;
413

414
				PS_SET_STATUS(commandTag = "CREATE");
415 416 417 418 419 420 421
				CHECK_IF_ABORTED();
				DefineIndex(stmt->relname,		/* relation name */
							stmt->idxname,		/* index name */
							stmt->accessMethod, /* am name */
							stmt->indexParams,	/* parameters */
							stmt->withClause,
							stmt->unique,
422
							stmt->primary,
423 424 425 426
							(Expr *) stmt->whereClause,
							stmt->rangetable);
			}
			break;
427

428 429 430 431
		case T_RuleStmt:		/* CREATE RULE */
			{
				RuleStmt   *stmt = (RuleStmt *) parsetree;
				int			aclcheck_result;
432

433
#ifndef NO_SECURITY
434 435 436
				relname = stmt->object->relname;
				aclcheck_result = pg_aclcheck(relname, userName, ACL_RU);
				if (aclcheck_result != ACLCHECK_OK)
437
					elog(ERROR, "%s: %s", relname, aclcheck_error_strings[aclcheck_result]);
438
#endif
439
				PS_SET_STATUS(commandTag = "CREATE");
440 441 442 443 444 445
				CHECK_IF_ABORTED();
				DefineQueryRewrite(stmt);
			}
			break;

		case T_CreateSeqStmt:
446
			PS_SET_STATUS(commandTag = "CREATE");
447 448
			CHECK_IF_ABORTED();

449 450
			DefineSequence((CreateSeqStmt *) parsetree);
			break;
451

452 453 454
		case T_ExtendStmt:
			{
				ExtendStmt *stmt = (ExtendStmt *) parsetree;
455

456
				PS_SET_STATUS(commandTag = "EXTEND");
457
				CHECK_IF_ABORTED();
458

459 460 461 462 463
				ExtendIndex(stmt->idxname,		/* index name */
							(Expr *) stmt->whereClause, /* where */
							stmt->rangetable);
			}
			break;
464

465 466 467
		case T_RemoveStmt:
			{
				RemoveStmt *stmt = (RemoveStmt *) parsetree;
468

469
				PS_SET_STATUS(commandTag = "DROP");
470
				CHECK_IF_ABORTED();
471

472 473 474 475
				switch (stmt->removeType)
				{
					case INDEX:
						relname = stmt->name;
476
						if (!allowSystemTableMods && IsSystemRelationName(relname))
477
							elog(ERROR, "class \"%s\" is a system catalog index",
478
								 relname);
479
#ifndef NO_SECURITY
480
						if (!pg_ownercheck(userName, relname, RELNAME))
481
							elog(ERROR, "%s: %s", relname, aclcheck_error_strings[ACLCHECK_NOT_OWNER]);
482
#endif
483 484 485 486 487 488
						RemoveIndex(relname);
						break;
					case RULE:
						{
							char	   *rulename = stmt->name;
							int			aclcheck_result;
489 490

#ifndef NO_SECURITY
491

492 493 494
							relationName = RewriteGetRuleEventRel(rulename);
							aclcheck_result = pg_aclcheck(relationName, userName, ACL_RU);
							if (aclcheck_result != ACLCHECK_OK)
495
								elog(ERROR, "%s: %s", relationName, aclcheck_error_strings[aclcheck_result]);
496
#endif
497 498 499
							RemoveRewriteRule(rulename);
						}
						break;
500
					case TYPE_P:
501
#ifndef NO_SECURITY
502
						/* XXX moved to remove.c */
503
#endif
504 505 506 507 508 509
						RemoveType(stmt->name);
						break;
					case VIEW:
						{
							char	   *viewName = stmt->name;
							char	   *ruleName;
510 511 512

#ifndef NO_SECURITY

513 514 515
							ruleName = MakeRetrieveViewRuleName(viewName);
							relationName = RewriteGetRuleEventRel(ruleName);
							if (!pg_ownercheck(userName, relationName, RELNAME))
516
								elog(ERROR, "%s: %s", relationName, aclcheck_error_strings[ACLCHECK_NOT_OWNER]);
517
							pfree(ruleName);
518
#endif
519 520 521
							RemoveView(viewName);
						}
						break;
522 523 524 525
				}
				break;
			}
			break;
526

527 528 529
		case T_RemoveAggrStmt:
			{
				RemoveAggrStmt *stmt = (RemoveAggrStmt *) parsetree;
530

531
				PS_SET_STATUS(commandTag = "DROP");
532 533 534 535
				CHECK_IF_ABORTED();
				RemoveAggregate(stmt->aggname, stmt->aggtype);
			}
			break;
536

537 538 539
		case T_RemoveFuncStmt:
			{
				RemoveFuncStmt *stmt = (RemoveFuncStmt *) parsetree;
540

541
				PS_SET_STATUS(commandTag = "DROP");
542 543 544 545 546 547
				CHECK_IF_ABORTED();
				RemoveFunction(stmt->funcname,
							   length(stmt->args),
							   stmt->args);
			}
			break;
548

549 550 551 552 553
		case T_RemoveOperStmt:
			{
				RemoveOperStmt *stmt = (RemoveOperStmt *) parsetree;
				char	   *type1 = (char *) NULL;
				char	   *type2 = (char *) NULL;
554

555
				PS_SET_STATUS(commandTag = "DROP");
556
				CHECK_IF_ABORTED();
557

558 559 560 561 562 563 564
				if (lfirst(stmt->args) != NULL)
					type1 = strVal(lfirst(stmt->args));
				if (lsecond(stmt->args) != NULL)
					type2 = strVal(lsecond(stmt->args));
				RemoveOperator(stmt->opname, type1, type2);
			}
			break;
565

566
		case T_VersionStmt:
567
			elog(ERROR, "CREATE VERSION is not currently implemented");
568
			break;
569

570 571 572
		case T_CreatedbStmt:
			{
				CreatedbStmt *stmt = (CreatedbStmt *) parsetree;
573

574
				PS_SET_STATUS(commandTag = "CREATEDB");
575
				CHECK_IF_ABORTED();
Bruce Momjian's avatar
Bruce Momjian committed
576
				createdb(stmt->dbname, stmt->dbpath, stmt->encoding, dest);
577 578 579 580 581 582
			}
			break;

		case T_DestroydbStmt:
			{
				DestroydbStmt *stmt = (DestroydbStmt *) parsetree;
583

584
				PS_SET_STATUS(commandTag = "DESTROYDB");
585
				CHECK_IF_ABORTED();
Bruce Momjian's avatar
Bruce Momjian committed
586
				destroydb(stmt->dbname, dest);
587 588
			}
			break;
589

590 591 592 593
			/* Query-level asynchronous notification */
		case T_NotifyStmt:
			{
				NotifyStmt *stmt = (NotifyStmt *) parsetree;
594

595
				PS_SET_STATUS(commandTag = "NOTIFY");
596
				CHECK_IF_ABORTED();
597

598 599 600
				Async_Notify(stmt->relname);
			}
			break;
601

602 603 604
		case T_ListenStmt:
			{
				ListenStmt *stmt = (ListenStmt *) parsetree;
605

606
				PS_SET_STATUS(commandTag = "LISTEN");
607
				CHECK_IF_ABORTED();
608

Bruce Momjian's avatar
Bruce Momjian committed
609
				Async_Listen(stmt->relname, MyProcPid);
610 611
			}
			break;
612

613 614 615 616
		case T_UnlistenStmt:
			{
				UnlistenStmt *stmt = (UnlistenStmt *) parsetree;

617
				PS_SET_STATUS(commandTag = "UNLISTEN");
618 619 620 621 622 623
				CHECK_IF_ABORTED();

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

624 625 626 627 628 629 630 631
			/*
			 * ******************************** dynamic loader ********************************
			 *
			 */
		case T_LoadStmt:
			{
				LoadStmt   *stmt = (LoadStmt *) parsetree;

632
				PS_SET_STATUS(commandTag = "LOAD");
633 634
				CHECK_IF_ABORTED();

Bruce Momjian's avatar
Bruce Momjian committed
635
				closeAllVfds(); /* probably not necessary... */
636
				load_file(stmt->filename);
637 638
			}
			break;
639

640 641 642
		case T_ClusterStmt:
			{
				ClusterStmt *stmt = (ClusterStmt *) parsetree;
643

644
				PS_SET_STATUS(commandTag = "CLUSTER");
645
				CHECK_IF_ABORTED();
646

647 648 649 650 651
				cluster(stmt->relname, stmt->indexname);
			}
			break;

		case T_VacuumStmt:
652
			PS_SET_STATUS(commandTag = "VACUUM");
653
			CHECK_IF_ABORTED();
654 655 656 657 658 659 660 661 662 663
			vacuum(((VacuumStmt *) parsetree)->vacrel,
				   ((VacuumStmt *) parsetree)->verbose,
				   ((VacuumStmt *) parsetree)->analyze,
				   ((VacuumStmt *) parsetree)->va_spec);
			break;

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

664
				PS_SET_STATUS(commandTag = "EXPLAIN");
665
				CHECK_IF_ABORTED();
666

667 668 669
				ExplainQuery(stmt->query, stmt->verbose, dest);
			}
			break;
670

671
#ifdef NOT_USED
Bruce Momjian's avatar
Bruce Momjian committed
672

673 674 675 676 677 678
			/*
			 * ******************************** Tioga-related statements *******************************
			 */
		case T_RecipeStmt:
			{
				RecipeStmt *stmt = (RecipeStmt *) parsetree;
679

680
				PS_SET_STATUS(commandTag = "EXECUTE RECIPE");
681 682 683 684
				CHECK_IF_ABORTED();
				beginRecipe(stmt);
			}
			break;
685
#endif
686 687 688 689 690 691 692 693 694

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

				SetPGVariable(n->name, n->value);
695
				PS_SET_STATUS(commandTag = "SET VARIABLE");
696 697 698 699 700 701 702 703
			}
			break;

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

				GetPGVariable(n->name);
704
				PS_SET_STATUS(commandTag = "SHOW VARIABLE");
705 706 707 708 709 710 711 712
			}
			break;

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

				ResetPGVariable(n->name);
713
				PS_SET_STATUS(commandTag = "RESET VARIABLE");
714 715 716 717 718 719 720
			}
			break;

			/*
			 * ******************************** TRIGGER statements *******************************
			 */
		case T_CreateTrigStmt:
721
			PS_SET_STATUS(commandTag = "CREATE");
722 723 724 725 726 727
			CHECK_IF_ABORTED();

			CreateTrigger((CreateTrigStmt *) parsetree);
			break;

		case T_DropTrigStmt:
728
			PS_SET_STATUS(commandTag = "DROP");
729
			CHECK_IF_ABORTED();
730 731 732 733

			DropTrigger((DropTrigStmt *) parsetree);
			break;

734 735 736 737
			/*
			 * ************* PROCEDURAL LANGUAGE statements *****************
			 */
		case T_CreatePLangStmt:
738
			PS_SET_STATUS(commandTag = "CREATE");
739 740 741 742 743 744
			CHECK_IF_ABORTED();

			CreateProceduralLanguage((CreatePLangStmt *) parsetree);
			break;

		case T_DropPLangStmt:
745
			PS_SET_STATUS(commandTag = "DROP");
746 747 748 749 750
			CHECK_IF_ABORTED();

			DropProceduralLanguage((DropPLangStmt *) parsetree);
			break;

751 752 753 754 755
			/*
			 * ******************************** USER statements ****
			 *
			 */
		case T_CreateUserStmt:
756
			PS_SET_STATUS(commandTag = "CREATE USER");
757
			CHECK_IF_ABORTED();
758

Bruce Momjian's avatar
Bruce Momjian committed
759
			DefineUser((CreateUserStmt *) parsetree, dest);
760
			break;
761

762
		case T_AlterUserStmt:
763
			PS_SET_STATUS(commandTag = "ALTER USER");
764
			CHECK_IF_ABORTED();
765

Bruce Momjian's avatar
Bruce Momjian committed
766
			AlterUser((AlterUserStmt *) parsetree, dest);
767
			break;
768

769
		case T_DropUserStmt:
770
			PS_SET_STATUS(commandTag = "DROP USER");
771
			CHECK_IF_ABORTED();
772

Bruce Momjian's avatar
Bruce Momjian committed
773
			RemoveUser(((DropUserStmt *) parsetree)->user, dest);
774
			break;
775

776 777 778 779 780 781 782
		case T_LockStmt:
			PS_SET_STATUS(commandTag = "LOCK TABLE");
			CHECK_IF_ABORTED();

			LockTableCommand((LockStmt *) parsetree);
			break;

783 784 785 786 787 788 789
		case T_ConstraintsSetStmt:
			PS_SET_STATUS(commandTag = "SET CONSTRAINTS");
			CHECK_IF_ABORTED();

			DeferredTriggerSetState((ConstraintsSetStmt *) parsetree);
			break;

790

791 792 793 794 795
			/*
			 * ******************************** default ********************************
			 *
			 */
		default:
796
			elog(ERROR, "ProcessUtility: command #%d unsupported",
797 798
				 nodeTag(parsetree));
			break;
799
	}
800 801 802 803

	/* ----------------
	 *	tell fe/be or whatever that we're done.
	 * ----------------
804
	 */
805
	EndCommand(commandTag, dest);
806
}