[
https://issues.apache.org/jira/browse/CALCITE-1965?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16143851#comment-16143851
]
Christian Beikov commented on CALCITE-1965:
-------------------------------------------
I read the paper and understand what happens now. I'd like to propose a
solution(more like a WIP right now) that should be compatible to the concepts
of the paper i.e. it's an extension.
We introduce a subtype of {{RexCall}} called {{RexCallOuter}} that similar to
the idea of the oracle style join syntax, keeps track of columns that are from
an outer joined relation i.e. are row preserving.
In {{RelMdAllPredicates}} we rewrite the {{RexCall}} instances to
{{RexCallOuter}}.
Not sure if the following is strictly necessary, but I felt this 1. reduces
complexity and feels kind of 2. being the analogy of transitivity for outer
joins.
_In addition to that, we introduce a step to normalize the join structure of a
query before beginning optimization. This step will essentially change the join
type of outer join to an inner join if they are followed by a dependent inner
join. The goal is to ensure the RHS of a left join or LHS of a right join will
always be a left join or right join respectively._
When computing the equivalence classes for a query and materialization query,
we will also compute the "outer equivalence classes" which are composed of the
outer joined columns. Note that the outer equivalence classes should contain
all connected columns of the normal equivalence classes i.e. the outer
equivalence classes for a query like "select ... from a join b on a.a = b.a and
left join c on a.a = c.a" are *{a.a, b.a, c.a}* whereas the normal equivalence
classes are just *{a.a, b.a}*
The *equijoin subsumption test* is extended. It will additionally check if the
columns of the view's outer equivalence classes are contained in either the
normal or outer equivalence classes of the query. This allows to match a view
like "select ... from a left join b on a.a = b.a" also for a query like "select
... from a join b on a.a = b.a" although it needs a {{IS_NOT_NULL}}
compensation predicate for all columns of the view's outer equivalence classes
that were matched against columns of the normal equivalence classes of the
query.
What do you think, could that work? I worked out some examples that seem to
work.
a | id | a
-------------
| 1 | 1
| 2 | 2
| 3 | NULL
b | id | a | c
---------------
| 1 | 1 | 1
| 2 | 3 | 1
c | id | c
-----------
| 1 | 1
| 2 | 2
*View: m0*
Query: select a.id, b.id from a left join b on a.a = b.a
EQ = {}
OEQ = {a.a, b.a}
Result:
1, 1
2, null
*View: m1*
Query: select a.id, b.id, c.id from a left join b on a.a = b.a left join c on
b.c = c.c
EQ = {}
OEQ = {a.a, b.a} {b.c, c.c}
Result:
1, 1, 1
2, null, null
*View: m2*
Query: select a.id, b.id, c.id from a join b on a.a = b.a left join c on b.c =
c.c
EQ = {a.a, b.a}
OEQ = {b.c, c.c}
Result:
1, 1, 1
*Query 1 for m0*
Query: select a.id, b.id from a join b on a.a = b.a
EQ = {a.a, b.a}
OEQ = {}
Result:
1, 1
=> Since OEQ matches EQ, we need a compensation predicate
Rewritten-Query: select a.id, b.id from m0 where b.id is not null
*Query 2 for m1*
Query: select a.id, b.id, c.id from a join b on a.a = b.a left join c on b.c =
c.c
Result:
1, 1, 1
EQ = {a.a, b.a}
OEQ = {b.c, c.c}
=> Since OEQ matches EQ, we need a compensation predicate
Rewritten-Query: select a.id, b.id, c.id from m1 where b.id is not null
*Query 3 for m1*
Query: select a.id, b.id, c.id from a join b on a.a = b.a inner join c on b.c =
c.c
Result:
1, 1, 1
EQ = {a.a, b.a, b.c, c.c}
OEQ = {}
=> Since OEQ matches EQ, we need a compensation predicate
Rewritten-Query: select a.id, b.id, c.id from m1 where b.id is not null and
c.id is not null
> Support outer joins for materialized views
> ------------------------------------------
>
> Key: CALCITE-1965
> URL: https://issues.apache.org/jira/browse/CALCITE-1965
> Project: Calcite
> Issue Type: Improvement
> Components: core
> Reporter: Christian Beikov
> Assignee: Julian Hyde
>
> Currently, only inner joins are supported for materialized view
> substitutions. The support for outer joins involves creating new pulled up
> predicates in case of outer joins that represent semantics of the join. For a
> join predicate like "a.id = b.id" the inner join just pulls up that
> predicate. When having a left join like e.g. {{select * from a left join b on
> a.id = b.id}}, the actual pulled up predicate would be {{OR(=(a.id,
> b.id),ISNULL(b.id))}}. For a right join it would be {{OR(=(a.id,
> b.id),ISNULL(a.id))}} and for a full outer join it would be {{OR(=(a.id,
> b.id),ISNULL(a.id),ISNULL(b.id))}}
--
This message was sent by Atlassian JIRA
(v6.4.14#64029)