mirror of
https://github.com/postgres/postgres.git
synced 2025-07-11 10:01:57 +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/util/relnode.c,v 1.42 2003/01/12 22:35:29 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/relnode.c,v 1.43 2003/01/15 19:35:44 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -110,9 +110,9 @@ build_other_rel(Query *root, int relid)
|
||||
/* No existing RelOptInfo for this other rel, so make a new one */
|
||||
rel = make_base_rel(root, relid);
|
||||
|
||||
/* if it's not a join rel, must be a child rel */
|
||||
if (rel->reloptkind == RELOPT_BASEREL)
|
||||
rel->reloptkind = RELOPT_OTHER_CHILD_REL;
|
||||
/* presently, must be an inheritance child rel */
|
||||
Assert(rel->reloptkind == RELOPT_BASEREL);
|
||||
rel->reloptkind = RELOPT_OTHER_CHILD_REL;
|
||||
|
||||
/* and add it to the list */
|
||||
root->other_rel_list = lcons(rel, root->other_rel_list);
|
||||
@ -146,8 +146,6 @@ make_base_rel(Query *root, int relid)
|
||||
rel->pages = 0;
|
||||
rel->tuples = 0;
|
||||
rel->subplan = NULL;
|
||||
rel->joinrti = 0;
|
||||
rel->joinrteids = NIL;
|
||||
rel->baserestrictinfo = NIL;
|
||||
rel->baserestrictcost.startup = 0;
|
||||
rel->baserestrictcost.per_tuple = 0;
|
||||
@ -174,10 +172,6 @@ make_base_rel(Query *root, int relid)
|
||||
case RTE_FUNCTION:
|
||||
/* Subquery or function --- nothing to do here */
|
||||
break;
|
||||
case RTE_JOIN:
|
||||
/* Join --- must be an otherrel */
|
||||
rel->reloptkind = RELOPT_OTHER_JOIN_REL;
|
||||
break;
|
||||
default:
|
||||
elog(ERROR, "make_base_rel: unsupported RTE kind %d",
|
||||
(int) rte->rtekind);
|
||||
@ -220,47 +214,6 @@ find_base_rel(Query *root, int relid)
|
||||
return NULL; /* keep compiler quiet */
|
||||
}
|
||||
|
||||
/*
|
||||
* find_other_rel
|
||||
* Find an otherrel entry, if one exists for the given relid.
|
||||
* Return NULL if no entry.
|
||||
*/
|
||||
RelOptInfo *
|
||||
find_other_rel(Query *root, int relid)
|
||||
{
|
||||
List *rels;
|
||||
|
||||
foreach(rels, root->other_rel_list)
|
||||
{
|
||||
RelOptInfo *rel = (RelOptInfo *) lfirst(rels);
|
||||
|
||||
if (lfirsti(rel->relids) == relid)
|
||||
return rel;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* find_other_rel_for_join
|
||||
* Look for an otherrel for a join RTE matching the given baserel set.
|
||||
* Return NULL if no entry.
|
||||
*/
|
||||
RelOptInfo *
|
||||
find_other_rel_for_join(Query *root, List *relids)
|
||||
{
|
||||
List *rels;
|
||||
|
||||
foreach(rels, root->other_rel_list)
|
||||
{
|
||||
RelOptInfo *rel = (RelOptInfo *) lfirst(rels);
|
||||
|
||||
if (rel->reloptkind == RELOPT_OTHER_JOIN_REL
|
||||
&& sameseti(relids, rel->outerjoinset))
|
||||
return rel;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* find_join_rel
|
||||
* Returns relation entry corresponding to 'relids' (a list of RT indexes),
|
||||
@ -310,7 +263,6 @@ build_join_rel(Query *root,
|
||||
{
|
||||
List *joinrelids;
|
||||
RelOptInfo *joinrel;
|
||||
RelOptInfo *joinrterel;
|
||||
List *restrictlist;
|
||||
List *new_outer_tlist;
|
||||
List *new_inner_tlist;
|
||||
@ -360,9 +312,6 @@ build_join_rel(Query *root,
|
||||
joinrel->pages = 0;
|
||||
joinrel->tuples = 0;
|
||||
joinrel->subplan = NULL;
|
||||
joinrel->joinrti = 0;
|
||||
joinrel->joinrteids = nconc(listCopy(outer_rel->joinrteids),
|
||||
inner_rel->joinrteids);
|
||||
joinrel->baserestrictinfo = NIL;
|
||||
joinrel->baserestrictcost.startup = 0;
|
||||
joinrel->baserestrictcost.per_tuple = 0;
|
||||
@ -371,15 +320,6 @@ build_join_rel(Query *root,
|
||||
joinrel->index_outer_relids = NIL;
|
||||
joinrel->index_inner_paths = NIL;
|
||||
|
||||
/* Is there a join RTE matching this join? */
|
||||
joinrterel = find_other_rel_for_join(root, joinrelids);
|
||||
if (joinrterel)
|
||||
{
|
||||
/* Yes, remember its RT index */
|
||||
joinrel->joinrti = lfirsti(joinrterel->relids);
|
||||
joinrel->joinrteids = lconsi(joinrel->joinrti, joinrel->joinrteids);
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a new tlist by removing irrelevant elements from both tlists
|
||||
* of the outer and inner join relations and then merging the results
|
||||
@ -400,23 +340,6 @@ build_join_rel(Query *root,
|
||||
length(new_outer_tlist) + 1);
|
||||
joinrel->targetlist = nconc(new_outer_tlist, new_inner_tlist);
|
||||
|
||||
/*
|
||||
* If there are any alias variables attached to the matching join RTE,
|
||||
* attach them to the tlist too, so that they will be evaluated for
|
||||
* use at higher plan levels.
|
||||
*/
|
||||
if (joinrterel)
|
||||
{
|
||||
List *jrtetl;
|
||||
|
||||
foreach(jrtetl, joinrterel->targetlist)
|
||||
{
|
||||
TargetEntry *jrtete = lfirst(jrtetl);
|
||||
|
||||
add_var_to_tlist(joinrel, (Var *) jrtete->expr);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Construct restrict and join clause lists for the new joinrel. (The
|
||||
* caller might or might not need the restrictlist, but I need it
|
||||
|
Reference in New Issue
Block a user