review/merge. I also maintain a up-to-date README.uniquekey
document since something may changed during discussion or later code.
Here is the simple introduction of each commit.
====
1. v7-0001-Introduce-RelOptInfo-notnullattrs-attribute.patch
reduce_unique_semijoins to use the new implementation.
4. v7-0004-Remove-distinct-node-AggNode-if-the-input-is-uniq.patch
This commit run join removal at build_join_rel. At that time, it can fully uses
unique key. It can handle some more cases, I added some new test cases to
join.sql. However it can be a replacement of the current one. There are some
cases the new strategy can work run well but the current one can. Like
SELECT a.* FROM a LEFT JOIN (b left join c on b.c_id =
c.id) ON (a.b_id =
b.id);
during the join a & b, the join can't be removed since
b.id is still useful in
future. However in the future, we know the
b.id can be removed as well, but
it is too late to remove the previous join.
At the implementation part, the main idea is if the join_canbe_removed. we
will copy the pathlist from outerrel to joinrel. There are several items need to
handle.
1. To make sure the overall join_search_one_level, we have to keep the joinrel
even the innerrel is removed (rather than discard the joinrel).
2. If the innerrel can be removed, we don't need to build pathlist for joinrel,
we just reuse the pathlist from outerrel. However there are many places where
use assert rel->pathlist[*]->parent == rel. so I copied the pathlist, we
have to change the parent to joinrel.
3. During create plan for some path on RTE_RELATION, it needs to know the
relation Oid with path->parent->relid. so we have to use the outerrel->relid
to overwrite the joinrel->relid which is 0 before.
4. Almost same paths as item 3, it usually assert best_path->parent->rtekind ==
RTE_RELATION; now the path may appeared in joinrel, so I used
outerrel->rtekind to overwrite joinrel->rtekind.
5. I guess there are some dependencies between path->pathtarget and
rel->reltarget. since we reuse the pathlist of outerrel, so I used the
outer->reltarget as well. If the join can be removed, I guess the length of
list_length(outrel->reltarget->exprs) >= (joinrel->reltarget->exprs). we can
rely on the ProjectionPath to reduce the tlist.
My patches is based on the current latest commit fb544735f1.