You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by al...@apache.org on 2021/05/12 13:15:28 UTC
[ignite] branch sql-calcite updated: IGNITE-14542 Table functions,
system_range() function - Fixes #9085.
This is an automated email from the ASF dual-hosted git repository.
alexpl pushed a commit to branch sql-calcite
in repository https://gitbox.apache.org/repos/asf/ignite.git
The following commit(s) were added to refs/heads/sql-calcite by this push:
new 89a47c7 IGNITE-14542 Table functions, system_range() function - Fixes #9085.
89a47c7 is described below
commit 89a47c785e3a4bd207ee6d48e1582458e708c9e8
Author: Aleksey Plekhanov <pl...@gmail.com>
AuthorDate: Wed May 12 16:05:30 2021 +0300
IGNITE-14542 Table functions, system_range() function - Fixes #9085.
Signed-off-by: Aleksey Plekhanov <pl...@gmail.com>
---
.../query/calcite/exec/LogicalRelImplementor.java | 21 ++-
.../query/calcite/exec/TableFunctionScan.java | 46 ++++++
.../calcite/exec/exp/ExpressionFactoryImpl.java | 4 +
.../exec/rel/CorrelatedNestedLoopJoinNode.java | 42 ++++-
.../query/calcite/fun/IgniteSqlFunctions.java | 129 ++++++++++++++-
.../calcite/metadata/IgniteMdFragmentMapping.java | 8 +
.../processors/query/calcite/prepare/Cloner.java | 6 +
.../query/calcite/prepare/IgniteRelShuttle.java | 6 +
.../query/calcite/prepare/PlannerPhase.java | 6 +-
.../processors/query/calcite/rel/IgniteFilter.java | 2 +-
.../query/calcite/rel/IgniteRelVisitor.java | 5 +
.../query/calcite/rel/IgniteTableFunctionScan.java | 75 +++++++++
.../calcite/rule/CorrelateToNestedLoopRule.java | 123 +++++++++++++++
.../calcite/rule/CorrelatedNestedLoopJoinRule.java | 2 +-
.../rule/TableFunctionScanConverterRule.java | 63 ++++++++
.../query/calcite/trait/CorrelationTrait.java | 7 +-
.../query/calcite/trait/CorrelationTraitDef.java | 2 +-
.../CalciteErrorHandlilngIntegrationTest.java | 4 +-
.../query/calcite/CalciteQueryProcessorTest.java | 2 +-
.../processors/query/calcite/FunctionsTest.java | 101 +++++++++++-
.../query/calcite/exec/rel/ExecutionTest.java | 70 +++++----
.../query/calcite/planner/AbstractPlannerTest.java | 131 +++++++++++++++-
.../query/calcite/planner/ExceptPlannerTest.java | 173 +++------------------
.../query/calcite/planner/TableFunctionTest.java | 110 +++++++++++++
.../apache/ignite/testsuites/PlannerTestSuite.java | 4 +-
.../aggregates/test_approx_quantile.test_ignore | 1 -
.../test_approximate_distinct_count.test_ignore | 1 -
.../test_group_by_many_groups.test_slow_ignore | 3 +-
.../sql/aggregate/aggregates/test_perfect_ht.test | 28 ++++
.../aggregates/test_perfect_ht.test_ignore | 17 +-
.../test_string_agg_many_groups.test_slow_ignore | 1 -
.../{test_sum.test_ignore => test_sum.test} | 11 +-
.../sql/aggregate/aggregates/test_sum.test_ignore | 10 +-
33 files changed, 986 insertions(+), 228 deletions(-)
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/LogicalRelImplementor.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/LogicalRelImplementor.java
index 873a2f0..15a1d6f 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/LogicalRelImplementor.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/LogicalRelImplementor.java
@@ -24,7 +24,6 @@ import java.util.UUID;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;
-
import org.apache.calcite.rel.RelCollation;
import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.core.JoinRelType;
@@ -72,6 +71,7 @@ import org.apache.ignite.internal.processors.query.calcite.rel.IgniteRelVisitor;
import org.apache.ignite.internal.processors.query.calcite.rel.IgniteSender;
import org.apache.ignite.internal.processors.query.calcite.rel.IgniteSort;
import org.apache.ignite.internal.processors.query.calcite.rel.IgniteSortedIndexSpool;
+import org.apache.ignite.internal.processors.query.calcite.rel.IgniteTableFunctionScan;
import org.apache.ignite.internal.processors.query.calcite.rel.IgniteTableModify;
import org.apache.ignite.internal.processors.query.calcite.rel.IgniteTableScan;
import org.apache.ignite.internal.processors.query.calcite.rel.IgniteTableSpool;
@@ -107,7 +107,7 @@ import static org.apache.ignite.internal.processors.query.calcite.util.TypeUtils
@SuppressWarnings("TypeMayBeWeakened")
public class LogicalRelImplementor<Row> implements IgniteRelVisitor<Node<Row>> {
/** */
- public static final String CNLJ_SUPPORTS_ONLY_INNER_ASSERTION_MSG = "only INNER join supported by IgniteCorrelatedNestedLoop";
+ public static final String CNLJ_NOT_SUPPORTED_JOIN_ASSERTION_MSG = "only INNER and LEFT join supported by IgniteCorrelatedNestedLoop";
/** */
private final ExecutionContext<Row> ctx;
@@ -237,9 +237,11 @@ public class LogicalRelImplementor<Row> implements IgniteRelVisitor<Node<Row>> {
RelDataType rowType = combinedRowType(ctx.getTypeFactory(), leftType, rightType);
Predicate<Row> cond = expressionFactory.predicate(rel.getCondition(), rowType);
- assert rel.getJoinType() == JoinRelType.INNER : CNLJ_SUPPORTS_ONLY_INNER_ASSERTION_MSG;
+ assert rel.getJoinType() == JoinRelType.INNER || rel.getJoinType() == JoinRelType.LEFT
+ : CNLJ_NOT_SUPPORTED_JOIN_ASSERTION_MSG;
- Node<Row> node = new CorrelatedNestedLoopJoinNode<>(ctx, outType, cond, rel.getVariablesSet());
+ Node<Row> node = new CorrelatedNestedLoopJoinNode<>(ctx, outType, cond, rel.getVariablesSet(),
+ rel.getJoinType());
Node<Row> leftInput = visit(rel.getLeft());
Node<Row> rightInput = visit(rel.getRight());
@@ -459,6 +461,17 @@ public class LogicalRelImplementor<Row> implements IgniteRelVisitor<Node<Row>> {
}
/** {@inheritDoc} */
+ @Override public Node<Row> visit(IgniteTableFunctionScan rel) {
+ Supplier<Iterable<Object[]>> dataSupplier = expressionFactory.execute(rel.getCall());
+
+ RelDataType rowType = rel.getRowType();
+
+ RowFactory<Row> rowFactory = ctx.rowHandler().factory(ctx.getTypeFactory(), rowType);
+
+ return new ScanNode<>(ctx, rowType, new TableFunctionScan<>(dataSupplier, rowFactory));
+ }
+
+ /** {@inheritDoc} */
@Override public Node<Row> visit(IgniteTableModify rel) {
switch (rel.getOperation()) {
case INSERT:
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/TableFunctionScan.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/TableFunctionScan.java
new file mode 100644
index 0000000..a853184
--- /dev/null
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/TableFunctionScan.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.query.calcite.exec;
+
+import java.util.Iterator;
+import java.util.function.Supplier;
+import org.apache.ignite.internal.processors.query.calcite.exec.RowHandler.RowFactory;
+import org.apache.ignite.internal.util.typedef.F;
+
+/** */
+public class TableFunctionScan<Row> implements Iterable<Row> {
+ /** */
+ private final Supplier<Iterable<Object[]>> dataSupplier;
+
+ /** */
+ private final RowFactory<Row> rowFactory;
+
+ /** */
+ public TableFunctionScan(
+ Supplier<Iterable<Object[]>> dataSupplier,
+ RowFactory<Row> rowFactory
+ ) {
+ this.dataSupplier = dataSupplier;
+ this.rowFactory = rowFactory;
+ }
+
+ /** {@inheritDoc} */
+ @Override public Iterator<Row> iterator() {
+ return F.iterator(dataSupplier.get(), rowFactory::create, true);
+ }
+}
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/ExpressionFactoryImpl.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/ExpressionFactoryImpl.java
index b54a26f..4da32f9 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/ExpressionFactoryImpl.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/exp/ExpressionFactoryImpl.java
@@ -32,6 +32,7 @@ import java.util.stream.Collectors;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Ordering;
import com.google.common.primitives.Primitives;
+import org.apache.calcite.DataContext;
import org.apache.calcite.adapter.enumerable.EnumUtils;
import org.apache.calcite.adapter.enumerable.RexToLixTranslator;
import org.apache.calcite.adapter.enumerable.RexToLixTranslator.InputGetter;
@@ -283,6 +284,9 @@ public class ExpressionFactoryImpl<Row> implements ExpressionFactory<Row> {
ParameterExpression out_ =
Expressions.parameter(Object.class, "out");
+ builder.add(
+ Expressions.declare(Modifier.FINAL, DataContext.ROOT, Expressions.convert_(ctx_, DataContext.class)));
+
Expression hnd_ = builder.append("hnd",
Expressions.call(ctx_,
IgniteMethod.CONTEXT_ROW_HANDLER.method()));
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/rel/CorrelatedNestedLoopJoinNode.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/rel/CorrelatedNestedLoopJoinNode.java
index 72c8de5..035f021 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/rel/CorrelatedNestedLoopJoinNode.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/exec/rel/CorrelatedNestedLoopJoinNode.java
@@ -18,12 +18,14 @@
package org.apache.ignite.internal.processors.query.calcite.exec.rel;
import java.util.ArrayList;
+import java.util.BitSet;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.function.Predicate;
import org.apache.calcite.rel.core.CorrelationId;
+import org.apache.calcite.rel.core.JoinRelType;
import org.apache.calcite.rel.type.RelDataType;
import org.apache.ignite.internal.processors.query.calcite.exec.ExecutionContext;
import org.apache.ignite.internal.processors.query.calcite.exec.RowHandler;
@@ -40,6 +42,9 @@ public class CorrelatedNestedLoopJoinNode<Row> extends AbstractNode<Row> {
private final List<CorrelationId> correlationIds;
/** */
+ private final JoinRelType joinType;
+
+ /** */
private final RowHandler<Row> handler;
/** */
@@ -49,6 +54,9 @@ public class CorrelatedNestedLoopJoinNode<Row> extends AbstractNode<Row> {
private final int rightInBufferSize;
/** */
+ private final BitSet leftMatched = new BitSet();
+
+ /** */
private int requested;
/** */
@@ -70,6 +78,9 @@ public class CorrelatedNestedLoopJoinNode<Row> extends AbstractNode<Row> {
private int rightIdx;
/** */
+ private Row rightEmptyRow;
+
+ /** */
private State state = State.INITIAL;
/** */
@@ -81,13 +92,15 @@ public class CorrelatedNestedLoopJoinNode<Row> extends AbstractNode<Row> {
* @param ctx Execution context.
* @param cond Join expression.
*/
- public CorrelatedNestedLoopJoinNode(ExecutionContext<Row> ctx, RelDataType rowType, Predicate<Row> cond, Set<CorrelationId> correlationIds) {
+ public CorrelatedNestedLoopJoinNode(ExecutionContext<Row> ctx, RelDataType rowType, Predicate<Row> cond,
+ Set<CorrelationId> correlationIds, JoinRelType joinType) {
super(ctx, rowType);
assert !F.isEmpty(correlationIds);
this.cond = cond;
this.correlationIds = new ArrayList<>(correlationIds);
+ this.joinType = joinType;
leftInBufferSize = correlationIds.size();
rightInBufferSize = IN_BUFFER_SIZE;
@@ -359,13 +372,15 @@ public class CorrelatedNestedLoopJoinNode<Row> extends AbstractNode<Row> {
Row row = handler.concat(leftInBuf.get(leftIdx), rightInBuf.get(rightIdx));
- leftIdx++;
-
if (cond.test(row)) {
+ leftMatched.set(leftIdx);
+
requested--;
downstream().push(row);
}
+
+ leftIdx++;
}
if (leftIdx == leftInBuf.size())
@@ -390,9 +405,30 @@ public class CorrelatedNestedLoopJoinNode<Row> extends AbstractNode<Row> {
return;
}
+ if (joinType == JoinRelType.LEFT && !F.isEmpty(leftInBuf)) {
+ if (rightEmptyRow == null)
+ rightEmptyRow = handler.factory(context().getTypeFactory(), rightSource().rowType()).create();
+
+ int notMatchedIdx = leftMatched.nextClearBit(0);
+
+ while (requested > 0 && notMatchedIdx < leftInBuf.size()) {
+ downstream().push(handler.concat(leftInBuf.get(notMatchedIdx), rightEmptyRow));
+
+ requested--;
+
+ leftMatched.set(notMatchedIdx);
+
+ notMatchedIdx = leftMatched.nextClearBit(notMatchedIdx + 1);
+ }
+
+ if (requested == 0 && notMatchedIdx < leftInBuf.size())
+ return; // Some rows required to be pushed, wait for request.
+ }
+
if (waitingLeft == 0) {
rightInBuf = null;
leftInBuf = null;
+ leftMatched.clear();
state = State.FILLING_LEFT;
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/fun/IgniteSqlFunctions.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/fun/IgniteSqlFunctions.java
index 8f3174b..7c914ba 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/fun/IgniteSqlFunctions.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/fun/IgniteSqlFunctions.java
@@ -16,12 +16,28 @@
*/
package org.apache.ignite.internal.processors.query.calcite.fun;
+import org.apache.calcite.DataContext;
+import org.apache.calcite.config.CalciteConnectionConfig;
+import org.apache.calcite.linq4j.AbstractEnumerable;
+import org.apache.calcite.linq4j.Enumerable;
+import org.apache.calcite.linq4j.Enumerator;
+import org.apache.calcite.linq4j.Linq4j;
import org.apache.calcite.linq4j.function.Strict;
+import org.apache.calcite.rel.type.RelDataType;
+import org.apache.calcite.rel.type.RelDataTypeFactory;
+import org.apache.calcite.schema.ScannableTable;
+import org.apache.calcite.schema.Schema;
+import org.apache.calcite.schema.Statistic;
+import org.apache.calcite.schema.Statistics;
+import org.apache.calcite.sql.SqlCall;
+import org.apache.calcite.sql.SqlNode;
+import org.apache.calcite.sql.type.SqlTypeName;
+import org.checkerframework.checker.nullness.qual.Nullable;
/**
* Ignite SQL functions.
*/
-public class IgniteSqlFunctions {
+public class IgniteSqlFunctions {
/**
* Default constructor.
*/
@@ -29,9 +45,120 @@ public class IgniteSqlFunctions {
// No-op.
}
+ /** SQL SYSTEM_RANGE(start, end) table function. */
+ public static ScannableTable system_range(Object rangeStart, Object rangeEnd) {
+ return new RangeTable(rangeStart, rangeEnd, 1L);
+ }
+
+ /** SQL SYSTEM_RANGE(start, end, increment) table function. */
+ public static ScannableTable system_range(Object rangeStart, Object rangeEnd, Object increment) {
+ return new RangeTable(rangeStart, rangeEnd, increment);
+ }
+
/** SQL LENGTH(string) function. */
@Strict
public static int length(String str) {
return str.length();
}
+
+ /** */
+ private static class RangeTable implements ScannableTable {
+ /** Start of the range. */
+ private final Object rangeStart;
+
+ /** End of the range. */
+ private final Object rangeEnd;
+
+ /** Increment. */
+ private final Object increment;
+
+ /**
+ * Note: {@code Object} arguments required here due to:
+ * 1. {@code NULL} arguments need to be supported, so we can't use {@code long} arguments type.
+ * 2. {@code Integer} and other numeric classes can be converted to {@code long} type by java, but can't be
+ * converted to {@code Long} type, so we can't use {@code Long} arguments type either.
+ * Instead, we accept {@code Object} arguments type and try to convert valid types to {@code long}.
+ */
+ RangeTable(Object rangeStart, Object rangeEnd, Object increment) {
+ this.rangeStart = rangeStart;
+ this.rangeEnd = rangeEnd;
+ this.increment = increment;
+ }
+
+ /** {@inheritDoc} */
+ @Override public RelDataType getRowType(RelDataTypeFactory typeFactory) {
+ return typeFactory.builder().add("X", SqlTypeName.BIGINT).build();
+ }
+
+ /** {@inheritDoc} */
+ @Override public Enumerable<@Nullable Object[]> scan(DataContext root) {
+ if (rangeStart == null || rangeEnd == null || increment == null)
+ return Linq4j.emptyEnumerable();
+
+ long rangeStart = convertToLongArg(this.rangeStart, "rangeStart");
+ long rangeEnd = convertToLongArg(this.rangeEnd, "rangeEnd");
+ long increment = convertToLongArg(this.increment, "increment");
+
+ if (increment == 0L)
+ throw new IllegalArgumentException("Increment can't be 0");
+
+ return new AbstractEnumerable<@Nullable Object[]>() {
+ @Override public Enumerator<@Nullable Object[]> enumerator() {
+ return new Enumerator<Object[]>() {
+ long cur = rangeStart - increment;
+
+ @Override public Object[] current() {
+ return new Object[] { cur };
+ }
+
+ @Override public boolean moveNext() {
+ cur += increment;
+
+ return increment > 0L ? cur <= rangeEnd : cur >= rangeEnd;
+ }
+
+ @Override public void reset() {
+ cur = rangeStart - increment;
+ }
+
+ @Override public void close() {
+ // No-op.
+ }
+ };
+ }
+ };
+ }
+
+ /** */
+ private long convertToLongArg(Object val, String name) {
+ if (val instanceof Byte || val instanceof Short || val instanceof Integer || val instanceof Long)
+ return ((Number)val).longValue();
+
+ throw new IllegalArgumentException("Unsupported argument type [arg=" + name +
+ ", type=" + val.getClass().getSimpleName() + ']');
+ }
+
+ /** {@inheritDoc} */
+ @Override public Statistic getStatistic() {
+ // We can't get access to this method from physical node on planning phase and Calcite dosn't use it either,
+ // so we can return any value here, it can't be used.
+ return Statistics.UNKNOWN;
+ }
+
+ /** {@inheritDoc} */
+ @Override public Schema.TableType getJdbcTableType() {
+ return Schema.TableType.TABLE;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean isRolledUp(String column) {
+ return false;
+ }
+
+ /** {@inheritDoc} */
+ @Override public boolean rolledUpColumnValidInsideAgg(String column, SqlCall call,
+ SqlNode parent, CalciteConnectionConfig cfg) {
+ return true;
+ }
+ }
}
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/metadata/IgniteMdFragmentMapping.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/metadata/IgniteMdFragmentMapping.java
index b8ed40f..e16ce58 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/metadata/IgniteMdFragmentMapping.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/metadata/IgniteMdFragmentMapping.java
@@ -34,6 +34,7 @@ import org.apache.ignite.internal.processors.query.calcite.rel.IgniteExchange;
import org.apache.ignite.internal.processors.query.calcite.rel.IgniteFilter;
import org.apache.ignite.internal.processors.query.calcite.rel.IgniteIndexScan;
import org.apache.ignite.internal.processors.query.calcite.rel.IgniteReceiver;
+import org.apache.ignite.internal.processors.query.calcite.rel.IgniteTableFunctionScan;
import org.apache.ignite.internal.processors.query.calcite.rel.IgniteTableScan;
import org.apache.ignite.internal.processors.query.calcite.rel.IgniteTrimExchange;
import org.apache.ignite.internal.processors.query.calcite.rel.IgniteValues;
@@ -205,6 +206,13 @@ public class IgniteMdFragmentMapping implements MetadataHandler<FragmentMappingM
}
/**
+ * See {@link IgniteMdFragmentMapping#fragmentMapping(RelNode, RelMetadataQuery)}
+ */
+ public FragmentMapping fragmentMapping(IgniteTableFunctionScan rel, RelMetadataQuery mq) {
+ return FragmentMapping.create();
+ }
+
+ /**
* Fragment info calculation entry point.
* @param rel Root node of a calculated fragment.
* @param mq Metadata query instance.
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/Cloner.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/Cloner.java
index 2a8b410..e5f88c4 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/Cloner.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/Cloner.java
@@ -34,6 +34,7 @@ import org.apache.ignite.internal.processors.query.calcite.rel.IgniteRelVisitor;
import org.apache.ignite.internal.processors.query.calcite.rel.IgniteSender;
import org.apache.ignite.internal.processors.query.calcite.rel.IgniteSort;
import org.apache.ignite.internal.processors.query.calcite.rel.IgniteSortedIndexSpool;
+import org.apache.ignite.internal.processors.query.calcite.rel.IgniteTableFunctionScan;
import org.apache.ignite.internal.processors.query.calcite.rel.IgniteTableModify;
import org.apache.ignite.internal.processors.query.calcite.rel.IgniteTableScan;
import org.apache.ignite.internal.processors.query.calcite.rel.IgniteTableSpool;
@@ -244,6 +245,11 @@ public class Cloner implements IgniteRelVisitor<IgniteRel> {
}
/** {@inheritDoc} */
+ @Override public IgniteRel visit(IgniteTableFunctionScan rel) {
+ return rel.clone(cluster, F.asList());
+ }
+
+ /** {@inheritDoc} */
@Override public IgniteRel visit(IgniteRel rel) {
return rel.accept(this);
}
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/IgniteRelShuttle.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/IgniteRelShuttle.java
index 6397b30..8f5aec2 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/IgniteRelShuttle.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/IgniteRelShuttle.java
@@ -34,6 +34,7 @@ import org.apache.ignite.internal.processors.query.calcite.rel.IgniteRelVisitor;
import org.apache.ignite.internal.processors.query.calcite.rel.IgniteSender;
import org.apache.ignite.internal.processors.query.calcite.rel.IgniteSort;
import org.apache.ignite.internal.processors.query.calcite.rel.IgniteSortedIndexSpool;
+import org.apache.ignite.internal.processors.query.calcite.rel.IgniteTableFunctionScan;
import org.apache.ignite.internal.processors.query.calcite.rel.IgniteTableModify;
import org.apache.ignite.internal.processors.query.calcite.rel.IgniteTableScan;
import org.apache.ignite.internal.processors.query.calcite.rel.IgniteTableSpool;
@@ -198,6 +199,11 @@ public class IgniteRelShuttle implements IgniteRelVisitor<IgniteRel> {
return processNode(rel);
}
+ /** {@inheritDoc} */
+ @Override public IgniteRel visit(IgniteTableFunctionScan rel) {
+ return processNode(rel);
+ }
+
/**
* Visits all children of a parent.
*/
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/PlannerPhase.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/PlannerPhase.java
index ccfce87..244b6bb 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/PlannerPhase.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/prepare/PlannerPhase.java
@@ -39,6 +39,7 @@ import org.apache.calcite.rel.rules.SortRemoveRule;
import org.apache.calcite.tools.Program;
import org.apache.calcite.tools.RuleSet;
import org.apache.calcite.tools.RuleSets;
+import org.apache.ignite.internal.processors.query.calcite.rule.CorrelateToNestedLoopRule;
import org.apache.ignite.internal.processors.query.calcite.rule.CorrelatedNestedLoopJoinRule;
import org.apache.ignite.internal.processors.query.calcite.rule.FilterConverterRule;
import org.apache.ignite.internal.processors.query.calcite.rule.FilterSpoolMergeToHashIndexSpoolRule;
@@ -51,6 +52,7 @@ import org.apache.ignite.internal.processors.query.calcite.rule.NestedLoopJoinCo
import org.apache.ignite.internal.processors.query.calcite.rule.ProjectConverterRule;
import org.apache.ignite.internal.processors.query.calcite.rule.SortAggregateConverterRule;
import org.apache.ignite.internal.processors.query.calcite.rule.SortConverterRule;
+import org.apache.ignite.internal.processors.query.calcite.rule.TableFunctionScanConverterRule;
import org.apache.ignite.internal.processors.query.calcite.rule.TableModifyConverterRule;
import org.apache.ignite.internal.processors.query.calcite.rule.UnionConverterRule;
import org.apache.ignite.internal.processors.query.calcite.rule.ValuesConverterRule;
@@ -160,6 +162,7 @@ public enum PlannerPhase {
LogicalOrToUnionRule.INSTANCE,
CorrelatedNestedLoopJoinRule.INSTANCE,
+ CorrelateToNestedLoopRule.INSTANCE,
NestedLoopJoinConverterRule.INSTANCE,
MergeJoinConverterRule.INSTANCE,
@@ -180,7 +183,8 @@ public enum PlannerPhase {
UnionConverterRule.INSTANCE,
SortConverterRule.INSTANCE,
FilterSpoolMergeToSortedIndexSpoolRule.INSTANCE,
- FilterSpoolMergeToHashIndexSpoolRule.INSTANCE
+ FilterSpoolMergeToHashIndexSpoolRule.INSTANCE,
+ TableFunctionScanConverterRule.INSTANCE
)
);
}
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteFilter.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteFilter.java
index cdf08d5..9e7425b 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteFilter.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteFilter.java
@@ -109,7 +109,7 @@ public class IgniteFilter extends Filter implements TraitsAwareIgniteRel {
CorrelationTrait correlation = TraitUtils.correlation(nodeTraits);
if (corrSet.isEmpty() || correlation.correlationIds().containsAll(corrSet))
- return Pair.of(nodeTraits, ImmutableList.of(inTraits.get(0)));
+ return Pair.of(nodeTraits, ImmutableList.of(inTraits.get(0).replace(correlation)));
return null;
}
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteRelVisitor.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteRelVisitor.java
index cab5c5f..95e5f2f 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteRelVisitor.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteRelVisitor.java
@@ -172,6 +172,11 @@ public interface IgniteRelVisitor<T> {
T visit(IgniteReduceMinus rel);
/**
+ * See {@link IgniteRelVisitor#visit(IgniteRel)}
+ */
+ T visit(IgniteTableFunctionScan rel);
+
+ /**
* Visits a relational node and calculates a result on the basis of node meta information.
* @param rel Relational node.
* @return Visit result.
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteTableFunctionScan.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteTableFunctionScan.java
new file mode 100644
index 0000000..0e0fb43
--- /dev/null
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rel/IgniteTableFunctionScan.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.query.calcite.rel;
+
+import java.lang.reflect.Type;
+import java.util.List;
+import java.util.Set;
+import com.google.common.collect.ImmutableList;
+import org.apache.calcite.plan.RelOptCluster;
+import org.apache.calcite.plan.RelTraitSet;
+import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.core.TableFunctionScan;
+import org.apache.calcite.rel.metadata.RelColumnMapping;
+import org.apache.calcite.rel.metadata.RelMetadataQuery;
+import org.apache.calcite.rel.type.RelDataType;
+import org.apache.calcite.rex.RexNode;
+import org.apache.ignite.internal.util.typedef.F;
+
+/**
+ * Relational operator for table function scan.
+ */
+public class IgniteTableFunctionScan extends TableFunctionScan implements IgniteRel {
+ /** Default estimate row count. */
+ private static final int ESTIMATE_ROW_COUNT = 100;
+
+ /**
+ * Creates a TableFunctionScan.
+ */
+ public IgniteTableFunctionScan(
+ RelOptCluster cluster,
+ RelTraitSet traits,
+ RexNode call,
+ RelDataType rowType
+ ) {
+ super(cluster, traits, ImmutableList.of(), call, null, rowType, null);
+ }
+
+ /** {@inheritDoc} */
+ @Override public IgniteRel clone(RelOptCluster cluster, List<IgniteRel> inputs) {
+ return new IgniteTableFunctionScan(cluster, getTraitSet(), getCall(), getRowType());
+ }
+
+ /** {@inheritDoc} */
+ @Override public <T> T accept(IgniteRelVisitor<T> visitor) {
+ return visitor.visit(this);
+ }
+
+ /** {@inheritDoc} */
+ @Override public TableFunctionScan copy(RelTraitSet traitSet, List<RelNode> inputs, RexNode rexCall,
+ Type elementType, RelDataType rowType, Set<RelColumnMapping> columnMappings) {
+ assert F.isEmpty(inputs);
+
+ return this;
+ }
+
+ /** {@inheritDoc} */
+ @Override public double estimateRowCount(RelMetadataQuery mq) {
+ return ESTIMATE_ROW_COUNT;
+ }
+}
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rule/CorrelateToNestedLoopRule.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rule/CorrelateToNestedLoopRule.java
new file mode 100644
index 0000000..0c31678
--- /dev/null
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rule/CorrelateToNestedLoopRule.java
@@ -0,0 +1,123 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.query.calcite.rule;
+
+import java.util.Collections;
+import java.util.Set;
+import org.apache.calcite.plan.Convention;
+import org.apache.calcite.plan.RelOptCluster;
+import org.apache.calcite.plan.RelOptRule;
+import org.apache.calcite.plan.RelOptRuleCall;
+import org.apache.calcite.plan.RelTrait;
+import org.apache.calcite.plan.RelTraitSet;
+import org.apache.calcite.rel.RelNode;
+import org.apache.calcite.rel.convert.ConverterRule;
+import org.apache.calcite.rel.core.Correlate;
+import org.apache.calcite.rel.core.CorrelationId;
+import org.apache.calcite.rel.core.JoinRelType;
+import org.apache.calcite.rel.core.RelFactories;
+import org.apache.calcite.rel.logical.LogicalCorrelate;
+import org.apache.ignite.internal.processors.query.calcite.rel.IgniteConvention;
+import org.apache.ignite.internal.processors.query.calcite.rel.IgniteCorrelatedNestedLoopJoin;
+import org.apache.ignite.internal.processors.query.calcite.trait.CorrelationTrait;
+import org.apache.ignite.internal.processors.query.calcite.trait.RewindabilityTrait;
+
+/**
+ * Rule to convert LogicalCorrelate operator to IgniteCorrelatedNestedLoopJoin.
+ *
+ * LogicalCorrelate operators are created during sub-query rewriting. In most cases LogicalCorrelate can be further
+ * converted to other logical operators if decorrelation is enabled, but in some cases query can't
+ * be decorrelated (when table function is used for example), this rule is required to support such cases.
+ */
+public class CorrelateToNestedLoopRule extends ConverterRule {
+ /** */
+ public static final RelOptRule INSTANCE = Config.DEFAULT.toRule();
+
+ /** */
+ public CorrelateToNestedLoopRule(Config cfg) {
+ super(cfg);
+ }
+
+ /** {@inheritDoc} */
+ @Override public RelNode convert(RelNode rel) {
+ throw new IllegalStateException("Should not be called");
+ }
+
+ /** {@inheritDoc} */
+ @Override public void onMatch(RelOptRuleCall call) {
+ LogicalCorrelate rel = call.rel(0);
+
+ final RelOptCluster cluster = rel.getCluster();
+
+ final Set<CorrelationId> correlationIds = Collections.singleton(rel.getCorrelationId());
+ CorrelationTrait corrTrait = CorrelationTrait.correlations(correlationIds);
+
+ RelTraitSet outTraits = cluster.traitSetOf(IgniteConvention.INSTANCE);
+ RelTraitSet leftInTraits = cluster.traitSetOf(IgniteConvention.INSTANCE);
+ RelTraitSet rightInTraits = cluster.traitSetOf(IgniteConvention.INSTANCE)
+ .replace(RewindabilityTrait.REWINDABLE)
+ .replace(corrTrait);
+
+ RelNode left = convert(rel.getLeft(), leftInTraits);
+ RelNode right = convert(rel.getRight(), rightInTraits);
+
+ call.transformTo(
+ new IgniteCorrelatedNestedLoopJoin(
+ cluster,
+ outTraits,
+ left,
+ right,
+ cluster.getRexBuilder().makeLiteral(true),
+ correlationIds,
+ rel.getJoinType()
+ )
+ );
+ }
+
+ /** */
+ @SuppressWarnings("ClassNameSameAsAncestorName")
+ public interface Config extends ConverterRule.Config {
+ /** */
+ Config DEFAULT = ConverterRule.Config.INSTANCE
+ .withDescription("CorrelateToNestedLoopRule")
+ .withRelBuilderFactory(RelFactories.LOGICAL_BUILDER)
+ .as(Config.class)
+ .withConversion(LogicalCorrelate.class, Convention.NONE, IgniteConvention.INSTANCE);
+
+ /** */
+ default Config withConversion(Class<? extends Correlate> clazz, RelTrait in, RelTrait out) {
+ return withInTrait(in)
+ .withOutTrait(out)
+ .withOperandSupplier(b ->
+ b.operand(clazz).predicate(CorrelateToNestedLoopRule::preMatch).convert(in))
+ .as(Config.class);
+ }
+
+ /** {@inheritDoc} */
+ @Override default CorrelateToNestedLoopRule toRule() {
+ return new CorrelateToNestedLoopRule(this);
+ }
+ }
+
+ /** */
+ private static boolean preMatch(Correlate corr) {
+ // Only these join types are currently supported by IgniteCorrelatedNestedLoopJoin
+ // and only these types are used to rewrite sub-query.
+ return corr.getJoinType() == JoinRelType.INNER || corr.getJoinType() == JoinRelType.LEFT;
+ }
+}
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rule/CorrelatedNestedLoopJoinRule.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rule/CorrelatedNestedLoopJoinRule.java
index d035404..a1e2c66 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rule/CorrelatedNestedLoopJoinRule.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rule/CorrelatedNestedLoopJoinRule.java
@@ -187,6 +187,6 @@ public class CorrelatedNestedLoopJoinRule extends ConverterRule {
/** */
private static boolean preMatch(Join join) {
- return join.getJoinType() == JoinRelType.INNER; // TODO LEFT, SEMI, ANTI
+ return join.getJoinType() == JoinRelType.INNER || join.getJoinType() == JoinRelType.LEFT; // TODO SEMI, ANTI
}
}
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rule/TableFunctionScanConverterRule.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rule/TableFunctionScanConverterRule.java
new file mode 100644
index 0000000..4a21c94
--- /dev/null
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/rule/TableFunctionScanConverterRule.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.ignite.internal.processors.query.calcite.rule;
+
+import java.util.Set;
+import org.apache.calcite.plan.RelOptPlanner;
+import org.apache.calcite.plan.RelOptRule;
+import org.apache.calcite.plan.RelTraitSet;
+import org.apache.calcite.rel.PhysicalNode;
+import org.apache.calcite.rel.core.CorrelationId;
+import org.apache.calcite.rel.logical.LogicalTableFunctionScan;
+import org.apache.calcite.rel.metadata.RelMetadataQuery;
+import org.apache.ignite.internal.processors.query.calcite.rel.IgniteConvention;
+import org.apache.ignite.internal.processors.query.calcite.rel.IgniteTableFunctionScan;
+import org.apache.ignite.internal.processors.query.calcite.trait.CorrelationTrait;
+import org.apache.ignite.internal.processors.query.calcite.trait.IgniteDistributions;
+import org.apache.ignite.internal.processors.query.calcite.trait.RewindabilityTrait;
+import org.apache.ignite.internal.processors.query.calcite.util.RexUtils;
+import org.apache.ignite.internal.util.typedef.F;
+
+/**
+ * Rule to convert a {@link LogicalTableFunctionScan} to an {@link IgniteTableFunctionScan}.
+ */
+public class TableFunctionScanConverterRule extends AbstractIgniteConverterRule<LogicalTableFunctionScan> {
+ /** */
+ public static final RelOptRule INSTANCE = new TableFunctionScanConverterRule();
+
+ /** Default constructor. */
+ private TableFunctionScanConverterRule() {
+ super(LogicalTableFunctionScan.class, "TableFunctionScanConverterRule");
+ }
+
+ /** {@inheritDoc} */
+ @Override protected PhysicalNode convert(RelOptPlanner planner, RelMetadataQuery mq, LogicalTableFunctionScan rel) {
+ assert F.isEmpty(rel.getInputs());
+
+ RelTraitSet traitSet = rel.getTraitSet()
+ .replace(IgniteConvention.INSTANCE)
+ .replace(RewindabilityTrait.REWINDABLE)
+ .replace(IgniteDistributions.broadcast());
+
+ Set<CorrelationId> corrIds = RexUtils.extractCorrelationIds(rel.getCall());
+
+ if (!corrIds.isEmpty())
+ traitSet = traitSet.replace(CorrelationTrait.correlations(corrIds));
+
+ return new IgniteTableFunctionScan(rel.getCluster(), traitSet, rel.getCall(), rel.getRowType());
+ }
+}
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/trait/CorrelationTrait.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/trait/CorrelationTrait.java
index 5c88ddf..523a701 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/trait/CorrelationTrait.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/trait/CorrelationTrait.java
@@ -92,7 +92,12 @@ public class CorrelationTrait implements RelTrait {
if (trait == this || this == UNCORRELATED)
return true;
- return equals(trait);
+ if (!(trait instanceof CorrelationTrait))
+ return false;
+
+ CorrelationTrait other = (CorrelationTrait) trait;
+
+ return other.correlated() && other.correlationIds().containsAll(correlationIds());
}
/** {@inheritDoc} */
diff --git a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/trait/CorrelationTraitDef.java b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/trait/CorrelationTraitDef.java
index de53642..9e0a020 100644
--- a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/trait/CorrelationTraitDef.java
+++ b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/trait/CorrelationTraitDef.java
@@ -43,7 +43,7 @@ public class CorrelationTraitDef extends RelTraitDef<CorrelationTrait> {
/** {@inheritDoc} */
@Override public boolean canConvert(RelOptPlanner planner, CorrelationTrait fromTrait, CorrelationTrait toTrait) {
- return false;
+ return fromTrait.satisfies(toTrait);
}
/** {@inheritDoc} */
diff --git a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/CalciteErrorHandlilngIntegrationTest.java b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/CalciteErrorHandlilngIntegrationTest.java
index 82e52a2..bbe1592 100644
--- a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/CalciteErrorHandlilngIntegrationTest.java
+++ b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/CalciteErrorHandlilngIntegrationTest.java
@@ -49,7 +49,7 @@ import org.junit.After;
import org.junit.Test;
import static org.apache.ignite.IgniteSystemProperties.IGNITE_EXPERIMENTAL_SQL_ENGINE;
-import static org.apache.ignite.internal.processors.query.calcite.exec.LogicalRelImplementor.CNLJ_SUPPORTS_ONLY_INNER_ASSERTION_MSG;
+import static org.apache.ignite.internal.processors.query.calcite.exec.LogicalRelImplementor.CNLJ_NOT_SUPPORTED_JOIN_ASSERTION_MSG;
/** */
@WithSystemProperty(key = "calcite.debug", value = "false")
@@ -98,7 +98,7 @@ public class CalciteErrorHandlilngIntegrationTest extends GridCommonAbstractTest
String sql = "select /*+ DISABLE_RULE('NestedLoopJoinConverter', 'MergeJoinConverter') */ t1.id from test t1, test t2 where t1.id = t2.id";
Throwable t = GridTestUtils.assertThrowsWithCause(() -> sql(client, sql), AssertionError.class);
- assertEquals(CNLJ_SUPPORTS_ONLY_INNER_ASSERTION_MSG, t.getCause().getMessage());
+ assertEquals(CNLJ_NOT_SUPPORTED_JOIN_ASSERTION_MSG, t.getCause().getMessage());
}
/**
diff --git a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/CalciteQueryProcessorTest.java b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/CalciteQueryProcessorTest.java
index 9b0195b..c80118a 100644
--- a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/CalciteQueryProcessorTest.java
+++ b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/CalciteQueryProcessorTest.java
@@ -913,7 +913,7 @@ public class CalciteQueryProcessorTest extends GridCommonAbstractTest {
employer.putAll(ImmutableMap.of(
keysNode0.get(0), new Employer("Igor", 10d),
- keysNode0.get(1), new Employer("Roman", 20d) ,
+ keysNode0.get(1), new Employer("Roman", 20d),
keysNode1.get(0), new Employer("Nikolay", 30d)
));
diff --git a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/FunctionsTest.java b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/FunctionsTest.java
index 851f11f..f200904 100644
--- a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/FunctionsTest.java
+++ b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/FunctionsTest.java
@@ -17,9 +17,13 @@
package org.apache.ignite.internal.processors.query.calcite;
+import org.apache.ignite.Ignite;
+import org.apache.ignite.IgniteCache;
+import org.apache.ignite.configuration.CacheConfiguration;
import org.apache.ignite.internal.IgniteEx;
import org.apache.ignite.internal.processors.query.QueryEngine;
import org.apache.ignite.internal.processors.query.calcite.util.Commons;
+import org.apache.ignite.testframework.GridTestUtils;
import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
import org.junit.Test;
@@ -32,19 +36,110 @@ public class FunctionsTest extends GridCommonAbstractTest {
/** {@inheritDoc} */
@Override protected void beforeTestsStarted() throws Exception {
- IgniteEx grid = startGrid();
+ Ignite grid = startGridsMultiThreaded(3);
- qryEngine = Commons.lookupComponent(grid.context(), QueryEngine.class);
+ qryEngine = Commons.lookupComponent(((IgniteEx)grid).context(), QueryEngine.class);
}
/** */
@Test
- public void testLength() throws Exception {
+ public void testLength() {
checkQuery("SELECT LENGTH('TEST')").returns(4).check();
checkQuery("SELECT LENGTH(NULL)").returns(new Object[] { null }).check();
}
/** */
+ @Test
+ public void testRange() {
+ checkQuery("SELECT * FROM table(system_range(1, 4))")
+ .returns(1L)
+ .returns(2L)
+ .returns(3L)
+ .returns(4L)
+ .check();
+
+ checkQuery("SELECT * FROM table(system_range(1, 4, 2))")
+ .returns(1L)
+ .returns(3L)
+ .check();
+
+ checkQuery("SELECT * FROM table(system_range(4, 1, -1))")
+ .returns(4L)
+ .returns(3L)
+ .returns(2L)
+ .returns(1L)
+ .check();
+
+ checkQuery("SELECT * FROM table(system_range(4, 1, -2))")
+ .returns(4L)
+ .returns(2L)
+ .check();
+
+ assertEquals(0, qryEngine.query(null, "PUBLIC",
+ "SELECT * FROM table(system_range(4, 1))").get(0).getAll().size());
+
+ assertEquals(0, qryEngine.query(null, "PUBLIC",
+ "SELECT * FROM table(system_range(null, 1))").get(0).getAll().size());
+
+ GridTestUtils.assertThrowsAnyCause(log, () -> qryEngine.query(null, "PUBLIC",
+ "SELECT * FROM table(system_range(1, 1, 0))").get(0).getAll(), IllegalArgumentException.class,
+ "Increment can't be 0");
+ }
+
+ /** */
+ @Test
+ public void testRangeWithCache() throws Exception {
+ IgniteCache<Integer, Integer> cache = grid(0).getOrCreateCache(
+ new CacheConfiguration<Integer, Integer>("test")
+ .setBackups(1)
+ .setIndexedTypes(Integer.class, Integer.class)
+ );
+
+ for (int i = 0; i < 100; i++)
+ cache.put(i, i);
+
+ awaitPartitionMapExchange();
+
+ // Correlated INNER join.
+ checkQuery("SELECT t._val FROM \"test\".Integer t WHERE t._val < 5 AND " +
+ "t._key in (SELECT x FROM table(system_range(t._val, t._val))) ")
+ .returns(0)
+ .returns(1)
+ .returns(2)
+ .returns(3)
+ .returns(4)
+ .check();
+
+ // Correlated LEFT joins.
+ checkQuery("SELECT t._val FROM \"test\".Integer t WHERE t._val < 5 AND " +
+ "EXISTS (SELECT x FROM table(system_range(t._val, t._val)) WHERE mod(x, 2) = 0) ")
+ .returns(0)
+ .returns(2)
+ .returns(4)
+ .check();
+
+ checkQuery("SELECT t._val FROM \"test\".Integer t WHERE t._val < 5 AND " +
+ "NOT EXISTS (SELECT x FROM table(system_range(t._val, t._val)) WHERE mod(x, 2) = 0) ")
+ .returns(1)
+ .returns(3)
+ .check();
+
+ assertEquals(0, qryEngine.query(null, "PUBLIC",
+ "SELECT t._val FROM \"test\".Integer t WHERE " +
+ "EXISTS (SELECT x FROM table(system_range(t._val, null))) ").get(0).getAll().size());
+
+ // Non-correlated join.
+ checkQuery("SELECT t._val FROM \"test\".Integer t JOIN table(system_range(1, 50)) as r ON t._key = r.x " +
+ "WHERE mod(r.x, 10) = 0")
+ .returns(10)
+ .returns(20)
+ .returns(30)
+ .returns(40)
+ .returns(50)
+ .check();
+ }
+
+ /** */
private QueryChecker checkQuery(String qry) {
return new QueryChecker(qry) {
@Override protected QueryEngine getEngine() {
diff --git a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/exec/rel/ExecutionTest.java b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/exec/rel/ExecutionTest.java
index bf2cff0..6bd51c6 100644
--- a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/exec/rel/ExecutionTest.java
+++ b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/exec/rel/ExecutionTest.java
@@ -21,9 +21,9 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
-
import com.google.common.collect.ImmutableSet;
import org.apache.calcite.rel.core.CorrelationId;
+import org.apache.calcite.rel.core.JoinRelType;
import org.apache.calcite.rel.type.RelDataType;
import org.apache.ignite.IgniteCheckedException;
import org.apache.ignite.internal.IgniteInterruptedCheckedException;
@@ -461,44 +461,50 @@ public class ExecutionTest extends AbstractExecutionTest {
int[] leftSizes = {1, 99, 100, 101, 512, 513, 2000};
int[] rightSizes = {1, 99, 100, 101, 512, 513, 2000};
int[] rightBufSizes = {1, 100, 512};
+ JoinRelType[] joinTypes = {INNER, LEFT};
- for (int rightBufSize : rightBufSizes) {
- for (int leftSize : leftSizes) {
- for (int rightSize : rightSizes) {
- log.info("Check: rightBufSize=" + rightBufSize + ", leftSize=" + leftSize + ", rightSize=" + rightSize);
+ for (JoinRelType joinType : joinTypes) {
+ for (int rightBufSize : rightBufSizes) {
+ for (int leftSize : leftSizes) {
+ for (int rightSize : rightSizes) {
+ log.info("Check: joinType=" + joinType + ", rightBufSize=" + rightBufSize +
+ ", leftSize=" + leftSize + ", rightSize=" + rightSize);
- ScanNode<Object[]> left = new ScanNode<>(ctx, rowType, new TestTable(leftSize, rowType));
- ScanNode<Object[]> right = new ScanNode<>(ctx, rowType, new TestTable(rightSize, rowType));
+ ScanNode<Object[]> left = new ScanNode<>(ctx, rowType, new TestTable(leftSize, rowType));
+ ScanNode<Object[]> right = new ScanNode<>(ctx, rowType, new TestTable(rightSize, rowType));
- RelDataType joinRowType = TypeUtils.createRowType(
- tf,
- int.class, String.class, int.class,
- int.class, String.class, int.class);
+ RelDataType joinRowType = TypeUtils.createRowType(
+ tf,
+ int.class, String.class, int.class,
+ int.class, String.class, int.class);
- CorrelatedNestedLoopJoinNode<Object[]> join = new CorrelatedNestedLoopJoinNode<>(
- ctx,
- joinRowType,
- r -> r[0].equals(r[3]),
- ImmutableSet.of(new CorrelationId(0)));
+ CorrelatedNestedLoopJoinNode<Object[]> join = new CorrelatedNestedLoopJoinNode<>(
+ ctx,
+ joinRowType,
+ r -> r[0].equals(r[3]),
+ ImmutableSet.of(new CorrelationId(0)),
+ joinType
+ );
- GridTestUtils.setFieldValue(join, "rightInBufferSize", rightBufSize);
+ GridTestUtils.setFieldValue(join, "rightInBufferSize", rightBufSize);
- join.register(Arrays.asList(left, right));
+ join.register(Arrays.asList(left, right));
- RootNode<Object[]> root = new RootNode<>(ctx, joinRowType);
- root.register(join);
+ RootNode<Object[]> root = new RootNode<>(ctx, joinRowType);
+ root.register(join);
- int cnt = 0;
- while (root.hasNext()) {
- root.next();
+ int cnt = 0;
+ while (root.hasNext()) {
+ root.next();
- cnt++;
- }
+ cnt++;
+ }
- assertEquals(
- "Invalid result size. [left=" + leftSize + ", right=" + rightSize + ", results=" + cnt,
- min(leftSize, rightSize),
- cnt);
+ assertEquals(
+ "Invalid result size. [left=" + leftSize + ", right=" + rightSize + ", results=" + cnt,
+ joinType == INNER ? min(leftSize, rightSize) : leftSize,
+ cnt);
+ }
}
}
}
@@ -604,10 +610,8 @@ public class ExecutionTest extends AbstractExecutionTest {
watchDog.interrupt();
}
- /**
- *
- */
- protected Object[] row(Object... fields) {
+ /** {@inheritDoc} */
+ @Override protected Object[] row(Object... fields) {
return fields;
}
diff --git a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/planner/AbstractPlannerTest.java b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/planner/AbstractPlannerTest.java
index 03a92bb..f8fa2f5 100644
--- a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/planner/AbstractPlannerTest.java
+++ b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/planner/AbstractPlannerTest.java
@@ -54,6 +54,7 @@ import org.apache.calcite.schema.Schema;
import org.apache.calcite.schema.SchemaPlus;
import org.apache.calcite.schema.Statistic;
import org.apache.calcite.sql.SqlCall;
+import org.apache.calcite.sql.SqlExplainLevel;
import org.apache.calcite.sql.SqlNode;
import org.apache.calcite.util.ImmutableBitSet;
import org.apache.ignite.cluster.ClusterNode;
@@ -75,6 +76,7 @@ import org.apache.ignite.internal.processors.query.calcite.prepare.PlanningConte
import org.apache.ignite.internal.processors.query.calcite.prepare.Splitter;
import org.apache.ignite.internal.processors.query.calcite.rel.IgniteConvention;
import org.apache.ignite.internal.processors.query.calcite.rel.IgniteRel;
+import org.apache.ignite.internal.processors.query.calcite.rel.IgniteTableScan;
import org.apache.ignite.internal.processors.query.calcite.rel.logical.IgniteLogicalIndexScan;
import org.apache.ignite.internal.processors.query.calcite.rel.logical.IgniteLogicalTableScan;
import org.apache.ignite.internal.processors.query.calcite.schema.IgniteIndex;
@@ -107,7 +109,7 @@ import static org.apache.ignite.internal.processors.query.calcite.externalize.Re
*
*/
//@WithSystemProperty(key = "calcite.debug", value = "true")
-@SuppressWarnings({"TooBroadScope", "FieldCanBeLocal", "TypeMayBeWeakened", "unchecked"})
+@SuppressWarnings({"TooBroadScope", "FieldCanBeLocal", "TypeMayBeWeakened"})
public abstract class AbstractPlannerTest extends GridCommonAbstractTest {
/** */
protected List<UUID> nodes;
@@ -118,6 +120,9 @@ public abstract class AbstractPlannerTest extends GridCommonAbstractTest {
/** */
protected volatile Throwable lastE;
+ /** Last error message. */
+ private String lastErrorMsg;
+
/** */
@Before
public void setup() {
@@ -139,6 +144,7 @@ public abstract class AbstractPlannerTest extends GridCommonAbstractTest {
/** */
interface TestVisitor {
+ /** */
public void visit(RelNode node, int ordinal, RelNode parent);
}
@@ -195,7 +201,7 @@ public abstract class AbstractPlannerTest extends GridCommonAbstractTest {
/** */
public static <T extends RelNode> Predicate<RelNode> byClass(Class<T> cls) {
- return node -> cls.isInstance(node);
+ return cls::isInstance;
}
/** */
@@ -375,7 +381,7 @@ public abstract class AbstractPlannerTest extends GridCommonAbstractTest {
}
List<RelNode> expectedRels = fragments.stream()
- .map(f -> f.root())
+ .map(Fragment::root)
.collect(Collectors.toList());
assertEquals("Invalid deserialization fragments count", expectedRels.size(), deserializedNodes.size());
@@ -437,6 +443,125 @@ public abstract class AbstractPlannerTest extends GridCommonAbstractTest {
}
/** */
+ protected static void createTable(IgniteSchema schema, String name, RelDataType type, IgniteDistribution distr,
+ List<List<UUID>> assignment) {
+ TestTable table = new TestTable(type) {
+ @Override public ColocationGroup colocationGroup(PlanningContext ctx) {
+ if (F.isEmpty(assignment))
+ return super.colocationGroup(ctx);
+ else
+ return ColocationGroup.forAssignments(assignment);
+ }
+
+ @Override public IgniteDistribution distribution() {
+ return distr;
+ }
+
+ @Override public String name() {
+ return name;
+ }
+ };
+
+ schema.addTable(name, table);
+ }
+
+ /** */
+ protected <T extends RelNode> void assertPlan(String sql, IgniteSchema schema, Predicate<T> predicate,
+ String... disabledRules) throws Exception {
+ IgniteRel plan = physicalPlan(sql, schema, disabledRules);
+
+ if (!predicate.test((T)plan)) {
+ String invalidPlanMsg = "Invalid plan (" + lastErrorMsg + "):\n" +
+ RelOptUtil.toString(plan, SqlExplainLevel.ALL_ATTRIBUTES);
+
+ fail(invalidPlanMsg);
+ }
+ }
+
+ /**
+ * Predicate builder for "Instance of class" condition.
+ */
+ protected <T extends RelNode> Predicate<T> isInstanceOf(Class<T> cls) {
+ return node -> {
+ if (cls.isInstance(node))
+ return true;
+
+ lastErrorMsg = "Unexpected node class [node=" + node + ", cls=" + cls.getSimpleName() + ']';
+
+ return false;
+ };
+ }
+
+ /**
+ * Predicate builder for "Table scan with given name" condition.
+ */
+ protected <T extends RelNode> Predicate<IgniteTableScan> isTableScan(String tableName) {
+ return isInstanceOf(IgniteTableScan.class).and(
+ n -> {
+ String scanTableName = n.getTable().unwrap(TestTable.class).name();
+
+ if (tableName.equalsIgnoreCase(scanTableName))
+ return true;
+
+ lastErrorMsg = "Unexpected table name [exp=" + tableName + ", act=" + scanTableName + ']';
+
+ return false;
+ });
+ }
+
+ /**
+ * Predicate builder for "Any child satisfy predicate" condition.
+ */
+ protected <T extends RelNode> Predicate<RelNode> hasChildThat(Predicate<T> predicate) {
+ return new Predicate<RelNode>() {
+ public boolean checkRecursively(RelNode node) {
+ if (predicate.test((T)node))
+ return true;
+
+ for (RelNode input : node.getInputs()) {
+ if (checkRecursively(input))
+ return true;
+ }
+
+ return false;
+ }
+
+ @Override public boolean test(RelNode node) {
+ for (RelNode input : node.getInputs()) {
+ if (checkRecursively(input))
+ return true;
+ }
+
+ lastErrorMsg = "Not found child for defined condition [node=" + node + ']';
+
+ return false;
+ }
+ };
+ }
+
+ /**
+ * Predicate builder for "Current node or any child satisfy predicate" condition.
+ */
+ protected Predicate<RelNode> nodeOrAnyChild(Predicate<? extends RelNode> predicate) {
+ return (Predicate<RelNode>)predicate.or(hasChildThat(predicate));
+ }
+
+ /**
+ * Predicate builder for "Input with given index satisfy predicate" condition.
+ */
+ protected <T extends RelNode> Predicate<RelNode> input(int idx, Predicate<T> predicate) {
+ return node -> {
+ if (F.size(node.getInputs()) <= idx) {
+ lastErrorMsg = "No input for node [idx=" + idx + ", node=" + node + ']';
+
+ return false;
+ }
+
+ return predicate.test((T)node.getInput(idx));
+ };
+ }
+
+ /** */
abstract static class TestTable implements IgniteTable {
/** */
private final String name;
diff --git a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/planner/ExceptPlannerTest.java b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/planner/ExceptPlannerTest.java
index c9cb0cc..1b04e91 100644
--- a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/planner/ExceptPlannerTest.java
+++ b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/planner/ExceptPlannerTest.java
@@ -20,25 +20,15 @@ package org.apache.ignite.internal.processors.query.calcite.planner;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
-import java.util.function.Predicate;
-import org.apache.calcite.plan.RelOptUtil;
-import org.apache.calcite.rel.RelNode;
import org.apache.calcite.rel.type.RelDataType;
import org.apache.calcite.rel.type.RelDataTypeFactory;
-import org.apache.calcite.sql.SqlExplainLevel;
-import org.apache.ignite.internal.processors.query.calcite.metadata.ColocationGroup;
-import org.apache.ignite.internal.processors.query.calcite.prepare.PlanningContext;
-import org.apache.ignite.internal.processors.query.calcite.rel.IgniteRel;
-import org.apache.ignite.internal.processors.query.calcite.rel.IgniteTableScan;
import org.apache.ignite.internal.processors.query.calcite.rel.set.IgniteMapMinus;
import org.apache.ignite.internal.processors.query.calcite.rel.set.IgniteReduceMinus;
import org.apache.ignite.internal.processors.query.calcite.rel.set.IgniteSingleMinus;
import org.apache.ignite.internal.processors.query.calcite.schema.IgniteSchema;
-import org.apache.ignite.internal.processors.query.calcite.trait.IgniteDistribution;
import org.apache.ignite.internal.processors.query.calcite.trait.IgniteDistributions;
import org.apache.ignite.internal.processors.query.calcite.type.IgniteTypeFactory;
import org.apache.ignite.internal.processors.query.calcite.type.IgniteTypeSystem;
-import org.apache.ignite.internal.util.typedef.F;
import org.junit.Before;
import org.junit.Test;
@@ -67,12 +57,12 @@ public class ExceptPlannerTest extends AbstractPlannerTest {
.add("SALARY", f.createJavaType(Double.class))
.build();
- createTable("RANDOM_TBL1", type, IgniteDistributions.random(), null);
- createTable("RANDOM_TBL2", type, IgniteDistributions.random(), null);
- createTable("BROADCAST_TBL1", type, IgniteDistributions.broadcast(), null);
- createTable("BROADCAST_TBL2", type, IgniteDistributions.broadcast(), null);
- createTable("SINGLE_TBL1", type, IgniteDistributions.single(), null);
- createTable("SINGLE_TBL2", type, IgniteDistributions.single(), null);
+ createTable(publicSchema, "RANDOM_TBL1", type, IgniteDistributions.random(), null);
+ createTable(publicSchema, "RANDOM_TBL2", type, IgniteDistributions.random(), null);
+ createTable(publicSchema, "BROADCAST_TBL1", type, IgniteDistributions.broadcast(), null);
+ createTable(publicSchema, "BROADCAST_TBL2", type, IgniteDistributions.broadcast(), null);
+ createTable(publicSchema, "SINGLE_TBL1", type, IgniteDistributions.single(), null);
+ createTable(publicSchema, "SINGLE_TBL2", type, IgniteDistributions.single(), null);
List<List<UUID>> assignment = Arrays.asList(
select(nodes, 0, 1),
@@ -82,11 +72,11 @@ public class ExceptPlannerTest extends AbstractPlannerTest {
select(nodes, 1, 2)
);
- createTable("AFFINITY_TBL1", type, IgniteDistributions.affinity(0, "Test1", "hash"),
- assignment);
+ createTable(publicSchema, "AFFINITY_TBL1", type,
+ IgniteDistributions.affinity(0, "Test1", "hash"), assignment);
- createTable("AFFINITY_TBL2", type, IgniteDistributions.affinity(0, "Test2", "hash"),
- assignment);
+ createTable(publicSchema, "AFFINITY_TBL2", type,
+ IgniteDistributions.affinity(0, "Test2", "hash"), assignment);
}
/**
@@ -99,7 +89,7 @@ public class ExceptPlannerTest extends AbstractPlannerTest {
"EXCEPT " +
"SELECT * FROM random_tbl2 ";
- assertPlan(sql, isInstanceOf(IgniteReduceMinus.class).and(n -> !n.all)
+ assertPlan(sql, publicSchema, isInstanceOf(IgniteReduceMinus.class).and(n -> !n.all)
.and(hasChildThat(isInstanceOf(IgniteMapMinus.class)
.and(input(0, isTableScan("random_tbl1")))
.and(input(1, isTableScan("random_tbl2")))
@@ -117,7 +107,7 @@ public class ExceptPlannerTest extends AbstractPlannerTest {
"EXCEPT ALL " +
"SELECT * FROM random_tbl2 ";
- assertPlan(sql, isInstanceOf(IgniteReduceMinus.class).and(n -> n.all)
+ assertPlan(sql, publicSchema, isInstanceOf(IgniteReduceMinus.class).and(n -> n.all)
.and(hasChildThat(isInstanceOf(IgniteMapMinus.class)
.and(input(0, isTableScan("random_tbl1")))
.and(input(1, isTableScan("random_tbl2")))
@@ -135,7 +125,7 @@ public class ExceptPlannerTest extends AbstractPlannerTest {
"EXCEPT " +
"SELECT * FROM broadcast_tbl2 ";
- assertPlan(sql, isInstanceOf(IgniteSingleMinus.class)
+ assertPlan(sql, publicSchema, isInstanceOf(IgniteSingleMinus.class)
.and(input(0, isTableScan("broadcast_tbl1")))
.and(input(1, isTableScan("broadcast_tbl2")))
);
@@ -151,7 +141,7 @@ public class ExceptPlannerTest extends AbstractPlannerTest {
"EXCEPT " +
"SELECT * FROM single_tbl2 ";
- assertPlan(sql, isInstanceOf(IgniteSingleMinus.class)
+ assertPlan(sql, publicSchema, isInstanceOf(IgniteSingleMinus.class)
.and(input(0, isTableScan("single_tbl1")))
.and(input(1, isTableScan("single_tbl2"))));
}
@@ -166,7 +156,7 @@ public class ExceptPlannerTest extends AbstractPlannerTest {
"EXCEPT " +
"SELECT * FROM random_tbl1 ";
- assertPlan(sql, isInstanceOf(IgniteSingleMinus.class)
+ assertPlan(sql, publicSchema, isInstanceOf(IgniteSingleMinus.class)
.and(input(0, isTableScan("single_tbl1")))
.and(input(1, hasChildThat(isTableScan("random_tbl1")))));
}
@@ -181,7 +171,7 @@ public class ExceptPlannerTest extends AbstractPlannerTest {
"EXCEPT " +
"SELECT * FROM affinity_tbl1 ";
- assertPlan(sql, isInstanceOf(IgniteSingleMinus.class)
+ assertPlan(sql, publicSchema, isInstanceOf(IgniteSingleMinus.class)
.and(input(0, isTableScan("single_tbl1")))
.and(input(1, hasChildThat(isTableScan("affinity_tbl1")))));
}
@@ -196,7 +186,7 @@ public class ExceptPlannerTest extends AbstractPlannerTest {
"EXCEPT " +
"SELECT * FROM broadcast_tbl1 ";
- assertPlan(sql, isInstanceOf(IgniteSingleMinus.class)
+ assertPlan(sql, publicSchema, isInstanceOf(IgniteSingleMinus.class)
.and(input(0, isTableScan("single_tbl1")))
.and(input(1, isTableScan("broadcast_tbl1")))
);
@@ -212,7 +202,7 @@ public class ExceptPlannerTest extends AbstractPlannerTest {
"EXCEPT " +
"SELECT * FROM affinity_tbl2 ";
- assertPlan(sql, isInstanceOf(IgniteReduceMinus.class)
+ assertPlan(sql, publicSchema, isInstanceOf(IgniteReduceMinus.class)
.and(hasChildThat(isInstanceOf(IgniteMapMinus.class)
.and(input(0, isTableScan("affinity_tbl1")))
.and(input(1, isTableScan("affinity_tbl2")))
@@ -230,7 +220,7 @@ public class ExceptPlannerTest extends AbstractPlannerTest {
"EXCEPT " +
"SELECT * FROM broadcast_tbl1 ";
- assertPlan(sql, isInstanceOf(IgniteSingleMinus.class)
+ assertPlan(sql, publicSchema, isInstanceOf(IgniteSingleMinus.class)
.and(input(0, hasChildThat(isTableScan("random_tbl1"))))
.and(input(1, isTableScan("broadcast_tbl1")))
);
@@ -248,7 +238,7 @@ public class ExceptPlannerTest extends AbstractPlannerTest {
" SELECT * FROM random_tbl2" +
")";
- assertPlan(sql, isInstanceOf(IgniteSingleMinus.class)
+ assertPlan(sql, publicSchema, isInstanceOf(IgniteSingleMinus.class)
.and(input(0, hasChildThat(isTableScan("random_tbl2"))))
.and(input(1, isInstanceOf(IgniteReduceMinus.class)
.and(hasChildThat(isInstanceOf(IgniteMapMinus.class)
@@ -271,7 +261,7 @@ public class ExceptPlannerTest extends AbstractPlannerTest {
" SELECT * FROM random_tbl2" +
")";
- assertPlan(sql, isInstanceOf(IgniteSingleMinus.class)
+ assertPlan(sql, publicSchema, isInstanceOf(IgniteSingleMinus.class)
.and(input(0, isTableScan("broadcast_tbl1")))
.and(input(1, isInstanceOf(IgniteReduceMinus.class)
.and(hasChildThat(isInstanceOf(IgniteMapMinus.class)
@@ -296,7 +286,7 @@ public class ExceptPlannerTest extends AbstractPlannerTest {
"EXCEPT " +
"SELECT * FROM affinity_tbl2 ";
- assertPlan(sql, isInstanceOf(IgniteReduceMinus.class)
+ assertPlan(sql, publicSchema, isInstanceOf(IgniteReduceMinus.class)
.and(hasChildThat(isInstanceOf(IgniteMapMinus.class)
.and(input(0, isTableScan("random_tbl1")))
.and(input(1, isTableScan("random_tbl2")))
@@ -320,7 +310,7 @@ public class ExceptPlannerTest extends AbstractPlannerTest {
"EXCEPT ALL " +
"SELECT * FROM affinity_tbl2 ";
- assertPlan(sql, isInstanceOf(IgniteReduceMinus.class).and(n -> n.all)
+ assertPlan(sql, publicSchema, isInstanceOf(IgniteReduceMinus.class).and(n -> n.all)
.and(hasChildThat(isInstanceOf(IgniteMapMinus.class)
.and(input(0, isTableScan("random_tbl1")))
.and(input(1, isTableScan("random_tbl2")))
@@ -342,7 +332,7 @@ public class ExceptPlannerTest extends AbstractPlannerTest {
"EXCEPT " +
"SELECT * FROM affinity_tbl1 ";
- assertPlan(sql, isInstanceOf(IgniteReduceMinus.class).and(n -> !n.all)
+ assertPlan(sql, publicSchema, isInstanceOf(IgniteReduceMinus.class).and(n -> !n.all)
.and(hasChildThat(isInstanceOf(IgniteMapMinus.class)
.and(input(0, isTableScan("random_tbl1")))
.and(input(1, isTableScan("random_tbl2")))
@@ -350,119 +340,4 @@ public class ExceptPlannerTest extends AbstractPlannerTest {
))
);
}
-
- /** */
- private <T extends RelNode> void assertPlan(String sql, Predicate<T> predicate) throws Exception {
- IgniteRel plan = physicalPlan(sql, publicSchema);
-
- if (!predicate.test((T)plan)) {
- String invalidPlanMsg = "Invalid plan (" + lastError + "):\n" +
- RelOptUtil.toString(plan, SqlExplainLevel.ALL_ATTRIBUTES);
-
- fail(invalidPlanMsg);
- }
- }
-
- /** */
- private <T extends RelNode> Predicate<T> isInstanceOf(Class<T> cls) {
- return node -> {
- if (cls.isInstance(node))
- return true;
-
- lastError = "Unexpected node class [node=" + node + ", cls=" + cls.getSimpleName() + ']';
-
- return false;
- };
- }
-
- /** */
- private <T extends RelNode> Predicate<IgniteTableScan> isTableScan(String tableName) {
- return isInstanceOf(IgniteTableScan.class).and(
- n -> {
- String scanTableName = n.getTable().unwrap(TestTable.class).name();
-
- if (tableName.equalsIgnoreCase(scanTableName))
- return true;
-
- lastError = "Unexpected table name [exp=" + tableName + ", act=" + scanTableName + ']';
-
- return false;
- });
- }
-
- /** */
- private <T extends RelNode> Predicate<RelNode> hasChildThat(Predicate<T> predicate) {
- return new Predicate<RelNode>() {
- public boolean checkRecursively(RelNode node) {
- if (predicate.test((T)node))
- return true;
-
- for (RelNode input : node.getInputs()) {
- if (checkRecursively(input))
- return true;
- }
-
- return false;
- }
-
- @Override public boolean test(RelNode node) {
- for (RelNode input : node.getInputs()) {
- if (checkRecursively(input))
- return true;
- }
-
- lastError = "Not found child for defined condition [node=" + node + ']';
-
- return false;
- }
- };
- }
-
- /** */
- private <T extends RelNode> Predicate<RelNode> input(Predicate<T> predicate) {
- return node -> {
- if (F.isEmpty(node.getInputs())) {
- lastError = "No inputs for node [node=" + node + ']';
-
- return false;
- }
-
- return predicate.test((T)node.getInput(0));
- };
- }
-
- /** */
- private <T extends RelNode> Predicate<RelNode> input(int idx, Predicate<T> predicate) {
- return node -> {
- if (F.size(node.getInputs()) <= idx) {
- lastError = "No input for node [idx=" + idx + ", node=" + node + ']';
-
- return false;
- }
-
- return predicate.test((T)node.getInput(idx));
- };
- }
-
- /** */
- private void createTable(String name, RelDataType type, IgniteDistribution distr, List<List<UUID>> assignment) {
- TestTable table = new TestTable(type) {
- @Override public ColocationGroup colocationGroup(PlanningContext ctx) {
- if (F.isEmpty(assignment))
- return super.colocationGroup(ctx);
- else
- return ColocationGroup.forAssignments(assignment);
- }
-
- @Override public IgniteDistribution distribution() {
- return distr;
- }
-
- @Override public String name() {
- return name;
- }
- };
-
- publicSchema.addTable(name, table);
- }
}
diff --git a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/planner/TableFunctionTest.java b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/planner/TableFunctionTest.java
new file mode 100644
index 0000000..fdd026d
--- /dev/null
+++ b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/planner/TableFunctionTest.java
@@ -0,0 +1,110 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.query.calcite.planner;
+
+import org.apache.calcite.rel.core.Join;
+import org.apache.calcite.rel.type.RelDataType;
+import org.apache.calcite.rel.type.RelDataTypeFactory;
+import org.apache.ignite.internal.processors.query.calcite.rel.IgniteCorrelatedNestedLoopJoin;
+import org.apache.ignite.internal.processors.query.calcite.rel.IgniteExchange;
+import org.apache.ignite.internal.processors.query.calcite.rel.IgniteTableFunctionScan;
+import org.apache.ignite.internal.processors.query.calcite.schema.IgniteSchema;
+import org.apache.ignite.internal.processors.query.calcite.trait.IgniteDistributions;
+import org.apache.ignite.internal.processors.query.calcite.type.IgniteTypeFactory;
+import org.apache.ignite.internal.processors.query.calcite.type.IgniteTypeSystem;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Test table functions.
+ */
+public class TableFunctionTest extends AbstractPlannerTest {
+ /** Public schema. */
+ private IgniteSchema publicSchema;
+
+
+ /** {@inheritDoc} */
+ @Before
+ @Override public void setup() {
+ super.setup();
+
+ publicSchema = new IgniteSchema("PUBLIC");
+
+ IgniteTypeFactory f = new IgniteTypeFactory(IgniteTypeSystem.INSTANCE);
+
+ RelDataType type = new RelDataTypeFactory.Builder(f)
+ .add("ID", f.createJavaType(Integer.class))
+ .add("NAME", f.createJavaType(String.class))
+ .add("SALARY", f.createJavaType(Double.class))
+ .build();
+
+ createTable(publicSchema, "RANDOM_TBL", type, IgniteDistributions.random(), null);
+ createTable(publicSchema, "BROADCAST_TBL", type, IgniteDistributions.broadcast(), null);
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ @Test
+ public void testTableFunctionScan() throws Exception {
+ String sql = "SELECT * FROM TABLE(system_range(1, 1))";
+
+ assertPlan(sql, publicSchema, isInstanceOf(IgniteTableFunctionScan.class));
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ @Test
+ public void testBroadcastTableAndTableFunctionJoin() throws Exception {
+ String sql = "SELECT * FROM broadcast_tbl t JOIN TABLE(system_range(1, 1)) r ON (t.id = r.x)";
+
+ assertPlan(sql, publicSchema, nodeOrAnyChild(isInstanceOf(IgniteExchange.class)).negate()
+ .and(nodeOrAnyChild(isInstanceOf(Join.class)
+ .and(input(0, nodeOrAnyChild(isTableScan("broadcast_tbl"))))
+ .and(input(1, nodeOrAnyChild(isInstanceOf(IgniteTableFunctionScan.class))))
+ )));
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ @Test
+ public void testRandomTableAndTableFunctionJoin() throws Exception {
+ String sql = "SELECT * FROM random_tbl t JOIN TABLE(system_range(1, 1)) r ON (t.id = r.x)";
+
+ assertPlan(sql, publicSchema, nodeOrAnyChild(isInstanceOf(Join.class)
+ .and(input(0, nodeOrAnyChild(isInstanceOf(IgniteExchange.class)
+ .and(nodeOrAnyChild(isTableScan("random_tbl"))))))
+ .and(input(1, nodeOrAnyChild(isInstanceOf(IgniteTableFunctionScan.class))))
+ ));
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ @Test
+ public void testCorrelatedTableFunctionJoin() throws Exception {
+ String sql = "SELECT t.id, (SELECT x FROM TABLE(system_range(t.id, t.id))) FROM random_tbl t";
+
+ assertPlan(sql, publicSchema, nodeOrAnyChild(isInstanceOf(IgniteCorrelatedNestedLoopJoin.class)
+ .and(input(0, nodeOrAnyChild(isTableScan("random_tbl"))))
+ .and(input(1, nodeOrAnyChild(isInstanceOf(IgniteTableFunctionScan.class))))
+ ));
+ }
+}
diff --git a/modules/calcite/src/test/java/org/apache/ignite/testsuites/PlannerTestSuite.java b/modules/calcite/src/test/java/org/apache/ignite/testsuites/PlannerTestSuite.java
index c466f72..6c8ac6e 100644
--- a/modules/calcite/src/test/java/org/apache/ignite/testsuites/PlannerTestSuite.java
+++ b/modules/calcite/src/test/java/org/apache/ignite/testsuites/PlannerTestSuite.java
@@ -27,6 +27,7 @@ import org.apache.ignite.internal.processors.query.calcite.planner.JoinColocatio
import org.apache.ignite.internal.processors.query.calcite.planner.PlannerTest;
import org.apache.ignite.internal.processors.query.calcite.planner.SortAggregatePlannerTest;
import org.apache.ignite.internal.processors.query.calcite.planner.SortedIndexSpoolPlannerTest;
+import org.apache.ignite.internal.processors.query.calcite.planner.TableFunctionTest;
import org.apache.ignite.internal.processors.query.calcite.planner.TableSpoolPlannerTest;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
@@ -46,7 +47,8 @@ import org.junit.runners.Suite;
HashAggregatePlannerTest.class,
SortAggregatePlannerTest.class,
JoinColocationPlannerTest.class,
- ExceptPlannerTest.class
+ ExceptPlannerTest.class,
+ TableFunctionTest.class,
})
public class PlannerTestSuite {
}
diff --git a/modules/calcite/src/test/sql/aggregate/aggregates/test_approx_quantile.test_ignore b/modules/calcite/src/test/sql/aggregate/aggregates/test_approx_quantile.test_ignore
index f97c5cb..66cf6cd 100644
--- a/modules/calcite/src/test/sql/aggregate/aggregates/test_approx_quantile.test_ignore
+++ b/modules/calcite/src/test/sql/aggregate/aggregates/test_approx_quantile.test_ignore
@@ -1,7 +1,6 @@
# name: test/sql/aggregate/aggregates/test_approx_quantile.test
# description: Test approx quantile operator
# group: [aggregates]
-# Ignored: https://issues.apache.org/jira/browse/IGNITE-14542
# Ignored: https://issues.apache.org/jira/browse/IGNITE-14637
statement ok
diff --git a/modules/calcite/src/test/sql/aggregate/aggregates/test_approximate_distinct_count.test_ignore b/modules/calcite/src/test/sql/aggregate/aggregates/test_approximate_distinct_count.test_ignore
index f5edbcb..4b14f51 100644
--- a/modules/calcite/src/test/sql/aggregate/aggregates/test_approximate_distinct_count.test_ignore
+++ b/modules/calcite/src/test/sql/aggregate/aggregates/test_approximate_distinct_count.test_ignore
@@ -1,7 +1,6 @@
# name: test/sql/aggregate/aggregates/test_approximate_distinct_count.test
# description: Test approx_count_distinct operator
# group: [aggregates]
-# Ignored: https://issues.apache.org/jira/browse/IGNITE-14542
# Ignored: https://issues.apache.org/jira/browse/IGNITE-14637
diff --git a/modules/calcite/src/test/sql/aggregate/aggregates/test_group_by_many_groups.test_slow_ignore b/modules/calcite/src/test/sql/aggregate/aggregates/test_group_by_many_groups.test_slow_ignore
index 648779d..92891f4 100644
--- a/modules/calcite/src/test/sql/aggregate/aggregates/test_group_by_many_groups.test_slow_ignore
+++ b/modules/calcite/src/test/sql/aggregate/aggregates/test_group_by_many_groups.test_slow_ignore
@@ -1,7 +1,8 @@
# name: test/sql/aggregate/aggregates/test_group_by_many_groups.test_slow
# description: Test GROUP BY with many groups
# group: [aggregates]
-# Ignored: https://issues.apache.org/jira/browse/IGNITE-14542
+# Ignored: https://issues.apache.org/jira/browse/IGNITE-14680
+# Ignored: https://issues.apache.org/jira/browse/IGNITE-14555
statement ok
CREATE TABLE integers AS SELECT i, 1 AS j FROM range(0, 10000, 1) t1(i) UNION ALL SELECT i, 2 j FROM range(0, 10000, 1) t1(i);
diff --git a/modules/calcite/src/test/sql/aggregate/aggregates/test_perfect_ht.test b/modules/calcite/src/test/sql/aggregate/aggregates/test_perfect_ht.test
index fd8721b..4884c3b 100644
--- a/modules/calcite/src/test/sql/aggregate/aggregates/test_perfect_ht.test
+++ b/modules/calcite/src/test/sql/aggregate/aggregates/test_perfect_ht.test
@@ -22,3 +22,31 @@ SELECT year, SUM(val), COUNT(val), COUNT(*) FROM timeseries GROUP BY year ORDER
2001 30 1 1
NULL 1 1 1
+# many small columns each having only the values 0 and 1
+# total possible combinations is 2^10, but there are only 2 groups
+statement ok
+create table manycolumns(a INTEGER, b INTEGER, c INTEGER, d INTEGER, e INTEGER);
+
+statement ok
+insert into manycolumns select x a, x b, x c, x d, x e from table(system_range(0,1));
+
+query IIIII
+select a, b, c, d, e FROM manycolumns GROUP BY a, b, c, d, e ORDER BY 1
+----
+0 0 0 0 0
+1 1 1 1 1
+
+# test edge cases: multiple tinyints without statistics
+# create a table of tinyints [-127, 127] stored as varchar
+# by forcing a varchar to tinyint cast we lose statistics
+statement ok
+CREATE TABLE tinyints (t TINYINT);
+
+statement ok
+INSERT INTO tinyints SELECT x::TINYINT::VARCHAR AS t FROM table(system_range(-127, 127));
+
+query IIII
+SELECT COUNT(DISTINCT i), MIN(i), MAX(i), SUM(i) / COUNT(i) FROM (SELECT t::TINYINT i FROM tinyints GROUP BY t)
+----
+255 -127 127 0
+
diff --git a/modules/calcite/src/test/sql/aggregate/aggregates/test_perfect_ht.test_ignore b/modules/calcite/src/test/sql/aggregate/aggregates/test_perfect_ht.test_ignore
index a4b4a65..769c329 100644
--- a/modules/calcite/src/test/sql/aggregate/aggregates/test_perfect_ht.test_ignore
+++ b/modules/calcite/src/test/sql/aggregate/aggregates/test_perfect_ht.test_ignore
@@ -1,7 +1,8 @@
# name: test/sql/aggregate/aggregates/test_perfect_ht.test
# description: Test aggregates that can trigger a perfect HT
# group: [aggregates]
-# Ignored: https://issues.apache.org/jira/browse/IGNITE-14542
+# Ignored: https://issues.apache.org/jira/browse/IGNITE-14555
+# Ignored: https://issues.apache.org/jira/browse/IGNITE-14680
statement ok
PRAGMA enable_verification
@@ -35,31 +36,31 @@ NULL [1] 1
# many small columns each having only the values 0 and 1
# total possible combinations is 2^10, but there are only 2 groups
statement ok
-create table manycolumns as select i a, i b, i c, i d, i e from range(0,2) tbl(i);
+create table manycolumns as select x a, x b, x c, x d, x e from table(system_range(0,1));
query IIIII
-select a, b, c, d, e FROM manycolumns GROUP BY 1, 2, 3, 4, 5
+select a, b, c, d, e FROM manycolumns GROUP BY a, b, c, d, e ORDER BY 1
----
0 0 0 0 0
1 1 1 1 1
# test edge cases: multiple tinyints without statistics
-# create a table of tinyints [-127, 128] stored as varchar
+# create a table of tinyints [-127, 127] stored as varchar
# by forcing a varchar to tinyint cast we lose statistics
statement ok
-CREATE TABLE tinyints AS SELECT i::TINYINT::VARCHAR AS t FROM range(-127, 128) tbl(i);
+CREATE TABLE tinyints AS SELECT x::TINYINT::VARCHAR AS t FROM table(system_range(-127, 127));
query IIII
-SELECT COUNT(DISTINCT i), MIN(i), MAX(i), SUM(i) / COUNT(i) FROM (SELECT t::TINYINT t1 FROM tinyints GROUP BY t1) tbl(i)
+SELECT COUNT(DISTINCT i), MIN(i), MAX(i), SUM(i) / COUNT(i) FROM (SELECT t::TINYINT i FROM tinyints GROUP BY t)
----
255 -127 127 0
# now do the same with a single smallint column
statement ok
-CREATE TABLE smallints AS SELECT i::SMALLINT::VARCHAR AS t FROM range(-32767, 32768) tbl(i);
+CREATE TABLE smallints AS SELECT x::SMALLINT::VARCHAR AS t FROM table(system_range(-32767, 32767));
query IIII
-SELECT COUNT(DISTINCT i), MIN(i), MAX(i), SUM(i) / COUNT(i) FROM (SELECT t::SMALLINT t1 FROM smallints GROUP BY t1) tbl(i)
+SELECT COUNT(DISTINCT i), MIN(i), MAX(i), SUM(i) / COUNT(i) FROM (SELECT t::SMALLINT i FROM smallints GROUP BY t)
----
65535 -32767 32767 0
diff --git a/modules/calcite/src/test/sql/aggregate/aggregates/test_string_agg_many_groups.test_slow_ignore b/modules/calcite/src/test/sql/aggregate/aggregates/test_string_agg_many_groups.test_slow_ignore
index e6932f4..daf8fa4 100644
--- a/modules/calcite/src/test/sql/aggregate/aggregates/test_string_agg_many_groups.test_slow_ignore
+++ b/modules/calcite/src/test/sql/aggregate/aggregates/test_string_agg_many_groups.test_slow_ignore
@@ -2,7 +2,6 @@
# description: Test STRING_AGG operator with many groups
# group: [aggregates]
# Ignored: https://issues.apache.org/jira/browse/IGNITE-14636
-# Ignored: https://issues.apache.org/jira/browse/IGNITE-14542
# generate a table
diff --git a/modules/calcite/src/test/sql/aggregate/aggregates/test_sum.test_ignore b/modules/calcite/src/test/sql/aggregate/aggregates/test_sum.test
similarity index 73%
copy from modules/calcite/src/test/sql/aggregate/aggregates/test_sum.test_ignore
copy to modules/calcite/src/test/sql/aggregate/aggregates/test_sum.test
index 40d7ed4..0593e6a 100644
--- a/modules/calcite/src/test/sql/aggregate/aggregates/test_sum.test_ignore
+++ b/modules/calcite/src/test/sql/aggregate/aggregates/test_sum.test
@@ -1,13 +1,12 @@
# name: test/sql/aggregate/aggregates/test_sum.test
# description: Test sum aggregate
# group: [aggregates]
-# Ignored: https://issues.apache.org/jira/browse/IGNITE-14542
statement ok
CREATE TABLE integers(i INTEGER);
statement ok
-INSERT INTO integers SELECT * FROM range(0, 1000, 1);
+INSERT INTO integers SELECT * FROM table(system_range(0, 999, 1));
# positive numbers
query I
@@ -17,7 +16,7 @@ SELECT SUM(i) FROM integers;
# negative numbers
statement ok
-INSERT INTO integers SELECT * FROM range(0, -1000, -1);
+INSERT INTO integers SELECT * FROM table(system_range(0, -999, -1));
query I
SELECT SUM(i) FROM integers;
@@ -26,7 +25,7 @@ SELECT SUM(i) FROM integers;
# more negative numbers
statement ok
-INSERT INTO integers SELECT * FROM range(0, -1000, -1);
+INSERT INTO integers SELECT * FROM table(system_range(0, -999, -1));
query I
SELECT SUM(i) FROM integers;
@@ -63,11 +62,11 @@ CREATE TABLE bigints(b BIGINT);
# a bunch of huge values
statement ok
-INSERT INTO bigints SELECT * FROM range(4611686018427387904, 4611686018427388904, 1);
+INSERT INTO bigints SELECT * FROM table(system_range(4611686018427387904, 4611686018427388903, 1));
# sum them up
query I
-SELECT SUM(b) FROM bigints
+SELECT SUM(b::DECIMAL) FROM bigints
----
4611686018427388403500
diff --git a/modules/calcite/src/test/sql/aggregate/aggregates/test_sum.test_ignore b/modules/calcite/src/test/sql/aggregate/aggregates/test_sum.test_ignore
index 40d7ed4..c72e6f1 100644
--- a/modules/calcite/src/test/sql/aggregate/aggregates/test_sum.test_ignore
+++ b/modules/calcite/src/test/sql/aggregate/aggregates/test_sum.test_ignore
@@ -1,13 +1,13 @@
# name: test/sql/aggregate/aggregates/test_sum.test
# description: Test sum aggregate
# group: [aggregates]
-# Ignored: https://issues.apache.org/jira/browse/IGNITE-14542
+# Ignored: https://issues.apache.org/jira/browse/IGNITE-14681
statement ok
CREATE TABLE integers(i INTEGER);
statement ok
-INSERT INTO integers SELECT * FROM range(0, 1000, 1);
+INSERT INTO integers SELECT * FROM table(system_range(0, 999, 1));
# positive numbers
query I
@@ -17,7 +17,7 @@ SELECT SUM(i) FROM integers;
# negative numbers
statement ok
-INSERT INTO integers SELECT * FROM range(0, -1000, -1);
+INSERT INTO integers SELECT * FROM table(system_range(0, -999, -1));
query I
SELECT SUM(i) FROM integers;
@@ -26,7 +26,7 @@ SELECT SUM(i) FROM integers;
# more negative numbers
statement ok
-INSERT INTO integers SELECT * FROM range(0, -1000, -1);
+INSERT INTO integers SELECT * FROM table(system_range(0, -999, -1));
query I
SELECT SUM(i) FROM integers;
@@ -63,7 +63,7 @@ CREATE TABLE bigints(b BIGINT);
# a bunch of huge values
statement ok
-INSERT INTO bigints SELECT * FROM range(4611686018427387904, 4611686018427388904, 1);
+INSERT INTO bigints SELECT * FROM table(system_range(4611686018427387904, 4611686018427388903, 1));
# sum them up
query I