[ 
https://issues.apache.org/jira/browse/CALCITE-4995?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17484634#comment-17484634
 ] 

Ruben Q L commented on CALCITE-4995:
------------------------------------

Problem can be reproduced with the following test (to be added in 
{{RelFieldTrimmerTest.java}}):
{code}
  /** Test case for
   * <a href="https://issues.apache.org/jira/browse/CALCITE-4995";>[CALCITE-4995]
   * AssertionError caused by RelFieldTrimmer on SEMI/ANTI join</a>. */
  @Test void testSemiJoinAntiJoinFieldTrimmer() {
    for (final JoinRelType joinType : new JoinRelType[]{JoinRelType.ANTI, 
JoinRelType.SEMI}) {
      final RelBuilder builder = RelBuilder.create(config().build());
      final RelNode root = builder
          .values(new String[]{"id"}, 1, 2).as("a")
          .values(new String[]{"id"}, 2, 3).as("b")
          .join(joinType,
              builder.equals(
                  builder.field(2, "a", "id"),
                  builder.field(2, "b", "id")))
          .values(new String[]{"id"}, 0, 2).as("c")
          .join(joinType,
              builder.equals(
                  builder.field(2, "a", "id"),
                  builder.field(2, "c", "id")))
          .build();

      final RelFieldTrimmer fieldTrimmer = new RelFieldTrimmer(null, builder);
      final RelNode trimmed = fieldTrimmer.trim(root);
      final String expected = ""
          + "LogicalJoin(condition=[=($0, $1)], joinType=[" + 
joinType.lowerName + "])\n"
          + "  LogicalJoin(condition=[=($0, $1)], joinType=[" + 
joinType.lowerName + "])\n"
          + "    LogicalValues(tuples=[[{ 1 }, { 2 }]])\n"
          + "    LogicalValues(tuples=[[{ 2 }, { 3 }]])\n"
          + "  LogicalValues(tuples=[[{ 0 }, { 2 }]])\n";
      assertThat(trimmed, hasTree(expected));
    }
  }
{code}

> AssertionError caused by RelFieldTrimmer on SEMI/ANTI join
> ----------------------------------------------------------
>
>                 Key: CALCITE-4995
>                 URL: https://issues.apache.org/jira/browse/CALCITE-4995
>             Project: Calcite
>          Issue Type: Bug
>          Components: core
>    Affects Versions: 1.29.0
>            Reporter: Ruben Q L
>            Assignee: Ruben Q L
>            Priority: Major
>
> It seems {{RelFieldTrimmer}} can cause an {{AssertionError}} (or later an 
> {{ArrayIndexOutOfBoundsException}} if assertions are disabled) on certain 
> plans involving SEMI/ANTI join (i.e. joins that do NOT project the RHS 
> fields).
> The root cause seems to be the "early return" in 
> {{RelFieldTrimmer#trimFields(Join join, ImmutableBitSet fieldsUsed, 
> Set<RelDataTypeField> extraFields)}} when nothing has been trimmed inside 
> join's inputs (so the join itself can be return as it is):
> {code:java}
>     if (changeCount == 0
>         && mapping.isIdentity()) {
>       return result(join, Mappings.createIdentity(fieldCount));
>     }
> {code}
> The problem is that this {{fieldCount}} is an addition of LHS + RHS fields (+ 
> system fields); but in case of a SEMI/ANTI the mappings to be returned must 
> not consider RHS fields (since they are not projected by these join types).
> The problem only happens here (when the trimmer does not trim the join). 
> Notice that, a few lines below, in the "other return scenario" of the method 
> (when something has been trimmed), there is a special treatment of the 
> mapping for ANTI/SEMI, so things will work fine in this case:
> {code:java}
>     switch (join.getJoinType()) {
>     case SEMI:
>     case ANTI:
>       // For SemiJoins and AntiJoins only map fields from the left-side
>       if (join.getJoinType() == JoinRelType.SEMI) {
>         relBuilder.semiJoin(newConditionExpr);
>       } else {
>         relBuilder.antiJoin(newConditionExpr);
>       }
>       Mapping inputMapping = inputMappings.get(0);
>       mapping = Mappings.create(MappingType.INVERSE_SURJECTION,
>           join.getRowType().getFieldCount(),
>           newSystemFieldCount + inputMapping.getTargetCount());
>       for (int i = 0; i < newSystemFieldCount; ++i) {
>         mapping.set(i, i);
>       }
>       offset = systemFieldCount;
>       newOffset = newSystemFieldCount;
>       for (IntPair pair : inputMapping) {
>         mapping.set(pair.source + offset, pair.target + newOffset);
>       }
>       break;
>     default:
>       relBuilder.join(join.getJoinType(), newConditionExpr);
>     }
>     relBuilder.hints(join.getHints());
>     return result(relBuilder.build(), mapping);
> {code}



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

Reply via email to