⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 relation.h

📁 PostgreSQL 8.2中增加了很多企业用户所需要的功能和性能上的提高,其开发团队说,该版本将加速更多企业向该数据库移植.核心开发成员之一Bruce Momjian表示,在新版PostgreSQL
💻 H
📖 第 1 页 / 共 3 页
字号:
 * When we construct a join rel that includes all the base rels referenced * in a multi-relation restriction clause, we place that clause into the * joinrestrictinfo lists of paths for the join rel, if neither left nor * right sub-path includes all base rels referenced in the clause.	The clause * will be applied at that join level, and will not propagate any further up * the join tree.  (Note: the "predicate migration" code was once intended to * push restriction clauses up and down the plan tree based on evaluation * costs, but it's dead code and is unlikely to be resurrected in the * foreseeable future.) * * Note that in the presence of more than two rels, a multi-rel restriction * might reach different heights in the join tree depending on the join * sequence we use.  So, these clauses cannot be associated directly with * the join RelOptInfo, but must be kept track of on a per-join-path basis. * * When dealing with outer joins we have to be very careful about pushing qual * clauses up and down the tree.  An outer join's own JOIN/ON conditions must * be evaluated exactly at that join node, and any quals appearing in WHERE or * in a JOIN above the outer join cannot be pushed down below the outer join. * Otherwise the outer join will produce wrong results because it will see the * wrong sets of input rows.  All quals are stored as RestrictInfo nodes * during planning, but there's a flag to indicate whether a qual has been * pushed down to a lower level than its original syntactic placement in the * join tree would suggest.  If an outer join prevents us from pushing a qual * down to its "natural" semantic level (the level associated with just the * base rels used in the qual) then we mark the qual with a "required_relids" * value including more than just the base rels it actually uses.  By * pretending that the qual references all the rels appearing in the outer * join, we prevent it from being evaluated below the outer join's joinrel. * When we do form the outer join's joinrel, we still need to distinguish * those quals that are actually in that join's JOIN/ON condition from those * that appeared elsewhere in the tree and were pushed down to the join rel * because they used no other rels.  That's what the is_pushed_down flag is * for; it tells us that a qual is not an OUTER JOIN qual for the set of base * rels listed in required_relids.  A clause that originally came from WHERE * or an INNER JOIN condition will *always* have its is_pushed_down flag set. * It's possible for an OUTER JOIN clause to be marked is_pushed_down too, * if we decide that it can be pushed down into the nullable side of the join. * In that case it acts as a plain filter qual for wherever it gets evaluated. * * When application of a qual must be delayed by outer join, we also mark it * with outerjoin_delayed = true.  This isn't redundant with required_relids * because that might equal clause_relids whether or not it's an outer-join * clause. * * In general, the referenced clause might be arbitrarily complex.	The * kinds of clauses we can handle as indexscan quals, mergejoin clauses, * or hashjoin clauses are fairly limited --- the code for each kind of * path is responsible for identifying the restrict clauses it can use * and ignoring the rest.  Clauses not implemented by an indexscan, * mergejoin, or hashjoin will be placed in the plan qual or joinqual field * of the finished Plan node, where they will be enforced by general-purpose * qual-expression-evaluation code.  (But we are still entitled to count * their selectivity when estimating the result tuple count, if we * can guess what it is...) * * When the referenced clause is an OR clause, we generate a modified copy * in which additional RestrictInfo nodes are inserted below the top-level * OR/AND structure.  This is a convenience for OR indexscan processing: * indexquals taken from either the top level or an OR subclause will have * associated RestrictInfo nodes. * * The can_join flag is set true if the clause looks potentially useful as * a merge or hash join clause, that is if it is a binary opclause with * nonoverlapping sets of relids referenced in the left and right sides. * (Whether the operator is actually merge or hash joinable isn't checked, * however.) * * The pseudoconstant flag is set true if the clause contains no Vars of * the current query level and no volatile functions.  Such a clause can be * pulled out and used as a one-time qual in a gating Result node.	We keep * pseudoconstant clauses in the same lists as other RestrictInfos so that * the regular clause-pushing machinery can assign them to the correct join * level, but they need to be treated specially for cost and selectivity * estimates.  Note that a pseudoconstant clause can never be an indexqual * or merge or hash join clause, so it's of no interest to large parts of * the planner. */typedef struct RestrictInfo{	NodeTag		type;	Expr	   *clause;			/* the represented clause of WHERE or JOIN */	bool		is_pushed_down; /* TRUE if clause was pushed down in level */	bool		outerjoin_delayed;		/* TRUE if delayed by outer join */	bool		can_join;		/* see comment above */	bool		pseudoconstant; /* see comment above */	/* The set of relids (varnos) actually referenced in the clause: */	Relids		clause_relids;	/* The set of relids required to evaluate the clause: */	Relids		required_relids;	/* These fields are set for any binary opclause: */	Relids		left_relids;	/* relids in left side of clause */	Relids		right_relids;	/* relids in right side of clause */	/* This field is NULL unless clause is an OR clause: */	Expr	   *orclause;		/* modified clause with RestrictInfos */	/* cache space for cost and selectivity */	QualCost	eval_cost;		/* eval cost of clause; -1 if not yet set */	Selectivity this_selec;		/* selectivity; -1 if not yet set */	/* valid if clause is mergejoinable, else InvalidOid: */	Oid			mergejoinoperator;		/* copy of clause operator */	Oid			left_sortop;	/* leftside sortop needed for mergejoin */	Oid			right_sortop;	/* rightside sortop needed for mergejoin */	/* cache space for mergeclause processing; NIL if not yet set */	List	   *left_pathkey;	/* canonical pathkey for left side */	List	   *right_pathkey;	/* canonical pathkey for right side */	/* cache space for mergeclause processing; -1 if not yet set */	Selectivity left_mergescansel;		/* fraction of left side to scan */	Selectivity right_mergescansel;		/* fraction of right side to scan */	/* valid if clause is hashjoinable, else InvalidOid: */	Oid			hashjoinoperator;		/* copy of clause operator */	/* cache space for hashclause processing; -1 if not yet set */	Selectivity left_bucketsize;	/* avg bucketsize of left side */	Selectivity right_bucketsize;		/* avg bucketsize of right side */} RestrictInfo;/* * Inner indexscan info. * * An inner indexscan is one that uses one or more joinclauses as index * conditions (perhaps in addition to plain restriction clauses).  So it * can only be used as the inner path of a nestloop join where the outer * relation includes all other relids appearing in those joinclauses. * The set of usable joinclauses, and thus the best inner indexscan, * thus varies depending on which outer relation we consider; so we have * to recompute the best such paths for every join.  To avoid lots of * redundant computation, we cache the results of such searches.  For * each relation we compute the set of possible otherrelids (all relids * appearing in joinquals that could become indexquals for this table). * Two outer relations whose relids have the same intersection with this * set will have the same set of available joinclauses and thus the same * best inner indexscans for the inner relation.  By taking the intersection * before scanning the cache, we avoid recomputing when considering * join rels that differ only by the inclusion of irrelevant other rels. * * The search key also includes a bool showing whether the join being * considered is an outer join.  Since we constrain the join order for * outer joins, I believe that this bool can only have one possible value * for any particular lookup key; but store it anyway to avoid confusion. */typedef struct InnerIndexscanInfo{	NodeTag		type;	/* The lookup key: */	Relids		other_relids;	/* a set of relevant other relids */	bool		isouterjoin;	/* true if join is outer */	/* Best paths for this lookup key (NULL if no available indexscans): */	Path	   *cheapest_startup_innerpath;	/* cheapest startup cost */	Path	   *cheapest_total_innerpath;	/* cheapest total cost */} InnerIndexscanInfo;/* * Outer join info. * * One-sided outer joins constrain the order of joining partially but not * completely.	We flatten such joins into the planner's top-level list of * relations to join, but record information about each outer join in an * OuterJoinInfo struct.  These structs are kept in the PlannerInfo node's * oj_info_list. * * min_lefthand and min_righthand are the sets of base relids that must be * available on each side when performing the outer join.  lhs_strict is * true if the outer join's condition cannot succeed when the LHS variables * are all NULL (this means that the outer join can commute with upper-level * outer joins even if it appears in their RHS).  We don't bother to set * lhs_strict for FULL JOINs, however. * * It is not valid for either min_lefthand or min_righthand to be empty sets; * if they were, this would break the logic that enforces join order. * * syn_lefthand and syn_righthand are the sets of base relids that are * syntactically below this outer join.  (These are needed to help compute * min_lefthand and min_righthand for higher joins, but are not used * thereafter.) * * delay_upper_joins is set TRUE if we detect a pushed-down clause that has * to be evaluated after this join is formed (because it references the RHS). * Any outer joins that have such a clause and this join in their RHS cannot * commute with this join, because that would leave noplace to check the * pushed-down clause.  (We don't track this for FULL JOINs, either.) * * Note: OuterJoinInfo directly represents only LEFT JOIN and FULL JOIN; * RIGHT JOIN is handled by switching the inputs to make it a LEFT JOIN. * We make an OuterJoinInfo for FULL JOINs even though there is no flexibility * of planning for them, because this simplifies make_join_rel()'s API. */typedef struct OuterJoinInfo{	NodeTag		type;	Relids		min_lefthand;	/* base relids in minimum LHS for join */	Relids		min_righthand;	/* base relids in minimum RHS for join */	Relids		syn_lefthand;	/* base relids syntactically within LHS */	Relids		syn_righthand;	/* base relids syntactically within RHS */	bool		is_full_join;	/* it's a FULL OUTER JOIN */	bool		lhs_strict;		/* joinclause is strict for some LHS rel */	bool		delay_upper_joins;	/* can't commute with upper RHS */} OuterJoinInfo;/* * IN clause info. * * When we convert top-level IN quals into join operations, we must restrict * the order of joining and use special join methods at some join points. * We record information about each such IN clause in an InClauseInfo struct. * These structs are kept in the PlannerInfo node's in_info_list. */typedef struct InClauseInfo{	NodeTag		type;	Relids		lefthand;		/* base relids in lefthand expressions */	Relids		righthand;		/* base relids coming from the subselect */	List	   *sub_targetlist; /* targetlist of original RHS subquery */	/*	 * Note: sub_targetlist is just a list of Vars or expressions; it does not	 * contain TargetEntry nodes.	 */} InClauseInfo;/* * Append-relation info. * * When we expand an inheritable table or a UNION-ALL subselect into an * "append relation" (essentially, a list of child RTEs), we build an * AppendRelInfo for each child RTE.  The list of AppendRelInfos indicates * which child RTEs must be included when expanding the parent, and each * node carries information needed to translate Vars referencing the parent * into Vars referencing that child. * * These structs are kept in the PlannerInfo node's append_rel_list. * Note that we just throw all the structs into one list, and scan the * whole list when desiring to expand any one parent.  We could have used * a more complex data structure (eg, one list per parent), but this would * be harder to update during operations such as pulling up subqueries, * and not really any easier to scan.  Considering that typical queries * will not have many different append parents, it doesn't seem worthwhile * to complicate things. * * Note: after completion of the planner prep phase, any given RTE is an * append parent having entries in append_rel_list if and only if its * "inh" flag is set.  We clear "inh" for plain tables that turn out not * to have inheritance children, and (in an abuse of the original meaning * of the flag) we set "inh" for subquery RTEs that turn out to be * flattenable UNION ALL queries.  This lets us avoid useless searches * of append_rel_list. * * Note: the data structure assumes that append-rel members are single * baserels.  This is OK for inheritance, but it prevents us from pulling * up a UNION ALL member subquery if it contains a join.  While that could * be fixed with a more complex data structure, at present there's not much * point because no improvement in the plan could result. */typedef struct AppendRelInfo{	NodeTag		type;	/*	 * These fields uniquely identify this append relationship.  There can be	 * (in fact, always should be) multiple AppendRelInfos for the same	 * parent_relid, but never more than one per child_relid, since a given	 * RTE cannot be a child of more than one append parent.	 */	Index		parent_relid;	/* RT index of append parent rel */	Index		child_relid;	/* RT index of append child rel */	/*	 * For an inheritance appendrel, the parent and child are both regular	 * relations, and we store their rowtype OIDs here for use in translating	 * whole-row Vars.	For a UNION-ALL appendrel, the parent and child are	 * both subqueries with no named rowtype, and we store InvalidOid here.	 */	Oid			parent_reltype; /* OID of parent's composite type */	Oid			child_reltype;	/* OID of child's composite type */	/*	 * The N'th element of this list is the integer column number of the child	 * column corresponding to the N'th column of the parent. A list element	 * is zero if it corresponds to a dropped column of the parent (this is	 * only possible for inheritance cases, not UNION ALL).	 */	List	   *col_mappings;	/* list of child attribute numbers */	/*	 * The N'th element of this list is a Var or expression representing the	 * child column corresponding to the N'th column of the parent. This is	 * used to translate Vars referencing the parent rel into references to	 * the child.  A list element is NULL if it corresponds to a dropped	 * column of the parent (this is only possible for inheritance cases, not	 * UNION ALL).	 *	 * This might seem redundant with the col_mappings data, but it is handy	 * because flattening of sub-SELECTs that are members of a UNION ALL will	 * cause changes in the expressions that need to be substituted for a	 * parent Var.	Adjusting this data structure lets us track what really	 * needs to be substituted.	 *	 * Notice we only store entries for user columns (attno > 0).  Whole-row	 * Vars are special-cased, and system columns (attno < 0) need no special	 * translation since their attnos are the same for all tables.	 *	 * Caution: the Vars have varlevelsup = 0.	Be careful to adjust as needed	 * when copying into a subquery.	 */	List	   *translated_vars;	/* Expressions in the child's Vars */	/*	 * We store the parent table's OID here for inheritance, or InvalidOid for	 * UNION ALL.  This is only needed to help in generating error messages if	 * an attempt is made to reference a dropped parent column.	 */	Oid			parent_reloid;	/* OID of parent relation */} AppendRelInfo;#endif   /* RELATION_H */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -