You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@calcite.apache.org by "luoyuxia (Jira)" <ji...@apache.org> on 2022/03/04 09:41:00 UTC

[jira] [Updated] (CALCITE-5032) The unexpected behavior on method RelOptUtil#splitJoinCondition

     [ https://issues.apache.org/jira/browse/CALCITE-5032?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

luoyuxia updated CALCITE-5032:
------------------------------
    Description: 
When I call the method 
{code:java}
RexNode splitJoinCondition(
      List<RelDataTypeField> sysFieldList,
      List<RelNode> inputs,
      RexNode condition,
      List<List<RexNode>> joinKeys,
      @Nullable List<Integer> filterNulls,
      @Nullable List<SqlOperator> rangeOp)
{code}
, and the passed `joinKeys` is  list with size 2, `condition` is like "1 = 1",  then I found the `joinKeys` passed dosen't change as expected. 

For the `joinKeys`,  the first list will contain two RexNodes, and the second list contains no RexNode. I think the expected behavior should be the first list contain one RexNode, and the second contain one RexNode too.

After I dive into the code, I found such code will be invoked:

{code:java}
if ((rangeOp == null)
          && ((leftKey == null) || (rightKey == null))) {
        // no equality join keys found yet:
        // try transforming the condition to
        // equality "join" conditions, e.g.
        //     f(LHS) > 0 ===> ( f(LHS) > 0 ) = TRUE,
        // and make the RHS produce TRUE, but only if we're strictly
        // looking for equi-joins
        final ImmutableBitSet projRefs = InputFinder.bits(condition);
        leftKey = null;
        rightKey = null;

        boolean foundInput = false;
        for (int i = 0; i < inputs.size() && !foundInput; i++) {
          if (inputsRange[i].contains(projRefs)) {
            leftInput = i;
            leftFields = inputs.get(leftInput).getRowType().getFieldList();

            leftKey = condition.accept(
                new RelOptUtil.RexInputConverter(
                    rexBuilder,
                    leftFields,
                    leftFields,
                    adjustments));

            rightKey = rexBuilder.makeLiteral(true);

            // effectively performing an equality comparison
            kind = SqlKind.EQUALS;

            foundInput = true;
          }
        }
      }
{code}
It'll set `leftKey` and `righeKey`,  but it won't set `rightInput`. So `rightInput` will be 0.
Then it'll try to add `leftKey` and `righeKey` to `joinKeys`,

{code:java}
addJoinKey(
            joinKeys.get(leftInput),
            leftKey,
            (rangeOp != null) && !rangeOp.isEmpty());
addJoinKey(
            joinKeys.get(rightInput),
            rightKey,
(rangeOp != null) && !rangeOp.isEmpty());
{code}
But the `rightInput` is 0, so the first list of `joinKeys`  will be also add `righeKey`.

[~julianhyde] Could you please have a look? Is it a bug or I misunderstand something? Thanks very much.









  was:
When I call the method 
{code:java}
RexNode splitJoinCondition(
      List<RelDataTypeField> sysFieldList,
      List<RelNode> inputs,
      RexNode condition,
      List<List<RexNode>> joinKeys,
      @Nullable List<Integer> filterNulls,
      @Nullable List<SqlOperator> rangeOp)
{code}
, and the passed `joinKeys` is  list with size 2, `condition` is like "1 = 1",  then I found the `joinKeys` passed dosen't change as expected. 

For the `joinKeys`,  the first list will contain two RexNodes, and the second list contains no RexNode. I think the expected behavior should be the first list contain one RexNode, and the second contain one RexNode two.

After I dive into the code, I found such code will be invoked:

{code:java}
if ((rangeOp == null)
          && ((leftKey == null) || (rightKey == null))) {
        // no equality join keys found yet:
        // try transforming the condition to
        // equality "join" conditions, e.g.
        //     f(LHS) > 0 ===> ( f(LHS) > 0 ) = TRUE,
        // and make the RHS produce TRUE, but only if we're strictly
        // looking for equi-joins
        final ImmutableBitSet projRefs = InputFinder.bits(condition);
        leftKey = null;
        rightKey = null;

        boolean foundInput = false;
        for (int i = 0; i < inputs.size() && !foundInput; i++) {
          if (inputsRange[i].contains(projRefs)) {
            leftInput = i;
            leftFields = inputs.get(leftInput).getRowType().getFieldList();

            leftKey = condition.accept(
                new RelOptUtil.RexInputConverter(
                    rexBuilder,
                    leftFields,
                    leftFields,
                    adjustments));

            rightKey = rexBuilder.makeLiteral(true);

            // effectively performing an equality comparison
            kind = SqlKind.EQUALS;

            foundInput = true;
          }
        }
      }
{code}
It'll set `leftKey` and `righeKey`,  but it won't set `rightInput`. So `rightInput` will be 0.
Then it'll try to add `leftKey` and `righeKey` to `joinKeys`,

{code:java}
addJoinKey(
            joinKeys.get(leftInput),
            leftKey,
            (rangeOp != null) && !rangeOp.isEmpty());
addJoinKey(
            joinKeys.get(rightInput),
            rightKey,
(rangeOp != null) && !rangeOp.isEmpty());
{code}
But the `rightInput` is 0, so the first list of `joinKeys`  will be also add `righeKey`.

@Hyde










> The unexpected behavior on method RelOptUtil#splitJoinCondition
> ---------------------------------------------------------------
>
>                 Key: CALCITE-5032
>                 URL: https://issues.apache.org/jira/browse/CALCITE-5032
>             Project: Calcite
>          Issue Type: Bug
>          Components: core
>            Reporter: luoyuxia
>            Priority: Major
>
> When I call the method 
> {code:java}
> RexNode splitJoinCondition(
>       List<RelDataTypeField> sysFieldList,
>       List<RelNode> inputs,
>       RexNode condition,
>       List<List<RexNode>> joinKeys,
>       @Nullable List<Integer> filterNulls,
>       @Nullable List<SqlOperator> rangeOp)
> {code}
> , and the passed `joinKeys` is  list with size 2, `condition` is like "1 = 1",  then I found the `joinKeys` passed dosen't change as expected. 
> For the `joinKeys`,  the first list will contain two RexNodes, and the second list contains no RexNode. I think the expected behavior should be the first list contain one RexNode, and the second contain one RexNode too.
> After I dive into the code, I found such code will be invoked:
> {code:java}
> if ((rangeOp == null)
>           && ((leftKey == null) || (rightKey == null))) {
>         // no equality join keys found yet:
>         // try transforming the condition to
>         // equality "join" conditions, e.g.
>         //     f(LHS) > 0 ===> ( f(LHS) > 0 ) = TRUE,
>         // and make the RHS produce TRUE, but only if we're strictly
>         // looking for equi-joins
>         final ImmutableBitSet projRefs = InputFinder.bits(condition);
>         leftKey = null;
>         rightKey = null;
>         boolean foundInput = false;
>         for (int i = 0; i < inputs.size() && !foundInput; i++) {
>           if (inputsRange[i].contains(projRefs)) {
>             leftInput = i;
>             leftFields = inputs.get(leftInput).getRowType().getFieldList();
>             leftKey = condition.accept(
>                 new RelOptUtil.RexInputConverter(
>                     rexBuilder,
>                     leftFields,
>                     leftFields,
>                     adjustments));
>             rightKey = rexBuilder.makeLiteral(true);
>             // effectively performing an equality comparison
>             kind = SqlKind.EQUALS;
>             foundInput = true;
>           }
>         }
>       }
> {code}
> It'll set `leftKey` and `righeKey`,  but it won't set `rightInput`. So `rightInput` will be 0.
> Then it'll try to add `leftKey` and `righeKey` to `joinKeys`,
> {code:java}
> addJoinKey(
>             joinKeys.get(leftInput),
>             leftKey,
>             (rangeOp != null) && !rangeOp.isEmpty());
> addJoinKey(
>             joinKeys.get(rightInput),
>             rightKey,
> (rangeOp != null) && !rangeOp.isEmpty());
> {code}
> But the `rightInput` is 0, so the first list of `joinKeys`  will be also add `righeKey`.
> [~julianhyde] Could you please have a look? Is it a bug or I misunderstand something? Thanks very much.



--
This message was sent by Atlassian Jira
(v8.20.1#820001)