utility.c 19.6 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.78 2000/01/14 22:11:35 petere 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
#include "catalog/catalog.h"
#include "catalog/pg_type.h"
#include "commands/async.h"
#include "commands/cluster.h"
#include "commands/command.h"
Bruce Momjian's avatar
Bruce Momjian committed
24
#include "commands/comment.h"
25 26
#include "commands/copy.h"
#include "commands/creatinh.h"
27
#include "commands/dbcommands.h"
28 29
#include "commands/defrem.h"
#include "commands/explain.h"
30
#include "commands/proclang.h"
Bruce Momjian's avatar
Bruce Momjian committed
31 32 33
#include "commands/rename.h"
#include "commands/sequence.h"
#include "commands/trigger.h"
34
#include "commands/user.h"
Bruce Momjian's avatar
Bruce Momjian committed
35
#include "commands/vacuum.h"
36
#include "commands/variable.h"
Bruce Momjian's avatar
Bruce Momjian committed
37 38
#include "commands/view.h"
#include "miscadmin.h"
39
#include "parser/parse.h"
40
#include "rewrite/rewriteDefine.h"
Bruce Momjian's avatar
Bruce Momjian committed
41
#include "rewrite/rewriteRemove.h"
Bruce Momjian's avatar
Bruce Momjian committed
42
#include "tcop/utility.h"
43
#include "utils/acl.h"
Bruce Momjian's avatar
Bruce Momjian committed
44
#include "utils/ps_status.h"
45
#include "utils/syscache.h"
Bruce Momjian's avatar
Bruce Momjian committed
46

47 48

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

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

	userName = GetPgUserName();

	switch (nodeTag(parsetree))
82
	{
83

84 85 86 87 88 89 90
			/*
			 * ******************************** transactions ********************************
			 *
			 */
		case T_TransactionStmt:
			{
				TransactionStmt *stmt = (TransactionStmt *) parsetree;
91

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

					case END_TRANS:
101
						PS_SET_STATUS(commandTag = "END");
102 103 104 105
						EndTransactionBlock();
						break;

					case ABORT_TRANS:
106
						PS_SET_STATUS(commandTag = "ABORT");
107 108 109 110 111 112 113 114 115 116 117
						UserAbortTransactionBlock();
						break;
				}
			}
			break;

			/*
			 * ******************************** portal manipulation ********************************
			 *
			 */
		case T_ClosePortalStmt:
118
			{
119
				ClosePortalStmt *stmt = (ClosePortalStmt *) parsetree;
120

121
				PS_SET_STATUS(commandTag = "CLOSE");
122
				CHECK_IF_ABORTED();
123

124
				PerformPortalClose(stmt->portalname, dest);
125
			}
126
			break;
127

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

135
				PS_SET_STATUS(commandTag = (stmt->ismove) ? "MOVE" : "FETCH");
136
				CHECK_IF_ABORTED();
137

138
				forward = (bool) (stmt->direction == FORWARD);
139

140 141 142
				/*
				 * parser ensures that count is >= 0 and 'fetch ALL' -> 0
				 */
143

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

			/*
151 152 153
			 * ******************************** relation and attribute
			 * manipulation ********************************
			 *
154
			 */
155
		case T_CreateStmt:
156
			PS_SET_STATUS(commandTag = "CREATE");
157 158
			CHECK_IF_ABORTED();

159
			DefineRelation((CreateStmt *) parsetree, RELKIND_RELATION);
160 161
			break;

162
		case T_DropStmt:
163
			{
164
				DropStmt *stmt = (DropStmt *) parsetree;
165
				List	   *args = stmt->relNames;
166
				List	   *arg;
167

168
				PS_SET_STATUS(commandTag = "DROP");
169 170
				CHECK_IF_ABORTED();

171
				/* check as much as we can before we start dropping ... */
172
				foreach(arg, args)
173
				{
174 175
					Relation	rel;

176
					relname = strVal(lfirst(arg));
177
					if (!allowSystemTableMods && IsSystemRelationName(relname))
178
						elog(ERROR, "class \"%s\" is a system catalog",
179
							 relname);
180 181 182 183 184 185 186 187 188 189 190
					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);
191
#ifndef NO_SECURITY
192
					if (!pg_ownercheck(userName, relname, RELNAME))
193
						elog(ERROR, "you do not own class \"%s\"",
194
							 relname);
195
#endif
196
				}
197
				/* OK, terminate 'em all */
198 199 200 201 202
				foreach(arg, args)
				{
					relname = strVal(lfirst(arg));
					RemoveRelation(relname);
				}
203
			}
204 205
			break;

206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222
		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);
223
			    heap_close(rel, NoLock);
224

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

233 234 235 236 237 238 239 240 241
	case T_CommentStmt:
	  {
	    
	    CommentStmt *statement;
	    
	    statement = ((CommentStmt *) parsetree);
	    
	    PS_SET_STATUS(commandTag = "COMMENT");
	    CHECK_IF_ABORTED();
Bruce Momjian's avatar
Bruce Momjian committed
242 243 244
	    CommentObject(statement->objtype, statement->objname,
			  statement->objproperty, statement->objlist,
			  statement->comment);
245 246 247 248 249
	  }
	  break;
	    


250 251 252
		case T_CopyStmt:
			{
				CopyStmt   *stmt = (CopyStmt *) parsetree;
253

254
				PS_SET_STATUS(commandTag = "COPY");
255
				CHECK_IF_ABORTED();
256

257 258 259 260 261
				DoCopy(stmt->relname,
					   stmt->binary,
					   stmt->oids,
					   (bool) (stmt->direction == FROM),
					   (bool) (stmt->filename == NULL),
262

263 264 265 266 267
				/*
				 * null filename means copy to/from stdout/stdin, rather
				 * than to/from a file.
				 */
					   stmt->filename,
268
					   stmt->delimiter,
269
                       stmt->null_print);
270 271
			}
			break;
272

273 274 275
		case T_AddAttrStmt:
			{
				AddAttrStmt *stmt = (AddAttrStmt *) parsetree;
276

277
				PS_SET_STATUS(commandTag = "ADD");
278
				CHECK_IF_ABORTED();
279

280
				/*
281 282
				 * owner checking done in PerformAddAttribute (now
				 * recursive)
283 284 285 286
				 */
				PerformAddAttribute(stmt->relname,
									userName,
									stmt->inh,
287
									(ColumnDef *) stmt->colDef);
288 289
			}
			break;
290 291

			/*
292
			 * schema
293
			 */
294 295 296
		case T_RenameStmt:
			{
				RenameStmt *stmt = (RenameStmt *) parsetree;
297

298
				PS_SET_STATUS(commandTag = "RENAME");
299
				CHECK_IF_ABORTED();
300

301
				relname = stmt->relname;
302
				if (!allowSystemTableMods && IsSystemRelationName(relname))
303
					elog(ERROR, "class \"%s\" is a system catalog",
304
						 relname);
305
#ifndef NO_SECURITY
306
				if (!pg_ownercheck(userName, relname, RELNAME))
307
					elog(ERROR, "you do not own class \"%s\"",
308
						 relname);
309
#endif
310 311

				/* ----------------
312 313 314 315 316
				 *	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
317
				 * ----------------
318
				 * [another piece of amuzing but useless anecdote -- ay]
319
				 */
320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345
				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? */
				}
346
			}
347
			break;
348

349 350 351 352 353 354
		case T_ChangeACLStmt:
			{
				ChangeACLStmt *stmt = (ChangeACLStmt *) parsetree;
				List	   *i;
				AclItem    *aip;
				unsigned	modechg;
355

356
				PS_SET_STATUS(commandTag = "CHANGE");
357
				CHECK_IF_ABORTED();
358

359
				aip = stmt->aclitem;
360

361
				modechg = stmt->modechg;
362
#ifndef NO_SECURITY
363 364 365 366
				foreach(i, stmt->relNames)
				{
					relname = strVal(lfirst(i));
					if (!pg_ownercheck(userName, relname, RELNAME))
367
						elog(ERROR, "you do not own class \"%s\"",
368 369
							 relname);
				}
370
#endif
371 372 373 374 375
				foreach(i, stmt->relNames)
				{
					relname = strVal(lfirst(i));
					ChangeAcl(relname, aip, modechg);
				}
376

377 378
			}
			break;
379

380 381 382 383 384 385 386 387
			/*
			 * ******************************** object creation /
			 * destruction ********************************
			 *
			 */
		case T_DefineStmt:
			{
				DefineStmt *stmt = (DefineStmt *) parsetree;
388

389
				PS_SET_STATUS(commandTag = "CREATE");
390
				CHECK_IF_ABORTED();
391

392
				switch (stmt->defType)
393
				{
394 395 396 397
					case OPERATOR:
						DefineOperator(stmt->defname,	/* operator name */
									   stmt->definition);		/* rest */
						break;
398
					case TYPE_P:
399
						DefineType(stmt->defname, stmt->definition);
400 401 402 403 404
						break;
					case AGGREGATE:
						DefineAggregate(stmt->defname,	/* aggregate name */
										stmt->definition);		/* rest */
						break;
405 406
				}
			}
407 408 409 410 411
			break;

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

413
				PS_SET_STATUS(commandTag = "CREATE");
414 415 416 417
				CHECK_IF_ABORTED();
				DefineView(stmt->viewname, stmt->query);		/* retrieve parsetree */
			}
			break;
418

419
		case T_ProcedureStmt:	/* CREATE FUNCTION */
420
			PS_SET_STATUS(commandTag = "CREATE");
421
			CHECK_IF_ABORTED();
422 423
			CreateFunction((ProcedureStmt *) parsetree, dest);	/* everything */
			break;
424

425 426 427
		case T_IndexStmt:		/* CREATE INDEX */
			{
				IndexStmt  *stmt = (IndexStmt *) parsetree;
428

429
				PS_SET_STATUS(commandTag = "CREATE");
430 431 432 433 434 435 436
				CHECK_IF_ABORTED();
				DefineIndex(stmt->relname,		/* relation name */
							stmt->idxname,		/* index name */
							stmt->accessMethod, /* am name */
							stmt->indexParams,	/* parameters */
							stmt->withClause,
							stmt->unique,
437
							stmt->primary,
438 439 440 441
							(Expr *) stmt->whereClause,
							stmt->rangetable);
			}
			break;
442

443 444 445 446
		case T_RuleStmt:		/* CREATE RULE */
			{
				RuleStmt   *stmt = (RuleStmt *) parsetree;
				int			aclcheck_result;
447

448
#ifndef NO_SECURITY
449 450 451
				relname = stmt->object->relname;
				aclcheck_result = pg_aclcheck(relname, userName, ACL_RU);
				if (aclcheck_result != ACLCHECK_OK)
452
					elog(ERROR, "%s: %s", relname, aclcheck_error_strings[aclcheck_result]);
453
#endif
454
				PS_SET_STATUS(commandTag = "CREATE");
455 456 457 458 459 460
				CHECK_IF_ABORTED();
				DefineQueryRewrite(stmt);
			}
			break;

		case T_CreateSeqStmt:
461
			PS_SET_STATUS(commandTag = "CREATE");
462 463
			CHECK_IF_ABORTED();

464 465
			DefineSequence((CreateSeqStmt *) parsetree);
			break;
466

467 468 469
		case T_ExtendStmt:
			{
				ExtendStmt *stmt = (ExtendStmt *) parsetree;
470

471
				PS_SET_STATUS(commandTag = "EXTEND");
472
				CHECK_IF_ABORTED();
473

474 475 476 477 478
				ExtendIndex(stmt->idxname,		/* index name */
							(Expr *) stmt->whereClause, /* where */
							stmt->rangetable);
			}
			break;
479

480 481 482
		case T_RemoveStmt:
			{
				RemoveStmt *stmt = (RemoveStmt *) parsetree;
483

484
				PS_SET_STATUS(commandTag = "DROP");
485
				CHECK_IF_ABORTED();
486

487 488 489 490
				switch (stmt->removeType)
				{
					case INDEX:
						relname = stmt->name;
491
						if (!allowSystemTableMods && IsSystemRelationName(relname))
492
							elog(ERROR, "class \"%s\" is a system catalog index",
493
								 relname);
494
#ifndef NO_SECURITY
495
						if (!pg_ownercheck(userName, relname, RELNAME))
496
							elog(ERROR, "%s: %s", relname, aclcheck_error_strings[ACLCHECK_NOT_OWNER]);
497
#endif
498 499 500 501 502 503
						RemoveIndex(relname);
						break;
					case RULE:
						{
							char	   *rulename = stmt->name;
							int			aclcheck_result;
504 505

#ifndef NO_SECURITY
506

507 508 509
							relationName = RewriteGetRuleEventRel(rulename);
							aclcheck_result = pg_aclcheck(relationName, userName, ACL_RU);
							if (aclcheck_result != ACLCHECK_OK)
510
								elog(ERROR, "%s: %s", relationName, aclcheck_error_strings[aclcheck_result]);
511
#endif
512 513 514
							RemoveRewriteRule(rulename);
						}
						break;
515
					case TYPE_P:
516
#ifndef NO_SECURITY
517
						/* XXX moved to remove.c */
518
#endif
519 520 521 522 523 524
						RemoveType(stmt->name);
						break;
					case VIEW:
						{
							char	   *viewName = stmt->name;
							char	   *ruleName;
525 526 527

#ifndef NO_SECURITY

528 529 530
							ruleName = MakeRetrieveViewRuleName(viewName);
							relationName = RewriteGetRuleEventRel(ruleName);
							if (!pg_ownercheck(userName, relationName, RELNAME))
531
								elog(ERROR, "%s: %s", relationName, aclcheck_error_strings[ACLCHECK_NOT_OWNER]);
532
							pfree(ruleName);
533
#endif
534 535 536
							RemoveView(viewName);
						}
						break;
537 538 539 540
				}
				break;
			}
			break;
541

542 543 544
		case T_RemoveAggrStmt:
			{
				RemoveAggrStmt *stmt = (RemoveAggrStmt *) parsetree;
545

546
				PS_SET_STATUS(commandTag = "DROP");
547 548 549 550
				CHECK_IF_ABORTED();
				RemoveAggregate(stmt->aggname, stmt->aggtype);
			}
			break;
551

552 553 554
		case T_RemoveFuncStmt:
			{
				RemoveFuncStmt *stmt = (RemoveFuncStmt *) parsetree;
555

556
				PS_SET_STATUS(commandTag = "DROP");
557 558 559 560 561 562
				CHECK_IF_ABORTED();
				RemoveFunction(stmt->funcname,
							   length(stmt->args),
							   stmt->args);
			}
			break;
563

564 565 566 567 568
		case T_RemoveOperStmt:
			{
				RemoveOperStmt *stmt = (RemoveOperStmt *) parsetree;
				char	   *type1 = (char *) NULL;
				char	   *type2 = (char *) NULL;
569

570
				PS_SET_STATUS(commandTag = "DROP");
571
				CHECK_IF_ABORTED();
572

573 574 575 576 577 578 579
				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;
580

581
		case T_VersionStmt:
582
			elog(ERROR, "CREATE VERSION is not currently implemented");
583
			break;
584

585 586 587
		case T_CreatedbStmt:
			{
				CreatedbStmt *stmt = (CreatedbStmt *) parsetree;
588

589
				PS_SET_STATUS(commandTag = "CREATE DATABASE");
590
				CHECK_IF_ABORTED();
591
				createdb(stmt->dbname, stmt->dbpath, stmt->encoding);
592 593 594
			}
			break;

595
		case T_DropdbStmt:
596
			{
597
				DropdbStmt *stmt = (DropdbStmt *) parsetree;
598

599
				PS_SET_STATUS(commandTag = "DROP DATABASE");
600
				CHECK_IF_ABORTED();
601
				dropdb(stmt->dbname);
602 603
			}
			break;
604

605 606 607 608
			/* Query-level asynchronous notification */
		case T_NotifyStmt:
			{
				NotifyStmt *stmt = (NotifyStmt *) parsetree;
609

610
				PS_SET_STATUS(commandTag = "NOTIFY");
611
				CHECK_IF_ABORTED();
612

613 614 615
				Async_Notify(stmt->relname);
			}
			break;
616

617 618 619
		case T_ListenStmt:
			{
				ListenStmt *stmt = (ListenStmt *) parsetree;
620

621
				PS_SET_STATUS(commandTag = "LISTEN");
622
				CHECK_IF_ABORTED();
623

Bruce Momjian's avatar
Bruce Momjian committed
624
				Async_Listen(stmt->relname, MyProcPid);
625 626
			}
			break;
627

628 629 630 631
		case T_UnlistenStmt:
			{
				UnlistenStmt *stmt = (UnlistenStmt *) parsetree;

632
				PS_SET_STATUS(commandTag = "UNLISTEN");
633 634 635 636 637 638
				CHECK_IF_ABORTED();

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

639 640 641 642 643 644 645 646
			/*
			 * ******************************** dynamic loader ********************************
			 *
			 */
		case T_LoadStmt:
			{
				LoadStmt   *stmt = (LoadStmt *) parsetree;

647
				PS_SET_STATUS(commandTag = "LOAD");
648 649
				CHECK_IF_ABORTED();

Bruce Momjian's avatar
Bruce Momjian committed
650
				closeAllVfds(); /* probably not necessary... */
651
				load_file(stmt->filename);
652 653
			}
			break;
654

655 656 657
		case T_ClusterStmt:
			{
				ClusterStmt *stmt = (ClusterStmt *) parsetree;
658

659
				PS_SET_STATUS(commandTag = "CLUSTER");
660
				CHECK_IF_ABORTED();
661

662 663 664 665 666
				cluster(stmt->relname, stmt->indexname);
			}
			break;

		case T_VacuumStmt:
667
			PS_SET_STATUS(commandTag = "VACUUM");
668
			CHECK_IF_ABORTED();
669 670 671 672 673 674 675 676 677 678
			vacuum(((VacuumStmt *) parsetree)->vacrel,
				   ((VacuumStmt *) parsetree)->verbose,
				   ((VacuumStmt *) parsetree)->analyze,
				   ((VacuumStmt *) parsetree)->va_spec);
			break;

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

679
				PS_SET_STATUS(commandTag = "EXPLAIN");
680
				CHECK_IF_ABORTED();
681

682 683 684
				ExplainQuery(stmt->query, stmt->verbose, dest);
			}
			break;
685

686
#ifdef NOT_USED
Bruce Momjian's avatar
Bruce Momjian committed
687

688 689 690 691 692 693
			/*
			 * ******************************** Tioga-related statements *******************************
			 */
		case T_RecipeStmt:
			{
				RecipeStmt *stmt = (RecipeStmt *) parsetree;
694

695
				PS_SET_STATUS(commandTag = "EXECUTE RECIPE");
696 697 698 699
				CHECK_IF_ABORTED();
				beginRecipe(stmt);
			}
			break;
700
#endif
701 702 703 704 705 706 707 708 709

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

				SetPGVariable(n->name, n->value);
710
				PS_SET_STATUS(commandTag = "SET VARIABLE");
711 712 713 714 715 716 717 718
			}
			break;

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

				GetPGVariable(n->name);
719
				PS_SET_STATUS(commandTag = "SHOW VARIABLE");
720 721 722 723 724 725 726 727
			}
			break;

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

				ResetPGVariable(n->name);
728
				PS_SET_STATUS(commandTag = "RESET VARIABLE");
729 730 731 732 733 734 735
			}
			break;

			/*
			 * ******************************** TRIGGER statements *******************************
			 */
		case T_CreateTrigStmt:
736
			PS_SET_STATUS(commandTag = "CREATE");
737 738 739 740 741 742
			CHECK_IF_ABORTED();

			CreateTrigger((CreateTrigStmt *) parsetree);
			break;

		case T_DropTrigStmt:
743
			PS_SET_STATUS(commandTag = "DROP");
744
			CHECK_IF_ABORTED();
745 746 747 748

			DropTrigger((DropTrigStmt *) parsetree);
			break;

749 750 751 752
			/*
			 * ************* PROCEDURAL LANGUAGE statements *****************
			 */
		case T_CreatePLangStmt:
753
			PS_SET_STATUS(commandTag = "CREATE");
754 755 756 757 758 759
			CHECK_IF_ABORTED();

			CreateProceduralLanguage((CreatePLangStmt *) parsetree);
			break;

		case T_DropPLangStmt:
760
			PS_SET_STATUS(commandTag = "DROP");
761 762 763 764 765
			CHECK_IF_ABORTED();

			DropProceduralLanguage((DropPLangStmt *) parsetree);
			break;

766 767 768 769 770
			/*
			 * ******************************** USER statements ****
			 *
			 */
		case T_CreateUserStmt:
771
			PS_SET_STATUS(commandTag = "CREATE USER");
772
			CHECK_IF_ABORTED();
773

774
			CreateUser((CreateUserStmt *) parsetree);
775
			break;
776

777
		case T_AlterUserStmt:
778
			PS_SET_STATUS(commandTag = "ALTER USER");
779
			CHECK_IF_ABORTED();
780

781
			AlterUser((AlterUserStmt *) parsetree);
782
			break;
783

784
		case T_DropUserStmt:
785
			PS_SET_STATUS(commandTag = "DROP USER");
786
			CHECK_IF_ABORTED();
787

788
			DropUser((DropUserStmt *) parsetree);
789
			break;
790

791 792 793 794 795 796 797
		case T_LockStmt:
			PS_SET_STATUS(commandTag = "LOCK TABLE");
			CHECK_IF_ABORTED();

			LockTableCommand((LockStmt *) parsetree);
			break;

798 799 800 801 802 803 804
		case T_ConstraintsSetStmt:
			PS_SET_STATUS(commandTag = "SET CONSTRAINTS");
			CHECK_IF_ABORTED();

			DeferredTriggerSetState((ConstraintsSetStmt *) parsetree);
			break;

805 806 807 808
        case T_CreateGroupStmt:
            PS_SET_STATUS(commandTag = "CREATE GROUP");
			CHECK_IF_ABORTED();

809
            CreateGroup((CreateGroupStmt *) parsetree);
810 811 812 813 814 815
            break;

        case T_AlterGroupStmt:
            PS_SET_STATUS(commandTag = "ALTER GROUP");
			CHECK_IF_ABORTED();

816
            AlterGroup((AlterGroupStmt *) parsetree, "ALTER GROUP");
817 818 819 820 821 822
            break;

        case T_DropGroupStmt:
            PS_SET_STATUS(commandTag = "DROP GROUP");
			CHECK_IF_ABORTED();

823
            DropGroup((DropGroupStmt *) parsetree);
824
            break;
825

826 827 828 829 830
			/*
			 * ******************************** default ********************************
			 *
			 */
		default:
831
			elog(ERROR, "ProcessUtility: command #%d unsupported",
832 833
				 nodeTag(parsetree));
			break;
834
	}
835 836 837 838

	/* ----------------
	 *	tell fe/be or whatever that we're done.
	 * ----------------
839
	 */
840
	EndCommand(commandTag, dest);
841
}