initsplan.c

来自「postgresql8.3.4源码,开源数据库」· C语言 代码 · 共 1,362 行 · 第 1/4 页

C
1,362
字号
		 */		foreach(l, (List *) f->quals)			distribute_qual_to_rels(root, (Node *) lfirst(l),									false, below_outer_join,									*qualscope, NULL, NULL);	}	else if (IsA(jtnode, JoinExpr))	{		JoinExpr   *j = (JoinExpr *) jtnode;		Relids		leftids,					rightids,					left_inners,					right_inners,					nonnullable_rels,					ojscope;		List	   *leftjoinlist,				   *rightjoinlist;		OuterJoinInfo *ojinfo;		ListCell   *qual;		/*		 * Order of operations here is subtle and critical.  First we recurse		 * to handle sub-JOINs.  Their join quals will be placed without		 * regard for whether this level is an outer join, which is correct.		 * Then we place our own join quals, which are restricted by lower		 * outer joins in any case, and are forced to this level if this is an		 * outer join and they mention the outer side.	Finally, if this is an		 * outer join, we create an oj_info_list entry for the join.  This		 * will prevent quals above us in the join tree that use those rels		 * from being pushed down below this level.  (It's okay for upper		 * quals to be pushed down to the outer side, however.)		 */		switch (j->jointype)		{			case JOIN_INNER:				leftjoinlist = deconstruct_recurse(root, j->larg,												   below_outer_join,												   &leftids, &left_inners);				rightjoinlist = deconstruct_recurse(root, j->rarg,													below_outer_join,													&rightids, &right_inners);				*qualscope = bms_union(leftids, rightids);				*inner_join_rels = *qualscope;				/* Inner join adds no restrictions for quals */				nonnullable_rels = NULL;				break;			case JOIN_LEFT:				leftjoinlist = deconstruct_recurse(root, j->larg,												   below_outer_join,												   &leftids, &left_inners);				rightjoinlist = deconstruct_recurse(root, j->rarg,													true,													&rightids, &right_inners);				*qualscope = bms_union(leftids, rightids);				*inner_join_rels = bms_union(left_inners, right_inners);				nonnullable_rels = leftids;				break;			case JOIN_FULL:				leftjoinlist = deconstruct_recurse(root, j->larg,												   true,												   &leftids, &left_inners);				rightjoinlist = deconstruct_recurse(root, j->rarg,													true,													&rightids, &right_inners);				*qualscope = bms_union(leftids, rightids);				*inner_join_rels = bms_union(left_inners, right_inners);				/* each side is both outer and inner */				nonnullable_rels = *qualscope;				break;			case JOIN_RIGHT:				/* notice we switch leftids and rightids */				leftjoinlist = deconstruct_recurse(root, j->larg,												   true,												   &rightids, &right_inners);				rightjoinlist = deconstruct_recurse(root, j->rarg,													below_outer_join,													&leftids, &left_inners);				*qualscope = bms_union(leftids, rightids);				*inner_join_rels = bms_union(left_inners, right_inners);				nonnullable_rels = leftids;				break;			default:				elog(ERROR, "unrecognized join type: %d",					 (int) j->jointype);				nonnullable_rels = NULL;		/* keep compiler quiet */				leftjoinlist = rightjoinlist = NIL;				break;		}		/*		 * For an OJ, form the OuterJoinInfo now, because we need the OJ's		 * semantic scope (ojscope) to pass to distribute_qual_to_rels.  But		 * we mustn't add it to oj_info_list just yet, because we don't want		 * distribute_qual_to_rels to think it is an outer join below us.		 */		if (j->jointype != JOIN_INNER)		{			ojinfo = make_outerjoininfo(root,										leftids, rightids,										*inner_join_rels,										(j->jointype == JOIN_FULL),										j->quals);			ojscope = bms_union(ojinfo->min_lefthand, ojinfo->min_righthand);		}		else		{			ojinfo = NULL;			ojscope = NULL;		}		/* Process the qual clauses */		foreach(qual, (List *) j->quals)			distribute_qual_to_rels(root, (Node *) lfirst(qual),									false, below_outer_join,									*qualscope, ojscope, nonnullable_rels);		/* Now we can add the OuterJoinInfo to oj_info_list */		if (ojinfo)			root->oj_info_list = lappend(root->oj_info_list, ojinfo);		/*		 * Finally, compute the output joinlist.  We fold subproblems together		 * except at a FULL JOIN or where join_collapse_limit would be		 * exceeded.		 */		if (j->jointype == JOIN_FULL)		{			/* force the join order exactly at this node */			joinlist = list_make1(list_make2(leftjoinlist, rightjoinlist));		}		else if (list_length(leftjoinlist) + list_length(rightjoinlist) <=				 join_collapse_limit)		{			/* OK to combine subproblems */			joinlist = list_concat(leftjoinlist, rightjoinlist);		}		else		{			/* can't combine, but needn't force join order above here */			Node	   *leftpart,					   *rightpart;			/* avoid creating useless 1-element sublists */			if (list_length(leftjoinlist) == 1)				leftpart = (Node *) linitial(leftjoinlist);			else				leftpart = (Node *) leftjoinlist;			if (list_length(rightjoinlist) == 1)				rightpart = (Node *) linitial(rightjoinlist);			else				rightpart = (Node *) rightjoinlist;			joinlist = list_make2(leftpart, rightpart);		}	}	else	{		elog(ERROR, "unrecognized node type: %d",			 (int) nodeTag(jtnode));		joinlist = NIL;			/* keep compiler quiet */	}	return joinlist;}/* * make_outerjoininfo *	  Build an OuterJoinInfo for the current outer join * * Inputs: *	left_rels: the base Relids syntactically on outer side of join *	right_rels: the base Relids syntactically on inner side of join *	inner_join_rels: base Relids participating in inner joins below this one *	is_full_join: what it says *	clause: the outer join's join condition * * If the join is a RIGHT JOIN, left_rels and right_rels are switched by * the caller, so that left_rels is always the nonnullable side.  Hence * we need only distinguish the LEFT and FULL cases. * * The node should eventually be appended to root->oj_info_list, but we * do not do that here. * * Note: we assume that this function is invoked bottom-up, so that * root->oj_info_list already contains entries for all outer joins that are * syntactically below this one. */static OuterJoinInfo *make_outerjoininfo(PlannerInfo *root,				   Relids left_rels, Relids right_rels,				   Relids inner_join_rels,				   bool is_full_join, Node *clause){	OuterJoinInfo *ojinfo = makeNode(OuterJoinInfo);	Relids		clause_relids;	Relids		strict_relids;	Relids		min_lefthand;	Relids		min_righthand;	ListCell   *l;	/*	 * Presently the executor cannot support FOR UPDATE/SHARE marking of rels	 * appearing on the nullable side of an outer join. (It's somewhat unclear	 * what that would mean, anyway: what should we mark when a result row is	 * generated from no element of the nullable relation?)  So, complain if	 * any nullable rel is FOR UPDATE/SHARE.	 *	 * You might be wondering why this test isn't made far upstream in the	 * parser.	It's because the parser hasn't got enough info --- consider	 * FOR UPDATE applied to a view.  Only after rewriting and flattening do	 * we know whether the view contains an outer join.	 */	foreach(l, root->parse->rowMarks)	{		RowMarkClause *rc = (RowMarkClause *) lfirst(l);		if (bms_is_member(rc->rti, right_rels) ||			(is_full_join && bms_is_member(rc->rti, left_rels)))			ereport(ERROR,					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),					 errmsg("SELECT FOR UPDATE/SHARE cannot be applied to the nullable side of an outer join")));	}	/* this always starts out false */	ojinfo->delay_upper_joins = false;	/* If it's a full join, no need to be very smart */	ojinfo->syn_lefthand = left_rels;	ojinfo->syn_righthand = right_rels;	ojinfo->is_full_join = is_full_join;	if (is_full_join)	{		ojinfo->min_lefthand = left_rels;		ojinfo->min_righthand = right_rels;		ojinfo->lhs_strict = false;		/* don't care about this */		return ojinfo;	}	/*	 * Retrieve all relids mentioned within the join clause.	 */	clause_relids = pull_varnos(clause);	/*	 * For which relids is the clause strict, ie, it cannot succeed if the	 * rel's columns are all NULL?	 */	strict_relids = find_nonnullable_rels(clause);	/* Remember whether the clause is strict for any LHS relations */	ojinfo->lhs_strict = bms_overlap(strict_relids, left_rels);	/*	 * Required LHS always includes the LHS rels mentioned in the clause. We	 * may have to add more rels based on lower outer joins; see below.	 */	min_lefthand = bms_intersect(clause_relids, left_rels);	/*	 * Similarly for required RHS.	But here, we must also include any lower	 * inner joins, to ensure we don't try to commute with any of them.	 */	min_righthand = bms_int_members(bms_union(clause_relids, inner_join_rels),									right_rels);	foreach(l, root->oj_info_list)	{		OuterJoinInfo *otherinfo = (OuterJoinInfo *) lfirst(l);		/* ignore full joins --- other mechanisms preserve their ordering */		if (otherinfo->is_full_join)			continue;		/*		 * For a lower OJ in our LHS, if our join condition uses the lower		 * join's RHS and is not strict for that rel, we must preserve the		 * ordering of the two OJs, so add lower OJ's full syntactic relset to		 * min_lefthand.  (We must use its full syntactic relset, not just its		 * min_lefthand + min_righthand.  This is because there might be other		 * OJs below this one that this one can commute with, but we cannot		 * commute with them if we don't with this one.)		 *		 * Note: I believe we have to insist on being strict for at least one		 * rel in the lower OJ's min_righthand, not its whole syn_righthand.		 */		if (bms_overlap(left_rels, otherinfo->syn_righthand) &&			bms_overlap(clause_relids, otherinfo->syn_righthand) &&			!bms_overlap(strict_relids, otherinfo->min_righthand))		{			min_lefthand = bms_add_members(min_lefthand,										   otherinfo->syn_lefthand);			min_lefthand = bms_add_members(min_lefthand,										   otherinfo->syn_righthand);		}		/*		 * For a lower OJ in our RHS, if our join condition does not use the		 * lower join's RHS and the lower OJ's join condition is strict, we		 * can interchange the ordering of the two OJs; otherwise we must add		 * lower OJ's full syntactic relset to min_righthand.		 *		 * Here, we have to consider that "our join condition" includes any		 * clauses that syntactically appeared above the lower OJ and below		 * ours; those are equivalent to degenerate clauses in our OJ and must		 * be treated as such.	Such clauses obviously can't reference our		 * LHS, and they must be non-strict for the lower OJ's RHS (else		 * reduce_outer_joins would have reduced the lower OJ to a plain		 * join).  Hence the other ways in which we handle clauses within our		 * join condition are not affected by them.  The net effect is		 * therefore sufficiently represented by the delay_upper_joins flag		 * saved for us by check_outerjoin_delay.		 */		if (bms_overlap(right_rels, otherinfo->syn_righthand))		{			if (bms_overlap(clause_relids, otherinfo->syn_righthand) ||				!otherinfo->lhs_strict || otherinfo->delay_upper_joins)			{				min_righthand = bms_add_members(min_righthand,												otherinfo->syn_lefthand);				min_righthand = bms_add_members(min_righthand,												otherinfo->syn_righthand);			}		}	}	/*	 * If we found nothing to put in min_lefthand, punt and make it the full	 * LHS, to avoid having an empty min_lefthand which will confuse later	 * processing. (We don't try to be smart about such cases, just correct.)	 * Likewise for min_righthand.	 */	if (bms_is_empty(min_lefthand))		min_lefthand = bms_copy(left_rels);	if (bms_is_empty(min_righthand))		min_righthand = bms_copy(right_rels);	/* Now they'd better be nonempty */	Assert(!bms_is_empty(min_lefthand));	Assert(!bms_is_empty(min_righthand));	/* Shouldn't overlap either */	Assert(!bms_overlap(min_lefthand, min_righthand));	ojinfo->min_lefthand = min_lefthand;

⌨️ 快捷键说明

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