mirror of
https://github.com/postgres/postgres.git
synced 2025-06-27 23:21:58 +03:00
Allow merge and hash joins to occur on arbitrary expressions (anything not
containing a volatile function), rather than only on 'Var = Var' clauses as before. This makes it practical to do flatten_join_alias_vars at the start of planning, which in turn eliminates a bunch of klugery inside the planner to deal with alias vars. As a free side effect, we now detect implied equality of non-Var expressions; for example in SELECT ... WHERE a.x = b.y and b.y = 42 we will deduce a.x = 42 and use that as a restriction qual on a. Also, we can remove the restriction introduced 12/5/02 to prevent pullup of subqueries whose targetlists contain sublinks. Still TODO: make statistical estimation routines in selfuncs.c and costsize.c smarter about expressions that are more complex than plain Vars. The need for this is considerably greater now that we have to be able to estimate the suitability of merge and hash join techniques on such expressions.
This commit is contained in:
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/joinpath.c,v 1.74 2002/11/30 05:21:02 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/joinpath.c,v 1.75 2003/01/15 19:35:40 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -774,10 +774,9 @@ hash_inner_and_outer(Query *root,
|
||||
foreach(i, restrictlist)
|
||||
{
|
||||
RestrictInfo *restrictinfo = (RestrictInfo *) lfirst(i);
|
||||
Var *left,
|
||||
*right;
|
||||
|
||||
if (restrictinfo->hashjoinoperator == InvalidOid)
|
||||
if (restrictinfo->left_relids == NIL ||
|
||||
restrictinfo->hashjoinoperator == InvalidOid)
|
||||
continue; /* not hashjoinable */
|
||||
|
||||
/*
|
||||
@ -787,26 +786,16 @@ hash_inner_and_outer(Query *root,
|
||||
if (isouterjoin && restrictinfo->ispusheddown)
|
||||
continue;
|
||||
|
||||
/* these must be OK, since check_hashjoinable accepted the clause */
|
||||
left = get_leftop(restrictinfo->clause);
|
||||
right = get_rightop(restrictinfo->clause);
|
||||
|
||||
/*
|
||||
* Check if clause is usable with these input rels.
|
||||
*
|
||||
* Since we currently accept only var-op-var clauses as hashjoinable,
|
||||
* we need only check the membership of the vars to determine whether
|
||||
* a particular clause can be used with this pair of sub-relations.
|
||||
* This code would need to be upgraded if we wanted to allow
|
||||
* more-complex expressions in hash joins.
|
||||
*/
|
||||
if (VARISRELMEMBER(left->varno, outerrel) &&
|
||||
VARISRELMEMBER(right->varno, innerrel))
|
||||
if (is_subseti(restrictinfo->left_relids, outerrel->relids) &&
|
||||
is_subseti(restrictinfo->right_relids, innerrel->relids))
|
||||
{
|
||||
/* righthand side is inner */
|
||||
}
|
||||
else if (VARISRELMEMBER(left->varno, innerrel) &&
|
||||
VARISRELMEMBER(right->varno, outerrel))
|
||||
else if (is_subseti(restrictinfo->left_relids, innerrel->relids) &&
|
||||
is_subseti(restrictinfo->right_relids, outerrel->relids))
|
||||
{
|
||||
/* lefthand side is inner */
|
||||
}
|
||||
@ -874,9 +863,6 @@ select_mergejoin_clauses(RelOptInfo *joinrel,
|
||||
foreach(i, restrictlist)
|
||||
{
|
||||
RestrictInfo *restrictinfo = (RestrictInfo *) lfirst(i);
|
||||
Expr *clause;
|
||||
Var *left,
|
||||
*right;
|
||||
|
||||
/*
|
||||
* If processing an outer join, only use its own join clauses in
|
||||
@ -896,11 +882,13 @@ select_mergejoin_clauses(RelOptInfo *joinrel,
|
||||
switch (jointype)
|
||||
{
|
||||
case JOIN_RIGHT:
|
||||
if (restrictinfo->mergejoinoperator == InvalidOid)
|
||||
if (restrictinfo->left_relids == NIL ||
|
||||
restrictinfo->mergejoinoperator == InvalidOid)
|
||||
return NIL; /* not mergejoinable */
|
||||
break;
|
||||
case JOIN_FULL:
|
||||
if (restrictinfo->mergejoinoperator == InvalidOid)
|
||||
if (restrictinfo->left_relids == NIL ||
|
||||
restrictinfo->mergejoinoperator == InvalidOid)
|
||||
elog(ERROR, "FULL JOIN is only supported with mergejoinable join conditions");
|
||||
break;
|
||||
default:
|
||||
@ -909,19 +897,27 @@ select_mergejoin_clauses(RelOptInfo *joinrel,
|
||||
}
|
||||
}
|
||||
|
||||
if (restrictinfo->mergejoinoperator == InvalidOid)
|
||||
if (restrictinfo->left_relids == NIL ||
|
||||
restrictinfo->mergejoinoperator == InvalidOid)
|
||||
continue; /* not mergejoinable */
|
||||
|
||||
clause = restrictinfo->clause;
|
||||
/* these must be OK, since check_mergejoinable accepted the clause */
|
||||
left = get_leftop(clause);
|
||||
right = get_rightop(clause);
|
||||
/*
|
||||
* Check if clause is usable with these input rels.
|
||||
*/
|
||||
if (is_subseti(restrictinfo->left_relids, outerrel->relids) &&
|
||||
is_subseti(restrictinfo->right_relids, innerrel->relids))
|
||||
{
|
||||
/* righthand side is inner */
|
||||
}
|
||||
else if (is_subseti(restrictinfo->left_relids, innerrel->relids) &&
|
||||
is_subseti(restrictinfo->right_relids, outerrel->relids))
|
||||
{
|
||||
/* lefthand side is inner */
|
||||
}
|
||||
else
|
||||
continue; /* no good for these input relations */
|
||||
|
||||
if ((VARISRELMEMBER(left->varno, outerrel) &&
|
||||
VARISRELMEMBER(right->varno, innerrel)) ||
|
||||
(VARISRELMEMBER(left->varno, innerrel) &&
|
||||
VARISRELMEMBER(right->varno, outerrel)))
|
||||
result_list = lcons(restrictinfo, result_list);
|
||||
result_list = lcons(restrictinfo, result_list);
|
||||
}
|
||||
|
||||
return result_list;
|
||||
|
Reference in New Issue
Block a user