This is an automated email from the ASF dual-hosted git repository.
alexpl pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ignite.git
The following commit(s) were added to refs/heads/master by this push:
new 9a4ddbf8d7f IGNITE-27662 SQL Calcite: Add IS NOT DISTINCT FROM support
for HASH JOIN - Fixes #12659.
9a4ddbf8d7f is described below
commit 9a4ddbf8d7fe46b984c1383bb7a235d043dd698d
Author: Aleksey Plekhanov <[email protected]>
AuthorDate: Wed Jan 28 14:09:07 2026 +0300
IGNITE-27662 SQL Calcite: Add IS NOT DISTINCT FROM support for HASH JOIN -
Fixes #12659.
Signed-off-by: Aleksey Plekhanov <[email protected]>
---
.../query/calcite/exec/exp/agg/GroupKey.java | 20 +-
.../query/calcite/exec/rel/HashJoinNode.java | 16 +-
.../query/calcite/rule/HashJoinConverterRule.java | 4 -
.../calcite/integration/JoinIntegrationTest.java | 282 ++++++++++-----------
.../query/calcite/planner/HashJoinPlannerTest.java | 10 +-
5 files changed, 164 insertions(+), 168 deletions(-)
diff --git
a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/agg/GroupKey.java
b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/agg/GroupKey.java
index 657c64a8891..f9e7a42dc6a 100644
---
a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/agg/GroupKey.java
+++
b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/agg/GroupKey.java
@@ -18,6 +18,7 @@
package org.apache.ignite.internal.processors.query.calcite.exec.exp.agg;
import java.util.Objects;
+import org.apache.calcite.util.ImmutableBitSet;
import org.apache.ignite.binary.BinaryObjectException;
import org.apache.ignite.binary.BinaryRawReader;
import org.apache.ignite.binary.BinaryRawWriter;
@@ -118,11 +119,20 @@ public class GroupKey<Row> implements Binarylizable {
* not allowed.
*/
public static <Row> @Nullable GroupKey<Row> of(Row r, RowHandler<Row> hnd,
boolean allowNulls) {
- if (!allowNulls) {
- for (int i = 0; i < hnd.columnCount(r); i++) {
- if (hnd.get(i, r) == null)
- return null;
- }
+ if (!allowNulls)
+ return of(r, hnd, ImmutableBitSet.of());
+
+ return new GroupKey<>(r, hnd);
+ }
+
+ /**
+ * @return Group key for provided row. Can be {@code null} if key fields
of row contain NULL values and nulls are
+ * not allowed for these columns.
+ */
+ public static <Row> @Nullable GroupKey<Row> of(Row r, RowHandler<Row> hnd,
ImmutableBitSet allowNulls) {
+ for (int i = 0; i < hnd.columnCount(r); i++) {
+ if (hnd.get(i, r) == null && !allowNulls.get(i))
+ return null;
}
return new GroupKey<>(r, hnd);
diff --git
a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/rel/HashJoinNode.java
b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/rel/HashJoinNode.java
index 45aa2d778dd..fbdec244838 100644
---
a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/rel/HashJoinNode.java
+++
b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/rel/HashJoinNode.java
@@ -26,6 +26,7 @@ import java.util.Map;
import java.util.function.BiPredicate;
import org.apache.calcite.rel.core.JoinRelType;
import org.apache.calcite.rel.type.RelDataType;
+import org.apache.calcite.util.ImmutableBitSet;
import
org.apache.ignite.internal.processors.query.calcite.exec.ExecutionContext;
import
org.apache.ignite.internal.processors.query.calcite.exec.MappingRowHandler;
import org.apache.ignite.internal.processors.query.calcite.exec.RowHandler;
@@ -49,6 +50,9 @@ public abstract class HashJoinNode<Row> extends
AbstractRightMaterializedJoinNod
/** */
private final boolean keepRowsWithNull;
+ /** */
+ private final ImmutableBitSet allowNulls;
+
/** Output row handler. */
protected final RowHandler<Row> outRowHnd;
@@ -83,6 +87,7 @@ public abstract class HashJoinNode<Row> extends
AbstractRightMaterializedJoinNod
) {
super(ctx, rowType);
+ allowNulls = info.allowNulls();
this.keepRowsWithNull = keepRowsWithNull;
leftRowHnd = new MappingRowHandler<>(ctx.rowHandler(),
info.leftKeys.toIntArray());
@@ -146,7 +151,7 @@ public abstract class HashJoinNode<Row> extends
AbstractRightMaterializedJoinNod
/** */
protected Collection<Row> lookup(Row row) {
- GroupKey<Row> key = GroupKey.of(row, leftRowHnd, false);
+ GroupKey<Row> key = GroupKey.of(row, leftRowHnd, allowNulls);
if (key == null)
return Collections.emptyList();
@@ -171,14 +176,15 @@ public abstract class HashJoinNode<Row> extends
AbstractRightMaterializedJoinNod
assert downstream() != null;
assert waitingRight > 0;
- nodeMemoryTracker.onRowAdded(row);
-
waitingRight--;
- GroupKey<Row> key = GroupKey.of(row, rightRowHnd, keepRowsWithNull);
+ GroupKey<Row> key = keepRowsWithNull ? GroupKey.of(row, rightRowHnd) :
GroupKey.of(row, rightRowHnd, allowNulls);
+
+ if (key != null) {
+ nodeMemoryTracker.onRowAdded(row);
- if (key != null)
hashStore.computeIfAbsent(key, k -> new
TouchedArrayList<>()).add(row);
+ }
if (waitingRight == 0)
rightSource().request(waitingRight = IN_BUFFER_SIZE);
diff --git
a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rule/HashJoinConverterRule.java
b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rule/HashJoinConverterRule.java
index d0008289373..de1016d3c51 100644
---
a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rule/HashJoinConverterRule.java
+++
b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rule/HashJoinConverterRule.java
@@ -55,10 +55,6 @@ public class HashJoinConverterRule extends
AbstractIgniteJoinConverterRule {
if (joinInfo.pairs().isEmpty())
return false;
- // IS NOT DISTINCT is currently not supported by HashJoin
- if (joinInfo.allowNulls().cardinality() > 0)
- return false;
-
// Current limitation: unmatched products on left or right part
requires special handling of non-equi condition
// on execution level.
return joinInfo.isEqui() ||
NON_EQ_CONDITIONS_SUPPORT.contains(join.getJoinType());
diff --git
a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/JoinIntegrationTest.java
b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/JoinIntegrationTest.java
index 29579c9a2f4..1343afe37b3 100644
---
a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/JoinIntegrationTest.java
+++
b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/JoinIntegrationTest.java
@@ -26,8 +26,6 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
-import static org.junit.Assume.assumeFalse;
-
/** */
@RunWith(Parameterized.class)
public class JoinIntegrationTest extends
AbstractBasicIntegrationTransactionalTest {
@@ -70,8 +68,6 @@ public class JoinIntegrationTest extends
AbstractBasicIntegrationTransactionalTe
/** */
@Test
public void testIsNotDistinctWithEquiConditionFrom() {
- assumeFalse(joinType == JoinType.HASH);
-
// 'IS NOT DISTINCT' is first.
assertQuery("select t1.c2, t1.c3, t2.c2, t2.c3 from t1 join t2 on
t1.c2 is not distinct from t2.c2 and t1.c3 = t2.c3 - 1")
.returns(null, 2, null, 3)
@@ -299,57 +295,54 @@ public class JoinIntegrationTest extends
AbstractBasicIntegrationTransactionalTe
.returns(null, 3, 3, 3, 3)
.check();
- // HASH join doesn't support IS NOT DISTINCT.
- if (joinType != JoinType.HASH) {
- assertQuery("select t1.c2, t2.c3 from t1 join t2 on t1.c2 is not
distinct from t2.c3 order by t1.c2, t2.c3")
- .returns(1, 1)
- .returns(2, 2)
- .returns(3, 3)
- .returns(3, 3)
- .returns(3, 3)
- .returns(3, 3)
- .returns(4, 4)
- .returns(null, null)
- .check();
+ assertQuery("select t1.c2, t2.c3 from t1 join t2 on t1.c2 is not
distinct from t2.c3 order by t1.c2, t2.c3")
+ .returns(1, 1)
+ .returns(2, 2)
+ .returns(3, 3)
+ .returns(3, 3)
+ .returns(3, 3)
+ .returns(3, 3)
+ .returns(4, 4)
+ .returns(null, null)
+ .check();
- assertQuery("select t1.c2, t1.c3, t2.c1, t2.c3 from t1 join t2 on
t1.c2 is not distinct from t2.c3 and " +
- "t1.c3 is not distinct from t2.c1 order by t1.c2, t1.c3,
t2.c1, t2.c3")
- .returns(1, 1, 1, 1)
- .returns(2, 2, 2, 2)
- .returns(3, 3, 3, 3)
- .returns(3, 3, 3, 3)
- .returns(4, 4, 4, 4)
- .returns(null, 2, 2, null)
- .check();
+ assertQuery("select t1.c2, t1.c3, t2.c1, t2.c3 from t1 join t2 on
t1.c2 is not distinct from t2.c3 and " +
+ "t1.c3 is not distinct from t2.c1 order by t1.c2, t1.c3, t2.c1,
t2.c3")
+ .returns(1, 1, 1, 1)
+ .returns(2, 2, 2, 2)
+ .returns(3, 3, 3, 3)
+ .returns(3, 3, 3, 3)
+ .returns(4, 4, 4, 4)
+ .returns(null, 2, 2, null)
+ .check();
- assertQuery("select t1.c2, t1.c3, t2.c3 from t1 join t2 on t1.c2
is not distinct from t2.c3 and t1.c3 > 3")
- .returns(4, 4, 4)
- .check();
+ assertQuery("select t1.c2, t1.c3, t2.c3 from t1 join t2 on t1.c2 is
not distinct from t2.c3 and t1.c3 > 3")
+ .returns(4, 4, 4)
+ .check();
- // MERGE JOIN doesn't support non-equi conditions.
- if (joinType != JoinType.MERGE) {
- assertQuery("select t1.c2, t1.c3, t2.c2+3 as t2c2, t2.c3 from
t1 join t2 on t1.c2 is not distinct from t2.c3 and " +
- "t1.c3<t2.c2+3 order by t1.c2, t1.c3, t2c2, t2.c3")
- .returns(1, 1, 4, 1)
- .returns(2, 2, 5, 2)
- .returns(3, 3, 6, 3)
- .returns(4, 4, 7, 4)
- .returns(null, 2, 5, null)
- .check();
- }
-
- assertQuery("select t1.c2, t1.c3, t2.c1, t2.c3 from t1 join t2 on
t1.c2 is not distinct from t2.c3 and " +
- "t1.c3 = t2.c1 order by t1.c2, t1.c3, t2.c1, t2.c3")
- .returns(1, 1, 1, 1)
- .returns(2, 2, 2, 2)
- .returns(3, 3, 3, 3)
- .returns(3, 3, 3, 3)
- .returns(4, 4, 4, 4)
- .returns(null, 2, 2, null)
+ // MERGE JOIN doesn't support non-equi conditions.
+ if (joinType != JoinType.MERGE) {
+ assertQuery("select t1.c2, t1.c3, t2.c2+3 as t2c2, t2.c3 from t1
join t2 on t1.c2 is not distinct from t2.c3 and " +
+ "t1.c3<t2.c2+3 order by t1.c2, t1.c3, t2c2, t2.c3")
+ .returns(1, 1, 4, 1)
+ .returns(2, 2, 5, 2)
+ .returns(3, 3, 6, 3)
+ .returns(4, 4, 7, 4)
+ .returns(null, 2, 5, null)
.check();
}
- // HASH JOIN doesn't support: IS NOT DISTINCT, completely non-equi
conditions, additional non-equi conditions
+ assertQuery("select t1.c2, t1.c3, t2.c1, t2.c3 from t1 join t2 on
t1.c2 is not distinct from t2.c3 and " +
+ "t1.c3 = t2.c1 order by t1.c2, t1.c3, t2.c1, t2.c3")
+ .returns(1, 1, 1, 1)
+ .returns(2, 2, 2, 2)
+ .returns(3, 3, 3, 3)
+ .returns(3, 3, 3, 3)
+ .returns(4, 4, 4, 4)
+ .returns(null, 2, 2, null)
+ .check();
+
+ // HASH JOIN doesn't support: completely non-equi conditions,
additional non-equi conditions
// except INNER and SEMI joins.
// MERGE JOIN doesn't support: non-equi conditions.
if (joinType == JoinType.HASH || joinType == JoinType.MERGE)
@@ -596,43 +589,40 @@ public class JoinIntegrationTest extends
AbstractBasicIntegrationTransactionalTe
.returns(null, 3, 3, 3, 3)
.check();
- // HASH join doesn't support IS NOT DISTINCT.
- if (joinType != JoinType.HASH) {
- assertQuery("select t1.c2, t2.c3 from t1 left join t2 on t1.c2 is
not distinct from t2.c3 order by t1.c2, t2.c3")
- .returns(1, 1)
- .returns(2, 2)
- .returns(3, 3)
- .returns(3, 3)
- .returns(3, 3)
- .returns(3, 3)
- .returns(4, 4)
- .returns(null, null)
- .check();
+ assertQuery("select t1.c2, t2.c3 from t1 left join t2 on t1.c2 is not
distinct from t2.c3 order by t1.c2, t2.c3")
+ .returns(1, 1)
+ .returns(2, 2)
+ .returns(3, 3)
+ .returns(3, 3)
+ .returns(3, 3)
+ .returns(3, 3)
+ .returns(4, 4)
+ .returns(null, null)
+ .check();
- assertQuery("select t1.c2, t1.c3, t2.c1, t2.c3 from t1 left join
t2 on t1.c2 is not distinct from t2.c3 and " +
- "t1.c3 is not distinct from t2.c1 order by t1.c2, t1.c3,
t2.c1, t2.c3")
- .returns(1, 1, 1, 1)
- .returns(2, 2, 2, 2)
- .returns(3, 3, 3, 3)
- .returns(3, 3, 3, 3)
- .returns(3, null, null, null)
- .returns(4, 4, 4, 4)
- .returns(null, 2, 2, null)
- .check();
+ assertQuery("select t1.c2, t1.c3, t2.c1, t2.c3 from t1 left join t2 on
t1.c2 is not distinct from t2.c3 and " +
+ "t1.c3 is not distinct from t2.c1 order by t1.c2, t1.c3, t2.c1,
t2.c3")
+ .returns(1, 1, 1, 1)
+ .returns(2, 2, 2, 2)
+ .returns(3, 3, 3, 3)
+ .returns(3, 3, 3, 3)
+ .returns(3, null, null, null)
+ .returns(4, 4, 4, 4)
+ .returns(null, 2, 2, null)
+ .check();
- assertQuery("select t1.c2, t1.c3, t2.c1, t2.c3 from t1 left join
t2 on t1.c2 is not distinct from t2.c3 and " +
- "t1.c3 = t2.c1 order by t1.c2, t1.c3, t2.c1, t2.c3")
- .returns(1, 1, 1, 1)
- .returns(2, 2, 2, 2)
- .returns(3, 3, 3, 3)
- .returns(3, 3, 3, 3)
- .returns(3, null, null, null)
- .returns(4, 4, 4, 4)
- .returns(null, 2, 2, null)
- .check();
- }
+ assertQuery("select t1.c2, t1.c3, t2.c1, t2.c3 from t1 left join t2 on
t1.c2 is not distinct from t2.c3 and " +
+ "t1.c3 = t2.c1 order by t1.c2, t1.c3, t2.c1, t2.c3")
+ .returns(1, 1, 1, 1)
+ .returns(2, 2, 2, 2)
+ .returns(3, 3, 3, 3)
+ .returns(3, 3, 3, 3)
+ .returns(3, null, null, null)
+ .returns(4, 4, 4, 4)
+ .returns(null, 2, 2, null)
+ .check();
- // HASH JOIN doesn't support: IS NOT DISTINCT, completely non-equi
conditions, additional non-equi conditions
+ // HASH JOIN doesn't support: completely non-equi conditions,
additional non-equi conditions
// except INNER and SEMI joins.
// MERGE JOIN doesn't support: non-equi conditions.
if (joinType == JoinType.MERGE || joinType == JoinType.HASH)
@@ -947,41 +937,38 @@ public class JoinIntegrationTest extends
AbstractBasicIntegrationTransactionalTe
.returns(2, 2, 2, 2, null)
.check();
- // HASH join doesn't support IS NOT DISTINCT.
- if (joinType != JoinType.HASH) {
- assertQuery("select t1.c2, t2.c3 from t1 right join t2 on t1.c2 is
not distinct from t2.c3 order by t1.c2, t2.c3")
- .returns(1, 1)
- .returns(2, 2)
- .returns(3, 3)
- .returns(3, 3)
- .returns(3, 3)
- .returns(3, 3)
- .returns(4, 4)
- .returns(null, null)
- .check();
+ assertQuery("select t1.c2, t2.c3 from t1 right join t2 on t1.c2 is not
distinct from t2.c3 order by t1.c2, t2.c3")
+ .returns(1, 1)
+ .returns(2, 2)
+ .returns(3, 3)
+ .returns(3, 3)
+ .returns(3, 3)
+ .returns(3, 3)
+ .returns(4, 4)
+ .returns(null, null)
+ .check();
- assertQuery("select t1.c2, t1.c3, t2.c1, t2.c3 from t1 right join
t2 on t1.c2 is not distinct from t2.c3 and " +
- "t1.c3 is not distinct from t2.c1 order by t1.c2, t1.c3,
t2.c1, t2.c3")
- .returns(1, 1, 1, 1)
- .returns(2, 2, 2, 2)
- .returns(3, 3, 3, 3)
- .returns(3, 3, 3, 3)
- .returns(4, 4, 4, 4)
- .returns(null, 2, 2, null)
- .check();
+ assertQuery("select t1.c2, t1.c3, t2.c1, t2.c3 from t1 right join t2
on t1.c2 is not distinct from t2.c3 and " +
+ "t1.c3 is not distinct from t2.c1 order by t1.c2, t1.c3, t2.c1,
t2.c3")
+ .returns(1, 1, 1, 1)
+ .returns(2, 2, 2, 2)
+ .returns(3, 3, 3, 3)
+ .returns(3, 3, 3, 3)
+ .returns(4, 4, 4, 4)
+ .returns(null, 2, 2, null)
+ .check();
- assertQuery("select t1.c2, t1.c3, t2.c1, t2.c3 from t1 right join
t2 on t1.c2 is not distinct from t2.c3 and " +
- "t1.c3 = t2.c1 order by t1.c2, t1.c3, t2.c1, t2.c3")
- .returns(1, 1, 1, 1)
- .returns(2, 2, 2, 2)
- .returns(3, 3, 3, 3)
- .returns(3, 3, 3, 3)
- .returns(4, 4, 4, 4)
- .returns(null, 2, 2, null)
- .check();
- }
+ assertQuery("select t1.c2, t1.c3, t2.c1, t2.c3 from t1 right join t2
on t1.c2 is not distinct from t2.c3 and " +
+ "t1.c3 = t2.c1 order by t1.c2, t1.c3, t2.c1, t2.c3")
+ .returns(1, 1, 1, 1)
+ .returns(2, 2, 2, 2)
+ .returns(3, 3, 3, 3)
+ .returns(3, 3, 3, 3)
+ .returns(4, 4, 4, 4)
+ .returns(null, 2, 2, null)
+ .check();
- // HASH JOIN doesn't support: IS NOT DISTINCT, completely non-equi
conditions, additional non-equi conditions
+ // HASH JOIN doesn't support: completely non-equi conditions,
additional non-equi conditions
// except INNER and SEMI joins.
// MERGE JOIN doesn't support: non-equi conditions.
if (joinType == JoinType.MERGE || joinType == JoinType.HASH)
@@ -1066,43 +1053,40 @@ public class JoinIntegrationTest extends
AbstractBasicIntegrationTransactionalTe
.returns(null, null, null, 3, null, 3)
.check();
- // HASH join doesn't support IS NOT DISTINCT.
- if (joinType != JoinType.HASH) {
- assertQuery("select t1.c2, t2.c3 from t1 full join t2 on t1.c2 is
not distinct from t2.c3 order by t1.c2, t2.c3")
- .returns(1, 1)
- .returns(2, 2)
- .returns(3, 3)
- .returns(3, 3)
- .returns(3, 3)
- .returns(3, 3)
- .returns(4, 4)
- .returns(null, null)
- .check();
+ assertQuery("select t1.c2, t2.c3 from t1 full join t2 on t1.c2 is not
distinct from t2.c3 order by t1.c2, t2.c3")
+ .returns(1, 1)
+ .returns(2, 2)
+ .returns(3, 3)
+ .returns(3, 3)
+ .returns(3, 3)
+ .returns(3, 3)
+ .returns(4, 4)
+ .returns(null, null)
+ .check();
- assertQuery("select t1.c2, t1.c3, t2.c1, t2.c3 from t1 full join
t2 on t1.c2 is not distinct from t2.c3 and " +
- "t1.c3 is not distinct from t2.c1 order by t1.c2, t1.c3,
t2.c1, t2.c3")
- .returns(1, 1, 1, 1)
- .returns(2, 2, 2, 2)
- .returns(3, 3, 3, 3)
- .returns(3, 3, 3, 3)
- .returns(3, null, null, null)
- .returns(4, 4, 4, 4)
- .returns(null, 2, 2, null)
- .check();
+ assertQuery("select t1.c2, t1.c3, t2.c1, t2.c3 from t1 full join t2 on
t1.c2 is not distinct from t2.c3 and " +
+ "t1.c3 is not distinct from t2.c1 order by t1.c2, t1.c3, t2.c1,
t2.c3")
+ .returns(1, 1, 1, 1)
+ .returns(2, 2, 2, 2)
+ .returns(3, 3, 3, 3)
+ .returns(3, 3, 3, 3)
+ .returns(3, null, null, null)
+ .returns(4, 4, 4, 4)
+ .returns(null, 2, 2, null)
+ .check();
- assertQuery("select t1.c2, t1.c3, t2.c1, t2.c3 from t1 full join
t2 on t1.c2 is not distinct from t2.c3 and " +
- "t1.c3 = t2.c1 order by t1.c2, t1.c3, t2.c1, t2.c3")
- .returns(1, 1, 1, 1)
- .returns(2, 2, 2, 2)
- .returns(3, 3, 3, 3)
- .returns(3, 3, 3, 3)
- .returns(3, null, null, null)
- .returns(4, 4, 4, 4)
- .returns(null, 2, 2, null)
- .check();
- }
+ assertQuery("select t1.c2, t1.c3, t2.c1, t2.c3 from t1 full join t2 on
t1.c2 is not distinct from t2.c3 and " +
+ "t1.c3 = t2.c1 order by t1.c2, t1.c3, t2.c1, t2.c3")
+ .returns(1, 1, 1, 1)
+ .returns(2, 2, 2, 2)
+ .returns(3, 3, 3, 3)
+ .returns(3, 3, 3, 3)
+ .returns(3, null, null, null)
+ .returns(4, 4, 4, 4)
+ .returns(null, 2, 2, null)
+ .check();
- // HASH JOIN doesn't support: IS NOT DISTINCT, completely non-equi
conditions, additional non-equi conditions
+ // HASH JOIN doesn't support: completely non-equi conditions,
additional non-equi conditions
// except INNER and SEMI joins.
// MERGE JOIN doesn't support: non-equi conditions.
if (joinType == JoinType.MERGE || joinType == JoinType.HASH)
diff --git
a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/planner/HashJoinPlannerTest.java
b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/planner/HashJoinPlannerTest.java
index 33ad96c64fe..88a95c20fce 100644
---
a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/planner/HashJoinPlannerTest.java
+++
b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/planner/HashJoinPlannerTest.java
@@ -116,11 +116,11 @@ public class HashJoinPlannerTest extends
AbstractPlannerTest {
F.asList("select t1.c1 from t1 %s join t2 on t1.id = t2.id and
t1.c1=t2.c1", true, false),
F.asList("select t1.c1 from t1 %s join t2 using(c1)", true, false),
F.asList("select t1.c1 from t1 %s join t2 on t1.c1 = 1", false,
false),
- F.asList("select t1.c1 from t1 %s join t2 ON t1.id is not distinct
from t2.c1", false, false),
- F.asList("select t1.c1 from t1 %s join t2 ON t1.id is not distinct
from t2.c1 and t1.c1 is not distinct from t2.id",
- false, false),
- F.asList("select t1.c1 from t1 %s join t2 ON t1.id is not distinct
from t2.c1 and t1.c1 = t2.id", false, false),
- F.asList("select t1.c1 from t1 %s join t2 ON t1.id is not distinct
from t2.c1 and t1.c1 > t2.id", false, true),
+ F.asList("select t1.c1 from t1 %s join t2 ON t1.id is not distinct
from t2.c1", true, false),
+ F.asList("select t1.c1 from t1 %s join t2 ON t1.id is not distinct
from t2.c1 and t1.c1 is not distinct from t2.id",
+ true, false),
+ F.asList("select t1.c1 from t1 %s join t2 ON t1.id is not distinct
from t2.c1 and t1.c1 = t2.id", true, false),
+ F.asList("select t1.c1 from t1 %s join t2 ON t1.id is not distinct
from t2.c1 and t1.c1 > t2.id", true, true),
F.asList("select t1.c1 from t1 %s join t2 on t1.c1 = ?", false,
false),
F.asList("select t1.c1 from t1 %s join t2 on t1.c1 =
OCTET_LENGTH('TEST')", false, false),
F.asList("select t1.c1 from t1 %s join t2 on t1.c1 =
LOG10(t1.c1)", false, false),