heap.c 56.6 KB
Newer Older
1 2
/*-------------------------------------------------------------------------
 *
3
 * heap.c
4
 *	  code to create and destroy POSTGRES heap relations
5
 *
B
Add:  
Bruce Momjian 已提交
6 7
 * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
 * Portions Copyright (c) 1994, Regents of the University of California
8 9 10
 *
 *
 * IDENTIFICATION
11
 *	  $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.138 2000/07/04 06:11:23 tgl Exp $
12
 *
13 14
 *
 * INTERFACE ROUTINES
15
 *		heap_create()			- Create an uncataloged heap relation
16
 *		heap_create_with_catalog() - Create a cataloged relation
17
 *		heap_drop_with_catalog() - Removes named relation from catalogs
18 19
 *
 * NOTES
20
 *	  this code taken from access/heap/create.c, which contains
21
 *	  the old heap_create_with_catalog, amcreate, and amdestroy.
22 23
 *	  those routines will soon call these routines using the function
 *	  manager,
24 25 26
 *	  just like the poorly named "NewXXX" routines do.	The
 *	  "New" routines are all going to die soon, once and for all!
 *		-cim 1/13/91
27 28 29
 *
 *-------------------------------------------------------------------------
 */
B
Bruce Momjian 已提交
30 31 32
#include "postgres.h"

#include "access/heapam.h"
33
#include "access/genam.h"
B
Bruce Momjian 已提交
34 35 36 37 38 39 40
#include "catalog/catalog.h"
#include "catalog/catname.h"
#include "catalog/heap.h"
#include "catalog/index.h"
#include "catalog/indexing.h"
#include "catalog/pg_attrdef.h"
#include "catalog/pg_inherits.h"
B
Bruce Momjian 已提交
41
#include "catalog/pg_index.h"
B
Bruce Momjian 已提交
42
#include "catalog/pg_ipl.h"
43
#include "catalog/pg_proc.h"
B
Bruce Momjian 已提交
44
#include "catalog/pg_relcheck.h"
45
#include "catalog/pg_statistic.h"
46
#include "catalog/pg_type.h"
B
Hello.  
Bruce Momjian 已提交
47
#include "commands/comment.h"
B
Bruce Momjian 已提交
48
#include "commands/trigger.h"
49
#include "miscadmin.h"
50 51 52
#include "optimizer/clauses.h"
#include "optimizer/planmain.h"
#include "optimizer/var.h"
53
#include "nodes/makefuncs.h"
54
#include "parser/parse_clause.h"
B
Bruce Momjian 已提交
55
#include "parser/parse_expr.h"
56
#include "parser/parse_relation.h"
57
#include "parser/parse_target.h"
B
Bruce Momjian 已提交
58
#include "parser/parse_type.h"
B
Bruce Momjian 已提交
59 60 61
#include "rewrite/rewriteRemove.h"
#include "storage/smgr.h"
#include "utils/builtins.h"
62
#include "utils/catcache.h"
63
#include "utils/fmgroids.h"
B
Bruce Momjian 已提交
64
#include "utils/relcache.h"
65
#include "utils/syscache.h"
66
#include "utils/temprel.h"
B
Bruce Momjian 已提交
67

68

69
static void AddNewRelationTuple(Relation pg_class_desc,
70 71 72
					Relation new_rel_desc, Oid new_rel_oid,
					int natts,
					char relkind, char *temp_relname);
73 74 75
static void DeleteAttributeTuples(Relation rel);
static void DeleteRelationTuple(Relation rel);
static void DeleteTypeTuple(Relation rel);
76 77
static void RelationRemoveIndexes(Relation relation);
static void RelationRemoveInheritance(Relation relation);
78
static void AddNewRelationType(char *typeName, Oid new_rel_oid);
79
static void StoreAttrDefault(Relation rel, AttrNumber attnum, char *adbin,
80
				 bool updatePgAttribute);
81
static void StoreRelCheck(Relation rel, char *ccname, char *ccbin);
82 83
static void StoreConstraints(Relation rel);
static void RemoveConstraints(Relation rel);
84
static void RemoveStatistics(Relation rel);
85 86


87
/* ----------------------------------------------------------------
88
 *				XXX UGLY HARD CODED BADNESS FOLLOWS XXX
89
 *
90 91
 *		these should all be moved to someplace in the lib/catalog
 *		module, if not obliterated first.
92 93 94 95 96 97
 * ----------------------------------------------------------------
 */


/*
 * Note:
98 99 100 101
 *		Should the executor special case these attributes in the future?
 *		Advantage:	consume 1/2 the space in the ATTRIBUTE relation.
 *		Disadvantage:  having rules to compute values in these tuples may
 *				be more difficult if not impossible.
102 103
 */

104
static FormData_pg_attribute a1 = {
105
	0xffffffff, {"ctid"}, TIDOID, 0, sizeof(ItemPointerData),
106
	SelfItemPointerAttributeNumber, 0, -1, -1, '\0', 'p', '\0', 'i', '\0', '\0'
107 108
};

109
static FormData_pg_attribute a2 = {
110
	0xffffffff, {"oid"}, OIDOID, 0, sizeof(Oid),
111
	ObjectIdAttributeNumber, 0, -1, -1, '\001', 'p', '\0', 'i', '\0', '\0'
112 113
};

114
static FormData_pg_attribute a3 = {
115
	0xffffffff, {"xmin"}, XIDOID, 0, sizeof(TransactionId),
116
	MinTransactionIdAttributeNumber, 0, -1, -1, '\001', 'p', '\0', 'i', '\0', '\0'
117 118
};

119
static FormData_pg_attribute a4 = {
120
	0xffffffff, {"cmin"}, CIDOID, 0, sizeof(CommandId),
121
	MinCommandIdAttributeNumber, 0, -1, -1, '\001', 'p', '\0', 'i', '\0', '\0'
122 123
};

124
static FormData_pg_attribute a5 = {
125
	0xffffffff, {"xmax"}, XIDOID, 0, sizeof(TransactionId),
126
	MaxTransactionIdAttributeNumber, 0, -1, -1, '\001', 'p', '\0', 'i', '\0', '\0'
127 128
};

129
static FormData_pg_attribute a6 = {
130
	0xffffffff, {"cmax"}, CIDOID, 0, sizeof(CommandId),
131
	MaxCommandIdAttributeNumber, 0, -1, -1, '\001', 'p', '\0', 'i', '\0', '\0'
132 133
};

134 135 136 137 138 139 140 141 142 143 144 145
/* 
   We decide to call this attribute "tableoid" rather than say
"classoid" on the basis that in the future there may be more than one
table of a particular class/type. In any case table is still the word
used in SQL. 
*/
static FormData_pg_attribute a7 = {
	0xffffffff, {"tableoid"}, OIDOID, 0, sizeof(Oid),
	TableOidAttributeNumber, 0, -1, -1, '\001', 'p', '\0', 'i', '\0', '\0'
};

static Form_pg_attribute HeapAtt[] = {&a1, &a2, &a3, &a4, &a5, &a6, &a7};
146 147

/* ----------------------------------------------------------------
148
 *				XXX END OF UGLY HARD CODED BADNESS XXX
149
 * ---------------------------------------------------------------- */
150 151 152


/* ----------------------------------------------------------------
153
 *		heap_create		- Create an uncataloged heap relation
154
 *
155
 *		Fields relpages, reltuples, reltuples, relkeys, relhistory,
156
 *		relisindexed, and relkind of rel->rd_rel are initialized
157
 *		to all zeros, as are rd_last and rd_hook.  Rd_refcnt is set to 1.
158
 *
159 160 161 162
 *		Remove the system relation specific code to elsewhere eventually.
 *
 *		Eventually, must place information about this temporary relation
 *		into the transaction context block.
163
 *
164 165
 * NOTE: if istemp is TRUE then heap_create will overwrite relname with
 * the unique "real" name chosen for the temp relation.
166
 *
167 168
 * If storage_create is TRUE then heap_storage_create is called here,
 * else caller must call heap_storage_create later.
169 170 171
 * ----------------------------------------------------------------
 */
Relation
172 173
heap_create(char *relname,
			TupleDesc tupDesc,
174
			bool istemp,
175 176
			bool storage_create,
			bool allow_system_table_mods)
177
{
178 179
	static unsigned int uniqueId = 0;

180
	Oid			relid;
181
	Relation	rel;
182 183
	bool		nailme = false;
	int			natts = tupDesc->natts;
184
	int			i;
185
	MemoryContext oldcxt;
186 187 188 189 190 191 192

	/* ----------------
	 *	sanity checks
	 * ----------------
	 */
	AssertArg(natts > 0);

193
	if (relname && !allow_system_table_mods &&
194
		IsSystemRelationName(relname) && IsNormalProcessingMode())
195
	{
T
Thomas G. Lockhart 已提交
196 197
		elog(ERROR, "Illegal class name '%s'"
			 "\n\tThe 'pg_' name prefix is reserved for system catalogs",
198 199 200 201 202 203 204 205
			 relname);
	}

	/* ----------------
	 *	real ugly stuff to assign the proper relid in the relation
	 *	descriptor follows.
	 * ----------------
	 */
206
	if (relname && strcmp(RelationRelationName, relname) == 0)
207 208 209
	{
		relid = RelOid_pg_class;
		nailme = true;
210
	}
211
	else if (relname && strcmp(AttributeRelationName, relname) == 0)
212
	{
213 214
		relid = RelOid_pg_attribute;
		nailme = true;
215
	}
216
	else if (relname && strcmp(ProcedureRelationName, relname) == 0)
217
	{
218 219
		relid = RelOid_pg_proc;
		nailme = true;
220
	}
221
	else if (relname && strcmp(TypeRelationName, relname) == 0)
222
	{
223 224
		relid = RelOid_pg_type;
		nailme = true;
225
	}
226 227 228
	else
		relid = newoid();

229 230
	if (istemp)
	{
231 232 233
		/* replace relname of caller with a unique name for a temp relation */
		snprintf(relname, NAMEDATALEN, "pg_temp.%d.%u",
				 (int) MyProcPid, uniqueId++);
234
	}
235

236 237 238 239 240 241 242 243 244
	/* ----------------
	 *	switch to the cache context to create the relcache entry.
	 * ----------------
	 */
	if (!CacheMemoryContext)
		CreateCacheMemoryContext();

	oldcxt = MemoryContextSwitchTo(CacheMemoryContext);

245 246 247 248
	/* ----------------
	 *	allocate a new relation descriptor.
	 * ----------------
	 */
249 250
	rel = (Relation) palloc(sizeof(RelationData));
	MemSet((char *) rel, 0, sizeof(RelationData));
251
	rel->rd_fd = -1;			/* table is not open */
252
	rel->rd_unlinked = true;	/* table is not created yet */
253

254 255
	RelationSetReferenceCount(rel, 1);

256 257
	/*
	 * create a new tuple descriptor from the one passed in
B
Bruce Momjian 已提交
258
	 */
259
	rel->rd_att = CreateTupleDescCopyConstr(tupDesc);
260 261 262 263 264 265 266 267

	/* ----------------
	 *	nail the reldesc if this is a bootstrap create reln and
	 *	we may need it in the cache later on in the bootstrap
	 *	process so we don't ever want it kicked out.  e.g. pg_attribute!!!
	 * ----------------
	 */
	if (nailme)
268
		rel->rd_isnailed = true;
269

270 271 272 273
	/* ----------------
	 *	initialize the fields of our new relation descriptor
	 * ----------------
	 */
274
	rel->rd_rel = (Form_pg_class) palloc(sizeof *rel->rd_rel);
275
	MemSet((char *) rel->rd_rel, 0, sizeof *rel->rd_rel);
276
	strcpy(RelationGetPhysicalRelationName(rel), relname);
277 278
	rel->rd_rel->relkind = RELKIND_UNCATALOGED;
	rel->rd_rel->relnatts = natts;
279
	if (tupDesc->constr)
280
		rel->rd_rel->relchecks = tupDesc->constr->num_check;
281 282

	for (i = 0; i < natts; i++)
283
		rel->rd_att->attrs[i]->attrelid = relid;
284

285
	RelationGetRelid(rel) = relid;
286 287 288 289

	if (nailme)
	{
		/* for system relations, set the reltype field here */
290
		rel->rd_rel->reltype = relid;
291 292
	}

293 294 295 296 297 298
	/* ----------------
	 *	done building relcache entry.
	 * ----------------
	 */
	MemoryContextSwitchTo(oldcxt);

299 300 301 302 303
	/* ----------------
	 *	have the storage manager create the relation.
	 * ----------------
	 */

304 305 306
	/* smgrcreate() is moved to heap_storage_create() */
	if (storage_create)
		heap_storage_create(rel);
307

308
	RelationRegisterRelation(rel);
309

310
	return rel;
311 312
}

313 314 315
bool
heap_storage_create(Relation rel)
{
316
	bool		smgrcall = false;
317 318 319 320

	if (rel->rd_unlinked)
	{
		rel->rd_fd = (File) smgrcreate(DEFAULT_SMGR, rel);
321
		rel->rd_unlinked = false;
322 323 324 325
		smgrcall = true;
	}
	return smgrcall;
}
326 327

/* ----------------------------------------------------------------
328
 *		heap_create_with_catalog		- Create a cataloged relation
329
 *
330
 *		this is done in 6 steps:
331
 *
332 333
 *		1) CheckAttributeNames() is used to make certain the tuple
 *		   descriptor contains a valid set of attribute names
334
 *
335
 *		2) pg_class is opened and RelationFindRelid()
336
 *		   performs a scan to ensure that no relation with the
337
 *		   same name already exists.
338
 *
339
 *		3) heap_create_with_catalog() is called to create the new relation
340
 *		   on disk.
341
 *
342 343
 *		4) TypeDefine() is called to define a new type corresponding
 *		   to the new relation.
344
 *
345 346
 *		5) AddNewAttributeTuples() is called to register the
 *		   new relation's schema in pg_attribute.
347
 *
348
 *		6) AddNewRelationTuple() is called to register the
349
 *		   relation itself in the catalogs.
350
 *
351 352 353 354
 *		7) StoreConstraints is called ()		- vadim 08/22/97
 *
 *		8) the relations are closed and the new relation's oid
 *		   is returned.
355 356
 *
 * old comments:
357 358 359 360 361 362 363 364 365 366 367 368 369 370
 *		A new relation is inserted into the RELATION relation
 *		with the specified attribute(s) (newly inserted into
 *		the ATTRIBUTE relation).  How does concurrency control
 *		work?  Is it automatic now?  Expects the caller to have
 *		attname, atttypid, atttyparg, attproc, and attlen domains filled.
 *		Create fills the attnum domains sequentually from zero,
 *		fills the attdisbursion domains with zeros, and fills the
 *		attrelid fields with the relid.
 *
 *		scan relation catalog for name conflict
 *		scan type catalog for typids (if not arg)
 *		create and insert attribute(s) into attribute catalog
 *		create new relation
 *		insert new relation into attribute catalog
371
 *
372
 *		Should coordinate with heap_create_with_catalog(). Either
373
 *		it should not be called or there should be a way to prevent
374 375 376 377
 *		the relation from being removed at the end of the
 *		transaction if it is successful ('u'/'r' may be enough).
 *		Also, if the transaction does not commit, then the
 *		relation should be removed.
378
 *
379 380
 *		XXX amcreate ignores "off" when inserting (for now).
 *		XXX amcreate (like the other utilities) needs to understand indexes.
381 382 383 384 385
 *
 * ----------------------------------------------------------------
 */

/* --------------------------------
386
 *		CheckAttributeNames
387
 *
388 389
 *		this is used to make certain the tuple descriptor contains a
 *		valid set of attribute names.  a problem simply generates
B
Bruce Momjian 已提交
390
 *		elog(ERROR) which aborts the current transaction.
391 392 393 394 395
 * --------------------------------
 */
static void
CheckAttributeNames(TupleDesc tupdesc)
{
396 397
	int			i;
	int			j;
398
	int			natts = tupdesc->natts;
399 400 401 402 403 404 405 406 407

	/* ----------------
	 *	first check for collision with system attribute names
	 * ----------------
	 *
	 *	 also, warn user if attribute to be created has
	 *	 an unknown typid  (usually as a result of a 'retrieve into'
	 *	  - jolly
	 */
408
	for (i = 0; i < natts; i++)
409
	{
410
		for (j = 0; j < (int) (sizeof(HeapAtt) / sizeof(HeapAtt[0])); j++)
411 412 413 414
		{
			if (nameeq(&(HeapAtt[j]->attname),
					   &(tupdesc->attrs[i]->attname)))
			{
T
Thomas G. Lockhart 已提交
415 416
				elog(ERROR, "Attribute '%s' has a name conflict"
					 "\n\tName matches an existing system attribute",
417
					 NameStr(HeapAtt[j]->attname));
418 419 420 421
			}
		}
		if (tupdesc->attrs[i]->atttypid == UNKNOWNOID)
		{
T
Thomas G. Lockhart 已提交
422 423
			elog(NOTICE, "Attribute '%s' has an unknown type"
				 "\n\tRelation created; continue",
424
				 NameStr(tupdesc->attrs[i]->attname));
425
		}
426
	}
427 428 429 430 431

	/* ----------------
	 *	next check for repeated attribute names
	 * ----------------
	 */
432
	for (i = 1; i < natts; i++)
433
	{
434
		for (j = 0; j < i; j++)
435 436 437 438
		{
			if (nameeq(&(tupdesc->attrs[j]->attname),
					   &(tupdesc->attrs[i]->attname)))
			{
T
Thomas G. Lockhart 已提交
439
				elog(ERROR, "Attribute '%s' is repeated",
440
					 NameStr(tupdesc->attrs[j]->attname));
441 442
			}
		}
443 444 445 446
	}
}

/* --------------------------------
447
 *		RelnameFindRelid
448
 *
449
 *		Find any existing relation of the given name.
450 451
 * --------------------------------
 */
452
Oid
453
RelnameFindRelid(const char *relname)
454
{
455 456
	HeapTuple	tuple;
	Oid			relid;
457 458 459 460 461 462 463

	/*
	 * If this is not bootstrap (initdb) time, use the catalog index on
	 * pg_class.
	 */
	if (!IsBootstrapProcessingMode())
	{
464
		tuple = SearchSysCacheTuple(RELNAME,
B
Bruce Momjian 已提交
465 466
									PointerGetDatum(relname),
									0, 0, 0);
467 468
		if (HeapTupleIsValid(tuple))
			relid = tuple->t_data->t_oid;
469
		else
470
			relid = InvalidOid;
471
	}
472 473
	else
	{
B
Bruce Momjian 已提交
474
		Relation	pg_class_desc;
475 476
		ScanKeyData key;
		HeapScanDesc pg_class_scan;
B
Bruce Momjian 已提交
477

478
		pg_class_desc = heap_openr(RelationRelationName, AccessShareLock);
479 480 481 482 483 484 485 486 487 488 489

		/* ----------------
		 *	At bootstrap time, we have to do this the hard way.  Form the
		 *	scan key.
		 * ----------------
		 */
		ScanKeyEntryInitialize(&key,
							   0,
							   (AttrNumber) Anum_pg_class_relname,
							   (RegProcedure) F_NAMEEQ,
							   (Datum) relname);
B
Bruce Momjian 已提交
490

491 492 493 494 495 496 497 498 499
		/* ----------------
		 *	begin the scan
		 * ----------------
		 */
		pg_class_scan = heap_beginscan(pg_class_desc,
									   0,
									   SnapshotNow,
									   1,
									   &key);
B
Bruce Momjian 已提交
500

501 502 503 504 505 506
		/* ----------------
		 *	get a tuple.  if the tuple is NULL then it means we
		 *	didn't find an existing relation.
		 * ----------------
		 */
		tuple = heap_getnext(pg_class_scan, 0);
B
Bruce Momjian 已提交
507

508 509 510 511
		if (HeapTupleIsValid(tuple))
			relid = tuple->t_data->t_oid;
		else
			relid = InvalidOid;
512

513
		heap_endscan(pg_class_scan);
514

515
		heap_close(pg_class_desc, AccessShareLock);
516 517
	}
	return relid;
518 519 520
}

/* --------------------------------
521
 *		AddNewAttributeTuples
522
 *
523 524
 *		this registers the new relation's schema by adding
 *		tuples to pg_attribute.
525 526 527 528
 * --------------------------------
 */
static void
AddNewAttributeTuples(Oid new_rel_oid,
529
					  TupleDesc tupdesc)
530
{
531
	Form_pg_attribute *dpp;
532
	int			i;
533
	HeapTuple	tup;
534
	Relation	rel;
535 536 537
	bool		hasindex;
	Relation	idescs[Num_pg_attr_indices];
	int			natts = tupdesc->natts;
538 539 540 541 542

	/* ----------------
	 *	open pg_attribute
	 * ----------------
	 */
543
	rel = heap_openr(AttributeRelationName, RowExclusiveLock);
544 545 546 547 548

	/* -----------------
	 * Check if we have any indices defined on pg_attribute.
	 * -----------------
	 */
549
	hasindex = RelationGetForm(rel)->relhasindex;
550
	if (hasindex)
551 552 553
		CatalogOpenIndices(Num_pg_attr_indices, Name_pg_attr_indices, idescs);

	/* ----------------
554
	 *	initialize tuple descriptor.
555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572
	 * ----------------
	 */
	fillatt(tupdesc);

	/* ----------------
	 *	first we add the user attributes..
	 * ----------------
	 */
	dpp = tupdesc->attrs;
	for (i = 0; i < natts; i++)
	{
		(*dpp)->attrelid = new_rel_oid;
		(*dpp)->attdisbursion = 0;

		tup = heap_addheader(Natts_pg_attribute,
							 ATTRIBUTE_TUPLE_SIZE,
							 (char *) *dpp);

573
		heap_insert(rel, tup);
B
Bruce Momjian 已提交
574

575
		if (hasindex)
576
			CatalogIndexInsert(idescs, Num_pg_attr_indices, rel, tup);
577

578
		heap_freetuple(tup);
579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595
		dpp++;
	}

	/* ----------------
	 *	next we add the system attributes..
	 * ----------------
	 */
	dpp = HeapAtt;
	for (i = 0; i < -1 - FirstLowInvalidHeapAttributeNumber; i++)
	{
		(*dpp)->attrelid = new_rel_oid;
		/* (*dpp)->attdisbursion = 0;	   unneeded */

		tup = heap_addheader(Natts_pg_attribute,
							 ATTRIBUTE_TUPLE_SIZE,
							 (char *) *dpp);

596
		heap_insert(rel, tup);
597 598

		if (hasindex)
599
			CatalogIndexInsert(idescs, Num_pg_attr_indices, rel, tup);
600

601
		heap_freetuple(tup);
602 603 604
		dpp++;
	}

605
	heap_close(rel, RowExclusiveLock);
606 607 608 609

	/*
	 * close pg_attribute indices
	 */
610
	if (hasindex)
611
		CatalogCloseIndices(Num_pg_attr_indices, idescs);
612 613 614
}

/* --------------------------------
615
 *		AddNewRelationTuple
616
 *
617 618
 *		this registers the new relation in the catalogs by
 *		adding a tuple to pg_class.
619 620
 * --------------------------------
 */
621
static void
622
AddNewRelationTuple(Relation pg_class_desc,
B
Bruce Momjian 已提交
623 624
					Relation new_rel_desc,
					Oid new_rel_oid,
625
					int natts,
B
Bruce Momjian 已提交
626 627
					char relkind,
					char *temp_relname)
628
{
629 630 631
	Form_pg_class new_rel_reltup;
	HeapTuple	tup;
	Relation	idescs[Num_pg_class_indices];
632 633 634 635 636 637 638 639

	/* ----------------
	 *	first we munge some of the information in our
	 *	uncataloged relation's relation descriptor.
	 * ----------------
	 */
	new_rel_reltup = new_rel_desc->rd_rel;

640 641 642 643 644 645 646 647 648 649 650 651 652
	/* ----------------
	 * Here we insert bogus estimates of the size of the new relation.
	 * In reality, of course, the new relation has 0 tuples and pages,
	 * and if we were tracking these statistics accurately then we'd
	 * set the fields that way.  But at present the stats will be updated
	 * only by VACUUM or CREATE INDEX, and the user might insert a lot of
	 * tuples before he gets around to doing either of those.  So, instead
	 * of saying the relation is empty, we insert guesstimates.  The point
	 * is to keep the optimizer from making really stupid choices on
	 * never-yet-vacuumed tables; so the estimates need only be large
	 * enough to discourage the optimizer from using nested-loop plans.
	 * With this hack, nested-loop plans will be preferred only after
	 * the table has been proven to be small by VACUUM or CREATE INDEX.
653 654 655 656
	 * Maintaining the stats on-the-fly would solve the problem more cleanly,
	 * but the overhead of that would likely cost more than it'd save.
	 * (NOTE: CREATE INDEX inserts the same bogus estimates if it finds the
	 * relation has 0 rows and pages. See index.c.)
657 658
	 * ----------------
	 */
B
Bruce Momjian 已提交
659
	new_rel_reltup->relpages = 10;		/* bogus estimates */
660
	new_rel_reltup->reltuples = 1000;
661 662

	new_rel_reltup->relowner = GetUserId();
663
	new_rel_reltup->relkind = relkind;
664 665 666 667 668 669 670 671 672 673
	new_rel_reltup->relnatts = natts;

	/* ----------------
	 *	now form a tuple to add to pg_class
	 *	XXX Natts_pg_class_fixed is a hack - see pg_class.h
	 * ----------------
	 */
	tup = heap_addheader(Natts_pg_class_fixed,
						 CLASS_TUPLE_SIZE,
						 (char *) new_rel_reltup);
674
	tup->t_data->t_oid = new_rel_oid;
675

676 677
	/*
	 * finally insert the new tuple and free it.
678 679 680
	 */
	heap_insert(pg_class_desc, tup);

681 682
	if (temp_relname)
		create_temp_relation(temp_relname, tup);
B
Bruce Momjian 已提交
683

H
Hiroshi Inoue 已提交
684
	if (!IsIgnoringSystemIndexes())
685
	{
686

687 688 689 690 691 692 693 694
		/*
		 * First, open the catalog indices and insert index tuples for the
		 * new relation.
		 */
		CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, idescs);
		CatalogIndexInsert(idescs, Num_pg_class_indices, pg_class_desc, tup);
		CatalogCloseIndices(Num_pg_class_indices, idescs);
	}
B
Bruce Momjian 已提交
695

696
	heap_freetuple(tup);
697 698 699 700
}


/* --------------------------------
701
 *		AddNewRelationType -
702
 *
703
 *		define a complex type corresponding to the new relation
704 705
 * --------------------------------
 */
706
static void
707
AddNewRelationType(char *typeName, Oid new_rel_oid)
708
{
709
	Oid			new_type_oid;
710 711 712 713 714 715 716 717 718 719 720 721 722

	/*
	 * The sizes are set to oid size because it makes implementing sets
	 * MUCH easier, and no one (we hope) uses these fields to figure out
	 * how much space to allocate for the type. An oid is the type used
	 * for a set definition.  When a user requests a set, what they
	 * actually get is the oid of a tuple in the pg_proc catalog, so the
	 * size of the "set" is the size of an oid. Similarly, byval being
	 * true makes sets much easier, and it isn't used by anything else.
	 * Note the assumption that OIDs are the same size as int4s.
	 */
	new_type_oid = TypeCreate(typeName, /* type name */
							  new_rel_oid,		/* relation oid */
723 724
							  typeLen(typeidType(OIDOID)),		/* internal size */
							  typeLen(typeidType(OIDOID)),		/* external size */
725 726
							  'c',		/* type-type (catalog) */
							  ',',		/* default array delimiter */
727 728 729 730
							  "int4in", /* input procedure */
							  "int4out",		/* output procedure */
							  "int4in", /* receive procedure */
							  "int4out",		/* send procedure */
731 732 733
							  NULL,		/* array element type - irrelevent */
							  "-",		/* default type value */
							  (bool) 1, /* passed by value */
J
TOAST  
Jan Wieck 已提交
734 735
							  'i',		/* default alignment */
							  'p');		/* Not TOASTable */
736 737 738
}

/* --------------------------------
739
 *		heap_create_with_catalog
740
 *
741
 *		creates a new cataloged relation.  see comments above.
742 743 744
 * --------------------------------
 */
Oid
745 746
heap_create_with_catalog(char *relname,
						 TupleDesc tupdesc,
747
						 char relkind,
748 749
						 bool istemp,
						 bool allow_system_table_mods)
750
{
751 752 753 754
	Relation	pg_class_desc;
	Relation	new_rel_desc;
	Oid			new_rel_oid;
	int			natts = tupdesc->natts;
B
Bruce Momjian 已提交
755 756
	char	   *temp_relname = NULL;

757 758 759 760
	/* ----------------
	 *	sanity checks
	 * ----------------
	 */
761
	Assert(IsNormalProcessingMode() || IsBootstrapProcessingMode());
762
	if (natts <= 0 || natts > MaxHeapAttributeNumber)
T
Thomas G. Lockhart 已提交
763 764 765
		elog(ERROR, "Number of attributes is out of range"
			 "\n\tFrom 1 to %d attributes may be specified",
			 MaxHeapAttributeNumber);
766 767 768

	CheckAttributeNames(tupdesc);

769 770
	/* temp tables can mask non-temp tables */
	if ((!istemp && RelnameFindRelid(relname)) ||
771
		(istemp && get_temp_rel_by_username(relname) != NULL))
T
Thomas G. Lockhart 已提交
772
		elog(ERROR, "Relation '%s' already exists", relname);
773

774 775
	if (istemp)
	{
776
		/* save user relation name because heap_create changes it */
B
Bruce Momjian 已提交
777
		temp_relname = pstrdup(relname);		/* save original value */
778
		relname = palloc(NAMEDATALEN);
B
Bruce Momjian 已提交
779
		strcpy(relname, temp_relname);	/* heap_create will change this */
780
	}
B
Bruce Momjian 已提交
781

782
	/* ----------------
783
	 *	get_temp_rel_by_username() couldn't check the simultaneous
784 785
	 *	creation. Uniqueness will be really checked by unique
	 *	indexes of system tables but we couldn't check it here.
786
	 *	We have to postpone creating the disk file for this
787 788 789 790 791 792 793 794
	 *	relation.
	 *	Another boolean parameter "storage_create" was added
	 *	to heap_create() function. If the parameter is false
	 *	heap_create() only registers an uncataloged relation
	 *	to relation cache and heap_storage_create() should be
	 *	called later.
	 *	We could pull its relation oid from the newly formed
	 *	relation descriptor.
795
	 *
796
	 *	Note: The call to heap_create() changes relname for
797
	 *	temp tables; it becomes the true physical relname.
798 799
	 *	The call to heap_storage_create() does all the "real"
	 *	work of creating the disk file for the relation.
800 801
	 * ----------------
	 */
802 803
	new_rel_desc = heap_create(relname, tupdesc, istemp, false,
							   allow_system_table_mods);
804

805 806 807 808 809 810 811
	new_rel_oid = new_rel_desc->rd_att->attrs[0]->attrelid;

	/* ----------------
	 *	since defining a relation also defines a complex type,
	 *	we add a new system type corresponding to the new relation.
	 * ----------------
	 */
812
	AddNewRelationType(relname, new_rel_oid);
813 814 815 816 817 818 819 820 821 822 823 824

	/* ----------------
	 *	now add tuples to pg_attribute for the attributes in
	 *	our new relation.
	 * ----------------
	 */
	AddNewAttributeTuples(new_rel_oid, tupdesc);

	/* ----------------
	 *	now update the information in pg_class.
	 * ----------------
	 */
825
	pg_class_desc = heap_openr(RelationRelationName, RowExclusiveLock);
826 827

	AddNewRelationTuple(pg_class_desc,
B
Bruce Momjian 已提交
828 829 830 831 832
						new_rel_desc,
						new_rel_oid,
						natts,
						relkind,
						temp_relname);
833 834 835

	StoreConstraints(new_rel_desc);

836 837 838 839 840 841
	if (istemp)
	{
		pfree(relname);
		pfree(temp_relname);
	}

842 843 844 845
	/*
	 * We create the disk file for this relation here
	 */
	heap_storage_create(new_rel_desc);
846 847 848 849 850 851 852
	/* ----------------
	 *	ok, the relation has been cataloged, so close our relations
	 *	and return the oid of the newly created relation.
	 *
	 *	SOMEDAY: fill the STATISTIC relation properly.
	 * ----------------
	 */
853
	heap_close(new_rel_desc, NoLock);	/* do not unlock till end of xact */
854
	heap_close(pg_class_desc, RowExclusiveLock);
855 856

	return new_rel_oid;
857 858 859 860
}


/* ----------------------------------------------------------------
861
 *		heap_drop_with_catalog	- removes all record of named relation from catalogs
862
 *
863 864 865 866
 *		1)	open relation, check for existence, etc.
 *		2)	remove inheritance information
 *		3)	remove indexes
 *		4)	remove pg_class tuple
867
 *		5)	remove pg_attribute tuples and related descriptions
868
 *				6)		remove pg_description tuples
869 870 871
 *		7)	remove pg_type tuples
 *		8)	RemoveConstraints ()
 *		9)	unlink relation
872 873
 *
 * old comments
874 875 876
 *		Except for vital relations, removes relation from
 *		relation catalog, and related attributes from
 *		attribute catalog (needed?).  (Anything else?)
877
 *
878 879 880 881 882 883
 *		get proper relation from relation catalog (if not arg)
 *		check if relation is vital (strcmp()/reltype?)
 *		scan attribute catalog deleting attributes of reldesc
 *				(necessary?)
 *		delete relation from relation catalog
 *		(How are the tuples of the relation discarded?)
884
 *
885 886 887 888
 *		XXX Must fix to work with indexes.
 *		There may be a better order for doing things.
 *		Problems with destroying a deleted database--cannot create
 *		a struct reldesc without having an open file descriptor.
889 890 891 892
 * ----------------------------------------------------------------
 */

/* --------------------------------
893
 *		RelationRemoveInheritance
894
 *
895 896 897 898
 *		Note: for now, we cause an exception if relation is a
 *		superclass.  Someday, we may want to allow this and merge
 *		the type info into subclass procedures....	this seems like
 *		lots of work.
899 900
 * --------------------------------
 */
901
static void
902 903
RelationRemoveInheritance(Relation relation)
{
904 905 906 907
	Relation	catalogRelation;
	HeapTuple	tuple;
	HeapScanDesc scan;
	ScanKeyData entry;
908
	bool		found = false;
909

910 911 912 913
	/* ----------------
	 *	open pg_inherits
	 * ----------------
	 */
914
	catalogRelation = heap_openr(InheritsRelationName, RowExclusiveLock);
915 916 917 918 919 920 921

	/* ----------------
	 *	form a scan key for the subclasses of this class
	 *	and begin scanning
	 * ----------------
	 */
	ScanKeyEntryInitialize(&entry, 0x0, Anum_pg_inherits_inhparent,
B
Bruce Momjian 已提交
922
						   F_OIDEQ,
923
						   ObjectIdGetDatum(RelationGetRelid(relation)));
924 925 926

	scan = heap_beginscan(catalogRelation,
						  false,
927
						  SnapshotNow,
928 929 930 931 932 933 934
						  1,
						  &entry);

	/* ----------------
	 *	if any subclasses exist, then we disallow the deletion.
	 * ----------------
	 */
935
	tuple = heap_getnext(scan, 0);
936 937
	if (HeapTupleIsValid(tuple))
	{
938
		Oid			subclass = ((Form_pg_inherits) GETSTRUCT(tuple))->inhrelid;
939

940
		heap_endscan(scan);
941
		heap_close(catalogRelation, RowExclusiveLock);
942

943
		elog(ERROR, "Relation '%u' inherits '%s'",
944
			 subclass, RelationGetRelationName(relation));
945
	}
946
	heap_endscan(scan);
947 948 949 950 951 952

	/* ----------------
	 *	If we get here, it means the relation has no subclasses
	 *	so we can trash it.  First we remove dead INHERITS tuples.
	 * ----------------
	 */
953
	entry.sk_attno = Anum_pg_inherits_inhrelid;
954 955 956

	scan = heap_beginscan(catalogRelation,
						  false,
957
						  SnapshotNow,
958 959 960
						  1,
						  &entry);

961
	while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
962
	{
V
Vadim B. Mikheev 已提交
963
		heap_delete(catalogRelation, &tuple->t_self, NULL);
964
		found = true;
965 966
	}

967
	heap_endscan(scan);
968
	heap_close(catalogRelation, RowExclusiveLock);
969 970 971 972 973

	/* ----------------
	 *	now remove dead IPL tuples
	 * ----------------
	 */
974 975
	catalogRelation = heap_openr(InheritancePrecidenceListRelationName,
								 RowExclusiveLock);
976

977
	entry.sk_attno = Anum_pg_ipl_iplrelid;
978 979 980

	scan = heap_beginscan(catalogRelation,
						  false,
981
						  SnapshotNow,
982 983 984
						  1,
						  &entry);

985
	while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
V
Vadim B. Mikheev 已提交
986
		heap_delete(catalogRelation, &tuple->t_self, NULL);
987 988

	heap_endscan(scan);
989
	heap_close(catalogRelation, RowExclusiveLock);
990 991 992
}

/* --------------------------------
993 994
 *		RelationRemoveIndexes
 *
995 996
 * --------------------------------
 */
997
static void
998 999
RelationRemoveIndexes(Relation relation)
{
1000 1001 1002 1003
	Relation	indexRelation;
	HeapTuple	tuple;
	HeapScanDesc scan;
	ScanKeyData entry;
1004

1005
	indexRelation = heap_openr(IndexRelationName, RowExclusiveLock);
1006

1007
	ScanKeyEntryInitialize(&entry, 0x0, Anum_pg_index_indrelid,
B
Bruce Momjian 已提交
1008
						   F_OIDEQ,
1009
						   ObjectIdGetDatum(RelationGetRelid(relation)));
1010 1011 1012

	scan = heap_beginscan(indexRelation,
						  false,
1013
						  SnapshotNow,
1014 1015 1016
						  1,
						  &entry);

1017
	while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
1018
		index_drop(((Form_pg_index) GETSTRUCT(tuple))->indexrelid);
1019 1020

	heap_endscan(scan);
1021
	heap_close(indexRelation, RowExclusiveLock);
1022 1023 1024
}

/* --------------------------------
1025
 *		DeleteRelationTuple
1026 1027 1028
 *
 * --------------------------------
 */
1029
static void
1030
DeleteRelationTuple(Relation rel)
1031
{
1032 1033
	Relation	pg_class_desc;
	HeapTuple	tup;
1034 1035 1036 1037 1038

	/* ----------------
	 *	open pg_class
	 * ----------------
	 */
1039
	pg_class_desc = heap_openr(RelationRelationName, RowExclusiveLock);
1040

1041
	tup = SearchSysCacheTupleCopy(RELOID,
1042
								  ObjectIdGetDatum(rel->rd_id),
1043
								  0, 0, 0);
1044
	if (!HeapTupleIsValid(tup))
1045
	{
1046
		heap_close(pg_class_desc, RowExclusiveLock);
T
Thomas G. Lockhart 已提交
1047
		elog(ERROR, "Relation '%s' does not exist",
1048
			 RelationGetRelationName(rel));
1049 1050 1051 1052 1053 1054
	}

	/* ----------------
	 *	delete the relation tuple from pg_class, and finish up.
	 * ----------------
	 */
V
Vadim B. Mikheev 已提交
1055
	heap_delete(pg_class_desc, &tup->t_self, NULL);
1056
	heap_freetuple(tup);
1057

1058
	heap_close(pg_class_desc, RowExclusiveLock);
1059 1060
}

1061 1062 1063 1064 1065 1066
/* --------------------------------
 * RelationTruncateIndexes - This routine is used to truncate all
 * indices associated with the heap relation to zero tuples.
 * The routine will truncate and then reconstruct the indices on
 * the relation specified by the heapRelation parameter.
 * --------------------------------
1067 1068 1069 1070
 */
static void
RelationTruncateIndexes(Relation heapRelation)
{
1071 1072
	Relation	indexRelation,
				currentIndex;
1073 1074
	ScanKeyData entry;
	HeapScanDesc scan;
1075 1076 1077
	HeapTuple	indexTuple,
				procTuple,
				classTuple;
1078
	Form_pg_index index;
1079 1080 1081 1082 1083 1084 1085
	Oid			heapId,
				indexId,
				procId,
				accessMethodId;
	Node	   *oldPred = NULL;
	PredInfo   *predInfo;
	List	   *cnfPred = NULL;
1086
	AttrNumber *attributeNumberA;
1087 1088
	FuncIndexInfo fInfo,
			   *funcInfo = NULL;
1089
	bool		unique;
1090 1091 1092
	int			i,
				numberOfAttributes;
	char	   *predString;
1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103

	heapId = RelationGetRelid(heapRelation);

	/* Scan pg_index to find indexes on heapRelation */

	indexRelation = heap_openr(IndexRelationName, AccessShareLock);
	ScanKeyEntryInitialize(&entry, 0, Anum_pg_index_indrelid, F_OIDEQ,
						   ObjectIdGetDatum(heapId));
	scan = heap_beginscan(indexRelation, false, SnapshotNow, 1, &entry);
	while (HeapTupleIsValid(indexTuple = heap_getnext(scan, 0)))
	{
1104

1105
		/*
1106 1107
		 * For each index, fetch index attributes so we can apply
		 * index_build
1108 1109 1110 1111
		 */
		index = (Form_pg_index) GETSTRUCT(indexTuple);
		indexId = index->indexrelid;
		procId = index->indproc;
1112
		unique = index->indisunique;
1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123

		for (i = 0; i < INDEX_MAX_KEYS; i++)
		{
			if (index->indkey[i] == InvalidAttrNumber)
				break;
		}
		numberOfAttributes = i;

		/* If a valid where predicate, compute predicate Node */
		if (VARSIZE(&index->indpred) != 0)
		{
1124
			predString = textout(&index->indpred);
1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142
			oldPred = stringToNode(predString);
			pfree(predString);
		}
		predInfo = (PredInfo *) palloc(sizeof(PredInfo));
		predInfo->pred = (Node *) cnfPred;
		predInfo->oldPred = oldPred;

		/* Assign Index keys to attributes array */
		attributeNumberA = (AttrNumber *) palloc(numberOfAttributes *
												 sizeof(AttrNumber));
		for (i = 0; i < numberOfAttributes; i++)
			attributeNumberA[i] = index->indkey[i];

		/* If this is a procedural index, initialize our FuncIndexInfo */
		if (procId != InvalidOid)
		{
			funcInfo = &fInfo;
			FIsetnArgs(funcInfo, numberOfAttributes);
1143
			procTuple = SearchSysCacheTuple(PROCOID, ObjectIdGetDatum(procId),
1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165
											0, 0, 0);
			if (!HeapTupleIsValid(procTuple))
				elog(ERROR, "RelationTruncateIndexes: index procedure not found");
			namecpy(&(funcInfo->funcName),
					&(((Form_pg_proc) GETSTRUCT(procTuple))->proname));
			FIsetProcOid(funcInfo, procTuple->t_data->t_oid);
		}

		/* Fetch the classTuple associated with this index */
		classTuple = SearchSysCacheTupleCopy(RELOID, ObjectIdGetDatum(indexId),
											 0, 0, 0);
		if (!HeapTupleIsValid(classTuple))
			elog(ERROR, "RelationTruncateIndexes: index access method not found");
		accessMethodId = ((Form_pg_class) GETSTRUCT(classTuple))->relam;

		/* Open our index relation */
		currentIndex = index_open(indexId);
		if (currentIndex == NULL)
			elog(ERROR, "RelationTruncateIndexes: can't open index relation");

		/* Obtain exclusive lock on it, just to be sure */
		LockRelation(currentIndex, AccessExclusiveLock);
1166

1167
		/*
1168 1169
		 * Release any buffers associated with this index.	If they're
		 * dirty, they're just dropped without bothering to flush to disk.
1170 1171 1172 1173 1174 1175 1176 1177 1178 1179
		 */
		ReleaseRelationBuffers(currentIndex);

		/* Now truncate the actual data and set blocks to zero */
		smgrtruncate(DEFAULT_SMGR, currentIndex, 0);
		currentIndex->rd_nblocks = 0;

		/* Initialize the index and rebuild */
		InitIndexStrategy(numberOfAttributes, currentIndex, accessMethodId);
		index_build(heapRelation, currentIndex, numberOfAttributes,
1180
					attributeNumberA, funcInfo, predInfo, unique);
1181 1182

		/*
1183 1184 1185 1186 1187
		 * index_build will close both the heap and index relations (but
		 * not give up the locks we hold on them).	That's fine for the
		 * index, but we need to open the heap again.  We need no new
		 * lock, since this backend still has the exclusive lock grabbed
		 * by heap_truncate.
1188 1189 1190 1191
		 */
		heapRelation = heap_open(heapId, NoLock);
		Assert(heapRelation != NULL);
	}
1192

1193
	/* Complete the scan and close pg_index */
1194
	heap_endscan(scan);
1195
	heap_close(indexRelation, AccessShareLock);
1196 1197 1198
}

/* ----------------------------
1199
 *	 heap_truncate
1200
 *
1201 1202 1203
 *	 This routine is used to truncate the data from the
 *	 storage manager of any data within the relation handed
 *	 to this routine.
1204 1205 1206
 * ----------------------------
 */

1207 1208 1209
void
heap_truncate(char *relname)
{
1210 1211
	Relation	rel;
	Oid			rid;
1212 1213 1214 1215

	/* Open relation for processing, and grab exclusive access on it. */

	rel = heap_openr(relname, AccessExclusiveLock);
1216
	rid = RelationGetRelid(rel);
1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229

	/* ----------------
	 *	TRUNCATE TABLE within a transaction block is dangerous, because
	 *	if the transaction is later rolled back we have no way to
	 *	undo truncation of the relation's physical file.  For now, allow it
	 *	but emit a warning message.
	 *	Someday we might want to consider postponing the physical truncate
	 *	until transaction commit, but that's a lot of work...
	 *	The only case that actually works right is for relations created
	 *	in the current transaction, since the post-abort state would be that
	 *	they don't exist anyway.  So, no warning in that case.
	 * ----------------
	 */
1230
	if (IsTransactionBlock() && !rel->rd_myxactonly)
1231 1232 1233
		elog(NOTICE, "Caution: TRUNCATE TABLE cannot be rolled back, so don't abort now");

	/*
1234 1235
	 * Release any buffers associated with this relation.  If they're
	 * dirty, they're just dropped without bothering to flush to disk.
1236 1237 1238
	 */

	ReleaseRelationBuffers(rel);
1239

1240 1241 1242 1243 1244 1245
	/* Now truncate the actual data and set blocks to zero */

	smgrtruncate(DEFAULT_SMGR, rel, 0);
	rel->rd_nblocks = 0;

	/* If this relation has indexes, truncate the indexes too */
H
Hiroshi Inoue 已提交
1246
	RelationTruncateIndexes(rel);
1247 1248 1249 1250 1251 1252 1253 1254 1255 1256

	/*
	 * Close the relation, but keep exclusive lock on it until commit.
	 */
	heap_close(rel, NoLock);

	/*
	 * Is this really necessary?
	 */
	RelationForgetRelation(rid);
1257 1258 1259
}


1260
/* --------------------------------
1261
 *		DeleteAttributeTuples
1262 1263 1264
 *
 * --------------------------------
 */
1265
static void
1266
DeleteAttributeTuples(Relation rel)
1267
{
1268 1269
	Relation	pg_attribute_desc;
	HeapTuple	tup;
1270
	int2		attnum;
1271

1272 1273 1274 1275
	/* ----------------
	 *	open pg_attribute
	 * ----------------
	 */
1276
	pg_attribute_desc = heap_openr(AttributeRelationName, RowExclusiveLock);
1277

B
Bruce Momjian 已提交
1278
	for (attnum = FirstLowInvalidHeapAttributeNumber + 1;
1279 1280
		 attnum <= rel->rd_att->natts;
		 attnum++)
1281
	{
B
Bruce Momjian 已提交
1282
		if (HeapTupleIsValid(tup = SearchSysCacheTupleCopy(ATTNUM,
1283 1284
								 ObjectIdGetDatum(RelationGetRelid(rel)),
												   Int16GetDatum(attnum),
1285
														   0, 0)))
B
Bruce Momjian 已提交
1286
		{
1287

1288 1289 1290
			/*** Delete any comments associated with this attribute ***/

			DeleteComments(tup->t_data->t_oid);
1291

1292 1293
			heap_delete(pg_attribute_desc, &tup->t_self, NULL);
			heap_freetuple(tup);
1294

B
Hello.  
Bruce Momjian 已提交
1295 1296
		}
	}
1297

B
Hello.  
Bruce Momjian 已提交
1298
	heap_close(pg_attribute_desc, RowExclusiveLock);
1299 1300
}

1301
/* --------------------------------
1302
 *		DeleteTypeTuple
1303
 *
1304 1305 1306 1307
 *		If the user attempts to destroy a relation and there
 *		exists attributes in other relations of type
 *		"relation we are deleting", then we have to do something
 *		special.  presently we disallow the destroy.
1308 1309
 * --------------------------------
 */
1310
static void
1311
DeleteTypeTuple(Relation rel)
1312
{
1313 1314 1315 1316 1317 1318 1319 1320 1321
	Relation	pg_type_desc;
	HeapScanDesc pg_type_scan;
	Relation	pg_attribute_desc;
	HeapScanDesc pg_attribute_scan;
	ScanKeyData key;
	ScanKeyData attkey;
	HeapTuple	tup;
	HeapTuple	atttup;
	Oid			typoid;
1322 1323 1324 1325 1326

	/* ----------------
	 *	open pg_type
	 * ----------------
	 */
1327
	pg_type_desc = heap_openr(TypeRelationName, RowExclusiveLock);
1328 1329 1330 1331 1332 1333

	/* ----------------
	 *	create a scan key to locate the type tuple corresponding
	 *	to this relation.
	 * ----------------
	 */
B
Bruce Momjian 已提交
1334
	ScanKeyEntryInitialize(&key, 0,
1335 1336 1337
						   Anum_pg_type_typrelid,
						   F_OIDEQ,
						   ObjectIdGetDatum(RelationGetRelid(rel)));
1338 1339 1340

	pg_type_scan = heap_beginscan(pg_type_desc,
								  0,
1341
								  SnapshotNow,
1342 1343 1344 1345 1346 1347 1348 1349
								  1,
								  &key);

	/* ----------------
	 *	use heap_getnext() to fetch the pg_type tuple.	If this
	 *	tuple is not valid then something's wrong.
	 * ----------------
	 */
1350
	tup = heap_getnext(pg_type_scan, 0);
1351

1352
	if (!HeapTupleIsValid(tup))
1353 1354
	{
		heap_endscan(pg_type_scan);
1355
		heap_close(pg_type_desc, RowExclusiveLock);
1356
		elog(ERROR, "DeleteTypeTuple: %s type nonexistent",
1357
			 RelationGetRelationName(rel));
1358 1359 1360 1361 1362 1363 1364 1365 1366
	}

	/* ----------------
	 *	now scan pg_attribute.	if any other relations have
	 *	attributes of the type of the relation we are deleteing
	 *	then we have to disallow the deletion.	should talk to
	 *	stonebraker about this.  -cim 6/19/90
	 * ----------------
	 */
1367
	typoid = tup->t_data->t_oid;
1368

1369
	pg_attribute_desc = heap_openr(AttributeRelationName, RowExclusiveLock);
1370 1371

	ScanKeyEntryInitialize(&attkey,
B
Bruce Momjian 已提交
1372 1373 1374
						   0,
						   Anum_pg_attribute_atttypid,
						   F_OIDEQ,
1375 1376 1377 1378
						   typoid);

	pg_attribute_scan = heap_beginscan(pg_attribute_desc,
									   0,
1379
									   SnapshotNow,
1380 1381 1382 1383 1384
									   1,
									   &attkey);

	/* ----------------
	 *	try and get a pg_attribute tuple.  if we succeed it means
B
Bruce Momjian 已提交
1385
	 *	we can't delete the relation because something depends on
1386 1387 1388
	 *	the schema.
	 * ----------------
	 */
1389
	atttup = heap_getnext(pg_attribute_scan, 0);
1390

B
Bruce Momjian 已提交
1391
	if (HeapTupleIsValid(atttup))
1392
	{
1393
		Oid			relid = ((Form_pg_attribute) GETSTRUCT(atttup))->attrelid;
1394 1395

		heap_endscan(pg_attribute_scan);
1396 1397 1398
		heap_close(pg_attribute_desc, RowExclusiveLock);
		heap_endscan(pg_type_scan);
		heap_close(pg_type_desc, RowExclusiveLock);
1399

1400
		elog(ERROR, "DeleteTypeTuple: att of type %s exists in relation %u",
1401
			 RelationGetRelationName(rel), relid);
1402
	}
M
Marc G. Fournier 已提交
1403
	heap_endscan(pg_attribute_scan);
1404
	heap_close(pg_attribute_desc, RowExclusiveLock);
1405 1406 1407 1408 1409 1410 1411

	/* ----------------
	 *	Ok, it's safe so we delete the relation tuple
	 *	from pg_type and finish up.  But first end the scan so that
	 *	we release the read lock on pg_type.  -mer 13 Aug 1991
	 * ----------------
	 */
1412

V
Vadim B. Mikheev 已提交
1413
	heap_delete(pg_type_desc, &tup->t_self, NULL);
1414

1415
	heap_endscan(pg_type_scan);
1416
	heap_close(pg_type_desc, RowExclusiveLock);
M
Marc G. Fournier 已提交
1417 1418 1419
}

/* --------------------------------
1420
 *		heap_drop_with_catalog
M
Marc G. Fournier 已提交
1421 1422 1423 1424
 *
 * --------------------------------
 */
void
1425 1426
heap_drop_with_catalog(const char *relname,
					   bool allow_system_table_mods)
M
Marc G. Fournier 已提交
1427
{
1428
	Relation	rel;
1429
	Oid			rid;
1430
	bool		istemp = (get_temp_rel_by_username(relname) != NULL);
J
TOAST  
Jan Wieck 已提交
1431
	bool		has_toasttable;
1432 1433

	/* ----------------
1434
	 *	Open and lock the relation.
1435 1436
	 * ----------------
	 */
1437
	rel = heap_openr(relname, AccessExclusiveLock);
1438
	rid = RelationGetRelid(rel);
1439 1440 1441 1442 1443

	/* ----------------
	 *	prevent deletion of system relations
	 * ----------------
	 */
1444
	/* allow temp of pg_class? Guess so. */
1445
	if (!istemp && !allow_system_table_mods &&
1446
		IsSystemRelationName(RelationGetRelationName(rel)))
T
Thomas G. Lockhart 已提交
1447
		elog(ERROR, "System relation '%s' cannot be destroyed",
1448
			 RelationGetRelationName(rel));
1449

1450
	/* ----------------
1451 1452 1453 1454 1455 1456 1457 1458 1459
	 *	DROP TABLE within a transaction block is dangerous, because
	 *	if the transaction is later rolled back there will be no way to
	 *	undo the unlink of the relation's physical file.  For now, allow it
	 *	but emit a warning message.
	 *	Someday we might want to consider postponing the physical unlink
	 *	until transaction commit, but that's a lot of work...
	 *	The only case that actually works right is for relations created
	 *	in the current transaction, since the post-abort state would be that
	 *	they don't exist anyway.  So, no warning in that case.
1460 1461
	 * ----------------
	 */
1462
	if (IsTransactionBlock() && !rel->rd_myxactonly)
1463
		elog(NOTICE, "Caution: DROP TABLE cannot be rolled back, so don't abort now");
1464

1465 1466 1467 1468
	/* ----------------
	 *	remove inheritance information
	 * ----------------
	 */
1469
	RelationRemoveInheritance(rel);
1470 1471 1472 1473 1474

	/* ----------------
	 *	remove indexes if necessary
	 * ----------------
	 */
H
Hiroshi Inoue 已提交
1475 1476
	/* should ignore relhasindex */
	RelationRemoveIndexes(rel);
1477 1478 1479 1480 1481

	/* ----------------
	 *	remove rules if necessary
	 * ----------------
	 */
1482
	if (rel->rd_rules != NULL)
1483 1484 1485
		RelationRemoveRules(rid);

	/* triggers */
1486
	RelationRemoveTriggers(rel);
1487 1488 1489 1490 1491

	/* ----------------
	 *	delete attribute tuples
	 * ----------------
	 */
1492
	DeleteAttributeTuples(rel);
1493

1494
	/* ----------------
1495
	 *	delete comments, statistics, and constraints
1496 1497
	 * ----------------
	 */
1498 1499
	DeleteComments(RelationGetRelid(rel));

1500 1501
	RemoveStatistics(rel);

1502 1503
	RemoveConstraints(rel);

1504
	/* ----------------
1505
	 *	delete type tuple
1506 1507
	 * ----------------
	 */
1508
	DeleteTypeTuple(rel);
1509 1510 1511 1512 1513

	/* ----------------
	 *	delete relation tuple
	 * ----------------
	 */
1514
	DeleteRelationTuple(rel);
1515 1516

	/*
1517
	 * release dirty buffers of this relation; don't bother to write them
1518
	 */
1519
	ReleaseRelationBuffers(rel);
1520 1521

	/* ----------------
1522
	 *	unlink the relation's physical file and finish up.
1523 1524
	 * ----------------
	 */
1525
	if (! rel->rd_unlinked)
1526
		smgrunlink(DEFAULT_SMGR, rel);
1527
	rel->rd_unlinked = true;
1528

J
TOAST  
Jan Wieck 已提交
1529 1530 1531 1532 1533
	/*
	 * Remember if there is a toast relation for below
	 */
	has_toasttable = rel->rd_rel->reltoastrelid != InvalidOid;

1534 1535
	/*
	 * Close relcache entry, but *keep* AccessExclusiveLock on the
1536 1537
	 * relation until transaction commit.  This ensures no one else will
	 * try to do something with the doomed relation.
1538 1539
	 */
	heap_close(rel, NoLock);
1540

1541 1542 1543 1544
	/* ----------------
	 *	flush the relation from the relcache
	 * ----------------
	 */
1545
	RelationForgetRelation(rid);
1546 1547 1548

	if (istemp)
		remove_temp_relation(rid);
J
TOAST  
Jan Wieck 已提交
1549 1550 1551 1552 1553

	if (has_toasttable)
	{
		char	toast_relname[NAMEDATALEN];

1554 1555
		sprintf(toast_relname, "pg_toast_%u", rid);
		heap_drop_with_catalog(toast_relname, true);
J
TOAST  
Jan Wieck 已提交
1556
	}
M
Marc G. Fournier 已提交
1557 1558 1559
}


1560 1561 1562 1563 1564 1565
/*
 * Store a default expression for column attnum of relation rel.
 * The expression must be presented as a nodeToString() string.
 * If updatePgAttribute is true, update the pg_attribute entry
 * for the column to show that a default exists.
 */
1566
static void
1567 1568
StoreAttrDefault(Relation rel, AttrNumber attnum, char *adbin,
				 bool updatePgAttribute)
1569
{
1570
	Node	   *expr;
1571 1572
	RangeTblEntry *rte;
	char	   *adsrc;
1573 1574 1575 1576
	Relation	adrel;
	Relation	idescs[Num_pg_attrdef_indices];
	HeapTuple	tuple;
	Datum		values[4];
1577
	static char nulls[4] = {' ', ' ', ' ', ' '};
1578 1579 1580 1581
	Relation	attrrel;
	Relation	attridescs[Num_pg_attr_indices];
	HeapTuple	atttup;
	Form_pg_attribute attStruct;
B
Bruce Momjian 已提交
1582

1583 1584 1585
	/*
	 * Need to construct source equivalent of given node-string.
	 */
1586
	expr = stringToNode(adbin);
1587

1588 1589 1590 1591
	/*
	 * deparse_expression needs a RangeTblEntry list, so make one
	 */
	rte = makeNode(RangeTblEntry);
1592
	rte->relname = RelationGetRelationName(rel);
1593
#ifndef DISABLE_EREF
1594 1595
	rte->ref = makeNode(Attr);
	rte->ref->relname = RelationGetRelationName(rel);
1596
#endif
1597 1598 1599 1600 1601
	rte->relid = RelationGetRelid(rel);
	rte->inh = false;
	rte->inFromCl = true;
	rte->skipAcl = false;
	adsrc = deparse_expression(expr, lcons(lcons(rte, NIL), NIL), false);
1602

1603
	values[Anum_pg_attrdef_adrelid - 1] = RelationGetRelid(rel);
1604 1605 1606
	values[Anum_pg_attrdef_adnum - 1] = attnum;
	values[Anum_pg_attrdef_adbin - 1] = PointerGetDatum(textin(adbin));
	values[Anum_pg_attrdef_adsrc - 1] = PointerGetDatum(textin(adsrc));
1607
	adrel = heap_openr(AttrDefaultRelationName, RowExclusiveLock);
1608 1609
	tuple = heap_formtuple(adrel->rd_att, values, nulls);
	heap_insert(adrel, tuple);
1610 1611
	CatalogOpenIndices(Num_pg_attrdef_indices, Name_pg_attrdef_indices,
					   idescs);
1612 1613
	CatalogIndexInsert(idescs, Num_pg_attrdef_indices, adrel, tuple);
	CatalogCloseIndices(Num_pg_attrdef_indices, idescs);
1614
	heap_close(adrel, RowExclusiveLock);
1615 1616 1617

	pfree(DatumGetPointer(values[Anum_pg_attrdef_adbin - 1]));
	pfree(DatumGetPointer(values[Anum_pg_attrdef_adsrc - 1]));
1618
	heap_freetuple(tuple);
1619 1620
	pfree(adsrc);

1621
	if (!updatePgAttribute)
1622 1623 1624 1625
		return;					/* done if pg_attribute is OK */

	attrrel = heap_openr(AttributeRelationName, RowExclusiveLock);
	atttup = SearchSysCacheTupleCopy(ATTNUM,
1626
								 ObjectIdGetDatum(RelationGetRelid(rel)),
1627 1628 1629
									 (Datum) attnum, 0, 0);
	if (!HeapTupleIsValid(atttup))
		elog(ERROR, "cache lookup of attribute %d in relation %u failed",
1630
			 attnum, RelationGetRelid(rel));
1631
	attStruct = (Form_pg_attribute) GETSTRUCT(atttup);
1632
	if (!attStruct->atthasdef)
1633 1634
	{
		attStruct->atthasdef = true;
1635
		heap_update(attrrel, &atttup->t_self, atttup, NULL);
1636 1637 1638 1639 1640 1641 1642
		/* keep catalog indices current */
		CatalogOpenIndices(Num_pg_attr_indices, Name_pg_attr_indices,
						   attridescs);
		CatalogIndexInsert(attridescs, Num_pg_attr_indices, attrrel, atttup);
		CatalogCloseIndices(Num_pg_attr_indices, attridescs);
	}
	heap_close(attrrel, RowExclusiveLock);
1643
	heap_freetuple(atttup);
1644 1645
}

1646 1647 1648 1649 1650 1651 1652
/*
 * Store a constraint expression for the given relation.
 * The expression must be presented as a nodeToString() string.
 *
 * Caller is responsible for updating the count of constraints
 * in the pg_class entry for the relation.
 */
1653
static void
1654
StoreRelCheck(Relation rel, char *ccname, char *ccbin)
1655
{
1656 1657 1658
	Node	   *expr;
	RangeTblEntry *rte;
	char	   *ccsrc;
1659 1660 1661 1662
	Relation	rcrel;
	Relation	idescs[Num_pg_relcheck_indices];
	HeapTuple	tuple;
	Datum		values[4];
1663
	static char nulls[4] = {' ', ' ', ' ', ' '};
1664

B
Bruce Momjian 已提交
1665
	/*
1666
	 * Convert condition to a normal boolean expression tree.
1667
	 */
1668 1669
	expr = stringToNode(ccbin);
	expr = (Node *) make_ands_explicit((List *) expr);
1670

1671 1672 1673 1674
	/*
	 * deparse_expression needs a RangeTblEntry list, so make one
	 */
	rte = makeNode(RangeTblEntry);
1675
	rte->relname = RelationGetRelationName(rel);
1676
#ifndef DISABLE_EREF
1677 1678
	rte->ref = makeNode(Attr);
	rte->ref->relname = RelationGetRelationName(rel);
1679
#endif
1680 1681 1682 1683 1684
	rte->relid = RelationGetRelid(rel);
	rte->inh = false;
	rte->inFromCl = true;
	rte->skipAcl = false;
	ccsrc = deparse_expression(expr, lcons(lcons(rte, NIL), NIL), false);
1685

1686
	values[Anum_pg_relcheck_rcrelid - 1] = RelationGetRelid(rel);
1687 1688 1689
	values[Anum_pg_relcheck_rcname - 1] = PointerGetDatum(namein(ccname));
	values[Anum_pg_relcheck_rcbin - 1] = PointerGetDatum(textin(ccbin));
	values[Anum_pg_relcheck_rcsrc - 1] = PointerGetDatum(textin(ccsrc));
1690
	rcrel = heap_openr(RelCheckRelationName, RowExclusiveLock);
1691 1692
	tuple = heap_formtuple(rcrel->rd_att, values, nulls);
	heap_insert(rcrel, tuple);
1693 1694
	CatalogOpenIndices(Num_pg_relcheck_indices, Name_pg_relcheck_indices,
					   idescs);
1695 1696
	CatalogIndexInsert(idescs, Num_pg_relcheck_indices, rcrel, tuple);
	CatalogCloseIndices(Num_pg_relcheck_indices, idescs);
1697
	heap_close(rcrel, RowExclusiveLock);
1698 1699 1700 1701

	pfree(DatumGetPointer(values[Anum_pg_relcheck_rcname - 1]));
	pfree(DatumGetPointer(values[Anum_pg_relcheck_rcbin - 1]));
	pfree(DatumGetPointer(values[Anum_pg_relcheck_rcsrc - 1]));
1702
	heap_freetuple(tuple);
1703
	pfree(ccsrc);
1704 1705
}

1706 1707 1708 1709 1710 1711 1712 1713 1714 1715
/*
 * Store defaults and constraints passed in via the tuple constraint struct.
 *
 * NOTE: only pre-cooked expressions will be passed this way, which is to
 * say expressions inherited from an existing relation.  Newly parsed
 * expressions can be added later, by direct calls to StoreAttrDefault
 * and StoreRelCheck (see AddRelationRawConstraints()).  We assume that
 * pg_attribute and pg_class entries for the relation were already set
 * to reflect the existence of these defaults/constraints.
 */
1716 1717
static void
StoreConstraints(Relation rel)
1718
{
1719 1720
	TupleConstr *constr = rel->rd_att->constr;
	int			i;
1721 1722 1723 1724

	if (!constr)
		return;

1725 1726 1727 1728
	/*
	 * deparsing of constraint expressions will fail unless the
	 * just-created pg_attribute tuples for this relation are made
	 * visible.  So, bump the command counter.
1729 1730 1731
	 */
	CommandCounterIncrement();

1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757
	for (i = 0; i < constr->num_defval; i++)
		StoreAttrDefault(rel, constr->defval[i].adnum,
						 constr->defval[i].adbin, false);

	for (i = 0; i < constr->num_check; i++)
		StoreRelCheck(rel, constr->check[i].ccname,
					  constr->check[i].ccbin);
}

/*
 * AddRelationRawConstraints
 *
 * Add raw (not-yet-transformed) column default expressions and/or constraint
 * check expressions to an existing relation.  This is defined to do both
 * for efficiency in DefineRelation, but of course you can do just one or
 * the other by passing empty lists.
 *
 * rel: relation to be modified
 * rawColDefaults: list of RawColumnDefault structures
 * rawConstraints: list of Constraint nodes
 *
 * All entries in rawColDefaults will be processed.  Entries in rawConstraints
 * will be processed only if they are CONSTR_CHECK type and contain a "raw"
 * expression.
 *
 * NB: caller should have opened rel with AccessExclusiveLock, and should
1758
 * hold that lock till end of transaction.	Also, we assume the caller has
1759 1760
 * done a CommandCounterIncrement if necessary to make the relation's catalog
 * tuples visible.
1761 1762 1763 1764 1765 1766
 */
void
AddRelationRawConstraints(Relation rel,
						  List *rawColDefaults,
						  List *rawConstraints)
{
1767
	char	   *relname = RelationGetRelationName(rel);
1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796
	TupleDesc	tupleDesc;
	TupleConstr *oldconstr;
	int			numoldchecks;
	ConstrCheck *oldchecks;
	ParseState *pstate;
	int			numchecks;
	List	   *listptr;
	Relation	relrel;
	Relation	relidescs[Num_pg_class_indices];
	HeapTuple	reltup;
	Form_pg_class relStruct;

	/*
	 * Get info about existing constraints.
	 */
	tupleDesc = RelationGetDescr(rel);
	oldconstr = tupleDesc->constr;
	if (oldconstr)
	{
		numoldchecks = oldconstr->num_check;
		oldchecks = oldconstr->check;
	}
	else
	{
		numoldchecks = 0;
		oldchecks = NULL;
	}

	/*
1797 1798
	 * Create a dummy ParseState and insert the target relation as its
	 * sole rangetable entry.  We need a ParseState for transformExpr.
1799 1800
	 */
	pstate = make_parsestate(NULL);
1801 1802
	makeRangeTable(pstate, NULL);
	addRangeTableEntry(pstate, relname, makeAttr(relname, NULL), false, true, true);
1803 1804 1805 1806 1807

	/*
	 * Process column default expressions.
	 */
	foreach(listptr, rawColDefaults)
1808
	{
1809 1810
		RawColumnDefault *colDef = (RawColumnDefault *) lfirst(listptr);
		Node	   *expr;
1811
		Oid			type_id;
1812 1813

		Assert(colDef->raw_default != NULL);
1814

1815 1816 1817 1818
		/*
		 * Transform raw parsetree to executable expression.
		 */
		expr = transformExpr(pstate, colDef->raw_default, EXPR_COLUMN_FIRST);
1819

1820 1821 1822 1823 1824
		/*
		 * Make sure default expr does not refer to any vars.
		 */
		if (contain_var_clause(expr))
			elog(ERROR, "Cannot use attribute(s) in DEFAULT clause");
1825

1826
		/*
1827 1828 1829
		 * Check that it will be possible to coerce the expression to the
		 * column's type.  We store the expression without coercion,
		 * however, to avoid premature coercion in cases like
1830 1831 1832
		 *
		 * CREATE TABLE tbl (fld datetime DEFAULT 'now');
		 *
1833 1834 1835
		 * NB: this should match the code in updateTargetListEntry() that
		 * will actually do the coercion, to ensure we don't accept an
		 * unusable default expression.
1836 1837 1838 1839 1840 1841 1842 1843
		 */
		type_id = exprType(expr);
		if (type_id != InvalidOid)
		{
			Form_pg_attribute atp = rel->rd_att->attrs[colDef->attnum - 1];

			if (type_id != atp->atttypid)
			{
1844
				if (CoerceTargetExpr(NULL, expr, type_id,
1845
								  atp->atttypid, atp->atttypmod) == NULL)
1846 1847
					elog(ERROR, "Attribute '%s' is of type '%s'"
						 " but default expression is of type '%s'"
1848
					"\n\tYou will need to rewrite or cast the expression",
1849
						 NameStr(atp->attname),
1850 1851 1852 1853
						 typeidTypeName(atp->atttypid),
						 typeidTypeName(type_id));
			}
		}
1854

1855 1856 1857 1858
		/*
		 * Might as well try to reduce any constant expressions.
		 */
		expr = eval_const_expressions(expr);
1859

1860 1861 1862 1863
		/*
		 * Must fix opids, in case any operators remain...
		 */
		fix_opids(expr);
1864

1865 1866 1867 1868
		/*
		 * OK, store it.
		 */
		StoreAttrDefault(rel, colDef->attnum, nodeToString(expr), true);
1869 1870
	}

1871 1872 1873 1874 1875
	/*
	 * Process constraint expressions.
	 */
	numchecks = numoldchecks;
	foreach(listptr, rawConstraints)
1876
	{
1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918
		Constraint *cdef = (Constraint *) lfirst(listptr);
		char	   *ccname;
		Node	   *expr;

		if (cdef->contype != CONSTR_CHECK || cdef->raw_expr == NULL)
			continue;
		Assert(cdef->cooked_expr == NULL);

		/* Check name uniqueness, or generate a new name */
		if (cdef->name != NULL)
		{
			int			i;
			List	   *listptr2;

			ccname = cdef->name;
			/* Check against old constraints */
			for (i = 0; i < numoldchecks; i++)
			{
				if (strcmp(oldchecks[i].ccname, ccname) == 0)
					elog(ERROR, "Duplicate CHECK constraint name: '%s'",
						 ccname);
			}
			/* Check against other new constraints */
			foreach(listptr2, rawConstraints)
			{
				Constraint *cdef2 = (Constraint *) lfirst(listptr2);

				if (cdef2 == cdef ||
					cdef2->contype != CONSTR_CHECK ||
					cdef2->raw_expr == NULL ||
					cdef2->name == NULL)
					continue;
				if (strcmp(cdef2->name, ccname) == 0)
					elog(ERROR, "Duplicate CHECK constraint name: '%s'",
						 ccname);
			}
		}
		else
		{
			ccname = (char *) palloc(NAMEDATALEN);
			snprintf(ccname, NAMEDATALEN, "$%d", numchecks + 1);
		}
1919

1920 1921 1922 1923
		/*
		 * Transform raw parsetree to executable expression.
		 */
		expr = transformExpr(pstate, cdef->raw_expr, EXPR_COLUMN_FIRST);
1924

1925 1926 1927 1928 1929 1930
		/*
		 * Make sure it yields a boolean result.
		 */
		if (exprType(expr) != BOOLOID)
			elog(ERROR, "CHECK '%s' does not yield boolean result",
				 ccname);
1931

1932 1933 1934 1935 1936 1937
		/*
		 * Make sure no outside relations are referred to.
		 */
		if (length(pstate->p_rtable) != 1)
			elog(ERROR, "Only relation '%s' can be referenced in CHECK",
				 relname);
1938

1939 1940 1941 1942
		/*
		 * Might as well try to reduce any constant expressions.
		 */
		expr = eval_const_expressions(expr);
1943

1944 1945 1946 1947 1948 1949 1950
		/*
		 * Constraints are evaluated with execQual, which expects an
		 * implicit-AND list, so convert expression to implicit-AND form.
		 * (We could go so far as to convert to CNF, but that's probably
		 * overkill...)
		 */
		expr = (Node *) make_ands_implicit((Expr *) expr);
1951

1952 1953 1954 1955
		/*
		 * Must fix opids in operator clauses.
		 */
		fix_opids(expr);
1956

1957 1958 1959 1960 1961 1962
		/*
		 * OK, store it.
		 */
		StoreRelCheck(rel, ccname, nodeToString(expr));

		numchecks++;
1963 1964
	}

1965 1966 1967 1968 1969
	/*
	 * Update the count of constraints in the relation's pg_class tuple.
	 * We do this even if there was no change, in order to ensure that an
	 * SI update message is sent out for the pg_class tuple, which will
	 * force other backends to rebuild their relcache entries for the rel.
1970 1971
	 * (Of course, for a newly created rel there is no need for an SI
	 * message, but for ALTER TABLE ADD ATTRIBUTE this'd be important.)
1972 1973 1974
	 */
	relrel = heap_openr(RelationRelationName, RowExclusiveLock);
	reltup = SearchSysCacheTupleCopy(RELOID,
1975
								 ObjectIdGetDatum(RelationGetRelid(rel)),
1976 1977
									 0, 0, 0);
	if (!HeapTupleIsValid(reltup))
1978
		elog(ERROR, "cache lookup of relation %u failed", RelationGetRelid(rel));
1979 1980 1981 1982
	relStruct = (Form_pg_class) GETSTRUCT(reltup);

	relStruct->relchecks = numchecks;

1983
	heap_update(relrel, &reltup->t_self, reltup, NULL);
1984 1985 1986 1987 1988 1989 1990 1991

	/* keep catalog indices current */
	CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices,
					   relidescs);
	CatalogIndexInsert(relidescs, Num_pg_class_indices, relrel, reltup);
	CatalogCloseIndices(Num_pg_class_indices, relidescs);

	heap_close(relrel, RowExclusiveLock);
1992
	heap_freetuple(reltup);
1993 1994
}

1995 1996
static void
RemoveAttrDefault(Relation rel)
1997
{
1998 1999 2000 2001
	Relation	adrel;
	HeapScanDesc adscan;
	ScanKeyData key;
	HeapTuple	tup;
2002

2003
	adrel = heap_openr(AttrDefaultRelationName, RowExclusiveLock);
2004 2005

	ScanKeyEntryInitialize(&key, 0, Anum_pg_attrdef_adrelid,
2006
						   F_OIDEQ, RelationGetRelid(rel));
2007

2008
	adscan = heap_beginscan(adrel, 0, SnapshotNow, 1, &key);
2009

2010
	while (HeapTupleIsValid(tup = heap_getnext(adscan, 0)))
V
Vadim B. Mikheev 已提交
2011
		heap_delete(adrel, &tup->t_self, NULL);
2012 2013

	heap_endscan(adscan);
2014
	heap_close(adrel, RowExclusiveLock);
2015 2016
}

2017 2018
static void
RemoveRelCheck(Relation rel)
2019
{
2020 2021 2022 2023
	Relation	rcrel;
	HeapScanDesc rcscan;
	ScanKeyData key;
	HeapTuple	tup;
2024

2025
	rcrel = heap_openr(RelCheckRelationName, RowExclusiveLock);
2026 2027

	ScanKeyEntryInitialize(&key, 0, Anum_pg_relcheck_rcrelid,
2028
						   F_OIDEQ, RelationGetRelid(rel));
2029

2030
	rcscan = heap_beginscan(rcrel, 0, SnapshotNow, 1, &key);
2031

2032
	while (HeapTupleIsValid(tup = heap_getnext(rcscan, 0)))
V
Vadim B. Mikheev 已提交
2033
		heap_delete(rcrel, &tup->t_self, NULL);
2034 2035

	heap_endscan(rcscan);
2036
	heap_close(rcrel, RowExclusiveLock);
2037
}
2038

2039 2040
static void
RemoveConstraints(Relation rel)
2041
{
2042
	TupleConstr *constr = rel->rd_att->constr;
2043 2044 2045 2046 2047 2048 2049 2050 2051

	if (!constr)
		return;

	if (constr->num_defval > 0)
		RemoveAttrDefault(rel);

	if (constr->num_check > 0)
		RemoveRelCheck(rel);
2052
}
2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074

static void
RemoveStatistics(Relation rel)
{
	Relation	pgstatistic;
	HeapScanDesc scan;
	ScanKeyData key;
	HeapTuple	tuple;

	pgstatistic = heap_openr(StatisticRelationName, RowExclusiveLock);

	ScanKeyEntryInitialize(&key, 0x0, Anum_pg_statistic_starelid,
						   F_OIDEQ,
						   ObjectIdGetDatum(RelationGetRelid(rel)));
	scan = heap_beginscan(pgstatistic, false, SnapshotNow, 1, &key);

	while (HeapTupleIsValid(tuple = heap_getnext(scan, 0)))
		heap_delete(pgstatistic, &tuple->t_self, NULL);

	heap_endscan(scan);
	heap_close(pgstatistic, RowExclusiveLock);
}