utility.c 34.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
 *
Bruce Momjian's avatar
Bruce Momjian committed
8
 * Portions Copyright (c) 1996-2003, 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.206 2003/09/09 23:22:21 petere 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/namespace.h"
22
#include "catalog/pg_shadow.h"
23
#include "commands/alter.h"
24 25
#include "commands/async.h"
#include "commands/cluster.h"
Bruce Momjian's avatar
Bruce Momjian committed
26
#include "commands/comment.h"
27
#include "commands/copy.h"
28
#include "commands/conversioncmds.h"
29
#include "commands/dbcommands.h"
30 31
#include "commands/defrem.h"
#include "commands/explain.h"
32 33
#include "commands/lockcmds.h"
#include "commands/portalcmds.h"
34
#include "commands/prepare.h"
35
#include "commands/proclang.h"
36
#include "commands/schemacmds.h"
Bruce Momjian's avatar
Bruce Momjian committed
37
#include "commands/sequence.h"
38
#include "commands/tablecmds.h"
Bruce Momjian's avatar
Bruce Momjian committed
39
#include "commands/trigger.h"
40
#include "commands/typecmds.h"
41
#include "commands/user.h"
Bruce Momjian's avatar
Bruce Momjian committed
42 43 44
#include "commands/vacuum.h"
#include "commands/view.h"
#include "miscadmin.h"
45
#include "nodes/makefuncs.h"
46
#include "parser/parse_clause.h"
47
#include "parser/parse_expr.h"
48
#include "parser/parse_type.h"
49
#include "rewrite/rewriteDefine.h"
Bruce Momjian's avatar
Bruce Momjian committed
50
#include "rewrite/rewriteRemove.h"
51
#include "tcop/pquery.h"
Bruce Momjian's avatar
Bruce Momjian committed
52
#include "tcop/utility.h"
53
#include "utils/acl.h"
54
#include "utils/guc.h"
55
#include "utils/lsyscache.h"
56
#include "utils/syscache.h"
Vadim B. Mikheev's avatar
Vadim B. Mikheev committed
57
#include "access/xlog.h"
58

59
/*
60
 * Error-checking support for DROP commands
61 62
 */

63
struct msgstrings
64 65
{
	char		kind;
66 67 68 69
	int			nonexistent_code;
	const char *nonexistent_msg;
	const char *nota_msg;
	const char *drophint_msg;
70 71
};

72
static const struct msgstrings msgstringarray[] = {
Bruce Momjian's avatar
Bruce Momjian committed
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
	{RELKIND_RELATION,
		ERRCODE_UNDEFINED_TABLE,
		gettext_noop("table \"%s\" does not exist"),
		gettext_noop("\"%s\" is not a table"),
	gettext_noop("Use DROP TABLE to remove a table.")},
	{RELKIND_SEQUENCE,
		ERRCODE_UNDEFINED_TABLE,
		gettext_noop("sequence \"%s\" does not exist"),
		gettext_noop("\"%s\" is not a sequence"),
	gettext_noop("Use DROP SEQUENCE to remove a sequence.")},
	{RELKIND_VIEW,
		ERRCODE_UNDEFINED_TABLE,
		gettext_noop("view \"%s\" does not exist"),
		gettext_noop("\"%s\" is not a view"),
	gettext_noop("Use DROP VIEW to remove a view.")},
	{RELKIND_INDEX,
		ERRCODE_UNDEFINED_OBJECT,
		gettext_noop("index \"%s\" does not exist"),
		gettext_noop("\"%s\" is not an index"),
	gettext_noop("Use DROP INDEX to remove an index.")},
	{RELKIND_COMPOSITE_TYPE,
		ERRCODE_UNDEFINED_OBJECT,
		gettext_noop("type \"%s\" does not exist"),
		gettext_noop("\"%s\" is not a type"),
	gettext_noop("Use DROP TYPE to remove a type.")},
	{'\0', 0, NULL, NULL, NULL}
99 100 101 102
};


static void
103
DropErrorMsg(char *relname, char wrongkind, char rightkind)
104
{
105 106
	const struct msgstrings *rentry;
	const struct msgstrings *wentry;
107

108
	for (rentry = msgstringarray; rentry->kind != '\0'; rentry++)
109 110 111 112
		if (rentry->kind == rightkind)
			break;
	Assert(rentry->kind != '\0');

113
	for (wentry = msgstringarray; wentry->kind != '\0'; wentry++)
114 115
		if (wentry->kind == wrongkind)
			break;
116
	/* wrongkind could be something we don't have in our table... */
117 118 119 120 121

	ereport(ERROR,
			(errcode(ERRCODE_WRONG_OBJECT_TYPE),
			 errmsg(rentry->nota_msg, relname),
			 (wentry->kind != '\0') ? errhint(wentry->drophint_msg) : 0));
122 123 124
}

static void
125
CheckDropPermissions(RangeVar *rel, char rightkind)
126
{
127
	const struct msgstrings *rentry;
128
	Oid			relOid;
129
	HeapTuple	tuple;
130 131
	Form_pg_class classform;

132
	for (rentry = msgstringarray; rentry->kind != '\0'; rentry++)
133 134 135 136
		if (rentry->kind == rightkind)
			break;
	Assert(rentry->kind != '\0');

137 138
	relOid = RangeVarGetRelid(rel, true);
	if (!OidIsValid(relOid))
139 140 141
		ereport(ERROR,
				(errcode(rentry->nonexistent_code),
				 errmsg(rentry->nonexistent_msg, rel->relname)));
142 143
	tuple = SearchSysCache(RELOID,
						   ObjectIdGetDatum(relOid),
144
						   0, 0, 0);
145
	if (!HeapTupleIsValid(tuple))
146
		elog(ERROR, "cache lookup failed for relation %u", relOid);
147 148 149 150

	classform = (Form_pg_class) GETSTRUCT(tuple);

	if (classform->relkind != rightkind)
151
		DropErrorMsg(rel->relname, classform->relkind, rightkind);
152

153 154 155
	/* Allow DROP to either table owner or schema owner */
	if (!pg_class_ownercheck(relOid, GetUserId()) &&
		!pg_namespace_ownercheck(classform->relnamespace, GetUserId()))
156 157
		aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
					   rel->relname);
158

159
	if (!allowSystemTableMods && IsSystemClass(classform))
160 161
		ereport(ERROR,
				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
162
				 errmsg("permission denied: \"%s\" is a system catalog",
163
						rel->relname)));
164 165

	ReleaseSysCache(tuple);
166 167
}

168 169 170 171 172 173 174 175
/*
 * Verify user has ownership of specified relation, else ereport.
 *
 * If noCatalogs is true then we also deny access to system catalogs,
 * except when allowSystemTableMods is true.
 */
void
CheckRelationOwnership(RangeVar *rel, bool noCatalogs)
176
{
177
	Oid			relOid;
178 179
	HeapTuple	tuple;

180 181 182
	relOid = RangeVarGetRelid(rel, false);
	tuple = SearchSysCache(RELOID,
						   ObjectIdGetDatum(relOid),
183
						   0, 0, 0);
Bruce Momjian's avatar
Bruce Momjian committed
184
	if (!HeapTupleIsValid(tuple))		/* should not happen */
185
		elog(ERROR, "cache lookup failed for relation %u", relOid);
186

187
	if (!pg_class_ownercheck(relOid, GetUserId()))
188 189
		aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
					   rel->relname);
190 191 192

	if (noCatalogs)
	{
193 194
		if (!allowSystemTableMods &&
			IsSystemClass((Form_pg_class) GETSTRUCT(tuple)))
195 196
			ereport(ERROR,
					(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
Bruce Momjian's avatar
Bruce Momjian committed
197 198
				  errmsg("permission denied: \"%s\" is a system catalog",
						 rel->relname)));
199 200 201 202 203
	}

	ReleaseSysCache(tuple);
}

204

205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
static void
check_xact_readonly(Node *parsetree)
{
	if (!XactReadOnly)
		return;

	/*
	 * Note: Commands that need to do more complicated checking are
	 * handled elsewhere.
	 */

	switch (nodeTag(parsetree))
	{
		case T_AlterDatabaseSetStmt:
		case T_AlterDomainStmt:
		case T_AlterGroupStmt:
Bruce Momjian's avatar
Bruce Momjian committed
221
		case T_AlterSeqStmt:
222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257
		case T_AlterTableStmt:
		case T_RenameStmt:
		case T_AlterUserStmt:
		case T_AlterUserSetStmt:
		case T_CommentStmt:
		case T_DefineStmt:
		case T_CreateCastStmt:
		case T_CreateConversionStmt:
		case T_CreatedbStmt:
		case T_CreateDomainStmt:
		case T_CreateFunctionStmt:
		case T_CreateGroupStmt:
		case T_IndexStmt:
		case T_CreatePLangStmt:
		case T_CreateOpClassStmt:
		case T_RuleStmt:
		case T_CreateSchemaStmt:
		case T_CreateSeqStmt:
		case T_CreateStmt:
		case T_CreateTrigStmt:
		case T_CompositeTypeStmt:
		case T_CreateUserStmt:
		case T_ViewStmt:
		case T_RemoveAggrStmt:
		case T_DropCastStmt:
		case T_DropStmt:
		case T_DropdbStmt:
		case T_RemoveFuncStmt:
		case T_DropGroupStmt:
		case T_DropPLangStmt:
		case T_RemoveOperStmt:
		case T_RemoveOpClassStmt:
		case T_DropPropertyStmt:
		case T_DropUserStmt:
		case T_GrantStmt:
		case T_TruncateStmt:
258 259 260
			ereport(ERROR,
					(errcode(ERRCODE_READ_ONLY_SQL_TRANSACTION),
					 errmsg("transaction is read-only")));
261 262
			break;
		default:
263 264
			/* do nothing */
			break;
265 266 267 268
	}
}


269 270
/*
 * ProcessUtility
271
 *		general utility function invoker
272 273 274 275 276 277 278 279 280 281
 *
 *	parsetree: the parse tree for the utility statement
 *	dest: where to send results
 *	completionTag: points to a buffer of size COMPLETION_TAG_BUFSIZE
 *		in which to store a command completion status string.
 *
 * completionTag is only set nonempty if we want to return a nondefault
 * status (currently, only used for MOVE/FETCH).
 *
 * completionTag may be NULL if caller doesn't want a status string.
282 283
 */
void
284
ProcessUtility(Node *parsetree,
285
			   DestReceiver *dest,
286
			   char *completionTag)
287
{
288 289
	check_xact_readonly(parsetree);

290 291 292
	if (completionTag)
		completionTag[0] = '\0';

293
	switch (nodeTag(parsetree))
294
	{
295
			/*
296
			 * ******************** transactions ********************
297 298 299 300
			 */
		case T_TransactionStmt:
			{
				TransactionStmt *stmt = (TransactionStmt *) parsetree;
301

302
				switch (stmt->kind)
303
				{
304
					case TRANS_STMT_BEGIN:
305 306 307
						BeginTransactionBlock();
						break;

Bruce Momjian's avatar
Bruce Momjian committed
308 309 310 311 312
						/*
						 * START TRANSACTION, as defined by SQL99:
						 * Identical to BEGIN, except that it takes a few
						 * additional options.
						 */
313
					case TRANS_STMT_START:
314 315 316 317 318
						{
							BeginTransactionBlock();

							if (stmt->options)
							{
Bruce Momjian's avatar
Bruce Momjian committed
319
								List	   *head;
320 321 322

								foreach(head, stmt->options)
								{
Bruce Momjian's avatar
Bruce Momjian committed
323
									DefElem    *item = (DefElem *) lfirst(head);
324

Bruce Momjian's avatar
Bruce Momjian committed
325
									if (strcmp(item->defname, "transaction_isolation") == 0)
326
										SetPGVariable("transaction_isolation",
Bruce Momjian's avatar
Bruce Momjian committed
327 328
											makeList1(item->arg), false);
									else if (strcmp(item->defname, "transaction_read_only") == 0)
329
										SetPGVariable("transaction_read_only",
Bruce Momjian's avatar
Bruce Momjian committed
330
											makeList1(item->arg), false);
331
								}
332 333 334 335
							}
						}
						break;

336
					case TRANS_STMT_COMMIT:
337 338 339
						EndTransactionBlock();
						break;

340
					case TRANS_STMT_ROLLBACK:
341 342 343 344 345 346 347
						UserAbortTransactionBlock();
						break;
				}
			}
			break;

			/*
348
			 * Portal (cursor) manipulation
349
			 */
350
		case T_DeclareCursorStmt:
351
			PerformCursorOpen((DeclareCursorStmt *) parsetree);
352 353
			break;

354
		case T_ClosePortalStmt:
355
			{
356
				ClosePortalStmt *stmt = (ClosePortalStmt *) parsetree;
357

358
				PerformPortalClose(stmt->portalname);
359
			}
360
			break;
361

362
		case T_FetchStmt:
363 364
			PerformPortalFetch((FetchStmt *) parsetree, dest,
							   completionTag);
365
			break;
366 367

			/*
368
			 * relation and attribute manipulation
369
			 */
370
		case T_CreateSchemaStmt:
371
			CreateSchemaCommand((CreateSchemaStmt *) parsetree);
372 373
			break;

374
		case T_CreateStmt:
375 376
			{
				Oid			relOid;
377

378 379 380 381
				relOid = DefineRelation((CreateStmt *) parsetree,
										RELKIND_RELATION);

				/*
Bruce Momjian's avatar
Bruce Momjian committed
382 383
				 * Let AlterTableCreateToastTable decide if this one needs
				 * a secondary relation too.
384 385 386 387
				 */
				CommandCounterIncrement();
				AlterTableCreateToastTable(relOid, true);
			}
388 389
			break;

390
		case T_DropStmt:
391
			{
392
				DropStmt   *stmt = (DropStmt *) parsetree;
393
				List	   *arg;
394

395
				foreach(arg, stmt->objects)
396
				{
Bruce Momjian's avatar
Bruce Momjian committed
397
					List	   *names = (List *) lfirst(arg);
398
					RangeVar   *rel;
399

400
					switch (stmt->removeType)
401
					{
402
						case OBJECT_TABLE:
403
							rel = makeRangeVarFromNameList(names);
404
							CheckDropPermissions(rel, RELKIND_RELATION);
405
							RemoveRelation(rel, stmt->behavior);
406 407
							break;

408
						case OBJECT_SEQUENCE:
409
							rel = makeRangeVarFromNameList(names);
410
							CheckDropPermissions(rel, RELKIND_SEQUENCE);
411
							RemoveRelation(rel, stmt->behavior);
412 413
							break;

414
						case OBJECT_VIEW:
415
							rel = makeRangeVarFromNameList(names);
416
							CheckDropPermissions(rel, RELKIND_VIEW);
417
							RemoveView(rel, stmt->behavior);
418 419
							break;

420
						case OBJECT_INDEX:
421
							rel = makeRangeVarFromNameList(names);
422
							CheckDropPermissions(rel, RELKIND_INDEX);
423
							RemoveIndex(rel, stmt->behavior);
424 425
							break;

426
						case OBJECT_TYPE:
427
							/* RemoveType does its own permissions checks */
428
							RemoveType(names, stmt->behavior);
429
							break;
430

431
						case OBJECT_DOMAIN:
Bruce Momjian's avatar
Bruce Momjian committed
432 433 434 435 436

							/*
							 * RemoveDomain does its own permissions
							 * checks
							 */
437
							RemoveDomain(names, stmt->behavior);
438
							break;
439

440
						case OBJECT_CONVERSION:
Tatsuo Ishii's avatar
Tatsuo Ishii committed
441
							DropConversionCommand(names, stmt->behavior);
442
							break;
443

444
						case OBJECT_SCHEMA:
Bruce Momjian's avatar
Bruce Momjian committed
445 446 447 448 449

							/*
							 * RemoveSchema does its own permissions
							 * checks
							 */
450 451
							RemoveSchema(names, stmt->behavior);
							break;
452 453

						default:
454 455 456
							elog(ERROR, "unrecognized drop object type: %d",
								 (int) stmt->removeType);
							break;
457 458
					}

459
					/*
460 461
					 * We used to need to do CommandCounterIncrement()
					 * here, but now it's done inside performDeletion().
462 463
					 */
				}
464
			}
465 466
			break;

467 468
		case T_TruncateStmt:
			{
Bruce Momjian's avatar
Bruce Momjian committed
469
				TruncateStmt *stmt = (TruncateStmt *) parsetree;
470 471

				TruncateRelation(stmt->relation);
472 473 474
			}
			break;

475
		case T_CommentStmt:
476
			CommentObject((CommentStmt *) parsetree);
477 478
			break;

479
		case T_CopyStmt:
480
			DoCopy((CopyStmt *) parsetree);
481
			break;
482

483 484 485 486 487 488 489 490 491 492 493 494
		case T_PrepareStmt:
			PrepareQuery((PrepareStmt *) parsetree);
			break;

		case T_ExecuteStmt:
			ExecuteQuery((ExecuteStmt *) parsetree, dest);
			break;

		case T_DeallocateStmt:
			DeallocateQuery((DeallocateStmt *) parsetree);
			break;

495
			/*
496
			 * schema
497
			 */
498
		case T_RenameStmt:
499
			ExecRenameStmt((RenameStmt *) parsetree);
500
			break;
501

502
			/* various Alter Table forms */
503 504

		case T_AlterTableStmt:
505 506
			{
				AlterTableStmt *stmt = (AlterTableStmt *) parsetree;
Bruce Momjian's avatar
Bruce Momjian committed
507
				Oid			relid;
508 509

				relid = RangeVarGetRelid(stmt->relation, false);
510 511 512 513 514 515 516 517

				/*
				 * 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 */
Bruce Momjian's avatar
Bruce Momjian committed
518

519
						/*
Bruce Momjian's avatar
Bruce Momjian committed
520 521
						 * Recursively add column to table and, if
						 * requested, to descendants
522
						 */
523
						AlterTableAddColumn(relid,
Bruce Momjian's avatar
Bruce Momjian committed
524
							  interpretInhOption(stmt->relation->inhOpt),
525
											(ColumnDef *) stmt->def);
526
						break;
527
					case 'T':	/* ALTER COLUMN DEFAULT */
Bruce Momjian's avatar
Bruce Momjian committed
528

Bruce Momjian's avatar
Bruce Momjian committed
529
						/*
530 531 532
						 * Recursively alter column default for table and,
						 * if requested, for descendants
						 */
533
						AlterTableAlterColumnDefault(relid,
Bruce Momjian's avatar
Bruce Momjian committed
534
							  interpretInhOption(stmt->relation->inhOpt),
535 536
													 stmt->name,
													 stmt->def);
537
						break;
538
					case 'N':	/* ALTER COLUMN DROP NOT NULL */
539
						AlterTableAlterColumnDropNotNull(relid,
Bruce Momjian's avatar
Bruce Momjian committed
540 541
							  interpretInhOption(stmt->relation->inhOpt),
														 stmt->name);
542
						break;
Bruce Momjian's avatar
Bruce Momjian committed
543
					case 'n':	/* ALTER COLUMN SET NOT NULL */
544
						AlterTableAlterColumnSetNotNull(relid,
Bruce Momjian's avatar
Bruce Momjian committed
545 546
							  interpretInhOption(stmt->relation->inhOpt),
														stmt->name);
547
						break;
548
					case 'S':	/* ALTER COLUMN STATISTICS */
Bruce Momjian's avatar
Bruce Momjian committed
549 550
					case 'M':	/* ALTER COLUMN STORAGE */

551
						/*
Bruce Momjian's avatar
Bruce Momjian committed
552 553
						 * Recursively alter column statistics for table
						 * and, if requested, for descendants
554
						 */
555
						AlterTableAlterColumnFlags(relid,
Bruce Momjian's avatar
Bruce Momjian committed
556
							  interpretInhOption(stmt->relation->inhOpt),
557 558 559
												   stmt->name,
												   stmt->def,
												   &(stmt->subtype));
560 561
						break;
					case 'D':	/* DROP COLUMN */
Bruce Momjian's avatar
Bruce Momjian committed
562 563 564 565

						/*
						 * Recursively drop column from table and, if
						 * requested, from descendants
566
						 */
567
						AlterTableDropColumn(relid,
Bruce Momjian's avatar
Bruce Momjian committed
568
							  interpretInhOption(stmt->relation->inhOpt),
569
											 false,
570 571
											 stmt->name,
											 stmt->behavior);
572 573
						break;
					case 'C':	/* ADD CONSTRAINT */
Bruce Momjian's avatar
Bruce Momjian committed
574

575
						/*
Bruce Momjian's avatar
Bruce Momjian committed
576 577
						 * Recursively add constraint to table and, if
						 * requested, to descendants
578
						 */
579
						AlterTableAddConstraint(relid,
Bruce Momjian's avatar
Bruce Momjian committed
580
							  interpretInhOption(stmt->relation->inhOpt),
581
												(List *) stmt->def);
582 583
						break;
					case 'X':	/* DROP CONSTRAINT */
Bruce Momjian's avatar
Bruce Momjian committed
584

Bruce Momjian's avatar
Bruce Momjian committed
585
						/*
Bruce Momjian's avatar
Bruce Momjian committed
586 587
						 * Recursively drop constraint from table and, if
						 * requested, from descendants
588
						 */
589
						AlterTableDropConstraint(relid,
Bruce Momjian's avatar
Bruce Momjian committed
590
							  interpretInhOption(stmt->relation->inhOpt),
591 592
												 stmt->name,
												 stmt->behavior);
593
						break;
Jan Wieck's avatar
TOAST  
Jan Wieck committed
594
					case 'E':	/* CREATE TOAST TABLE */
595
						AlterTableCreateToastTable(relid, false);
Jan Wieck's avatar
TOAST  
Jan Wieck committed
596
						break;
597
					case 'U':	/* ALTER OWNER */
598 599
						/* check that we are the superuser */
						if (!superuser())
600
							ereport(ERROR,
Bruce Momjian's avatar
Bruce Momjian committed
601 602
								(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
							errmsg("must be superuser to alter owner")));
603
						/* get_usesysid raises an error if no such user */
604
						AlterTableOwner(relid,
605
										get_usesysid(stmt->name));
606
						break;
607 608 609
					case 'L':	/* CLUSTER ON */
						AlterTableClusterOn(relid, stmt->name);
						break;
Bruce Momjian's avatar
Bruce Momjian committed
610
					case 'o':	/* ADD OIDS */
Bruce Momjian's avatar
Bruce Momjian committed
611
						AlterTableAlterOids(relid,
Bruce Momjian's avatar
Bruce Momjian committed
612
							  interpretInhOption(stmt->relation->inhOpt),
Bruce Momjian's avatar
Bruce Momjian committed
613 614
											false);
						break;
615
					default:	/* oops */
616 617
						elog(ERROR, "unrecognized alter table type: %d",
							 (int) stmt->subtype);
618 619 620 621
						break;
				}
			}
			break;
622

623 624 625 626 627 628 629 630 631 632
		case T_AlterDomainStmt:
			{
				AlterDomainStmt *stmt = (AlterDomainStmt *) parsetree;

				/*
				 * Some or all of these functions are recursive to cover
				 * inherited things, so permission checks are done there.
				 */
				switch (stmt->subtype)
				{
633
					case 'T':	/* ALTER DOMAIN DEFAULT */
634 635 636 637 638 639 640 641

						/*
						 * Recursively alter column default for table and,
						 * if requested, for descendants
						 */
						AlterDomainDefault(stmt->typename,
										   stmt->def);
						break;
642
					case 'N':	/* ALTER DOMAIN DROP NOT NULL */
643 644 645
						AlterDomainNotNull(stmt->typename,
										   false);
						break;
646
					case 'O':	/* ALTER DOMAIN SET NOT NULL */
647 648 649 650 651 652 653 654 655 656 657 658
						AlterDomainNotNull(stmt->typename,
										   true);
						break;
					case 'C':	/* ADD CONSTRAINT */
						AlterDomainAddConstraint(stmt->typename,
												 stmt->def);
						break;
					case 'X':	/* DROP CONSTRAINT */
						AlterDomainDropConstraint(stmt->typename,
												  stmt->name,
												  stmt->behavior);
						break;
659 660 661
					case 'U':	/* OWNER TO */
						/* check that we are the superuser */
						if (!superuser())
662
							ereport(ERROR,
Bruce Momjian's avatar
Bruce Momjian committed
663 664
								(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
							errmsg("must be superuser to alter owner")));
665 666 667 668
						/* get_usesysid raises an error if no such user */
						AlterTypeOwner(stmt->typename,
									   get_usesysid(stmt->name));
						break;
669
					default:	/* oops */
670 671
						elog(ERROR, "unrecognized alter domain type: %d",
							 (int) stmt->subtype);
672 673 674 675 676
						break;
				}
			}
			break;

677

678
		case T_GrantStmt:
679
			ExecuteGrantStmt((GrantStmt *) parsetree);
680
			break;
681

682 683 684 685 686 687 688 689
			/*
			 * ******************************** object creation /
			 * destruction ********************************
			 *
			 */
		case T_DefineStmt:
			{
				DefineStmt *stmt = (DefineStmt *) parsetree;
690

691
				switch (stmt->kind)
692
				{
693
					case OBJECT_AGGREGATE:
694 695
						DefineAggregate(stmt->defnames, stmt->definition);
						break;
696
					case OBJECT_OPERATOR:
697
						DefineOperator(stmt->defnames, stmt->definition);
698
						break;
699
					case OBJECT_TYPE:
700
						DefineType(stmt->defnames, stmt->definition);
701
						break;
702
					default:
703 704 705
						elog(ERROR, "unrecognized define stmt type: %d",
							 (int) stmt->kind);
						break;
706 707
				}
			}
708 709
			break;

Bruce Momjian's avatar
Bruce Momjian committed
710 711
		case T_CompositeTypeStmt:		/* CREATE TYPE (composite) */
			{
Bruce Momjian's avatar
Bruce Momjian committed
712
				CompositeTypeStmt *stmt = (CompositeTypeStmt *) parsetree;
Bruce Momjian's avatar
Bruce Momjian committed
713

714
				DefineCompositeType(stmt->typevar, stmt->coldeflist);
Bruce Momjian's avatar
Bruce Momjian committed
715 716 717
			}
			break;

718 719 720
		case T_ViewStmt:		/* CREATE VIEW */
			{
				ViewStmt   *stmt = (ViewStmt *) parsetree;
721

722
				DefineView(stmt->view, stmt->query, stmt->replace);
723 724
			}
			break;
725

Bruce Momjian's avatar
Bruce Momjian committed
726
		case T_CreateFunctionStmt:		/* CREATE FUNCTION */
727
			CreateFunction((CreateFunctionStmt *) parsetree);
728
			break;
729

730 731 732
		case T_IndexStmt:		/* CREATE INDEX */
			{
				IndexStmt  *stmt = (IndexStmt *) parsetree;
733

734
				CheckRelationOwnership(stmt->relation, true);
735

Bruce Momjian's avatar
Bruce Momjian committed
736 737 738 739
				DefineIndex(stmt->relation,		/* relation */
							stmt->idxname,		/* index name */
							stmt->accessMethod, /* am name */
							stmt->indexParams,	/* parameters */
740
							stmt->unique,
741
							stmt->primary,
742
							stmt->isconstraint,
743 744 745 746
							(Expr *) stmt->whereClause,
							stmt->rangetable);
			}
			break;
747

748
		case T_RuleStmt:		/* CREATE RULE */
749
			DefineQueryRewrite((RuleStmt *) parsetree);
750 751 752 753 754
			break;

		case T_CreateSeqStmt:
			DefineSequence((CreateSeqStmt *) parsetree);
			break;
755

Bruce Momjian's avatar
Bruce Momjian committed
756 757 758 759
		case T_AlterSeqStmt:
			AlterSequence((AlterSeqStmt *) parsetree);
			break;

760
		case T_RemoveAggrStmt:
761
			RemoveAggregate((RemoveAggrStmt *) parsetree);
762
			break;
763

764
		case T_RemoveFuncStmt:
765
			RemoveFunction((RemoveFuncStmt *) parsetree);
766
			break;
767

768
		case T_RemoveOperStmt:
769
			RemoveOperator((RemoveOperStmt *) parsetree);
770
			break;
771

772
		case T_CreatedbStmt:
773
			createdb((CreatedbStmt *) parsetree);
774 775
			break;

776
		case T_AlterDatabaseSetStmt:
777
			AlterDatabaseSet((AlterDatabaseSetStmt *) parsetree);
778 779
			break;

780
		case T_DropdbStmt:
781
			{
782
				DropdbStmt *stmt = (DropdbStmt *) parsetree;
783

784
				dropdb(stmt->dbname);
785 786
			}
			break;
787

788 789 790 791
			/* Query-level asynchronous notification */
		case T_NotifyStmt:
			{
				NotifyStmt *stmt = (NotifyStmt *) parsetree;
792

793
				Async_Notify(stmt->relation->relname);
794 795
			}
			break;
796

797 798 799
		case T_ListenStmt:
			{
				ListenStmt *stmt = (ListenStmt *) parsetree;
800

801
				Async_Listen(stmt->relation->relname, MyProcPid);
802 803
			}
			break;
804

805 806 807 808
		case T_UnlistenStmt:
			{
				UnlistenStmt *stmt = (UnlistenStmt *) parsetree;

809
				Async_Unlisten(stmt->relation->relname, MyProcPid);
810 811 812
			}
			break;

813 814 815 816
		case T_LoadStmt:
			{
				LoadStmt   *stmt = (LoadStmt *) parsetree;

Bruce Momjian's avatar
Bruce Momjian committed
817
				closeAllVfds(); /* probably not necessary... */
818
				load_file(stmt->filename);
819 820
			}
			break;
821

822
		case T_ClusterStmt:
823
			cluster((ClusterStmt *) parsetree);
824 825 826
			break;

		case T_VacuumStmt:
827
			vacuum((VacuumStmt *) parsetree);
828 829 830
			break;

		case T_ExplainStmt:
831
			ExplainQuery((ExplainStmt *) parsetree, dest);
832
			break;
833

834 835 836 837
		case T_VariableSetStmt:
			{
				VariableSetStmt *n = (VariableSetStmt *) parsetree;

838
				/*
Bruce Momjian's avatar
Bruce Momjian committed
839 840
				 * Special cases for special SQL syntax that effectively
				 * sets more than one variable per statement.
841
				 */
Bruce Momjian's avatar
Bruce Momjian committed
842
				if (strcmp(n->name, "TRANSACTION") == 0)
843
				{
Bruce Momjian's avatar
Bruce Momjian committed
844
					List	   *head;
845 846 847

					foreach(head, n->args)
					{
Bruce Momjian's avatar
Bruce Momjian committed
848
						DefElem    *item = (DefElem *) lfirst(head);
849

Bruce Momjian's avatar
Bruce Momjian committed
850
						if (strcmp(item->defname, "transaction_isolation") == 0)
851
							SetPGVariable("transaction_isolation",
Bruce Momjian's avatar
Bruce Momjian committed
852 853
									  makeList1(item->arg), n->is_local);
						else if (strcmp(item->defname, "transaction_read_only") == 0)
854
							SetPGVariable("transaction_read_only",
Bruce Momjian's avatar
Bruce Momjian committed
855
									  makeList1(item->arg), n->is_local);
856 857
					}
				}
Bruce Momjian's avatar
Bruce Momjian committed
858
				else if (strcmp(n->name, "SESSION CHARACTERISTICS") == 0)
859
				{
Bruce Momjian's avatar
Bruce Momjian committed
860
					List	   *head;
861 862 863

					foreach(head, n->args)
					{
Bruce Momjian's avatar
Bruce Momjian committed
864
						DefElem    *item = (DefElem *) lfirst(head);
865

Bruce Momjian's avatar
Bruce Momjian committed
866
						if (strcmp(item->defname, "transaction_isolation") == 0)
867
							SetPGVariable("default_transaction_isolation",
Bruce Momjian's avatar
Bruce Momjian committed
868 869
									  makeList1(item->arg), n->is_local);
						else if (strcmp(item->defname, "transaction_read_only") == 0)
870
							SetPGVariable("default_transaction_read_only",
Bruce Momjian's avatar
Bruce Momjian committed
871
									  makeList1(item->arg), n->is_local);
872 873 874 875
					}
				}
				else
					SetPGVariable(n->name, n->args, n->is_local);
876 877 878 879 880 881 882
			}
			break;

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

883
				GetPGVariable(n->name, dest);
884 885 886 887 888 889 890 891 892 893 894 895
			}
			break;

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

				ResetPGVariable(n->name);
			}
			break;

		case T_CreateTrigStmt:
896
			CreateTrigger((CreateTrigStmt *) parsetree, false);
897 898
			break;

899
		case T_DropPropertyStmt:
900
			{
901
				DropPropertyStmt *stmt = (DropPropertyStmt *) parsetree;
Bruce Momjian's avatar
Bruce Momjian committed
902
				Oid			relId;
903

904 905 906 907
				relId = RangeVarGetRelid(stmt->relation, false);

				switch (stmt->removeType)
				{
908
					case OBJECT_RULE:
909
						/* RemoveRewriteRule checks permissions */
910 911
						RemoveRewriteRule(relId, stmt->property,
										  stmt->behavior);
912
						break;
913
					case OBJECT_TRIGGER:
914
						/* DropTrigger checks permissions */
915 916
						DropTrigger(relId, stmt->property,
									stmt->behavior);
917
						break;
918
					default:
919 920 921
						elog(ERROR, "unrecognized object type: %d",
							 (int) stmt->removeType);
						break;
922
				}
923
			}
924 925
			break;

926 927 928 929 930 931 932 933
		case T_CreatePLangStmt:
			CreateProceduralLanguage((CreatePLangStmt *) parsetree);
			break;

		case T_DropPLangStmt:
			DropProceduralLanguage((DropPLangStmt *) parsetree);
			break;

934 935 936 937 938 939 940 941 942 943
			/*
			 * ******************************** DOMAIN statements ****
			 */
		case T_CreateDomainStmt:
			DefineDomain((CreateDomainStmt *) parsetree);
			break;

			/*
			 * ******************************** USER statements ****
			 */
944
		case T_CreateUserStmt:
945
			CreateUser((CreateUserStmt *) parsetree);
946
			break;
947

948
		case T_AlterUserStmt:
949
			AlterUser((AlterUserStmt *) parsetree);
950
			break;
951

952 953 954 955
		case T_AlterUserSetStmt:
			AlterUserSet((AlterUserSetStmt *) parsetree);
			break;

956
		case T_DropUserStmt:
957
			DropUser((DropUserStmt *) parsetree);
958
			break;
959

960 961 962 963
		case T_LockStmt:
			LockTableCommand((LockStmt *) parsetree);
			break;

964 965 966 967
		case T_ConstraintsSetStmt:
			DeferredTriggerSetState((ConstraintsSetStmt *) parsetree);
			break;

968 969 970
		case T_CreateGroupStmt:
			CreateGroup((CreateGroupStmt *) parsetree);
			break;
971

972 973 974
		case T_AlterGroupStmt:
			AlterGroup((AlterGroupStmt *) parsetree, "ALTER GROUP");
			break;
975

976 977 978
		case T_DropGroupStmt:
			DropGroup((DropGroupStmt *) parsetree);
			break;
979

Vadim B. Mikheev's avatar
Vadim B. Mikheev committed
980
		case T_CheckPointStmt:
981
			if (!superuser())
982 983
				ereport(ERROR,
						(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
984
						 errmsg("must be superuser to do CHECKPOINT")));
985
			CreateCheckPoint(false, false);
Vadim B. Mikheev's avatar
Vadim B. Mikheev committed
986 987
			break;

Hiroshi Inoue's avatar
Hiroshi Inoue committed
988 989 990 991
		case T_ReindexStmt:
			{
				ReindexStmt *stmt = (ReindexStmt *) parsetree;

992
				switch (stmt->kind)
Hiroshi Inoue's avatar
Hiroshi Inoue committed
993
				{
994
					case OBJECT_INDEX:
995
						CheckRelationOwnership(stmt->relation, false);
996
						ReindexIndex(stmt->relation, stmt->force);
Hiroshi Inoue's avatar
Hiroshi Inoue committed
997
						break;
998
					case OBJECT_TABLE:
999
						CheckRelationOwnership(stmt->relation, false);
1000
						ReindexTable(stmt->relation, stmt->force);
Hiroshi Inoue's avatar
Hiroshi Inoue committed
1001
						break;
1002
					case OBJECT_DATABASE:
1003
						ReindexDatabase(stmt->name, stmt->force, false);
Hiroshi Inoue's avatar
Hiroshi Inoue committed
1004
						break;
1005
					default:
1006 1007 1008
						elog(ERROR, "unrecognized object type: %d",
							 (int) stmt->kind);
						break;
Hiroshi Inoue's avatar
Hiroshi Inoue committed
1009 1010 1011 1012
				}
				break;
			}
			break;
1013

1014
		case T_CreateConversionStmt:
1015
			CreateConversionCommand((CreateConversionStmt *) parsetree);
1016 1017
			break;

1018 1019 1020 1021 1022 1023 1024 1025
		case T_CreateCastStmt:
			CreateCast((CreateCastStmt *) parsetree);
			break;

		case T_DropCastStmt:
			DropCast((DropCastStmt *) parsetree);
			break;

1026 1027 1028 1029 1030 1031 1032 1033
		case T_CreateOpClassStmt:
			DefineOpClass((CreateOpClassStmt *) parsetree);
			break;

		case T_RemoveOpClassStmt:
			RemoveOpClass((RemoveOpClassStmt *) parsetree);
			break;

1034
		default:
1035 1036
			elog(ERROR, "unrecognized node type: %d",
				 (int) nodeTag(parsetree));
1037
			break;
1038
	}
1039
}
1040

1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055
/*
 * UtilityReturnsTuples
 *		Return "true" if this utility statement will send output to the
 *		destination.
 *
 * Generally, there should be a case here for each case in ProcessUtility
 * where "dest" is passed on.
 */
bool
UtilityReturnsTuples(Node *parsetree)
{
	switch (nodeTag(parsetree))
	{
		case T_FetchStmt:
			{
Bruce Momjian's avatar
Bruce Momjian committed
1056 1057
				FetchStmt  *stmt = (FetchStmt *) parsetree;
				Portal		portal;
1058 1059 1060 1061 1062

				if (stmt->ismove)
					return false;
				portal = GetPortalByName(stmt->portalname);
				if (!PortalIsValid(portal))
Bruce Momjian's avatar
Bruce Momjian committed
1063
					return false;		/* not our business to raise error */
1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075
				return portal->tupDesc ? true : false;
			}

		case T_ExecuteStmt:
			{
				ExecuteStmt *stmt = (ExecuteStmt *) parsetree;
				PreparedStatement *entry;

				if (stmt->into)
					return false;
				entry = FetchPreparedStatement(stmt->name, false);
				if (!entry)
Bruce Momjian's avatar
Bruce Momjian committed
1076
					return false;		/* not our business to raise error */
1077 1078 1079 1080 1081 1082 1083
				switch (ChoosePortalStrategy(entry->query_list))
				{
					case PORTAL_ONE_SELECT:
						return true;
					case PORTAL_UTIL_SELECT:
						return true;
					case PORTAL_MULTI_QUERY:
1084
						/* will not return tuples */
1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115
						break;
				}
				return false;
			}

		case T_ExplainStmt:
			return true;

		case T_VariableShowStmt:
			return true;

		default:
			return false;
	}
}

/*
 * UtilityTupleDescriptor
 *		Fetch the actual output tuple descriptor for a utility statement
 *		for which UtilityReturnsTuples() previously returned "true".
 *
 * The returned descriptor is created in (or copied into) the current memory
 * context.
 */
TupleDesc
UtilityTupleDescriptor(Node *parsetree)
{
	switch (nodeTag(parsetree))
	{
		case T_FetchStmt:
			{
Bruce Momjian's avatar
Bruce Momjian committed
1116 1117
				FetchStmt  *stmt = (FetchStmt *) parsetree;
				Portal		portal;
1118 1119 1120 1121 1122

				if (stmt->ismove)
					return NULL;
				portal = GetPortalByName(stmt->portalname);
				if (!PortalIsValid(portal))
Bruce Momjian's avatar
Bruce Momjian committed
1123
					return NULL;	/* not our business to raise error */
1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135
				return CreateTupleDescCopy(portal->tupDesc);
			}

		case T_ExecuteStmt:
			{
				ExecuteStmt *stmt = (ExecuteStmt *) parsetree;
				PreparedStatement *entry;

				if (stmt->into)
					return NULL;
				entry = FetchPreparedStatement(stmt->name, false);
				if (!entry)
Bruce Momjian's avatar
Bruce Momjian committed
1136
					return NULL;	/* not our business to raise error */
1137
				return FetchPreparedStatementResultDesc(entry);
1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154
			}

		case T_ExplainStmt:
			return ExplainResultDesc((ExplainStmt *) parsetree);

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

				return GetPGVariableResultDesc(n->name);
			}

		default:
			return NULL;
	}
}

1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249

/*
 * CreateCommandTag
 *		utility to get a string representation of the
 *		command operation, given a raw (un-analyzed) parsetree.
 *
 * This must handle all raw command types, but since the vast majority
 * of 'em are utility commands, it seems sensible to keep it here.
 *
 * NB: all result strings must be shorter than COMPLETION_TAG_BUFSIZE.
 * Also, the result must point at a true constant (permanent storage).
 */
const char *
CreateCommandTag(Node *parsetree)
{
	const char *tag;

	switch (nodeTag(parsetree))
	{
		case T_InsertStmt:
			tag = "INSERT";
			break;

		case T_DeleteStmt:
			tag = "DELETE";
			break;

		case T_UpdateStmt:
			tag = "UPDATE";
			break;

		case T_SelectStmt:
			tag = "SELECT";
			break;

		case T_TransactionStmt:
			{
				TransactionStmt *stmt = (TransactionStmt *) parsetree;

				switch (stmt->kind)
				{
					case TRANS_STMT_BEGIN:
						tag = "BEGIN";
						break;

					case TRANS_STMT_START:
						tag = "START TRANSACTION";
						break;

					case TRANS_STMT_COMMIT:
						tag = "COMMIT";
						break;

					case TRANS_STMT_ROLLBACK:
						tag = "ROLLBACK";
						break;

					default:
						tag = "???";
						break;
				}
			}
			break;

		case T_DeclareCursorStmt:
			tag = "DECLARE CURSOR";
			break;

		case T_ClosePortalStmt:
			tag = "CLOSE CURSOR";
			break;

		case T_FetchStmt:
			{
				FetchStmt  *stmt = (FetchStmt *) parsetree;

				tag = (stmt->ismove) ? "MOVE" : "FETCH";
			}
			break;

		case T_CreateDomainStmt:
			tag = "CREATE DOMAIN";
			break;

		case T_CreateSchemaStmt:
			tag = "CREATE SCHEMA";
			break;

		case T_CreateStmt:
			tag = "CREATE TABLE";
			break;

		case T_DropStmt:
			switch (((DropStmt *) parsetree)->removeType)
			{
1250
				case OBJECT_TABLE:
1251 1252
					tag = "DROP TABLE";
					break;
1253
				case OBJECT_SEQUENCE:
1254 1255
					tag = "DROP SEQUENCE";
					break;
1256
				case OBJECT_VIEW:
1257 1258
					tag = "DROP VIEW";
					break;
1259
				case OBJECT_INDEX:
1260 1261
					tag = "DROP INDEX";
					break;
1262
				case OBJECT_TYPE:
1263 1264
					tag = "DROP TYPE";
					break;
1265
				case OBJECT_DOMAIN:
1266 1267
					tag = "DROP DOMAIN";
					break;
1268
				case OBJECT_CONVERSION:
1269 1270
					tag = "DROP CONVERSION";
					break;
1271
				case OBJECT_SCHEMA:
1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291
					tag = "DROP SCHEMA";
					break;
				default:
					tag = "???";
			}
			break;

		case T_TruncateStmt:
			tag = "TRUNCATE TABLE";
			break;

		case T_CommentStmt:
			tag = "COMMENT";
			break;

		case T_CopyStmt:
			tag = "COPY";
			break;

		case T_RenameStmt:
1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326
			switch (((RenameStmt *) parsetree)->renameType)
			{
				case OBJECT_AGGREGATE:
					tag = "ALTER AGGREGATE";
					break;
				case OBJECT_CONVERSION:
					tag = "ALTER CONVERSION";
					break;
				case OBJECT_DATABASE:
					tag = "ALTER DATABASE";
					break;
				case OBJECT_FUNCTION:
					tag = "ALTER FUNCTION";
					break;
				case OBJECT_GROUP:
					tag = "ALTER GROUP";
					break;
				case OBJECT_LANGUAGE:
					tag = "ALTER LANGUAGE";
					break;
				case OBJECT_OPCLASS:
					tag = "ALTER OPERATOR CLASS";
					break;
				case OBJECT_SCHEMA:
					tag = "ALTER SCHEMA";
					break;
				case OBJECT_TRIGGER:
					tag = "ALTER TRIGGER";
					break;
				case OBJECT_USER:
					tag = "ALTER USER";
					break;
				default:
					tag = "ALTER TABLE";
			}
1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347
			break;

		case T_AlterTableStmt:
			tag = "ALTER TABLE";
			break;

		case T_AlterDomainStmt:
			tag = "ALTER DOMAIN";
			break;

		case T_GrantStmt:
			{
				GrantStmt  *stmt = (GrantStmt *) parsetree;

				tag = (stmt->is_grant) ? "GRANT" : "REVOKE";
			}
			break;

		case T_DefineStmt:
			switch (((DefineStmt *) parsetree)->kind)
			{
1348
				case OBJECT_AGGREGATE:
1349 1350
					tag = "CREATE AGGREGATE";
					break;
1351
				case OBJECT_OPERATOR:
1352 1353
					tag = "CREATE OPERATOR";
					break;
1354
				case OBJECT_TYPE:
1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463
					tag = "CREATE TYPE";
					break;
				default:
					tag = "???";
			}
			break;

		case T_CompositeTypeStmt:
			tag = "CREATE TYPE";
			break;

		case T_ViewStmt:
			tag = "CREATE VIEW";
			break;

		case T_CreateFunctionStmt:
			tag = "CREATE FUNCTION";
			break;

		case T_IndexStmt:
			tag = "CREATE INDEX";
			break;

		case T_RuleStmt:
			tag = "CREATE RULE";
			break;

		case T_CreateSeqStmt:
			tag = "CREATE SEQUENCE";
			break;

		case T_AlterSeqStmt:
			tag = "ALTER SEQUENCE";
			break;

		case T_RemoveAggrStmt:
			tag = "DROP AGGREGATE";
			break;

		case T_RemoveFuncStmt:
			tag = "DROP FUNCTION";
			break;

		case T_RemoveOperStmt:
			tag = "DROP OPERATOR";
			break;

		case T_CreatedbStmt:
			tag = "CREATE DATABASE";
			break;

		case T_AlterDatabaseSetStmt:
			tag = "ALTER DATABASE";
			break;

		case T_DropdbStmt:
			tag = "DROP DATABASE";
			break;

		case T_NotifyStmt:
			tag = "NOTIFY";
			break;

		case T_ListenStmt:
			tag = "LISTEN";
			break;

		case T_UnlistenStmt:
			tag = "UNLISTEN";
			break;

		case T_LoadStmt:
			tag = "LOAD";
			break;

		case T_ClusterStmt:
			tag = "CLUSTER";
			break;

		case T_VacuumStmt:
			if (((VacuumStmt *) parsetree)->vacuum)
				tag = "VACUUM";
			else
				tag = "ANALYZE";
			break;

		case T_ExplainStmt:
			tag = "EXPLAIN";
			break;

		case T_VariableSetStmt:
			tag = "SET";
			break;

		case T_VariableShowStmt:
			tag = "SHOW";
			break;

		case T_VariableResetStmt:
			tag = "RESET";
			break;

		case T_CreateTrigStmt:
			tag = "CREATE TRIGGER";
			break;

		case T_DropPropertyStmt:
			switch (((DropPropertyStmt *) parsetree)->removeType)
			{
1464
				case OBJECT_TRIGGER:
1465 1466
					tag = "DROP TRIGGER";
					break;
1467
				case OBJECT_RULE:
1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559
					tag = "DROP RULE";
					break;
				default:
					tag = "???";
			}
			break;

		case T_CreatePLangStmt:
			tag = "CREATE LANGUAGE";
			break;

		case T_DropPLangStmt:
			tag = "DROP LANGUAGE";
			break;

		case T_CreateUserStmt:
			tag = "CREATE USER";
			break;

		case T_AlterUserStmt:
			tag = "ALTER USER";
			break;

		case T_AlterUserSetStmt:
			tag = "ALTER USER";
			break;

		case T_DropUserStmt:
			tag = "DROP USER";
			break;

		case T_LockStmt:
			tag = "LOCK TABLE";
			break;

		case T_ConstraintsSetStmt:
			tag = "SET CONSTRAINTS";
			break;

		case T_CreateGroupStmt:
			tag = "CREATE GROUP";
			break;

		case T_AlterGroupStmt:
			tag = "ALTER GROUP";
			break;

		case T_DropGroupStmt:
			tag = "DROP GROUP";
			break;

		case T_CheckPointStmt:
			tag = "CHECKPOINT";
			break;

		case T_ReindexStmt:
			tag = "REINDEX";
			break;

		case T_CreateConversionStmt:
			tag = "CREATE CONVERSION";
			break;

		case T_CreateCastStmt:
			tag = "CREATE CAST";
			break;

		case T_DropCastStmt:
			tag = "DROP CAST";
			break;

		case T_CreateOpClassStmt:
			tag = "CREATE OPERATOR CLASS";
			break;

		case T_RemoveOpClassStmt:
			tag = "DROP OPERATOR CLASS";
			break;

		case T_PrepareStmt:
			tag = "PREPARE";
			break;

		case T_ExecuteStmt:
			tag = "EXECUTE";
			break;

		case T_DeallocateStmt:
			tag = "DEALLOCATE";
			break;

		default:
1560 1561
			elog(NOTICE, "unrecognized node type: %d",
				 (int) nodeTag(parsetree));
1562 1563 1564 1565 1566 1567
			tag = "???";
			break;
	}

	return tag;
}