This is an automated email from the ASF dual-hosted git repository.

korlov pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/ignite-3.git


The following commit(s) were added to refs/heads/main by this push:
     new ffb7a424f2 IGNITE-20000: Add planner test to verify numeric type 
coercion in binary arithmetic (#2583)
ffb7a424f2 is described below

commit ffb7a424f262b39b903050bbb52a826c356a4917
Author: ygerzhedovich <[email protected]>
AuthorDate: Wed Sep 20 13:29:18 2023 +0300

    IGNITE-20000: Add planner test to verify numeric type coercion in binary 
arithmetic (#2583)
---
 README.md                                          |   4 +-
 .../planner/datatypes/BaseTypeCoercionTest.java    | 185 +++++
 .../NumericBinaryOperationsTypeCoercionTest.java   | 830 +++++++++++++++++++++
 .../NumericComparisonTypeCoercionTest.java         | 146 +---
 .../sql/engine/planner/datatypes/utils/Types.java  |   3 +
 5 files changed, 1023 insertions(+), 145 deletions(-)

diff --git a/README.md b/README.md
index 2b05d118cf..66971bdd2c 100644
--- a/README.md
+++ b/README.md
@@ -61,8 +61,8 @@ In SQL interactive mode user can simply type SQL commands in 
CLI:
 
 ```sql
 CREATE TABLE IF NOT EXISTS Person (id int primary key,  city varchar,  name 
varchar,  age int,  company varchar);
-INSERT INTO Person (id, city, name, age, company) VALUES ('1', 'London', 'John 
Doe', '42', 'Apache');
-INSERT INTO Person (id, city, name, age, company) VALUES ('2', 'New York', 
'Jane Doe', '36', 'Apache');
+INSERT INTO Person (id, city, name, age, company) VALUES (1, 'London', 'John 
Doe', 42, 'Apache');
+INSERT INTO Person (id, city, name, age, company) VALUES (2, 'New York', 'Jane 
Doe', 36, 'Apache');
 SELECT * FROM Person;
 ```
 
diff --git 
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/datatypes/BaseTypeCoercionTest.java
 
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/datatypes/BaseTypeCoercionTest.java
new file mode 100644
index 0000000000..1cba1b38e5
--- /dev/null
+++ 
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/datatypes/BaseTypeCoercionTest.java
@@ -0,0 +1,185 @@
+/*
+ * 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.sql.engine.planner.datatypes;
+
+import static org.apache.ignite.lang.IgniteStringFormatter.format;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.instanceOf;
+
+import java.util.Arrays;
+import java.util.stream.Stream;
+import org.apache.calcite.rel.type.RelDataType;
+import org.apache.calcite.rex.RexCall;
+import org.apache.calcite.rex.RexNode;
+import org.apache.calcite.sql.SqlKind;
+import org.apache.calcite.sql.type.SqlTypeUtil;
+import org.apache.ignite.internal.schema.NativeType;
+import org.apache.ignite.internal.sql.engine.framework.TestBuilders;
+import org.apache.ignite.internal.sql.engine.planner.AbstractPlannerTest;
+import 
org.apache.ignite.internal.sql.engine.planner.datatypes.utils.NumericPair;
+import org.apache.ignite.internal.sql.engine.planner.datatypes.utils.TypePair;
+import org.apache.ignite.internal.sql.engine.rel.IgniteRel;
+import 
org.apache.ignite.internal.sql.engine.rel.ProjectableFilterableTableScan;
+import org.apache.ignite.internal.sql.engine.schema.IgniteSchema;
+import org.apache.ignite.internal.sql.engine.trait.IgniteDistributions;
+import org.apache.ignite.internal.sql.engine.type.IgniteTypeFactory;
+import org.apache.ignite.internal.sql.engine.util.Commons;
+import org.apache.ignite.internal.sql.engine.util.TypeUtils;
+import org.hamcrest.BaseMatcher;
+import org.hamcrest.Description;
+import org.hamcrest.Matcher;
+import org.junit.jupiter.params.provider.Arguments;
+
+abstract class BaseTypeCoercionTest extends AbstractPlannerTest {
+
+    static Stream<Arguments> allNumericPairs() {
+        return Arrays.stream(NumericPair.values()).map(Arguments::of);
+    }
+
+    static IgniteSchema createSchemaWithTwoColumnTable(NativeType c1, 
NativeType c2) {
+        return createSchema(
+                TestBuilders.table()
+                        .name("T")
+                        .distribution(IgniteDistributions.single())
+                        .addColumn("C1", c1)
+                        .addColumn("C2", c2)
+                        .build()
+        );
+    }
+
+    static Matcher<IgniteRel> operandMatcher(Matcher<RexNode> first, 
Matcher<RexNode> second) {
+        return new BaseMatcher<>() {
+            @Override
+            public boolean matches(Object actual) {
+                RexNode comparison = ((ProjectableFilterableTableScan) 
actual).projects().get(0);
+
+                assertThat(comparison, instanceOf(RexCall.class));
+
+                RexCall comparisonCall = (RexCall) comparison;
+
+                RexNode leftOperand = comparisonCall.getOperands().get(0);
+                RexNode rightOperand = comparisonCall.getOperands().get(1);
+
+                assertThat(leftOperand, first);
+                assertThat(rightOperand, second);
+
+                return true;
+            }
+
+            @Override
+            public void describeTo(Description description) {
+
+            }
+        };
+    }
+
+    /**
+     * Creates a matcher to verify that given expression has expected return 
type, but it is not CAST operator.
+     *
+     * @param type Expected return type.
+     * @return A matcher.
+     */
+    static Matcher<RexNode> ofTypeWithoutCast(NativeType type) {
+        IgniteTypeFactory typeFactory = Commons.typeFactory();
+        RelDataType sqlType = TypeUtils.native2relationalType(typeFactory, 
type);
+
+        return new BaseMatcher<>() {
+            @Override
+            public boolean matches(Object actual) {
+                return SqlTypeUtil.equalSansNullability(typeFactory, 
((RexNode) actual).getType(), sqlType)
+                        && !((RexNode) actual).isA(SqlKind.CAST);
+            }
+
+            @Override
+            public void describeMismatch(Object item, Description description) 
{
+                description.appendText("was ").appendValue(item).appendText(" 
of type " + ((RexNode) item).getType());
+            }
+
+            @Override
+            public void describeTo(Description description) {
+                description.appendText(format("Operand of type {} that is not 
CAST", sqlType));
+            }
+        };
+    }
+
+    /**
+     * Creates a matcher to verify that given expression is CAST operator with 
expected return type.
+     *
+     * @param type Expected return type.
+     * @return A matcher.
+     */
+    static Matcher<RexNode> castTo(NativeType type) {
+        IgniteTypeFactory typeFactory = Commons.typeFactory();
+        RelDataType sqlType = TypeUtils.native2relationalType(typeFactory, 
type);
+
+        return new BaseMatcher<>() {
+            @Override
+            public boolean matches(Object actual) {
+                return actual instanceof RexCall
+                        && ((RexNode) actual).isA(SqlKind.CAST)
+                        && SqlTypeUtil.equalSansNullability(typeFactory, 
((RexNode) actual).getType(), sqlType);
+            }
+
+            @Override
+            public void describeTo(Description description) {
+                description.appendText("Operand that is CAST(..):" + sqlType);
+            }
+
+            @Override
+            public void describeMismatch(Object item, Description description) 
{
+                description.appendText("was ").appendValue(item).appendText(" 
of type " + ((RexNode) item).getType());
+            }
+        };
+    }
+
+    static TestCaseBuilder forTypePair(TypePair typePair) {
+        return new TestCaseBuilder(typePair);
+    }
+
+    /**
+     * Not really a builder, but provides DSL-like API to describe test case.
+     */
+    static class TestCaseBuilder {
+        private final TypePair pair;
+        private Matcher<RexNode> firstOpMatcher;
+
+        private TestCaseBuilder(TypePair pair) {
+            this.pair = pair;
+        }
+
+        TestCaseBuilder firstOpMatches(Matcher<RexNode> operandMatcher) {
+            firstOpMatcher = operandMatcher;
+
+            return this;
+        }
+
+        TestCaseBuilder firstOpBeSame() {
+            firstOpMatcher = ofTypeWithoutCast(pair.first());
+
+            return this;
+        }
+
+        Arguments secondOpMatches(Matcher<RexNode> operandMatcher) {
+            return Arguments.of(pair, firstOpMatcher, operandMatcher);
+        }
+
+        Arguments secondOpBeSame() {
+            return Arguments.of(pair, firstOpMatcher, 
ofTypeWithoutCast(pair.second()));
+        }
+    }
+}
diff --git 
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/datatypes/NumericBinaryOperationsTypeCoercionTest.java
 
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/datatypes/NumericBinaryOperationsTypeCoercionTest.java
new file mode 100644
index 0000000000..da3b47e13a
--- /dev/null
+++ 
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/datatypes/NumericBinaryOperationsTypeCoercionTest.java
@@ -0,0 +1,830 @@
+/*
+ * 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.sql.engine.planner.datatypes;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import java.util.EnumSet;
+import java.util.List;
+import java.util.stream.Stream;
+import org.apache.calcite.rex.RexNode;
+import 
org.apache.ignite.internal.sql.engine.planner.datatypes.utils.NumericPair;
+import org.apache.ignite.internal.sql.engine.planner.datatypes.utils.TypePair;
+import org.apache.ignite.internal.sql.engine.planner.datatypes.utils.Types;
+import org.apache.ignite.internal.sql.engine.schema.IgniteSchema;
+import org.hamcrest.Matcher;
+import org.hamcrest.Matchers;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+/**
+ * A set of test to verify behavior of type coercion for binary arithmetic, 
when operands belongs to the NUMERIC type family.
+ *
+ * <p>This tests aim to help to understand in which cases implicit cast will 
be added to which operand when does arithmetic with a given
+ * numeric type pair.
+ */
+public class NumericBinaryOperationsTypeCoercionTest extends 
BaseTypeCoercionTest {
+
+    // No any type changes for `addition` operation from planner perspective.
+    @ParameterizedTest
+    @MethodSource("allNumericPairs")
+    public void additionOp(NumericPair pair) throws Exception {
+        IgniteSchema schema = createSchemaWithTwoColumnTable(pair.first(), 
pair.second());
+
+        Matcher<RexNode> first = ofTypeWithoutCast(pair.first());
+        Matcher<RexNode> second = ofTypeWithoutCast(pair.second());
+
+        assertPlan("SELECT c1 + c2 FROM t", schema, operandMatcher(first, 
second)::matches, List.of());
+        assertPlan("SELECT c2 + c1 FROM t", schema, operandMatcher(second, 
first)::matches, List.of());
+    }
+
+    // No any type changes for `subtraction` operation from planner 
perspective.
+    @ParameterizedTest
+    @MethodSource("allNumericPairs")
+    public void subtractionOp(NumericPair pair) throws Exception {
+        IgniteSchema schema = createSchemaWithTwoColumnTable(pair.first(), 
pair.second());
+
+        Matcher<RexNode> first = ofTypeWithoutCast(pair.first());
+        Matcher<RexNode> second = ofTypeWithoutCast(pair.second());
+
+        assertPlan("SELECT c1 - c2 FROM t", schema, operandMatcher(first, 
second)::matches, List.of());
+        assertPlan("SELECT c2 - c1 FROM t", schema, operandMatcher(second, 
first)::matches, List.of());
+    }
+
+    // No any type changes for `division` operation from planner perspective.
+    @ParameterizedTest
+    @MethodSource("allNumericPairs")
+    public void divisionOp(NumericPair pair) throws Exception {
+        IgniteSchema schema = createSchemaWithTwoColumnTable(pair.first(), 
pair.second());
+
+        Matcher<RexNode> first = ofTypeWithoutCast(pair.first());
+        Matcher<RexNode> second = ofTypeWithoutCast(pair.second());
+
+        assertPlan("SELECT c1 / c2 FROM t", schema, operandMatcher(first, 
second)::matches, List.of());
+        assertPlan("SELECT c2 / c1 FROM t", schema, operandMatcher(second, 
first)::matches, List.of());
+    }
+
+    // No any type changes for `multiplication` operation from planner 
perspective.
+    @ParameterizedTest
+    @MethodSource("allNumericPairs")
+    public void multiplicationOp(NumericPair pair) throws Exception {
+        IgniteSchema schema = createSchemaWithTwoColumnTable(pair.first(), 
pair.second());
+
+        Matcher<RexNode> first = ofTypeWithoutCast(pair.first());
+        Matcher<RexNode> second = ofTypeWithoutCast(pair.second());
+
+        assertPlan("SELECT c1 * c2 FROM t", schema, operandMatcher(first, 
second)::matches, List.of());
+        assertPlan("SELECT c2 * c1 FROM t", schema, operandMatcher(second, 
first)::matches, List.of());
+    }
+
+    //Have the following casts for modulo operation:
+    // REAL datatype always casts to DECIMAL(14,7)
+    // DOUBLE datatype always casts to DECIMAL(30,15)
+    // Any other types with no any changes
+    @ParameterizedTest
+    @MethodSource("moduloArgs")
+    public void moduloOp(
+            TypePair typePair,
+            Matcher<RexNode> firstOperandMatcher,
+            Matcher<RexNode> secondOperandMatcher
+    ) throws Exception {
+        IgniteSchema schema = createSchemaWithTwoColumnTable(typePair.first(), 
typePair.second());
+
+        assertPlan("SELECT c1 % c2 FROM t", schema, 
operandMatcher(firstOperandMatcher, secondOperandMatcher)::matches, List.of());
+        assertPlan("SELECT c2 % c1 FROM t", schema, 
operandMatcher(secondOperandMatcher, firstOperandMatcher)::matches, List.of());
+    }
+
+    /**
+     * This test ensures that {@link #moduloArgs()} doesn't miss any type pair 
from {@link NumericPair}.
+     */
+    @Test
+    void moduloArgsIncludesAllTypePairs() {
+        EnumSet<NumericPair> remainingPairs = EnumSet.allOf(NumericPair.class);
+
+        moduloArgs().map(Arguments::get).map(arg -> (NumericPair) 
arg[0]).forEach(remainingPairs::remove);
+
+        assertThat(remainingPairs, Matchers.empty());
+    }
+
+    private static Stream<Arguments> moduloArgs() {
+        return Stream.of(
+                forTypePair(NumericPair.TINYINT_TINYINT)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.TINYINT_SMALLINT)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.TINYINT_INT)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.TINYINT_BIGINT)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.TINYINT_NUMBER_1)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.TINYINT_NUMBER_2)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.TINYINT_NUMBER_5)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.TINYINT_DECIMAL_1_0)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.TINYINT_DECIMAL_2_1)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.TINYINT_DECIMAL_4_3)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.TINYINT_DECIMAL_2_0)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.TINYINT_DECIMAL_3_1)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.TINYINT_DECIMAL_5_3)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.TINYINT_DECIMAL_5_0)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.TINYINT_DECIMAL_6_1)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.TINYINT_DECIMAL_8_3)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.TINYINT_REAL)
+                        .firstOpBeSame()
+                        .secondOpMatches(castTo(Types.DECIMAL_14_7)),
+
+                forTypePair(NumericPair.TINYINT_DOUBLE)
+                        .firstOpBeSame()
+                        .secondOpMatches(castTo(Types.DECIMAL_30_15)),
+
+
+                forTypePair(NumericPair.SMALLINT_SMALLINT)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.SMALLINT_INT)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.SMALLINT_BIGINT)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.SMALLINT_NUMBER_1)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.SMALLINT_NUMBER_2)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.SMALLINT_NUMBER_5)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.SMALLINT_DECIMAL_1_0)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.SMALLINT_DECIMAL_2_1)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.SMALLINT_DECIMAL_4_3)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.SMALLINT_DECIMAL_2_0)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.SMALLINT_DECIMAL_3_1)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.SMALLINT_DECIMAL_5_3)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.SMALLINT_DECIMAL_5_0)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.SMALLINT_DECIMAL_6_1)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.SMALLINT_DECIMAL_8_3)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.SMALLINT_REAL)
+                        .firstOpBeSame()
+                        .secondOpMatches(castTo(Types.DECIMAL_14_7)),
+
+                forTypePair(NumericPair.SMALLINT_DOUBLE)
+                        .firstOpBeSame()
+                        .secondOpMatches(castTo(Types.DECIMAL_30_15)),
+
+
+                forTypePair(NumericPair.INT_INT)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.INT_BIGINT)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.INT_NUMBER_1)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.INT_NUMBER_2)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.INT_NUMBER_5)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.INT_DECIMAL_1_0)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.INT_DECIMAL_2_1)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.INT_DECIMAL_4_3)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.INT_DECIMAL_2_0)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.INT_DECIMAL_3_1)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.INT_DECIMAL_5_3)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.INT_DECIMAL_5_0)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.INT_DECIMAL_6_1)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.INT_DECIMAL_8_3)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.INT_REAL)
+                        .firstOpBeSame()
+                        .secondOpMatches(castTo(Types.DECIMAL_14_7)),
+
+                forTypePair(NumericPair.INT_DOUBLE)
+                        .firstOpBeSame()
+                        .secondOpMatches(castTo(Types.DECIMAL_30_15)),
+
+
+                forTypePair(NumericPair.BIGINT_BIGINT)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.BIGINT_NUMBER_1)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.BIGINT_NUMBER_2)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.BIGINT_NUMBER_5)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.BIGINT_DECIMAL_1_0)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.BIGINT_DECIMAL_2_1)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.BIGINT_DECIMAL_4_3)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.BIGINT_DECIMAL_2_0)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.BIGINT_DECIMAL_3_1)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.BIGINT_DECIMAL_5_3)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.BIGINT_DECIMAL_5_0)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.BIGINT_DECIMAL_6_1)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.BIGINT_DECIMAL_8_3)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.BIGINT_REAL)
+                        .firstOpBeSame()
+                        .secondOpMatches(castTo(Types.DECIMAL_14_7)),
+
+                forTypePair(NumericPair.BIGINT_DOUBLE)
+                        .firstOpBeSame()
+                        .secondOpMatches(castTo(Types.DECIMAL_30_15)),
+
+
+                forTypePair(NumericPair.NUMBER_1_NUMBER_1)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.NUMBER_1_NUMBER_2)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.NUMBER_1_NUMBER_5)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.NUMBER_1_DECIMAL_1_0)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.NUMBER_1_DECIMAL_2_1)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.NUMBER_1_DECIMAL_4_3)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.NUMBER_1_DECIMAL_2_0)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.NUMBER_1_DECIMAL_3_1)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.NUMBER_1_DECIMAL_5_3)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.NUMBER_1_DECIMAL_5_0)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.NUMBER_1_DECIMAL_6_1)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.NUMBER_1_DECIMAL_8_3)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.NUMBER_1_REAL)
+                        .firstOpBeSame()
+                        .secondOpMatches(castTo(Types.DECIMAL_14_7)),
+
+                forTypePair(NumericPair.NUMBER_1_DOUBLE)
+                        .firstOpBeSame()
+                        .secondOpMatches(castTo(Types.DECIMAL_30_15)),
+
+
+                forTypePair(NumericPair.NUMBER_2_NUMBER_2)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.NUMBER_2_NUMBER_5)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.NUMBER_2_DECIMAL_1_0)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.NUMBER_2_DECIMAL_2_1)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.NUMBER_2_DECIMAL_4_3)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.NUMBER_2_DECIMAL_2_0)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.NUMBER_2_DECIMAL_3_1)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.NUMBER_2_DECIMAL_5_3)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.NUMBER_2_DECIMAL_5_0)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.NUMBER_2_DECIMAL_6_1)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.NUMBER_2_DECIMAL_8_3)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.NUMBER_2_REAL)
+                        .firstOpBeSame()
+                        .secondOpMatches(castTo(Types.DECIMAL_14_7)),
+
+                forTypePair(NumericPair.NUMBER_2_DOUBLE)
+                        .firstOpBeSame()
+                        .secondOpMatches(castTo(Types.DECIMAL_30_15)),
+
+
+                forTypePair(NumericPair.NUMBER_5_NUMBER_5)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.NUMBER_5_DECIMAL_1_0)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.NUMBER_5_DECIMAL_2_1)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.NUMBER_5_DECIMAL_4_3)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.NUMBER_5_DECIMAL_2_0)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.NUMBER_5_DECIMAL_3_1)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.NUMBER_5_DECIMAL_5_3)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.NUMBER_5_DECIMAL_5_0)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.NUMBER_5_DECIMAL_6_1)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.NUMBER_5_DECIMAL_8_3)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.NUMBER_5_REAL)
+                        .firstOpBeSame()
+                        .secondOpMatches(castTo(Types.DECIMAL_14_7)),
+
+                forTypePair(NumericPair.NUMBER_5_DOUBLE)
+                        .firstOpBeSame()
+                        .secondOpMatches(castTo(Types.DECIMAL_30_15)),
+
+
+                forTypePair(NumericPair.DECIMAL_1_0_DECIMAL_1_0)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.DECIMAL_1_0_DECIMAL_2_1)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.DECIMAL_1_0_DECIMAL_4_3)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.DECIMAL_1_0_DECIMAL_2_0)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.DECIMAL_1_0_DECIMAL_3_1)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.DECIMAL_1_0_DECIMAL_5_3)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.DECIMAL_1_0_DECIMAL_5_0)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.DECIMAL_1_0_DECIMAL_6_1)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.DECIMAL_1_0_DECIMAL_8_3)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.DECIMAL_1_0_REAL)
+                        .firstOpBeSame()
+                        .secondOpMatches(castTo(Types.DECIMAL_14_7)),
+
+                forTypePair(NumericPair.DECIMAL_1_0_DOUBLE)
+                        .firstOpBeSame()
+                        .secondOpMatches(castTo(Types.DECIMAL_30_15)),
+
+
+                forTypePair(NumericPair.DECIMAL_2_1_DECIMAL_2_1)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.DECIMAL_2_1_DECIMAL_4_3)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.DECIMAL_2_1_DECIMAL_2_0)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.DECIMAL_2_1_DECIMAL_3_1)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.DECIMAL_2_1_DECIMAL_5_3)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.DECIMAL_2_1_DECIMAL_5_0)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.DECIMAL_2_1_DECIMAL_6_1)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.DECIMAL_2_1_DECIMAL_8_3)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.DECIMAL_2_1_REAL)
+                        .firstOpBeSame()
+                        .secondOpMatches(castTo(Types.DECIMAL_14_7)),
+
+                forTypePair(NumericPair.DECIMAL_2_1_DOUBLE)
+                        .firstOpBeSame()
+                        .secondOpMatches(castTo(Types.DECIMAL_30_15)),
+
+
+                forTypePair(NumericPair.DECIMAL_4_3_DECIMAL_4_3)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.DECIMAL_4_3_DECIMAL_2_0)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.DECIMAL_4_3_DECIMAL_3_1)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.DECIMAL_4_3_DECIMAL_5_3)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.DECIMAL_4_3_DECIMAL_5_0)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.DECIMAL_4_3_DECIMAL_6_1)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.DECIMAL_4_3_DECIMAL_8_3)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.DECIMAL_4_3_REAL)
+                        .firstOpBeSame()
+                        .secondOpMatches(castTo(Types.DECIMAL_14_7)),
+
+                forTypePair(NumericPair.DECIMAL_4_3_DOUBLE)
+                        .firstOpBeSame()
+                        .secondOpMatches(castTo(Types.DECIMAL_30_15)),
+
+
+                forTypePair(NumericPair.DECIMAL_2_0_DECIMAL_2_0)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.DECIMAL_2_0_DECIMAL_3_1)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.DECIMAL_2_0_DECIMAL_5_3)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.DECIMAL_2_0_DECIMAL_5_0)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.DECIMAL_2_0_DECIMAL_6_1)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.DECIMAL_2_0_DECIMAL_8_3)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.DECIMAL_2_0_REAL)
+                        .firstOpBeSame()
+                        .secondOpMatches(castTo(Types.DECIMAL_14_7)),
+
+                forTypePair(NumericPair.DECIMAL_2_0_DOUBLE)
+                        .firstOpBeSame()
+                        .secondOpMatches(castTo(Types.DECIMAL_30_15)),
+
+
+                forTypePair(NumericPair.DECIMAL_3_1_DECIMAL_3_1)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.DECIMAL_3_1_DECIMAL_5_3)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.DECIMAL_3_1_DECIMAL_5_0)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.DECIMAL_3_1_DECIMAL_6_1)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.DECIMAL_3_1_DECIMAL_8_3)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.DECIMAL_3_1_REAL)
+                        .firstOpBeSame()
+                        .secondOpMatches(castTo(Types.DECIMAL_14_7)),
+
+                forTypePair(NumericPair.DECIMAL_3_1_DOUBLE)
+                        .firstOpBeSame()
+                        .secondOpMatches(castTo(Types.DECIMAL_30_15)),
+
+
+                forTypePair(NumericPair.DECIMAL_5_3_DECIMAL_5_3)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.DECIMAL_5_3_DECIMAL_5_0)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.DECIMAL_5_3_DECIMAL_6_1)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.DECIMAL_5_3_DECIMAL_8_3)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.DECIMAL_5_3_REAL)
+                        .firstOpBeSame()
+                        .secondOpMatches(castTo(Types.DECIMAL_14_7)),
+
+                forTypePair(NumericPair.DECIMAL_5_3_DOUBLE)
+                        .firstOpBeSame()
+                        .secondOpMatches(castTo(Types.DECIMAL_30_15)),
+
+
+                forTypePair(NumericPair.DECIMAL_5_0_DECIMAL_5_0)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.DECIMAL_5_0_DECIMAL_6_1)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.DECIMAL_5_0_DECIMAL_8_3)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.DECIMAL_5_0_REAL)
+                        .firstOpBeSame()
+                        .secondOpMatches(castTo(Types.DECIMAL_14_7)),
+
+                forTypePair(NumericPair.DECIMAL_5_0_DOUBLE)
+                        .firstOpBeSame()
+                        .secondOpMatches(castTo(Types.DECIMAL_30_15)),
+
+
+                forTypePair(NumericPair.DECIMAL_6_1_DECIMAL_6_1)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.DECIMAL_6_1_DECIMAL_8_3)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.DECIMAL_6_1_REAL)
+                        .firstOpBeSame()
+                        .secondOpMatches(castTo(Types.DECIMAL_14_7)),
+
+                forTypePair(NumericPair.DECIMAL_6_1_DOUBLE)
+                        .firstOpBeSame()
+                        .secondOpMatches(castTo(Types.DECIMAL_30_15)),
+
+
+                forTypePair(NumericPair.DECIMAL_8_3_DECIMAL_8_3)
+                        .firstOpBeSame()
+                        .secondOpBeSame(),
+
+                forTypePair(NumericPair.DECIMAL_8_3_REAL)
+                        .firstOpBeSame()
+                        .secondOpMatches(castTo(Types.DECIMAL_14_7)),
+
+                forTypePair(NumericPair.DECIMAL_8_3_DOUBLE)
+                        .firstOpBeSame()
+                        .secondOpMatches(castTo(Types.DECIMAL_30_15)),
+
+
+                forTypePair(NumericPair.REAL_REAL)
+                        .firstOpMatches(castTo(Types.DECIMAL_14_7))
+                        .secondOpMatches(castTo((Types.DECIMAL_14_7))),
+
+                forTypePair(NumericPair.REAL_DOUBLE)
+                        .firstOpMatches(castTo(Types.DECIMAL_14_7))
+                        .secondOpMatches(castTo(Types.DECIMAL_30_15)),
+
+
+                forTypePair(NumericPair.DOUBLE_DOUBLE)
+                        .firstOpMatches(castTo(Types.DECIMAL_30_15))
+                        .secondOpMatches(castTo(Types.DECIMAL_30_15))
+        );
+    }
+}
diff --git 
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/datatypes/NumericComparisonTypeCoercionTest.java
 
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/datatypes/NumericComparisonTypeCoercionTest.java
index abd9b6c783..3475e6256d 100644
--- 
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/datatypes/NumericComparisonTypeCoercionTest.java
+++ 
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/datatypes/NumericComparisonTypeCoercionTest.java
@@ -17,34 +17,17 @@
 
 package org.apache.ignite.internal.sql.engine.planner.datatypes;
 
-import static org.apache.ignite.lang.IgniteStringFormatter.format;
 import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.instanceOf;
 
 import java.util.EnumSet;
 import java.util.List;
 import java.util.stream.Stream;
-import org.apache.calcite.rel.type.RelDataType;
-import org.apache.calcite.rex.RexCall;
 import org.apache.calcite.rex.RexNode;
-import org.apache.calcite.sql.SqlKind;
-import org.apache.calcite.sql.type.SqlTypeUtil;
-import org.apache.ignite.internal.schema.NativeType;
 import org.apache.ignite.internal.schema.NativeTypes;
-import org.apache.ignite.internal.sql.engine.framework.TestBuilders;
-import org.apache.ignite.internal.sql.engine.planner.AbstractPlannerTest;
 import 
org.apache.ignite.internal.sql.engine.planner.datatypes.utils.NumericPair;
 import org.apache.ignite.internal.sql.engine.planner.datatypes.utils.TypePair;
 import org.apache.ignite.internal.sql.engine.planner.datatypes.utils.Types;
-import org.apache.ignite.internal.sql.engine.rel.IgniteRel;
-import 
org.apache.ignite.internal.sql.engine.rel.ProjectableFilterableTableScan;
 import org.apache.ignite.internal.sql.engine.schema.IgniteSchema;
-import org.apache.ignite.internal.sql.engine.trait.IgniteDistributions;
-import org.apache.ignite.internal.sql.engine.type.IgniteTypeFactory;
-import org.apache.ignite.internal.sql.engine.util.Commons;
-import org.apache.ignite.internal.sql.engine.util.TypeUtils;
-import org.hamcrest.BaseMatcher;
-import org.hamcrest.Description;
 import org.hamcrest.Matcher;
 import org.hamcrest.Matchers;
 import org.junit.jupiter.api.Test;
@@ -53,12 +36,11 @@ import org.junit.jupiter.params.provider.Arguments;
 import org.junit.jupiter.params.provider.MethodSource;
 
 /**
- *  A set of test to verify behavior of type coercion for binary comparison, 
when operands belongs
- *  to the NUMERIC type family.
+ * A set of test to verify behavior of type coercion for binary comparison, 
when operands belongs to the NUMERIC type family.
  *
- *  <p>This tests aim to help to understand in which cases implicit cast will 
be added to which operand.
+ * <p>This tests aim to help to understand in which cases implicit cast will 
be added to which operand.
  */
-public class NumericComparisonTypeCoercionTest extends AbstractPlannerTest {
+public class NumericComparisonTypeCoercionTest extends BaseTypeCoercionTest {
     private static Stream<Arguments> args() {
         return Stream.of(
                 forTypePair(NumericPair.TINYINT_TINYINT)
@@ -840,126 +822,4 @@ public class NumericComparisonTypeCoercionTest extends 
AbstractPlannerTest {
 
         assertThat(remainingPairs, Matchers.empty());
     }
-
-    private static IgniteSchema createSchemaWithTwoColumnTable(NativeType c1, 
NativeType c2) {
-        return createSchema(
-                TestBuilders.table()
-                        .name("T")
-                        .distribution(IgniteDistributions.single())
-                        .addColumn("C1", c1)
-                        .addColumn("C2", c2)
-                        .build()
-        );
-    }
-
-    private static Matcher<IgniteRel> operandMatcher(Matcher<RexNode> first, 
Matcher<RexNode> second) {
-        return new BaseMatcher<IgniteRel>() {
-            @Override
-            public boolean matches(Object actual) {
-                RexNode comparison = ((ProjectableFilterableTableScan) 
actual).projects().get(0);
-
-                assertThat(comparison, instanceOf(RexCall.class));
-
-                RexCall comparisonCall = (RexCall) comparison;
-
-                RexNode leftOperand = comparisonCall.getOperands().get(0);
-                RexNode rightOperand = comparisonCall.getOperands().get(1);
-
-                assertThat(leftOperand, first);
-                assertThat(rightOperand, second);
-
-                return true;
-            }
-
-            @Override
-            public void describeTo(Description description) {
-
-            }
-        };
-    }
-
-    /**
-     * Creates a matcher to verify that given expression has expected return 
type, but it is not CAST operator.
-     *
-     * @param type Expected return type.
-     * @return A matcher.
-     */
-    private static Matcher<RexNode> ofTypeWithoutCast(NativeType type) {
-        IgniteTypeFactory typeFactory = Commons.typeFactory();
-        RelDataType sqlType = TypeUtils.native2relationalType(typeFactory, 
type);
-
-        return new BaseMatcher<RexNode>() {
-            @Override
-            public boolean matches(Object actual) {
-                return SqlTypeUtil.equalSansNullability(typeFactory, 
((RexNode) actual).getType(), sqlType)
-                        && !((RexNode) actual).isA(SqlKind.CAST);
-            }
-
-            @Override
-            public void describeMismatch(Object item, Description description) 
{
-                description.appendText("was ").appendValue(item).appendText(" 
of type " + ((RexNode) item).getType());
-            }
-
-            @Override
-            public void describeTo(Description description) {
-                description.appendText(format("Operand of type {} that is not 
CAST", sqlType));
-            }
-        };
-    }
-
-    /**
-     * Creates a matcher to verify that given expression is CAST operator with 
expected return type.
-     *
-     * @param type Expected return type.
-     * @return A matcher.
-     */
-    private static Matcher<RexNode> castTo(NativeType type) {
-        IgniteTypeFactory typeFactory = Commons.typeFactory();
-        RelDataType sqlType = TypeUtils.native2relationalType(typeFactory, 
type);
-
-        return new BaseMatcher<RexNode>() {
-            @Override
-            public boolean matches(Object actual) {
-                return actual instanceof RexCall
-                        && ((RexNode) actual).isA(SqlKind.CAST)
-                        && SqlTypeUtil.equalSansNullability(typeFactory, 
((RexNode) actual).getType(), sqlType);
-            }
-
-            @Override
-            public void describeTo(Description description) {
-                description.appendText("Operand that is CAST(..):" + sqlType);
-            }
-
-            @Override
-            public void describeMismatch(Object item, Description description) 
{
-                description.appendText("was ").appendValue(item).appendText(" 
of type " + ((RexNode) item).getType());
-            }
-        };
-    }
-
-    private static TestCaseBuilder forTypePair(TypePair typePair) {
-        return new TestCaseBuilder(typePair);
-    }
-
-    /**
-     * Not really a builder, but provides DSL-like API to describe test case.
-     */
-    static class TestCaseBuilder {
-        private final TypePair pair;
-        private Matcher<RexNode> firstOpMatcher;
-
-        private TestCaseBuilder(TypePair pair) {
-            this.pair = pair;
-        }
-
-        TestCaseBuilder firstOpMatches(Matcher<RexNode> operandMatcher) {
-            firstOpMatcher = operandMatcher;
-
-            return this;
-        }
-
-        Arguments secondOpMatches(Matcher<RexNode> operandMatcher) {
-            return Arguments.of(pair, firstOpMatcher, operandMatcher);
-        }
-    }
 }
diff --git 
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/datatypes/utils/Types.java
 
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/datatypes/utils/Types.java
index 6f8efc4ff2..71f4f83f53 100644
--- 
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/datatypes/utils/Types.java
+++ 
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/datatypes/utils/Types.java
@@ -42,6 +42,9 @@ public final class Types {
     public static final NativeType DECIMAL_6_1 = NativeTypes.decimalOf(6, 1);
     public static final NativeType DECIMAL_8_3 = NativeTypes.decimalOf(8, 3);
 
+    public static final NativeType DECIMAL_14_7 = NativeTypes.decimalOf(14, 7);
+    public static final NativeType DECIMAL_30_15 = NativeTypes.decimalOf(30, 
15);
+
     private Types() {
         throw new AssertionError("Should not be called");
     }

Reply via email to