plancat.c 27.7 KB
Newer Older
1 2
/*-------------------------------------------------------------------------
 *
3
 * plancat.c
4
 *	   routines for accessing the system catalogs
5 6
 *
 *
7
 * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
B
Add:  
Bruce Momjian 已提交
8
 * Portions Copyright (c) 1994, Regents of the University of California
9 10 11
 *
 *
 * IDENTIFICATION
12
 *	  $PostgreSQL: pgsql/src/backend/optimizer/util/plancat.c,v 1.149 2008/08/16 00:01:36 tgl Exp $
13 14 15
 *
 *-------------------------------------------------------------------------
 */
16
#include "postgres.h"
17

18 19
#include <math.h>

B
Bruce Momjian 已提交
20 21
#include "access/genam.h"
#include "access/heapam.h"
22
#include "access/sysattr.h"
23
#include "access/transam.h"
24
#include "catalog/catalog.h"
25
#include "catalog/pg_inherits.h"
26
#include "miscadmin.h"
27
#include "nodes/makefuncs.h"
28
#include "optimizer/clauses.h"
29
#include "optimizer/plancat.h"
30
#include "optimizer/predtest.h"
31
#include "optimizer/prep.h"
32
#include "parser/parse_expr.h"
33
#include "parser/parse_relation.h"
34
#include "parser/parsetree.h"
35
#include "rewrite/rewriteManip.h"
36
#include "storage/bufmgr.h"
37
#include "utils/fmgroids.h"
38
#include "utils/lsyscache.h"
39
#include "utils/rel.h"
40
#include "utils/snapmgr.h"
41
#include "utils/syscache.h"
42
#include "utils/tqual.h"
43 44


45 46 47
/* GUC parameter */
bool		constraint_exclusion = false;

48 49 50
/* Hook for plugins to get control in get_relation_info() */
get_relation_info_hook_type get_relation_info_hook = NULL;

51

52 53
static List *get_relation_constraints(PlannerInfo *root,
						 Oid relationObjectId, RelOptInfo *rel,
54
						 bool include_notnull);
55 56


57
/*
58
 * get_relation_info -
59
 *	  Retrieves catalog information for a given relation.
60 61 62 63
 *
 * Given the Oid of the relation, return the following info into fields
 * of the RelOptInfo struct:
 *
64 65
 *	min_attr	lowest valid AttrNumber
 *	max_attr	highest valid AttrNumber
66 67 68
 *	indexlist	list of IndexOptInfos for relation's indexes
 *	pages		number of pages
 *	tuples		number of tuples
69 70 71 72
 *
 * Also, initialize the attr_needed[] and attr_widths[] arrays.  In most
 * cases these are left as zeroes, but sometimes we need to compute attr
 * widths here, and we may as well cache the results for costsize.c.
73 74 75 76 77
 *
 * If inhparent is true, all we need to do is set up the attr arrays:
 * the RelOptInfo actually represents the appendrel formed by an inheritance
 * tree, and so the parent rel's physical size and index information isn't
 * important for it.
78 79
 */
void
80 81
get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
				  RelOptInfo *rel)
82
{
83
	Index		varno = rel->relid;
84
	Relation	relation;
85 86
	bool		hasindex;
	List	   *indexinfos = NIL;
87

88
	/*
B
Bruce Momjian 已提交
89 90 91
	 * We need not lock the relation since it was already locked, either by
	 * the rewriter or when expand_inherited_rtentry() added it to the query's
	 * rangetable.
92
	 */
93
	relation = heap_open(relationObjectId, NoLock);
94

95 96
	rel->min_attr = FirstLowInvalidHeapAttributeNumber + 1;
	rel->max_attr = RelationGetNumberOfAttributes(relation);
97

98 99 100 101 102 103 104
	Assert(rel->max_attr >= rel->min_attr);
	rel->attr_needed = (Relids *)
		palloc0((rel->max_attr - rel->min_attr + 1) * sizeof(Relids));
	rel->attr_widths = (int32 *)
		palloc0((rel->max_attr - rel->min_attr + 1) * sizeof(int32));

	/*
105
	 * Estimate relation size --- unless it's an inheritance parent, in which
B
Bruce Momjian 已提交
106 107
	 * case the size will be computed later in set_append_rel_pathlist, and we
	 * must leave it zero for now to avoid bollixing the total_table_pages
108
	 * calculation.
109
	 */
110 111 112
	if (!inhparent)
		estimate_rel_size(relation, rel->attr_widths - rel->min_attr,
						  &rel->pages, &rel->tuples);
113

114
	/*
B
Bruce Momjian 已提交
115
	 * Make list of indexes.  Ignore indexes on system catalogs if told to.
116
	 * Don't bother with indexes for an inheritance parent, either.
117
	 */
118 119
	if (inhparent ||
		(IgnoreSystemIndexes && IsSystemClass(relation->rd_rel)))
120 121 122
		hasindex = false;
	else
		hasindex = relation->rd_rel->relhasindex;
123

124
	if (hasindex)
125
	{
126 127
		List	   *indexoidlist;
		ListCell   *l;
128
		LOCKMODE	lmode;
129

130
		indexoidlist = RelationGetIndexList(relation);
131

132 133 134 135 136 137 138 139 140 141 142 143 144
		/*
		 * For each index, we get the same type of lock that the executor will
		 * need, and do not release it.  This saves a couple of trips to the
		 * shared lock manager while not creating any real loss of
		 * concurrency, because no schema changes could be happening on the
		 * index while we hold lock on the parent rel, and neither lock type
		 * blocks any other kind of index operation.
		 */
		if (rel->relid == root->parse->resultRelation)
			lmode = RowExclusiveLock;
		else
			lmode = AccessShareLock;

145
		foreach(l, indexoidlist)
146
		{
147
			Oid			indexoid = lfirst_oid(l);
148 149 150
			Relation	indexRelation;
			Form_pg_index index;
			IndexOptInfo *info;
151
			int			ncolumns;
152 153
			int			i;

154 155 156
			/*
			 * Extract info from the relation descriptor for the index.
			 */
157
			indexRelation = index_open(indexoid, lmode);
158
			index = indexRelation->rd_index;
159

160 161
			/*
			 * Ignore invalid indexes, since they can't safely be used for
B
Bruce Momjian 已提交
162 163 164
			 * queries.  Note that this is OK because the data structure we
			 * are constructing is only used by the planner --- the executor
			 * still needs to insert into "invalid" indexes!
165 166 167 168 169 170 171
			 */
			if (!index->indisvalid)
			{
				index_close(indexRelation, NoLock);
				continue;
			}

172
			/*
B
Bruce Momjian 已提交
173 174 175
			 * If the index is valid, but cannot yet be used, ignore it; but
			 * mark the plan we are generating as transient. See
			 * src/backend/access/heap/README.HOT for discussion.
176 177 178 179 180 181 182 183 184 185
			 */
			if (index->indcheckxmin &&
				!TransactionIdPrecedes(HeapTupleHeaderGetXmin(indexRelation->rd_indextuple->t_data),
									   TransactionXmin))
			{
				root->glob->transientPlan = true;
				index_close(indexRelation, NoLock);
				continue;
			}

186 187 188
			info = makeNode(IndexOptInfo);

			info->indexoid = index->indexrelid;
189
			info->rel = rel;
190
			info->ncolumns = ncolumns = index->indnatts;
191

192
			/*
193
			 * Allocate per-column info arrays.  To save a few palloc cycles
B
Bruce Momjian 已提交
194
			 * we allocate all the Oid-type arrays in one request.	Note that
195 196
			 * the opfamily array needs an extra, terminating zero at the end.
			 * We pre-zero the ordering info in case the index is unordered.
197 198
			 */
			info->indexkeys = (int *) palloc(sizeof(int) * ncolumns);
199 200 201 202
			info->opfamily = (Oid *) palloc0(sizeof(Oid) * (4 * ncolumns + 1));
			info->opcintype = info->opfamily + (ncolumns + 1);
			info->fwdsortop = info->opcintype + ncolumns;
			info->revsortop = info->fwdsortop + ncolumns;
203
			info->nulls_first = (bool *) palloc0(sizeof(bool) * ncolumns);
204

205
			for (i = 0; i < ncolumns; i++)
206
			{
207
				info->indexkeys[i] = index->indkey.values[i];
208 209
				info->opfamily[i] = indexRelation->rd_opfamily[i];
				info->opcintype[i] = indexRelation->rd_opcintype[i];
210 211 212
			}

			info->relam = indexRelation->rd_rel->relam;
213 214
			info->amcostestimate = indexRelation->rd_am->amcostestimate;
			info->amoptionalkey = indexRelation->rd_am->amoptionalkey;
215
			info->amsearchnulls = indexRelation->rd_am->amsearchnulls;
216 217

			/*
B
Bruce Momjian 已提交
218
			 * Fetch the ordering operators associated with the index, if any.
219 220
			 * We expect that all ordering-capable indexes use btree's
			 * strategy numbers for the ordering operators.
221
			 */
222
			if (indexRelation->rd_am->amcanorder)
223
			{
224
				int			nstrat = indexRelation->rd_am->amstrategies;
225

226
				for (i = 0; i < ncolumns; i++)
227
				{
B
Bruce Momjian 已提交
228 229 230
					int16		opt = indexRelation->rd_indoption[i];
					int			fwdstrat;
					int			revstrat;
231 232 233

					if (opt & INDOPTION_DESC)
					{
234 235
						fwdstrat = BTGreaterStrategyNumber;
						revstrat = BTLessStrategyNumber;
236 237 238
					}
					else
					{
239 240
						fwdstrat = BTLessStrategyNumber;
						revstrat = BTGreaterStrategyNumber;
241
					}
B
Bruce Momjian 已提交
242

243
					/*
B
Bruce Momjian 已提交
244 245 246
					 * Index AM must have a fixed set of strategies for it to
					 * make sense to specify amcanorder, so we need not allow
					 * the case amstrategies == 0.
247 248 249 250 251 252 253 254 255 256 257 258
					 */
					if (fwdstrat > 0)
					{
						Assert(fwdstrat <= nstrat);
						info->fwdsortop[i] = indexRelation->rd_operator[i * nstrat + fwdstrat - 1];
					}
					if (revstrat > 0)
					{
						Assert(revstrat <= nstrat);
						info->revsortop[i] = indexRelation->rd_operator[i * nstrat + revstrat - 1];
					}
					info->nulls_first[i] = (opt & INDOPTION_NULLS_FIRST) != 0;
259 260
				}
			}
261

262 263 264
			/*
			 * Fetch the index expressions and predicate, if any.  We must
			 * modify the copies we obtain from the relcache to have the
B
Bruce Momjian 已提交
265 266
			 * correct varno for the parent relation, so that they match up
			 * correctly against qual clauses.
267 268 269 270 271 272 273
			 */
			info->indexprs = RelationGetIndexExpressions(indexRelation);
			info->indpred = RelationGetIndexPredicate(indexRelation);
			if (info->indexprs && varno != 1)
				ChangeVarNodes((Node *) info->indexprs, 1, varno, 0);
			if (info->indpred && varno != 1)
				ChangeVarNodes((Node *) info->indpred, 1, varno, 0);
B
Bruce Momjian 已提交
274
			info->predOK = false;		/* set later in indxpath.c */
275 276
			info->unique = index->indisunique;

277
			/*
B
Bruce Momjian 已提交
278 279 280 281 282
			 * Estimate the index size.  If it's not a partial index, we lock
			 * the number-of-tuples estimate to equal the parent table; if it
			 * is partial then we have to use the same methods as we would for
			 * a table, except we can be sure that the index is not larger
			 * than the table.
283 284 285 286 287 288 289 290 291 292 293 294 295 296
			 */
			if (info->indpred == NIL)
			{
				info->pages = RelationGetNumberOfBlocks(indexRelation);
				info->tuples = rel->tuples;
			}
			else
			{
				estimate_rel_size(indexRelation, NULL,
								  &info->pages, &info->tuples);
				if (info->tuples > rel->tuples)
					info->tuples = rel->tuples;
			}

297
			index_close(indexRelation, NoLock);
298 299 300 301

			indexinfos = lcons(info, indexinfos);
		}

302
		list_free(indexoidlist);
303
	}
304

305 306
	rel->indexlist = indexinfos;

307
	heap_close(relation, NoLock);
308 309 310 311 312 313 314 315

	/*
	 * Allow a plugin to editorialize on the info we obtained from the
	 * catalogs.  Actions might include altering the assumed relation size,
	 * removing an index, or adding a hypothetical index to the indexlist.
	 */
	if (get_relation_info_hook)
		(*get_relation_info_hook) (root, relationObjectId, inhparent, rel);
316 317
}

318 319 320 321 322 323 324
/*
 * estimate_rel_size - estimate # pages and # tuples in a table or index
 *
 * If attr_widths isn't NULL, it points to the zero-index entry of the
 * relation's attr_width[] cache; we fill this in if we have need to compute
 * the attribute widths for estimation purposes.
 */
325
void
326 327 328
estimate_rel_size(Relation rel, int32 *attr_widths,
				  BlockNumber *pages, double *tuples)
{
B
Bruce Momjian 已提交
329 330
	BlockNumber curpages;
	BlockNumber relpages;
331 332 333 334 335 336 337 338 339
	double		reltuples;
	double		density;

	switch (rel->rd_rel->relkind)
	{
		case RELKIND_RELATION:
		case RELKIND_INDEX:
		case RELKIND_TOASTVALUE:
			/* it has storage, ok to call the smgr */
340 341 342 343
			curpages = RelationGetNumberOfBlocks(rel);

			/*
			 * HACK: if the relation has never yet been vacuumed, use a
B
Bruce Momjian 已提交
344 345 346 347 348 349 350 351 352 353
			 * minimum estimate of 10 pages.  This emulates a desirable aspect
			 * of pre-8.0 behavior, which is that we wouldn't assume a newly
			 * created relation is really small, which saves us from making
			 * really bad plans during initial data loading.  (The plans are
			 * not wrong when they are made, but if they are cached and used
			 * again after the table has grown a lot, they are bad.) It would
			 * be better to force replanning if the table size has changed a
			 * lot since the plan was made ... but we don't currently have any
			 * infrastructure for redoing cached plans at all, so we have to
			 * kluge things here instead.
354
			 *
355 356 357 358 359
			 * We approximate "never vacuumed" by "has relpages = 0", which
			 * means this will also fire on genuinely empty relations.	Not
			 * great, but fortunately that's a seldom-seen case in the real
			 * world, and it shouldn't degrade the quality of the plan too
			 * much anyway to err in this direction.
360 361 362 363 364 365
			 */
			if (curpages < 10 && rel->rd_rel->relpages == 0)
				curpages = 10;

			/* report estimated # pages */
			*pages = curpages;
366 367 368 369 370 371 372 373 374
			/* quick exit if rel is clearly empty */
			if (curpages == 0)
			{
				*tuples = 0;
				break;
			}
			/* coerce values in pg_class to more desirable types */
			relpages = (BlockNumber) rel->rd_rel->relpages;
			reltuples = (double) rel->rd_rel->reltuples;
B
Bruce Momjian 已提交
375

376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395
			/*
			 * If it's an index, discount the metapage.  This is a kluge
			 * because it assumes more than it ought to about index contents;
			 * it's reasonably OK for btrees but a bit suspect otherwise.
			 */
			if (rel->rd_rel->relkind == RELKIND_INDEX &&
				relpages > 0)
			{
				curpages--;
				relpages--;
			}
			/* estimate number of tuples from previous tuple density */
			if (relpages > 0)
				density = reltuples / (double) relpages;
			else
			{
				/*
				 * When we have no data because the relation was truncated,
				 * estimate tuple width from attribute datatypes.  We assume
				 * here that the pages are completely full, which is OK for
B
Bruce Momjian 已提交
396 397
				 * tables (since they've presumably not been VACUUMed yet) but
				 * is probably an overestimate for indexes.  Fortunately
398 399
				 * get_relation_info() can clamp the overestimate to the
				 * parent table's size.
400 401
				 *
				 * Note: this code intentionally disregards alignment
B
Bruce Momjian 已提交
402 403 404 405
				 * considerations, because (a) that would be gilding the lily
				 * considering how crude the estimate is, and (b) it creates
				 * platform dependencies in the default plans which are kind
				 * of a headache for regression testing.
406
				 */
B
Bruce Momjian 已提交
407 408
				int32		tuple_width = 0;
				int			i;
409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428

				for (i = 1; i <= RelationGetNumberOfAttributes(rel); i++)
				{
					Form_pg_attribute att = rel->rd_att->attrs[i - 1];
					int32		item_width;

					if (att->attisdropped)
						continue;
					/* This should match set_rel_width() in costsize.c */
					item_width = get_attavgwidth(RelationGetRelid(rel), i);
					if (item_width <= 0)
					{
						item_width = get_typavgwidth(att->atttypid,
													 att->atttypmod);
						Assert(item_width > 0);
					}
					if (attr_widths != NULL)
						attr_widths[i] = item_width;
					tuple_width += item_width;
				}
429
				tuple_width += sizeof(HeapTupleHeaderData);
430 431
				tuple_width += sizeof(ItemPointerData);
				/* note: integer division is intentional here */
432
				density = (BLCKSZ - SizeOfPageHeaderData) / tuple_width;
433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448
			}
			*tuples = rint(density * (double) curpages);
			break;
		case RELKIND_SEQUENCE:
			/* Sequences always have a known size */
			*pages = 1;
			*tuples = 1;
			break;
		default:
			/* else it has no disk storage; probably shouldn't get here? */
			*pages = 0;
			*tuples = 0;
			break;
	}
}

449 450 451 452 453 454 455 456 457 458 459

/*
 * get_relation_constraints
 *
 * Retrieve the CHECK constraint expressions of the given relation.
 *
 * Returns a List (possibly empty) of constraint expressions.  Each one
 * has been canonicalized, and its Vars are changed to have the varno
 * indicated by rel->relid.  This allows the expressions to be easily
 * compared to expressions taken from WHERE.
 *
460 461 462
 * If include_notnull is true, "col IS NOT NULL" expressions are generated
 * and added to the result for each column that's marked attnotnull.
 *
463 464 465 466
 * Note: at present this is invoked at most once per relation per planner
 * run, and in many cases it won't be invoked at all, so there seems no
 * point in caching the data in RelOptInfo.
 */
467
static List *
468 469
get_relation_constraints(PlannerInfo *root,
						 Oid relationObjectId, RelOptInfo *rel,
470
						 bool include_notnull)
471 472 473 474 475 476 477 478 479 480 481 482 483 484
{
	List	   *result = NIL;
	Index		varno = rel->relid;
	Relation	relation;
	TupleConstr *constr;

	/*
	 * We assume the relation has already been safely locked.
	 */
	relation = heap_open(relationObjectId, NoLock);

	constr = relation->rd_att->constr;
	if (constr != NULL)
	{
B
Bruce Momjian 已提交
485 486
		int			num_check = constr->num_check;
		int			i;
487 488 489

		for (i = 0; i < num_check; i++)
		{
B
Bruce Momjian 已提交
490
			Node	   *cexpr;
491 492 493 494 495 496 497 498 499 500 501 502 503

			cexpr = stringToNode(constr->check[i].ccbin);

			/*
			 * Run each expression through const-simplification and
			 * canonicalization.  This is not just an optimization, but is
			 * necessary, because we will be comparing it to
			 * similarly-processed qual clauses, and may fail to detect valid
			 * matches without this.  This must match the processing done to
			 * qual clauses in preprocess_expression()!  (We can skip the
			 * stuff involving subqueries, however, since we don't allow any
			 * in check constraints.)
			 */
504
			cexpr = eval_const_expressions(root, cexpr);
505 506 507 508 509 510 511 512 513 514 515 516 517 518

			cexpr = (Node *) canonicalize_qual((Expr *) cexpr);

			/*
			 * Also mark any coercion format fields as "don't care", so that
			 * we can match to both explicit and implicit coercions.
			 */
			set_coercionform_dontcare(cexpr);

			/* Fix Vars to have the desired varno */
			if (varno != 1)
				ChangeVarNodes(cexpr, 1, varno, 0);

			/*
B
Bruce Momjian 已提交
519 520
			 * Finally, convert to implicit-AND format (that is, a List) and
			 * append the resulting item(s) to our output list.
521 522 523 524
			 */
			result = list_concat(result,
								 make_ands_implicit((Expr *) cexpr));
		}
525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548

		/* Add NOT NULL constraints in expression form, if requested */
		if (include_notnull && constr->has_not_null)
		{
			int		natts = relation->rd_att->natts;

			for (i = 1; i <= natts; i++)
			{
				Form_pg_attribute att = relation->rd_att->attrs[i - 1];

				if (att->attnotnull && !att->attisdropped)
				{
					NullTest *ntest = makeNode(NullTest);

					ntest->arg = (Expr *) makeVar(varno,
												  i,
												  att->atttypid,
												  att->atttypmod,
												  0);
					ntest->nulltesttype = IS_NOT_NULL;
					result = lappend(result, ntest);
				}
			}
		}
549 550 551 552 553 554 555 556
	}

	heap_close(relation, NoLock);

	return result;
}


557 558 559
/*
 * relation_excluded_by_constraints
 *
560 561 562
 * Detect whether the relation need not be scanned because it has either
 * self-inconsistent restrictions, or restrictions inconsistent with the
 * relation's CHECK constraints.
563 564 565
 *
 * Note: this examines only rel->relid and rel->baserestrictinfo; therefore
 * it can be called before filling in other fields of the RelOptInfo.
566 567
 */
bool
568 569
relation_excluded_by_constraints(PlannerInfo *root,
								 RelOptInfo *rel, RangeTblEntry *rte)
570
{
571
	List	   *safe_restrictions;
572
	List	   *constraint_pred;
573 574
	List	   *safe_constraints;
	ListCell   *lc;
575 576 577 578 579

	/* Skip the test if constraint exclusion is disabled */
	if (!constraint_exclusion)
		return false;

580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599
	/*
	 * Check for self-contradictory restriction clauses.  We dare not make
	 * deductions with non-immutable functions, but any immutable clauses that
	 * are self-contradictory allow us to conclude the scan is unnecessary.
	 *
	 * Note: strip off RestrictInfo because predicate_refuted_by() isn't
	 * expecting to see any in its predicate argument.
	 */
	safe_restrictions = NIL;
	foreach(lc, rel->baserestrictinfo)
	{
		RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);

		if (!contain_mutable_functions((Node *) rinfo->clause))
			safe_restrictions = lappend(safe_restrictions, rinfo->clause);
	}

	if (predicate_refuted_by(safe_restrictions, safe_restrictions))
		return true;

600 601 602 603
	/* Only plain relations have constraints */
	if (rte->rtekind != RTE_RELATION || rte->inh)
		return false;

604 605 606 607
	/*
	 * OK to fetch the constraint expressions.  Include "col IS NOT NULL"
	 * expressions for attnotnull columns, in case we can refute those.
	 */
608
	constraint_pred = get_relation_constraints(root, rte->relid, rel, true);
609 610 611 612

	/*
	 * We do not currently enforce that CHECK constraints contain only
	 * immutable functions, so it's necessary to check here. We daren't draw
B
Bruce Momjian 已提交
613 614 615
	 * conclusions from plan-time evaluation of non-immutable functions. Since
	 * they're ANDed, we can just ignore any mutable constraints in the list,
	 * and reason about the rest.
616
	 */
617 618 619
	safe_constraints = NIL;
	foreach(lc, constraint_pred)
	{
B
Bruce Momjian 已提交
620
		Node	   *pred = (Node *) lfirst(lc);
621 622 623 624

		if (!contain_mutable_functions(pred))
			safe_constraints = lappend(safe_constraints, pred);
	}
625 626 627 628 629

	/*
	 * The constraints are effectively ANDed together, so we can just try to
	 * refute the entire collection at once.  This may allow us to make proofs
	 * that would fail if we took them individually.
630
	 *
B
Bruce Momjian 已提交
631 632 633
	 * Note: we use rel->baserestrictinfo, not safe_restrictions as might seem
	 * an obvious optimization.  Some of the clauses might be OR clauses that
	 * have volatile and nonvolatile subclauses, and it's OK to make
634
	 * deductions with the nonvolatile parts.
635
	 */
636
	if (predicate_refuted_by(safe_constraints, rel->baserestrictinfo))
637 638 639 640 641 642
		return true;

	return false;
}


643 644 645 646 647 648 649 650 651 652
/*
 * build_physical_tlist
 *
 * Build a targetlist consisting of exactly the relation's user attributes,
 * in order.  The executor can special-case such tlists to avoid a projection
 * step at runtime, so we use such tlists preferentially for scan nodes.
 *
 * Exception: if there are any dropped columns, we punt and return NIL.
 * Ideally we would like to handle the dropped-column case too.  However this
 * creates problems for ExecTypeFromTL, which may be asked to build a tupdesc
B
Bruce Momjian 已提交
653
 * for a tlist that includes vars of no-longer-existent types.	In theory we
654 655 656 657
 * could dig out the required info from the pg_attribute entries of the
 * relation, but that data is not readily available to ExecTypeFromTL.
 * For now, we don't apply the physical-tlist optimization when there are
 * dropped cols.
658
 *
659 660 661
 * We also support building a "physical" tlist for subqueries, functions,
 * and values lists, since the same optimization can occur in SubqueryScan,
 * FunctionScan, and ValuesScan nodes.
662 663
 */
List *
664
build_physical_tlist(PlannerInfo *root, RelOptInfo *rel)
665
{
666
	List	   *tlist = NIL;
667
	Index		varno = rel->relid;
668
	RangeTblEntry *rte = planner_rt_fetch(varno, root);
669
	Relation	relation;
670 671 672
	Query	   *subquery;
	Var		   *var;
	ListCell   *l;
673 674
	int			attrno,
				numattrs;
675
	List	   *colvars;
676

677 678 679
	switch (rte->rtekind)
	{
		case RTE_RELATION:
680 681
			/* Assume we already have adequate lock */
			relation = heap_open(rte->relid, NoLock);
682

683 684 685 686
			numattrs = RelationGetNumberOfAttributes(relation);
			for (attrno = 1; attrno <= numattrs; attrno++)
			{
				Form_pg_attribute att_tup = relation->rd_att->attrs[attrno - 1];
687

688 689 690 691 692 693
				if (att_tup->attisdropped)
				{
					/* found a dropped col, so punt */
					tlist = NIL;
					break;
				}
694

695 696 697 698 699 700 701 702 703 704 705 706
				var = makeVar(varno,
							  attrno,
							  att_tup->atttypid,
							  att_tup->atttypmod,
							  0);

				tlist = lappend(tlist,
								makeTargetEntry((Expr *) var,
												attrno,
												NULL,
												false));
			}
707

708
			heap_close(relation, NoLock);
709 710
			break;

711 712 713 714 715 716
		case RTE_SUBQUERY:
			subquery = rte->subquery;
			foreach(l, subquery->targetList)
			{
				TargetEntry *tle = (TargetEntry *) lfirst(l);

717 718 719 720
				/*
				 * A resjunk column of the subquery can be reflected as
				 * resjunk in the physical tlist; we need not punt.
				 */
721 722 723 724 725 726 727 728 729 730 731 732 733
				var = makeVar(varno,
							  tle->resno,
							  exprType((Node *) tle->expr),
							  exprTypmod((Node *) tle->expr),
							  0);

				tlist = lappend(tlist,
								makeTargetEntry((Expr *) var,
												tle->resno,
												NULL,
												tle->resjunk));
			}
			break;
734

735
		case RTE_FUNCTION:
B
Bruce Momjian 已提交
736
			expandRTE(rte, varno, 0, true /* include dropped */ ,
737 738 739 740
					  NULL, &colvars);
			foreach(l, colvars)
			{
				var = (Var *) lfirst(l);
B
Bruce Momjian 已提交
741

742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759
				/*
				 * A non-Var in expandRTE's output means a dropped column;
				 * must punt.
				 */
				if (!IsA(var, Var))
				{
					tlist = NIL;
					break;
				}

				tlist = lappend(tlist,
								makeTargetEntry((Expr *) var,
												var->varattno,
												NULL,
												false));
			}
			break;

760 761 762 763 764 765 766 767 768 769 770 771 772 773 774
		case RTE_VALUES:
			expandRTE(rte, varno, 0, false /* dropped not applicable */ ,
					  NULL, &colvars);
			foreach(l, colvars)
			{
				var = (Var *) lfirst(l);

				tlist = lappend(tlist,
								makeTargetEntry((Expr *) var,
												var->varattno,
												NULL,
												false));
			}
			break;

775 776 777 778 779 780
		default:
			/* caller error */
			elog(ERROR, "unsupported RTE kind %d in build_physical_tlist",
				 (int) rte->rtekind);
			break;
	}
781

782
	return tlist;
783 784
}

785
/*
786
 * restriction_selectivity
787
 *
788
 * Returns the selectivity of a specified restriction operator clause.
789 790 791
 * This code executes registered procedures stored in the
 * operator relation, by calling the function manager.
 *
792
 * See clause_selectivity() for the meaning of the additional parameters.
793
 */
794
Selectivity
795
restriction_selectivity(PlannerInfo *root,
796 797 798
						Oid operator,
						List *args,
						int varRelid)
799
{
800
	RegProcedure oprrest = get_oprrest(operator);
801 802
	float8		result;

803
	/*
804 805
	 * if the oprrest procedure is missing for whatever reason, use a
	 * selectivity of 0.5
806 807 808 809 810 811 812 813 814
	 */
	if (!oprrest)
		return (Selectivity) 0.5;

	result = DatumGetFloat8(OidFunctionCall4(oprrest,
											 PointerGetDatum(root),
											 ObjectIdGetDatum(operator),
											 PointerGetDatum(args),
											 Int32GetDatum(varRelid)));
815 816

	if (result < 0.0 || result > 1.0)
817
		elog(ERROR, "invalid restriction selectivity: %f", result);
818 819

	return (Selectivity) result;
820 821 822
}

/*
823
 * join_selectivity
824
 *
825 826 827
 * Returns the selectivity of a specified join operator clause.
 * This code executes registered procedures stored in the
 * operator relation, by calling the function manager.
828
 */
829
Selectivity
830
join_selectivity(PlannerInfo *root,
831
				 Oid operator,
832
				 List *args,
833 834
				 JoinType jointype,
				 SpecialJoinInfo *sjinfo)
835
{
836
	RegProcedure oprjoin = get_oprjoin(operator);
837 838
	float8		result;

839
	/*
840 841
	 * if the oprjoin procedure is missing for whatever reason, use a
	 * selectivity of 0.5
842 843 844 845
	 */
	if (!oprjoin)
		return (Selectivity) 0.5;

846
	result = DatumGetFloat8(OidFunctionCall5(oprjoin,
847 848
											 PointerGetDatum(root),
											 ObjectIdGetDatum(operator),
849
											 PointerGetDatum(args),
850 851
											 Int16GetDatum(jointype),
											 PointerGetDatum(sjinfo)));
852 853

	if (result < 0.0 || result > 1.0)
854
		elog(ERROR, "invalid join selectivity: %f", result);
855 856

	return (Selectivity) result;
857 858 859
}

/*
860
 * find_inheritance_children
861
 *
862
 * Returns a list containing the OIDs of all relations which
863
 * inherit *directly* from the relation with OID 'inhparent'.
864 865 866 867 868
 *
 * XXX might be a good idea to create an index on pg_inherits' inhparent
 * field, so that we can use an indexscan instead of sequential scan here.
 * However, in typical databases pg_inherits won't have enough entries to
 * justify an indexscan...
869
 */
870
List *
871 872
find_inheritance_children(Oid inhparent)
{
873
	List	   *list = NIL;
874 875
	Relation	relation;
	HeapScanDesc scan;
876
	HeapTuple	inheritsTuple;
877
	Oid			inhrelid;
B
Bruce Momjian 已提交
878
	ScanKeyData key[1];
879

880
	/*
B
Bruce Momjian 已提交
881 882
	 * Can skip the scan if pg_class shows the relation has never had a
	 * subclass.
883
	 */
B
Bruce Momjian 已提交
884
	if (!has_subclass(inhparent))
885 886
		return NIL;

887 888 889 890
	ScanKeyInit(&key[0],
				Anum_pg_inherits_inhparent,
				BTEqualStrategyNumber, F_OIDEQ,
				ObjectIdGetDatum(inhparent));
891
	relation = heap_open(InheritsRelationId, AccessShareLock);
892 893
	scan = heap_beginscan(relation, SnapshotNow, 1, key);
	while ((inheritsTuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
894
	{
895
		inhrelid = ((Form_pg_inherits) GETSTRUCT(inheritsTuple))->inhrelid;
896
		list = lappend_oid(list, inhrelid);
897 898
	}
	heap_endscan(scan);
899
	heap_close(relation, AccessShareLock);
900
	return list;
901 902
}

903
/*
904 905
 * has_subclass
 *
B
Bruce Momjian 已提交
906
 * In the current implementation, has_subclass returns whether a
907 908
 * particular class *might* have a subclass. It will not return the
 * correct result if a class had a subclass which was later dropped.
909 910 911 912 913
 * This is because relhassubclass in pg_class is not updated when a
 * subclass is dropped, primarily because of concurrency concerns.
 *
 * Currently has_subclass is only used as an efficiency hack to skip
 * unnecessary inheritance searches, so this is OK.
914
 */
915 916
bool
has_subclass(Oid relationId)
917
{
918 919
	HeapTuple	tuple;
	bool		result;
920

921 922 923
	tuple = SearchSysCache(RELOID,
						   ObjectIdGetDatum(relationId),
						   0, 0, 0);
924
	if (!HeapTupleIsValid(tuple))
925
		elog(ERROR, "cache lookup failed for relation %u", relationId);
926 927 928 929

	result = ((Form_pg_class) GETSTRUCT(tuple))->relhassubclass;
	ReleaseSysCache(tuple);
	return result;
930
}
931 932 933 934 935 936 937 938 939 940 941

/*
 * has_unique_index
 *
 * Detect whether there is a unique index on the specified attribute
 * of the specified relation, thus allowing us to conclude that all
 * the (non-null) values of the attribute are distinct.
 */
bool
has_unique_index(RelOptInfo *rel, AttrNumber attno)
{
942
	ListCell   *ilist;
943 944 945 946 947 948

	foreach(ilist, rel->indexlist)
	{
		IndexOptInfo *index = (IndexOptInfo *) lfirst(ilist);

		/*
B
Bruce Momjian 已提交
949 950 951 952 953
		 * Note: ignore partial indexes, since they don't allow us to conclude
		 * that all attr values are distinct.  We don't take any interest in
		 * expressional indexes either. Also, a multicolumn unique index
		 * doesn't allow us to conclude that just the specified attr is
		 * unique.
954 955
		 */
		if (index->unique &&
956
			index->ncolumns == 1 &&
957
			index->indexkeys[0] == attno &&
958
			index->indpred == NIL)
959 960 961 962
			return true;
	}
	return false;
}