utility.c 18.1 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.53 1999/01/21 22:48:11 momjian Exp $
13 14 15 16 17
 *
 *-------------------------------------------------------------------------
 */
#include "postgres.h"
#include "access/xact.h"
18
#include "access/heapam.h"
19 20 21 22 23 24 25 26
#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"
27
#include "commands/dbcommands.h"
28
#include "commands/sequence.h"
29 30 31 32 33 34 35
#include "commands/defrem.h"
#include "commands/rename.h"
#include "commands/view.h"
#include "commands/version.h"
#include "commands/vacuum.h"
#include "commands/recipe.h"
#include "commands/explain.h"
Vadim B. Mikheev's avatar
Vadim B. Mikheev committed
36
#include "commands/trigger.h"
37
#include "commands/proclang.h"
38
#include "commands/variable.h"
39 40

#include "nodes/parsenodes.h"
Bruce Momjian's avatar
Bruce Momjian committed
41
#include "../backend/parser/parse.h"
42 43 44 45 46 47 48
#include "utils/builtins.h"
#include "utils/acl.h"
#include "utils/palloc.h"
#include "rewrite/rewriteRemove.h"
#include "rewrite/rewriteDefine.h"
#include "tcop/tcopdebug.h"
#include "tcop/dest.h"
Bruce Momjian's avatar
Bruce Momjian committed
49
#include "tcop/utility.h"
50
#include "fmgr.h"				/* For load_file() */
51
#include "storage/fd.h"
52
#include "utils/ps_status.h"
53 54 55 56 57 58 59

#ifndef NO_SECURITY
#include "miscadmin.h"
#include "utils/acl.h"
#include "utils/syscache.h"
#endif

60 61 62
void		DefineUser(CreateUserStmt *stmt);
void		AlterUser(AlterUserStmt *stmt);
void		RemoveUser(char *username);
63 64

/* ----------------
65 66
 *		CHECK_IF_ABORTED() is used to avoid doing unnecessary
 *		processing within an aborted transaction block.
67 68
 * ----------------
 */
69
 /* we have to use IF because of the 'break' */
70
#define CHECK_IF_ABORTED() \
71 72 73 74
if (1) \
{ \
	if (IsAbortedTransactionBlockState()) \
	{ \
75
		elog(NOTICE, "(transaction aborted): %s", \
76
			 "all queries ignored until end of transaction block"); \
77 78 79
		commandTag = "*ABORT STATE*"; \
		break; \
	} \
80
} else
81

82
/* ----------------
83
 *		general utility function invoker
84 85 86
 * ----------------
 */
void
87
ProcessUtility(Node *parsetree,
88
			   CommandDest dest)
89
{
90 91 92 93
	char	   *commandTag = NULL;
	char	   *relname;
	char	   *relationName;
	char	   *userName;
94 95 96 97

	userName = GetPgUserName();

	switch (nodeTag(parsetree))
98
	{
99

100 101 102 103 104 105 106
			/*
			 * ******************************** transactions ********************************
			 *
			 */
		case T_TransactionStmt:
			{
				TransactionStmt *stmt = (TransactionStmt *) parsetree;
107

108 109 110
				switch (stmt->command)
				{
					case BEGIN_TRANS:
111
						PS_SET_STATUS(commandTag = "BEGIN");
112 113 114 115 116
						CHECK_IF_ABORTED();
						BeginTransactionBlock();
						break;

					case END_TRANS:
117
						PS_SET_STATUS(commandTag = "END");
118 119 120 121
						EndTransactionBlock();
						break;

					case ABORT_TRANS:
122
						PS_SET_STATUS(commandTag = "ABORT");
123 124 125 126 127 128 129 130 131 132 133
						UserAbortTransactionBlock();
						break;
				}
			}
			break;

			/*
			 * ******************************** portal manipulation ********************************
			 *
			 */
		case T_ClosePortalStmt:
134
			{
135
				ClosePortalStmt *stmt = (ClosePortalStmt *) parsetree;
136

137
				PS_SET_STATUS(commandTag = "CLOSE");
138
				CHECK_IF_ABORTED();
139

140
				PerformPortalClose(stmt->portalname, dest);
141
			}
142
			break;
143

144 145 146 147 148 149 150
		case T_FetchStmt:
			{
				FetchStmt  *stmt = (FetchStmt *) parsetree;
				char	   *portalName = stmt->portalname;
				bool		forward;
				int			count;

151
				PS_SET_STATUS(commandTag = (stmt->ismove) ? "MOVE" : "FETCH");
152
				CHECK_IF_ABORTED();
153

154
				forward = (bool) (stmt->direction == FORWARD);
155

156 157 158
				/*
				 * parser ensures that count is >= 0 and 'fetch ALL' -> 0
				 */
159

160
				count = stmt->howMany;
161 162
				PerformPortalFetch(portalName, forward, count, commandTag,
								   (stmt->ismove) ? None : dest);		/* /dev/null for MOVE */
163 164
			}
			break;
165 166

			/*
167 168 169
			 * ******************************** relation and attribute
			 * manipulation ********************************
			 *
170
			 */
171
		case T_CreateStmt:
172
			PS_SET_STATUS(commandTag = "CREATE");
173 174
			CHECK_IF_ABORTED();

175
			DefineRelation((CreateStmt *) parsetree, RELKIND_RELATION);
176 177 178
			break;

		case T_DestroyStmt:
179
			{
180 181 182 183 184
				DestroyStmt *stmt = (DestroyStmt *) parsetree;
				List	   *arg;
				List	   *args = stmt->relNames;
				Relation	rel;

185
				PS_SET_STATUS(commandTag = "DROP");
186 187 188
				CHECK_IF_ABORTED();

				foreach(arg, args)
189
				{
190 191
					relname = strVal(lfirst(arg));
					if (IsSystemRelationName(relname))
192
						elog(ERROR, "class \"%s\" is a system catalog",
193
							 relname);
194 195 196 197 198
					rel = heap_openr(relname);
					if (RelationIsValid(rel))
					{
						if (stmt->sequence &&
							rel->rd_rel->relkind != RELKIND_SEQUENCE)
199
							elog(ERROR, "Use DROP TABLE to drop table '%s'",
200 201 202
								 relname);
						if (!(stmt->sequence) &&
							rel->rd_rel->relkind == RELKIND_SEQUENCE)
203
							elog(ERROR, "Use DROP SEQUENCE to drop sequence '%s'",
204 205 206
								 relname);
						heap_close(rel);
					}
207
#ifndef NO_SECURITY
208
					if (!pg_ownercheck(userName, relname, RELNAME))
209
						elog(ERROR, "you do not own class \"%s\"",
210
							 relname);
211
#endif
212 213 214 215 216 217
				}
				foreach(arg, args)
				{
					relname = strVal(lfirst(arg));
					RemoveRelation(relname);
				}
218
			}
219 220 221 222 223
			break;

		case T_CopyStmt:
			{
				CopyStmt   *stmt = (CopyStmt *) parsetree;
224

225
				PS_SET_STATUS(commandTag = "COPY");
226
				CHECK_IF_ABORTED();
227

228 229 230 231 232
				DoCopy(stmt->relname,
					   stmt->binary,
					   stmt->oids,
					   (bool) (stmt->direction == FROM),
					   (bool) (stmt->filename == NULL),
233

234 235 236 237 238 239 240 241
				/*
				 * null filename means copy to/from stdout/stdin, rather
				 * than to/from a file.
				 */
					   stmt->filename,
					   stmt->delimiter);
			}
			break;
242

243 244 245
		case T_AddAttrStmt:
			{
				AddAttrStmt *stmt = (AddAttrStmt *) parsetree;
246

247
				PS_SET_STATUS(commandTag = "ADD");
248
				CHECK_IF_ABORTED();
249

250
				/*
251 252
				 * owner checking done in PerformAddAttribute (now
				 * recursive)
253 254 255 256
				 */
				PerformAddAttribute(stmt->relname,
									userName,
									stmt->inh,
257
									(ColumnDef *) stmt->colDef);
258 259
			}
			break;
260 261

			/*
262
			 * schema
263
			 */
264 265 266
		case T_RenameStmt:
			{
				RenameStmt *stmt = (RenameStmt *) parsetree;
267

268
				PS_SET_STATUS(commandTag = "RENAME");
269
				CHECK_IF_ABORTED();
270

271 272
				relname = stmt->relname;
				if (IsSystemRelationName(relname))
273
					elog(ERROR, "class \"%s\" is a system catalog",
274
						 relname);
275
#ifndef NO_SECURITY
276
				if (!pg_ownercheck(userName, relname, RELNAME))
277
					elog(ERROR, "you do not own class \"%s\"",
278
						 relname);
279
#endif
280 281

				/* ----------------
282 283 284 285 286
				 *	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
287
				 * ----------------
288
				 * [another piece of amuzing but useless anecdote -- ay]
289
				 */
290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315
				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? */
				}
316
			}
317
			break;
318

319 320 321 322 323 324
		case T_ChangeACLStmt:
			{
				ChangeACLStmt *stmt = (ChangeACLStmt *) parsetree;
				List	   *i;
				AclItem    *aip;
				unsigned	modechg;
325

326
				PS_SET_STATUS(commandTag = "CHANGE");
327
				CHECK_IF_ABORTED();
328

329
				aip = stmt->aclitem;
330

331
				modechg = stmt->modechg;
332
#ifndef NO_SECURITY
333 334 335 336
				foreach(i, stmt->relNames)
				{
					relname = strVal(lfirst(i));
					if (!pg_ownercheck(userName, relname, RELNAME))
337
						elog(ERROR, "you do not own class \"%s\"",
338 339
							 relname);
				}
340
#endif
341 342 343 344 345
				foreach(i, stmt->relNames)
				{
					relname = strVal(lfirst(i));
					ChangeAcl(relname, aip, modechg);
				}
346

347 348
			}
			break;
349

350 351 352 353 354 355 356 357
			/*
			 * ******************************** object creation /
			 * destruction ********************************
			 *
			 */
		case T_DefineStmt:
			{
				DefineStmt *stmt = (DefineStmt *) parsetree;
358

359
				PS_SET_STATUS(commandTag = "CREATE");
360
				CHECK_IF_ABORTED();
361

362
				switch (stmt->defType)
363
				{
364 365 366 367
					case OPERATOR:
						DefineOperator(stmt->defname,	/* operator name */
									   stmt->definition);		/* rest */
						break;
368
					case TYPE_P:
369
						DefineType(stmt->defname, stmt->definition);
370 371 372 373 374
						break;
					case AGGREGATE:
						DefineAggregate(stmt->defname,	/* aggregate name */
										stmt->definition);		/* rest */
						break;
375 376
				}
			}
377 378 379 380 381
			break;

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

383
				PS_SET_STATUS(commandTag = "CREATE");
384 385 386 387
				CHECK_IF_ABORTED();
				DefineView(stmt->viewname, stmt->query);		/* retrieve parsetree */
			}
			break;
388

389
		case T_ProcedureStmt:	/* CREATE FUNCTION */
390
			PS_SET_STATUS(commandTag = "CREATE");
391
			CHECK_IF_ABORTED();
392 393
			CreateFunction((ProcedureStmt *) parsetree, dest);	/* everything */
			break;
394

395 396 397
		case T_IndexStmt:		/* CREATE INDEX */
			{
				IndexStmt  *stmt = (IndexStmt *) parsetree;
398

399
				PS_SET_STATUS(commandTag = "CREATE");
400 401 402 403 404 405 406
				CHECK_IF_ABORTED();
				DefineIndex(stmt->relname,		/* relation name */
							stmt->idxname,		/* index name */
							stmt->accessMethod, /* am name */
							stmt->indexParams,	/* parameters */
							stmt->withClause,
							stmt->unique,
407
							0,		/* CREATE INDEX can't be primary */
408 409 410 411
							(Expr *) stmt->whereClause,
							stmt->rangetable);
			}
			break;
412

413 414 415 416
		case T_RuleStmt:		/* CREATE RULE */
			{
				RuleStmt   *stmt = (RuleStmt *) parsetree;
				int			aclcheck_result;
417

418
#ifndef NO_SECURITY
419 420 421
				relname = stmt->object->relname;
				aclcheck_result = pg_aclcheck(relname, userName, ACL_RU);
				if (aclcheck_result != ACLCHECK_OK)
422
					elog(ERROR, "%s: %s", relname, aclcheck_error_strings[aclcheck_result]);
423
#endif
424
				PS_SET_STATUS(commandTag = "CREATE");
425 426 427 428 429 430
				CHECK_IF_ABORTED();
				DefineQueryRewrite(stmt);
			}
			break;

		case T_CreateSeqStmt:
431
			PS_SET_STATUS(commandTag = "CREATE");
432 433
			CHECK_IF_ABORTED();

434 435
			DefineSequence((CreateSeqStmt *) parsetree);
			break;
436

437 438 439
		case T_ExtendStmt:
			{
				ExtendStmt *stmt = (ExtendStmt *) parsetree;
440

441
				PS_SET_STATUS(commandTag = "EXTEND");
442
				CHECK_IF_ABORTED();
443

444 445 446 447 448
				ExtendIndex(stmt->idxname,		/* index name */
							(Expr *) stmt->whereClause, /* where */
							stmt->rangetable);
			}
			break;
449

450 451 452
		case T_RemoveStmt:
			{
				RemoveStmt *stmt = (RemoveStmt *) parsetree;
453

454
				PS_SET_STATUS(commandTag = "DROP");
455
				CHECK_IF_ABORTED();
456

457 458 459 460 461
				switch (stmt->removeType)
				{
					case INDEX:
						relname = stmt->name;
						if (IsSystemRelationName(relname))
462
							elog(ERROR, "class \"%s\" is a system catalog index",
463
								 relname);
464
#ifndef NO_SECURITY
465
						if (!pg_ownercheck(userName, relname, RELNAME))
466
							elog(ERROR, "%s: %s", relname, aclcheck_error_strings[ACLCHECK_NOT_OWNER]);
467
#endif
468 469 470 471 472 473
						RemoveIndex(relname);
						break;
					case RULE:
						{
							char	   *rulename = stmt->name;
							int			aclcheck_result;
474 475

#ifndef NO_SECURITY
476

477 478 479
							relationName = RewriteGetRuleEventRel(rulename);
							aclcheck_result = pg_aclcheck(relationName, userName, ACL_RU);
							if (aclcheck_result != ACLCHECK_OK)
480
								elog(ERROR, "%s: %s", relationName, aclcheck_error_strings[aclcheck_result]);
481
#endif
482 483 484
							RemoveRewriteRule(rulename);
						}
						break;
485
					case TYPE_P:
486
#ifndef NO_SECURITY
487
						/* XXX moved to remove.c */
488
#endif
489 490 491 492 493 494
						RemoveType(stmt->name);
						break;
					case VIEW:
						{
							char	   *viewName = stmt->name;
							char	   *ruleName;
495 496 497

#ifndef NO_SECURITY

498 499 500
							ruleName = MakeRetrieveViewRuleName(viewName);
							relationName = RewriteGetRuleEventRel(ruleName);
							if (!pg_ownercheck(userName, relationName, RELNAME))
501
								elog(ERROR, "%s: %s", relationName, aclcheck_error_strings[ACLCHECK_NOT_OWNER]);
502
							pfree(ruleName);
503
#endif
504 505 506
							RemoveView(viewName);
						}
						break;
507 508 509 510
				}
				break;
			}
			break;
511

512 513 514
		case T_RemoveAggrStmt:
			{
				RemoveAggrStmt *stmt = (RemoveAggrStmt *) parsetree;
515

516
				PS_SET_STATUS(commandTag = "DROP");
517 518 519 520
				CHECK_IF_ABORTED();
				RemoveAggregate(stmt->aggname, stmt->aggtype);
			}
			break;
521

522 523 524
		case T_RemoveFuncStmt:
			{
				RemoveFuncStmt *stmt = (RemoveFuncStmt *) parsetree;
525

526
				PS_SET_STATUS(commandTag = "DROP");
527 528 529 530 531 532
				CHECK_IF_ABORTED();
				RemoveFunction(stmt->funcname,
							   length(stmt->args),
							   stmt->args);
			}
			break;
533

534 535 536 537 538
		case T_RemoveOperStmt:
			{
				RemoveOperStmt *stmt = (RemoveOperStmt *) parsetree;
				char	   *type1 = (char *) NULL;
				char	   *type2 = (char *) NULL;
539

540
				PS_SET_STATUS(commandTag = "DROP");
541
				CHECK_IF_ABORTED();
542

543 544 545 546 547 548 549
				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;
550

551
		case T_VersionStmt:
552
			elog(ERROR, "CREATE VERSION is not currently implemented");
553
			break;
554

555 556 557
		case T_CreatedbStmt:
			{
				CreatedbStmt *stmt = (CreatedbStmt *) parsetree;
558

559
				PS_SET_STATUS(commandTag = "CREATEDB");
560
				CHECK_IF_ABORTED();
561
				createdb(stmt->dbname, stmt->dbpath, stmt->encoding);
562 563 564 565 566 567
			}
			break;

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

569
				PS_SET_STATUS(commandTag = "DESTROYDB");
570 571 572 573
				CHECK_IF_ABORTED();
				destroydb(stmt->dbname);
			}
			break;
574

575 576 577 578
			/* Query-level asynchronous notification */
		case T_NotifyStmt:
			{
				NotifyStmt *stmt = (NotifyStmt *) parsetree;
579

580
				PS_SET_STATUS(commandTag = "NOTIFY");
581
				CHECK_IF_ABORTED();
582

583 584 585
				Async_Notify(stmt->relname);
			}
			break;
586

587 588 589
		case T_ListenStmt:
			{
				ListenStmt *stmt = (ListenStmt *) parsetree;
590

591
				PS_SET_STATUS(commandTag = "LISTEN");
592
				CHECK_IF_ABORTED();
593

Bruce Momjian's avatar
Bruce Momjian committed
594
				Async_Listen(stmt->relname, MyProcPid);
595 596
			}
			break;
597

598 599 600 601
		case T_UnlistenStmt:
			{
				UnlistenStmt *stmt = (UnlistenStmt *) parsetree;

602
				PS_SET_STATUS(commandTag = "UNLISTEN");
603 604 605 606 607 608
				CHECK_IF_ABORTED();

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

609 610 611 612 613 614 615 616 617 618
			/*
			 * ******************************** dynamic loader ********************************
			 *
			 */
		case T_LoadStmt:
			{
				LoadStmt   *stmt = (LoadStmt *) parsetree;
				FILE	   *fp;
				char	   *filename;

619
				PS_SET_STATUS(commandTag = "LOAD");
620 621 622 623
				CHECK_IF_ABORTED();

				filename = stmt->filename;
				closeAllVfds();
624
#ifndef __CYGWIN32__
625
				if ((fp = AllocateFile(filename, "r")) == NULL)
626 627 628
#else
				if ((fp = AllocateFile(filename, "rb")) == NULL)
#endif
629
					elog(ERROR, "LOAD: could not open file '%s'", filename);
630 631 632 633
				FreeFile(fp);
				load_file(filename);
			}
			break;
634

635 636 637
		case T_ClusterStmt:
			{
				ClusterStmt *stmt = (ClusterStmt *) parsetree;
638

639
				PS_SET_STATUS(commandTag = "CLUSTER");
640
				CHECK_IF_ABORTED();
641

642 643 644 645 646
				cluster(stmt->relname, stmt->indexname);
			}
			break;

		case T_VacuumStmt:
647
			PS_SET_STATUS(commandTag = "VACUUM");
648
			CHECK_IF_ABORTED();
649 650 651 652 653 654 655 656 657 658
			vacuum(((VacuumStmt *) parsetree)->vacrel,
				   ((VacuumStmt *) parsetree)->verbose,
				   ((VacuumStmt *) parsetree)->analyze,
				   ((VacuumStmt *) parsetree)->va_spec);
			break;

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

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

662 663 664
				ExplainQuery(stmt->query, stmt->verbose, dest);
			}
			break;
665

666 667 668 669 670 671
			/*
			 * ******************************** Tioga-related statements *******************************
			 */
		case T_RecipeStmt:
			{
				RecipeStmt *stmt = (RecipeStmt *) parsetree;
672

673
				PS_SET_STATUS(commandTag = "EXECUTE RECIPE");
674 675 676 677 678 679 680 681 682 683 684 685 686
				CHECK_IF_ABORTED();
				beginRecipe(stmt);
			}
			break;

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

				SetPGVariable(n->name, n->value);
687
				PS_SET_STATUS(commandTag = "SET VARIABLE");
688 689 690 691 692 693 694 695
			}
			break;

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

				GetPGVariable(n->name);
696
				PS_SET_STATUS(commandTag = "SHOW VARIABLE");
697 698 699 700 701 702 703 704
			}
			break;

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

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

			/*
			 * ******************************** TRIGGER statements *******************************
			 */
		case T_CreateTrigStmt:
713
			PS_SET_STATUS(commandTag = "CREATE");
714 715 716 717 718 719
			CHECK_IF_ABORTED();

			CreateTrigger((CreateTrigStmt *) parsetree);
			break;

		case T_DropTrigStmt:
720
			PS_SET_STATUS(commandTag = "DROP");
721
			CHECK_IF_ABORTED();
722 723 724 725

			DropTrigger((DropTrigStmt *) parsetree);
			break;

726 727 728 729
			/*
			 * ************* PROCEDURAL LANGUAGE statements *****************
			 */
		case T_CreatePLangStmt:
730
			PS_SET_STATUS(commandTag = "CREATE");
731 732 733 734 735 736
			CHECK_IF_ABORTED();

			CreateProceduralLanguage((CreatePLangStmt *) parsetree);
			break;

		case T_DropPLangStmt:
737
			PS_SET_STATUS(commandTag = "DROP");
738 739 740 741 742
			CHECK_IF_ABORTED();

			DropProceduralLanguage((DropPLangStmt *) parsetree);
			break;

743 744 745 746 747
			/*
			 * ******************************** USER statements ****
			 *
			 */
		case T_CreateUserStmt:
748
			PS_SET_STATUS(commandTag = "CREATE USER");
749
			CHECK_IF_ABORTED();
750

751 752
			DefineUser((CreateUserStmt *) parsetree);
			break;
753

754
		case T_AlterUserStmt:
755
			PS_SET_STATUS(commandTag = "ALTER USER");
756
			CHECK_IF_ABORTED();
757

758 759
			AlterUser((AlterUserStmt *) parsetree);
			break;
760

761
		case T_DropUserStmt:
762
			PS_SET_STATUS(commandTag = "DROP USER");
763
			CHECK_IF_ABORTED();
764

765 766
			RemoveUser(((DropUserStmt *) parsetree)->user);
			break;
767

768 769 770 771 772 773 774
		case T_LockStmt:
			PS_SET_STATUS(commandTag = "LOCK TABLE");
			CHECK_IF_ABORTED();

			LockTableCommand((LockStmt *) parsetree);
			break;

775

776 777 778 779 780
			/*
			 * ******************************** default ********************************
			 *
			 */
		default:
781
			elog(ERROR, "ProcessUtility: command #%d unsupported",
782 783
				 nodeTag(parsetree));
			break;
784
	}
785 786 787 788

	/* ----------------
	 *	tell fe/be or whatever that we're done.
	 * ----------------
789
	 */
790
	EndCommand(commandTag, dest);
791
}