1996-07-09 08:22:35 +02:00
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
*
|
1999-02-14 00:22:53 +01:00
|
|
|
* joininfo.c
|
2005-06-09 06:19:00 +02:00
|
|
|
* joininfo list manipulation routines
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
2004-12-31 23:04:05 +01:00
|
|
|
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
2000-01-26 06:58:53 +01:00
|
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*
|
|
|
|
* IDENTIFICATION
|
2005-06-09 06:19:00 +02:00
|
|
|
* $PostgreSQL: pgsql/src/backend/optimizer/util/joininfo.c,v 1.43 2005/06/09 04:19:00 tgl Exp $
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
#include "postgres.h"
|
|
|
|
|
1999-07-16 07:00:38 +02:00
|
|
|
#include "optimizer/joininfo.h"
|
2003-01-24 04:58:44 +01:00
|
|
|
#include "optimizer/pathnode.h"
|
1996-07-09 08:22:35 +02:00
|
|
|
|
|
|
|
|
1997-09-07 07:04:48 +02:00
|
|
|
/*
|
2005-06-09 06:19:00 +02:00
|
|
|
* have_relevant_joinclause
|
|
|
|
* Detect whether there is a joinclause that can be used to join
|
|
|
|
* the two given relations.
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
2005-06-09 06:19:00 +02:00
|
|
|
bool
|
|
|
|
have_relevant_joinclause(RelOptInfo *rel1, RelOptInfo *rel2)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
2005-06-09 06:19:00 +02:00
|
|
|
bool result = false;
|
|
|
|
Relids join_relids;
|
|
|
|
List *joininfo;
|
2004-05-26 06:41:50 +02:00
|
|
|
ListCell *l;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
2005-06-09 06:19:00 +02:00
|
|
|
join_relids = bms_union(rel1->relids, rel2->relids);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We could scan either relation's joininfo list; may as well use the
|
|
|
|
* shorter one.
|
|
|
|
*/
|
|
|
|
if (list_length(rel1->joininfo) <= list_length(rel2->joininfo))
|
|
|
|
joininfo = rel1->joininfo;
|
|
|
|
else
|
|
|
|
joininfo = rel2->joininfo;
|
|
|
|
|
|
|
|
foreach(l, joininfo)
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
2005-06-09 06:19:00 +02:00
|
|
|
RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);
|
1999-02-18 01:49:48 +01:00
|
|
|
|
2005-06-09 06:19:00 +02:00
|
|
|
if (bms_is_subset(rinfo->required_relids, join_relids))
|
|
|
|
{
|
|
|
|
result = true;
|
|
|
|
break;
|
|
|
|
}
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
1996-07-09 08:22:35 +02:00
|
|
|
|
2005-06-09 06:19:00 +02:00
|
|
|
bms_free(join_relids);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
2005-06-09 06:19:00 +02:00
|
|
|
return result;
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
2003-01-24 04:58:44 +01:00
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* add_join_clause_to_rels
|
2005-06-09 06:19:00 +02:00
|
|
|
* Add 'restrictinfo' to the joininfo list of each relation it requires.
|
2003-01-24 04:58:44 +01:00
|
|
|
*
|
|
|
|
* Note that the same copy of the restrictinfo node is linked to by all the
|
2003-08-04 02:43:34 +02:00
|
|
|
* lists it is in. This allows us to exploit caching of information about
|
2003-01-24 04:58:44 +01:00
|
|
|
* the restriction clause (but we must be careful that the information does
|
|
|
|
* not depend on context).
|
|
|
|
*
|
|
|
|
* 'restrictinfo' describes the join clause
|
|
|
|
* 'join_relids' is the list of relations participating in the join clause
|
|
|
|
* (there must be more than one)
|
|
|
|
*/
|
|
|
|
void
|
2005-06-06 00:32:58 +02:00
|
|
|
add_join_clause_to_rels(PlannerInfo *root,
|
2003-01-24 04:58:44 +01:00
|
|
|
RestrictInfo *restrictinfo,
|
|
|
|
Relids join_relids)
|
|
|
|
{
|
2003-02-08 21:20:55 +01:00
|
|
|
Relids tmprelids;
|
|
|
|
int cur_relid;
|
2003-01-24 04:58:44 +01:00
|
|
|
|
2003-02-08 21:20:55 +01:00
|
|
|
tmprelids = bms_copy(join_relids);
|
|
|
|
while ((cur_relid = bms_first_member(tmprelids)) >= 0)
|
2003-01-24 04:58:44 +01:00
|
|
|
{
|
2005-06-09 06:19:00 +02:00
|
|
|
RelOptInfo *rel = find_base_rel(root, cur_relid);
|
2003-01-24 04:58:44 +01:00
|
|
|
|
2005-06-09 06:19:00 +02:00
|
|
|
rel->joininfo = lappend(rel->joininfo, restrictinfo);
|
2003-01-24 04:58:44 +01:00
|
|
|
}
|
2003-02-08 21:20:55 +01:00
|
|
|
bms_free(tmprelids);
|
2003-01-24 04:58:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* remove_join_clause_from_rels
|
|
|
|
* Delete 'restrictinfo' from all the joininfo lists it is in
|
|
|
|
*
|
|
|
|
* This reverses the effect of add_join_clause_to_rels. It's used when we
|
|
|
|
* discover that a join clause is redundant.
|
|
|
|
*
|
|
|
|
* 'restrictinfo' describes the join clause
|
|
|
|
* 'join_relids' is the list of relations participating in the join clause
|
|
|
|
* (there must be more than one)
|
|
|
|
*/
|
|
|
|
void
|
2005-06-06 00:32:58 +02:00
|
|
|
remove_join_clause_from_rels(PlannerInfo *root,
|
2003-01-24 04:58:44 +01:00
|
|
|
RestrictInfo *restrictinfo,
|
|
|
|
Relids join_relids)
|
|
|
|
{
|
2003-02-08 21:20:55 +01:00
|
|
|
Relids tmprelids;
|
|
|
|
int cur_relid;
|
2003-01-24 04:58:44 +01:00
|
|
|
|
2003-02-08 21:20:55 +01:00
|
|
|
tmprelids = bms_copy(join_relids);
|
|
|
|
while ((cur_relid = bms_first_member(tmprelids)) >= 0)
|
2003-01-24 04:58:44 +01:00
|
|
|
{
|
2005-06-09 06:19:00 +02:00
|
|
|
RelOptInfo *rel = find_base_rel(root, cur_relid);
|
2003-08-04 02:43:34 +02:00
|
|
|
|
2003-01-24 04:58:44 +01:00
|
|
|
/*
|
2003-08-04 02:43:34 +02:00
|
|
|
* Remove the restrictinfo from the list. Pointer comparison is
|
|
|
|
* sufficient.
|
2003-01-24 04:58:44 +01:00
|
|
|
*/
|
2005-06-09 06:19:00 +02:00
|
|
|
Assert(list_member_ptr(rel->joininfo, restrictinfo));
|
|
|
|
rel->joininfo = list_delete_ptr(rel->joininfo, restrictinfo);
|
2003-01-24 04:58:44 +01:00
|
|
|
}
|
2003-02-08 21:20:55 +01:00
|
|
|
bms_free(tmprelids);
|
2003-01-24 04:58:44 +01:00
|
|
|
}
|