Thanks. I guess you mean https://issues.apache.org/jira/browse/CALCITE-3810 
<https://issues.apache.org/jira/browse/CALCITE-3810>.


> On Feb 20, 2020, at 11:21 AM, Christian Beikov <[email protected]> 
> wrote:
> 
> Alright, so here is the PR for the Rel-to-Sql translation.
> 
> I thought about what you wrote here already Julian, but thanks for mentioning 
> it.
> 
> Would be great if this could make it into 1.22.0, or is it too late for that 
> already?
> 
> Am 19.02.2020 um 22:49 schrieb Julian Hyde:
>> Agreed, it should be in reverse order. Translate to semi-join (or
>> anti-join for NOT EXISTS), then optionally use a rule to rewrite semi-
>> or anti-join to Join+Aggregate.
>> 
>> Note that if the EXISTS is in a disjunction (e.g. "delete from orders
>> where exists (select null from order_items where ...) or shipping >
>> 20") we cannot use a semi-join. We have to use a left join, using an
>> indicator column on the right-hand side that will be null iff there is
>> no match. Which is what we do currently.
>> 
>> On Wed, Feb 19, 2020 at 10:03 AM Haisheng Yuan <[email protected]> 
>> wrote:
>>> Hi Christian,
>>> 
>>> For the query in your example, Calcite first generates inner join plan with 
>>> aggregate child, then through SemJoinRule transform the inner join to semi 
>>> or antisemi join. The reason to have inner join is that it allows join 
>>> commutativity, which is good for generating a potential better plan with 
>>> nestedloop join or hash join.
>>> 
>>> Admittedly, this process in Calcite is counter intuitive. It should be in 
>>> reverse order, first generate a semi or anti-semi join, then generate an 
>>> inner/outer join.
>>> 
>>> - Haisheng
>>> 
>>> ------------------------------------------------------------------
>>> 发件人:Christian Beikov<[email protected]>
>>> 日 期:2020年02月19日 21:12:13
>>> 收件人:<[email protected]>
>>> 主 题:Translation of SQL EXISTS
>>> 
>>> Hello,
>>> 
>>> I'm a bit confused about how the SQL EXISTS predicate is translated. I'd
>>> assume that an EXISTS is translated in relational algebra to a SEMI- and
>>> NOT EXISTS to an ANTI-join, but it's not.
>>> 
>>> PlannerImpl p = new PlannerImpl(config);
>>> SqlNode sqlNode = p.parse("delete from _order o where exists (select 1
>>> from order_position p where o.id = p.order_id)");
>>> p.validate(sqlNode);
>>> RelRoot rel = p.rel(sqlNode);
>>> RelToSqlConverter sqlConverter = new RelToSqlConverter(dialect);
>>> SqlImplementor.Result result = sqlConverter.visitChild(0, rel.rel);
>>> sqlWriter.format(result.asStatement());
>>> 
>>> Worse, when printing this, I only get DELETE FROM "public"."_order" i.e.
>>> the EXISTS part is not rendered. This is the plan I get.
>>> 
>>> LogicalTableModify(table=[[adhoc, _order]], operation=[DELETE],
>>> flattened=[true])
>>>    LogicalProject(inputs=[0])
>>>      LogicalProject(inputs=[0], exprs=[[CAST($1):BIGINT, CAST($2):BOOLEAN]])
>>>        LogicalJoin(condition=[=($0, $1)], joinType=[inner])
>>>          JdbcTableScan(table=[[adhoc, _order]])
>>>          LogicalAggregate(group=[{0}], agg#0=[MIN($1)])
>>>            LogicalProject(exprs=[[$1, true]])
>>>              JdbcTableScan(table=[[adhoc, order_position]])
>>> 
>>> I'd expect something along the lines of
>>> 
>>> LogicalTableModify(table=[[adhoc, _order]], operation=[DELETE],
>>> flattened=[true])
>>>    LogicalProject(inputs=[0])
>>>        LogicalJoin(condition=[=($0, $1)], joinType=[semi])
>>>          JdbcTableScan(table=[[adhoc, _order]])
>>>          JdbcTableScan(table=[[adhoc, order_position]])
>>> 
>>> and for NOT EXISTS
>>> 
>>> LogicalTableModify(table=[[adhoc, _order]], operation=[DELETE],
>>> flattened=[true])
>>>    LogicalProject(inputs=[0])
>>>        LogicalJoin(condition=[=($0, $1)], joinType=[anti])
>>>          JdbcTableScan(table=[[adhoc, _order]])
>>>          JdbcTableScan(table=[[adhoc, order_position]])
>>> 
>>> Am I missing something and the current aggregate function translation
>>> makes sense?
>>> 
>>> I constructed relational algebra structures for some other statements
>>> with SEMI- and ANTI-joins and already noticed that these join types
>>> weren't handled in
>>> org.apache.calcite.rel.rel2sql.RelToSqlConverter#visit(org.apache.calcite.rel.core.Join),
>>> which I fixed locally. Is the lack of a translation intentional?
>>> 
>>> Is such a translation of SEMI- and ANTI-join to EXISTS and NOT EXISTS an
>>> over-simplification or would you say it's correct? As far as I
>>> understood from https://en.wikipedia.org/wiki/Relational_algebra this is
>>> correct.
>>> 
>>> I'd be happy to contribute that back. I didn't look into the Sql-to-Rel
>>> translation for EXISTS and NOT EXISTS to SEMI- and ANTI-join yet, but I
>>> assume that's not that hard and I could add that.
>>> 
>>> Regards,
>>> 
>>> Christian
>>> 
>>> 

Reply via email to