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

amashenkov 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 a75bf47a4a0 IGNITE-25818:  Sql. Bump calcite version to 1.41 (#7249)
a75bf47a4a0 is described below

commit a75bf47a4a06792e338f021fef486a3862955a37
Author: Max Zhuravkov <[email protected]>
AuthorDate: Tue Dec 23 16:02:21 2025 +0200

    IGNITE-25818:  Sql. Bump calcite version to 1.41 (#7249)
---
 gradle/libs.versions.toml                          |   2 +-
 .../org/apache/ignite/InitParametersBuilder.java   |   2 +-
 .../sql/group1/aggregate/group/test_group_by.test  |  12 +-
 .../sql/engine/exec/exp/RexToLixTranslator.java    |  97 +++++++-------
 .../engine/prepare/IgniteSqlToRelConvertor.java    | 141 +++++++++++++++++----
 .../sql/engine/prepare/IgniteTypeCoercion.java     |   4 +-
 .../ignite/internal/sql/engine/util/RexUtils.java  |  47 ++++++-
 .../sql/engine/planner/AbstractPlannerTest.java    |  36 +++++-
 .../sql/engine/planner/CastResolutionTest.java     |   5 +-
 .../planner/CorrelatedSubqueryPlannerTest.java     |   7 +-
 .../sql/engine/planner/DynamicParametersTest.java  |   9 +-
 .../sql/engine/planner/ImplicitCastsTest.java      |   1 +
 .../planner/IndexSearchBoundsPlannerTest.java      |  16 ++-
 .../datatypes/NumericInTypeCoercionTest.java       | 104 +++++++++++++--
 .../prepare/ddl/DdlSqlToCommandConverterTest.java  |  13 +-
 .../sql/engine/sql/SqlReservedWordsTest.java       |   1 +
 .../internal/sql/engine/util/QueryCheckerTest.java |   2 +-
 .../src/test/resources/tpcds/plan/q15.plan         |   2 +-
 .../src/test/resources/tpcds/plan/q45.plan         |   2 +-
 .../src/test/resources/tpcds/plan/q50.plan         |   2 +-
 .../src/test/resources/tpcds/plan/q62.plan         |   2 +-
 .../src/test/resources/tpcds/plan/q64.plan         |   4 +-
 .../src/test/resources/tpcds/plan/q78.plan         |   2 +-
 .../src/test/resources/tpcds/plan/q8.plan          |   8 +-
 .../src/test/resources/tpcds/plan/q99.plan         |   2 +-
 .../src/test/resources/tpch/plan/q22.plan          |   4 +-
 26 files changed, 394 insertions(+), 133 deletions(-)

diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index b984f2713d0..5675596abb9 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -59,7 +59,7 @@ hamcrestOptional = "2.0.0"
 hamcrestPath = "1.0.1"
 hamcrestJson = "0.3"
 scalecube = "2.6.15"
-calcite = "1.40.0"
+calcite = "1.41.0"
 value = "2.12.0"
 janino = "3.1.12"
 jsonpath = "2.10.0"
diff --git 
a/modules/runner/src/main/java/org/apache/ignite/InitParametersBuilder.java 
b/modules/runner/src/main/java/org/apache/ignite/InitParametersBuilder.java
index 431a1a5e810..7a5a37537c6 100644
--- a/modules/runner/src/main/java/org/apache/ignite/InitParametersBuilder.java
+++ b/modules/runner/src/main/java/org/apache/ignite/InitParametersBuilder.java
@@ -23,7 +23,7 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 import java.util.stream.Collectors;
-import javax.annotation.Nullable;
+import org.jetbrains.annotations.Nullable;
 
 /** Builder of {@link InitParameters}. */
 public class InitParametersBuilder {
diff --git 
a/modules/sql-engine/src/integrationTest/sql/group1/aggregate/group/test_group_by.test
 
b/modules/sql-engine/src/integrationTest/sql/group1/aggregate/group/test_group_by.test
index 6cd2d03f655..1cad5cbf535 100644
--- 
a/modules/sql-engine/src/integrationTest/sql/group1/aggregate/group/test_group_by.test
+++ 
b/modules/sql-engine/src/integrationTest/sql/group1/aggregate/group/test_group_by.test
@@ -188,13 +188,17 @@ SELECT SUM(i) FROM integers GROUP BY GROUPING SETS 
(POWER(ROUND(ABS(SQRT(i*i)),
 3
 NULL
 
-# expression with aliases can't be used in group by <columns> clause.
-statement error: Column 'K' not found in any table
+# expression with aliases can be used in group by <columns> clause.
+query II
 SELECT 1 AS k, SUM(i) FROM integers GROUP BY k+1 ORDER BY 2
+----
+1      6
 
-# expression with aliases can't be used in group by <grouping sets> clause.
-statement error: Column 'K' not found in any table
+# expression with aliases can be used in group by <grouping sets> clause.
+query II
 SELECT 1 AS k, SUM(i) FROM integers GROUP BY GROUPING SETS ((k+1)) ORDER BY 2
+----
+1      6
 
 # group by column refs should be recognized, even if one uses an explicit 
table specifier and the other does not
 query II
diff --git 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/exp/RexToLixTranslator.java
 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/exp/RexToLixTranslator.java
index 7c53c185b64..e37fc4f446e 100644
--- 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/exp/RexToLixTranslator.java
+++ 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/exp/RexToLixTranslator.java
@@ -60,6 +60,7 @@ import org.apache.calcite.linq4j.tree.ParameterExpression;
 import org.apache.calcite.linq4j.tree.Primitive;
 import org.apache.calcite.linq4j.tree.Statement;
 import org.apache.calcite.rel.type.RelDataType;
+import org.apache.calcite.rel.type.RelDataTypeField;
 import org.apache.calcite.rex.RexBuilder;
 import org.apache.calcite.rex.RexCall;
 import org.apache.calcite.rex.RexCallBinding;
@@ -72,6 +73,7 @@ import org.apache.calcite.rex.RexLambdaRef;
 import org.apache.calcite.rex.RexLiteral;
 import org.apache.calcite.rex.RexLocalRef;
 import org.apache.calcite.rex.RexNode;
+import org.apache.calcite.rex.RexNodeAndFieldIndex;
 import org.apache.calcite.rex.RexOver;
 import org.apache.calcite.rex.RexPatternFieldRef;
 import org.apache.calcite.rex.RexProgram;
@@ -82,6 +84,7 @@ import org.apache.calcite.rex.RexUtil;
 import org.apache.calcite.rex.RexVisitor;
 import org.apache.calcite.runtime.SpatialTypeFunctions;
 import org.apache.calcite.runtime.rtti.RuntimeTypeInformation;
+import org.apache.calcite.runtime.variant.VariantValue;
 import org.apache.calcite.schema.FunctionContext;
 import org.apache.calcite.sql.SqlIntervalQualifier;
 import org.apache.calcite.sql.SqlOperator;
@@ -354,53 +357,54 @@ public class RexToLixTranslator implements 
RexVisitor<RexToLixTranslator.Result>
     final Supplier<Expression> defaultExpression = () ->
             ConverterUtils.convert(operand, targetType);
 
-//    if (sourceType.getSqlTypeName() == SqlTypeName.VARIANT) {
-//      // Converting VARIANT to VARIANT uses the default conversion
-//      if (targetType.getSqlTypeName() == SqlTypeName.VARIANT) {
-//        return defaultExpression.get();
-//      }
-//      // Converting a VARIANT to any other type calls the Variant.cast method
-//      // First cast operand to a VariantValue (it may be an Object)
-//      Expression operandCast = Expressions.convert_(operand, 
VariantValue.class);
-//      Expression cast =
-//              Expressions.call(operandCast, 
BuiltInMethod.VARIANT_CAST.method,
-//                      RuntimeTypeInformation.createExpression(targetType));
-//      // The cast returns an Object, so we need a convert to the expected 
Java type
-//      RelDataType nullableTarget = 
typeFactory.createTypeWithNullability(targetType, true);
-//      return Expressions.convert_(cast, 
typeFactory.getJavaClass(nullableTarget));
-//    }
-//
-//    if (targetType.getSqlTypeName() == SqlTypeName.ROW) {
-//      assert sourceType.getSqlTypeName() == SqlTypeName.ROW;
-//      List<RelDataTypeField> targetTypes = targetType.getFieldList();
-//      List<RelDataTypeField> sourceTypes = sourceType.getFieldList();
-//      assert targetTypes.size() == sourceTypes.size();
-//      List<Expression> fields = new ArrayList<>();
-//      for (int i = 0; i < targetTypes.size(); i++) {
-//        RelDataTypeField targetField = targetTypes.get(i);
-//        RelDataTypeField sourceField = sourceTypes.get(i);
-//        Expression field = Expressions.arrayIndex(operand, 
Expressions.constant(i));
-//        // In the generated Java code 'field' is an Object,
-//        // we need to also cast it to the correct type to enable correct 
method dispatch in Java.
-//        // We force the type to be nullable; this way, instead of (int) we 
get (Integer).
-//        // Casting an object ot an int is not legal.
-//        RelDataType nullableSourceFieldType =
-//                typeFactory.createTypeWithNullability(sourceField.getType(), 
true);
-//        Type javaType = typeFactory.getJavaClass(nullableSourceFieldType);
-//        if (!javaType.getTypeName().equals("java.lang.Void")
-//                && !nullableSourceFieldType.isStruct()) {
-//          // Cannot cast to Void - this is the type of NULL literals.
-//          field = Expressions.convert_(field, javaType);
-//        }
-//        Expression convert =
-//                getConvertExpression(sourceField.getType(), 
targetField.getType(), field, format);
-//        fields.add(convert);
-//      }
-//      return Expressions.call(BuiltInMethod.ARRAY.method, fields);
-//    }
+    if (sourceType.getSqlTypeName() == SqlTypeName.VARIANT) {
+      // Converting VARIANT to VARIANT uses the default conversion
+      if (targetType.getSqlTypeName() == SqlTypeName.VARIANT) {
+        return defaultExpression.get();
+      }
+      // Converting a VARIANT to any other type calls the Variant.cast method
+      // First cast operand to a VariantValue (it may be an Object)
+      Expression operandCast = Expressions.convert_(operand, 
VariantValue.class);
+      Expression cast =
+              Expressions.call(operandCast, BuiltInMethod.VARIANT_CAST.method,
+                      RuntimeTypeInformation.createExpression(targetType));
+      // The cast returns an Object, so we need a convert to the expected Java 
type
+      RelDataType nullableTarget = 
typeFactory.createTypeWithNullability(targetType, true);
+      return Expressions.convert_(cast, 
typeFactory.getJavaClass(nullableTarget));
+    }
+
+    if (targetType.getSqlTypeName() == SqlTypeName.ROW) {
+      assert sourceType.getSqlTypeName() == SqlTypeName.ROW;
+      List<RelDataTypeField> targetTypes = targetType.getFieldList();
+      List<RelDataTypeField> sourceTypes = sourceType.getFieldList();
+      assert targetTypes.size() == sourceTypes.size();
+      List<Expression> fields = new ArrayList<>();
+      for (int i = 0; i < targetTypes.size(); i++) {
+        RelDataTypeField targetField = targetTypes.get(i);
+        RelDataTypeField sourceField = sourceTypes.get(i);
+        Expression field = Expressions.arrayIndex(operand, 
Expressions.constant(i));
+        // In the generated Java code 'field' is an Object,
+        // we need to also cast it to the correct type to enable correct 
method dispatch in Java.
+        // We force the type to be nullable; this way, instead of (int) we get 
(Integer).
+        // Casting an object ot an int is not legal.
+        RelDataType nullableSourceFieldType =
+                typeFactory.createTypeWithNullability(sourceField.getType(), 
true);
+        Type javaType = typeFactory.getJavaClass(nullableSourceFieldType);
+        if (!javaType.getTypeName().equals("java.lang.Void")
+                && !nullableSourceFieldType.isStruct()) {
+          // Cannot cast to Void - this is the type of NULL literals.
+          field = Expressions.convert_(field, javaType);
+        }
+        Expression convert =
+                getConvertExpression(sourceField.getType(), 
targetField.getType(), field, format);
+        fields.add(convert);
+      }
+      return Expressions.call(BuiltInMethod.ARRAY.method, fields);
+    }
 
     switch (targetType.getSqlTypeName()) {
     case ARRAY:
+    case MULTISET:
       final RelDataType sourceDataType = sourceType.getComponentType();
       final RelDataType targetDataType = targetType.getComponentType();
       assert sourceDataType != null;
@@ -1908,6 +1912,11 @@ public class RexToLixTranslator implements 
RexVisitor<RexToLixTranslator.Result>
     return new Result(isNullVariable, valueVariable);
   }
 
+  @Override
+  public Result visitNodeAndFieldIndex(RexNodeAndFieldIndex nodeAndFieldIndex) 
{
+    throw new RuntimeException("cannot translate expression " + 
nodeAndFieldIndex);
+  }
+  
   Expression checkNull(Expression expr) {
     if (Primitive.flavor(expr.getType())
         == Primitive.Flavor.PRIMITIVE) {
diff --git 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/IgniteSqlToRelConvertor.java
 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/IgniteSqlToRelConvertor.java
index adb6012cf4b..d64c508775b 100644
--- 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/IgniteSqlToRelConvertor.java
+++ 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/IgniteSqlToRelConvertor.java
@@ -19,12 +19,17 @@ package org.apache.ignite.internal.sql.engine.prepare;
 
 import static java.util.Objects.requireNonNull;
 
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodHandles.Lookup;
+import java.lang.invoke.MethodType;
 import java.util.ArrayDeque;
 import java.util.ArrayList;
 import java.util.Deque;
 import java.util.List;
 import org.apache.calcite.plan.RelOptCluster;
 import org.apache.calcite.plan.RelOptTable;
+import org.apache.calcite.plan.RelOptUtil;
 import org.apache.calcite.prepare.Prepare;
 import org.apache.calcite.rel.RelNode;
 import org.apache.calcite.rel.RelRoot;
@@ -43,8 +48,8 @@ import org.apache.calcite.sql.SqlInsert;
 import org.apache.calcite.sql.SqlKind;
 import org.apache.calcite.sql.SqlMerge;
 import org.apache.calcite.sql.SqlNode;
+import org.apache.calcite.sql.SqlSelect;
 import org.apache.calcite.sql.SqlUpdate;
-import org.apache.calcite.sql.util.SqlShuttle;
 import org.apache.calcite.sql.validate.SqlValidator;
 import org.apache.calcite.sql.validate.SqlValidatorScope;
 import org.apache.calcite.sql.validate.SqlValidatorUtil;
@@ -52,13 +57,41 @@ import org.apache.calcite.sql2rel.InitializerContext;
 import org.apache.calcite.sql2rel.SqlRexConvertletTable;
 import org.apache.calcite.sql2rel.SqlToRelConverter;
 import org.apache.calcite.tools.RelBuilder;
-import org.apache.calcite.util.ControlFlowException;
 import org.apache.calcite.util.Pair;
+import org.apache.calcite.util.Util;
 import org.apache.ignite.internal.sql.engine.schema.IgniteDataSource;
 import org.jetbrains.annotations.Nullable;
 
 /** Converts a SQL parse tree into a relational algebra operators. */
 public class IgniteSqlToRelConvertor extends SqlToRelConverter implements 
InitializerContext {
+
+    private static final MethodHandle REPLACE_SUB_QUERIES;
+
+    private static final Throwable INIT_ERROR;
+
+    static {
+        // TODO https://issues.apache.org/jira/browse/IGNITE-27398 Remove this 
workaround
+        MethodHandle handle;
+        Throwable err;
+        try {
+            Lookup lookup = 
MethodHandles.privateLookupIn(SqlToRelConverter.class, MethodHandles.lookup());
+            Class<?> bbClass = 
lookup.findClass("org.apache.calcite.sql2rel.SqlToRelConverter$Blackboard");
+            Class<?> logicClass = 
lookup.findClass("org.apache.calcite.plan.RelOptUtil$Logic");
+            Class<?> sqlNodeClass = SqlNode.class;
+            MethodType tpe = MethodType.methodType(void.class, bbClass, 
sqlNodeClass, logicClass);
+
+            handle = lookup.findVirtual(SqlToRelConverter.class, 
"replaceSubQueries", tpe);
+            err = null;
+        } catch (Throwable e) {
+            // Postpone error reporting to have a better chance of logging an 
error.
+            err = e;
+            handle = null;
+        }
+
+        INIT_ERROR = err;
+        REPLACE_SUB_QUERIES = handle;
+    }
+
     private final Deque<SqlCall> datasetStack = new ArrayDeque<>();
 
     private RelBuilder relBuilder;
@@ -73,12 +106,19 @@ public class IgniteSqlToRelConvertor extends 
SqlToRelConverter implements Initia
         super(viewExpander, validator, catalogReader, cluster, 
convertletTable, cfg);
 
         relBuilder = config.getRelBuilderFactory().create(cluster, null);
+
+        if (INIT_ERROR != null) {
+            throw new IllegalStateException("Failed to initialize " + 
IgniteSqlToRelConvertor.class.getName(), INIT_ERROR);
+        }
     }
 
     /** {@inheritDoc} */
     @Override protected RelRoot convertQueryRecursive(SqlNode qry, boolean 
top, @Nullable RelDataType targetRowType) {
         if (qry.getKind() == SqlKind.MERGE) {
             return RelRoot.of(convertMerge((SqlMerge) qry), qry.getKind());
+        } else if (qry.getKind() == SqlKind.UPDATE) {
+            // TODO https://issues.apache.org/jira/browse/IGNITE-27398 Remove 
this workaround and use calcite's method.
+            return RelRoot.of(convertUpdateFixed((SqlUpdate) qry), 
qry.getKind());
         } else {
             return super.convertQueryRecursive(qry, top, targetRowType);
         }
@@ -99,31 +139,23 @@ public class IgniteSqlToRelConvertor extends 
SqlToRelConverter implements Initia
         throw new UnsupportedOperationException("Not implemented yet");
     }
 
-    private static class DefaultChecker extends SqlShuttle {
-        private boolean hasDefaults(SqlCall call) {
-            try {
-                call.accept(this);
-                return false;
-            } catch (ControlFlowException e) {
-                return true;
-            }
-        }
-
-        @Override public @Nullable SqlNode visit(SqlCall call) {
-            if (call.getKind() == SqlKind.DEFAULT) {
-                throw new ControlFlowException();
-            }
-
-            return super.visit(call);
-        }
-    }
-
     @Override public RelNode convertValues(SqlCall values, RelDataType 
targetRowType) {
-        DefaultChecker checker = new DefaultChecker();
-
-        boolean hasDefaults = checker.hasDefaults(values);
-
-        if (hasDefaults) {
+        // TODO https://issues.apache.org/jira/browse/IGNITE-27396
+        // FIX: Original convertValuesImpl adds additional type casts that are 
not correct
+        // and break NOT NULL constraints.
+        //
+        // See these lines in convertValuesImpl: 
+        // if (!(def instanceof RexDynamicParam) && 
!def.getType().equals(fieldType)) {
+        //   def = rexBuilder.makeCast(operand.getParserPosition(), fieldType, 
def);
+        // }
+        // exps.add(def, SqlValidatorUtil.alias(operand, i));
+        //
+        // Example: INSERT INTO t1 VALUES(1, (SELECT NULL))
+        // 
+        // if fieldType is NOT NULLABLE INT and def's type is NULLABLE INT then
+        // resulting expression is wrapped into CAST(NULLABLE INT AS NOT 
NULLABLE INT)
+        // but that cast expression always results in 0 (INT) thus breaking a 
NOT NULL constraint.
+        if (datasetStack.peek() instanceof SqlInsert) {
             SqlValidatorScope scope = validator.getOverScope(values);
             assert scope != null;
             Blackboard bb = createBlackboard(scope, null, false);
@@ -131,7 +163,6 @@ public class IgniteSqlToRelConvertor extends 
SqlToRelConverter implements Initia
             convertValuesImplEx(bb, values, targetRowType);
             return bb.root();
         } else {
-            // a bit lightweight than default processing one.
             return super.convertValues(values, targetRowType);
         }
     }
@@ -345,4 +376,60 @@ public class IgniteSqlToRelConvertor extends 
SqlToRelConverter implements Initia
     public RelOptTable getTargetTable(SqlNode call) {
         return super.getTargetTable(call);
     }
+
+    // TODO https://issues.apache.org/jira/browse/IGNITE-27398 Remove this 
workaround
+    // This method is a copy of SqlToRelConverter convertUpdate.
+    private RelNode convertUpdateFixed(SqlUpdate call) {
+        final SqlSelect sourceSelect =
+                requireNonNull(call.getSourceSelect(),
+                        () -> "sourceSelect for " + call);
+        final SqlValidatorScope scope = validator.getWhereScope(sourceSelect);
+        Blackboard bb = createBlackboard(scope, null, false);
+
+        RelOptTable targetTable = getTargetTable(call);
+
+        // convert update column list from SqlIdentifier to String
+        final List<String> targetColumnNameList = new ArrayList<>();
+        final RelDataType targetRowType = targetTable.getRowType();
+        for (SqlNode node : call.getTargetColumnList()) {
+            SqlIdentifier id = (SqlIdentifier) node;
+            RelDataTypeField field =
+                    SqlValidatorUtil.getTargetField(
+                            targetRowType, typeFactory, id, catalogReader, 
targetTable);
+            if (field == null) {
+                throw new AssertionError("column " + id + " not found");
+            }
+            targetColumnNameList.add(field.getName());
+        }
+
+        // A call to replaceSubQueries(bb, call, 
RelOptUtil.Logic.TRUE_FALSE_UNKNOWN);
+        try {
+            REPLACE_SUB_QUERIES.invoke(this, bb, call, 
RelOptUtil.Logic.TRUE_FALSE_UNKNOWN);
+        } catch (Throwable e) {
+            throw new AssertionError("Failed to replace subqueries", e);
+        }
+
+        // FIX: The condition below is incorrect, it ignores virtual columns 
that present is the target table.
+        // sourceSelect` should contain target columns values plus source 
expressions
+        //
+        // if (sourceSelect.getSelectList().size()
+        //         != targetTable.getRowType().getFieldCount() + 
call.getSourceExpressionList().size()) {
+        //     throw new AssertionError(
+        //             "Unexpected select list size. Select list should 
contain both target table columns and "
+        //                     + "set expressions");
+        // }
+
+        RelNode sourceRel = convertSelect(sourceSelect, false);
+        bb.setRoot(sourceRel, false);
+
+        // sourceRel already contains all source expressions. Only create 
references to those fields.
+        List<RexNode> rexExpressionList =
+                Util.transform(
+                        Util.last(sourceRel.getRowType().getFieldList(), 
targetColumnNameList.size()),
+                        expressionField -> new 
RexInputRef(expressionField.getIndex(),
+                                expressionField.getType()));
+
+        return LogicalTableModify.create(targetTable, catalogReader, sourceRel,
+                LogicalTableModify.Operation.UPDATE, targetColumnNameList, 
rexExpressionList, false);
+    }
 }
diff --git 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/IgniteTypeCoercion.java
 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/IgniteTypeCoercion.java
index 45e16ace9a6..13d2ea2101c 100644
--- 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/IgniteTypeCoercion.java
+++ 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/IgniteTypeCoercion.java
@@ -212,7 +212,7 @@ public class IgniteTypeCoercion extends TypeCoercionImpl {
         }
 
         if (operatorIsQuantify(operator)) {
-            return quantifyOperationCoercion(binding);
+            return inOperationCoercionFixed(binding);
         }
 
         return super.inOperationCoercion(binding);
@@ -230,7 +230,7 @@ public class IgniteTypeCoercion extends TypeCoercionImpl {
         return operatorIsIn(operator) || operatorIsQuantify(operator);
     }
 
-    private boolean quantifyOperationCoercion(SqlCallBinding binding) {
+    private boolean inOperationCoercionFixed(SqlCallBinding binding) {
         // This method is a copy-paste of 
org.apache.calcite.sql.validate.implicit.TypeCoercionImpl.inOperationCoercion
         // with stripped validation of operation kind.
         assert operatorIsQuantify(binding.getOperator());
diff --git 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/util/RexUtils.java
 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/util/RexUtils.java
index 5041ca85076..c564c2e42e8 100644
--- 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/util/RexUtils.java
+++ 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/util/RexUtils.java
@@ -190,7 +190,8 @@ public class RexUtils {
         return true;
     }
 
-    /** Try to transform expression into DNF form.
+    /**
+     * Try to transform expression into DNF form.
      *
      * @param rexBuilder Expression builder.
      * @param node Expression to process.
@@ -212,7 +213,8 @@ public class RexUtils {
         final RexBuilder rexBuilder;
         final int maxOrNodes;
 
-        /** Constructor.
+        /**
+         * Constructor.
          *
          * @param rexBuilder Rex builder.
          * @param maxOrNodes Limit for OR nodes, if limit is reached further 
processing will be stopped.
@@ -342,7 +344,7 @@ public class RexUtils {
             return null;
         }
 
-        return bounds; 
+        return bounds;
     }
 
     /**
@@ -1440,8 +1442,10 @@ public class RexUtils {
         return wasChanged ? newSearchBounds : searchBounds;
     }
 
-    /** Check if given {@link RexNode} is a 'loss-less' cast, that is, a cast 
from which
-     * the original value of the field can be certainly recovered. */
+    /**
+     * Check if given {@link RexNode} is a 'loss-less' cast, that is, a cast 
from which the original value of the field can be certainly
+     * recovered.
+     */
     public static boolean isLosslessCast(RexNode node) {
         if (!node.isA(SqlKind.CAST)) {
             return false;
@@ -1473,6 +1477,37 @@ public class RexUtils {
             return source.getPrecision() <= target.getPrecision();
         }
 
-        return RexUtil.isLosslessCast(source, target);
+        return isLosslessCast(source, target);
+    }
+
+    // TODO: https://issues.apache.org/jira/browse/IGNITE-27390 
+    //  This is copy of RexUtil.isLosslessCast from Calcite 1.40. We should 
replace RexUtils.isLosslessCast
+    //  with calcite's implementation.
+    private static boolean isLosslessCast(RelDataType source, RelDataType 
target) {
+        final SqlTypeName sourceSqlTypeName = source.getSqlTypeName();
+        final SqlTypeName targetSqlTypeName = target.getSqlTypeName();
+        // 1) Both INT numeric types
+        if (SqlTypeFamily.INTEGER.getTypeNames().contains(sourceSqlTypeName)
+                && 
SqlTypeFamily.INTEGER.getTypeNames().contains(targetSqlTypeName)) {
+            return targetSqlTypeName.compareTo(sourceSqlTypeName) >= 0;
+        }
+        // 2) Both CHARACTER types: it depends on the precision (length)
+        if (SqlTypeFamily.CHARACTER.getTypeNames().contains(sourceSqlTypeName)
+                && 
SqlTypeFamily.CHARACTER.getTypeNames().contains(targetSqlTypeName)) {
+            return targetSqlTypeName.compareTo(sourceSqlTypeName) >= 0
+                    && source.getPrecision() <= target.getPrecision();
+        }
+        // 3) From NUMERIC family to CHARACTER family: it depends on the 
precision/scale
+        if (sourceSqlTypeName.getFamily() == SqlTypeFamily.NUMERIC
+                && targetSqlTypeName.getFamily() == SqlTypeFamily.CHARACTER) {
+            int sourceLength = source.getPrecision() + 1; // include sign
+            if (source.getScale() != -1 && source.getScale() != 0) {
+                sourceLength += source.getScale() + 1; // include decimal mark
+            }
+            final int targetPrecision = target.getPrecision();
+            return targetPrecision == RelDataType.PRECISION_NOT_SPECIFIED || 
targetPrecision >= sourceLength;
+        }
+        // Return FALSE by default
+        return false;
     }
 }
diff --git 
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/AbstractPlannerTest.java
 
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/AbstractPlannerTest.java
index 6949462627c..5bb7e3869d7 100644
--- 
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/AbstractPlannerTest.java
+++ 
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/AbstractPlannerTest.java
@@ -62,14 +62,17 @@ import org.apache.calcite.rel.core.TableScan;
 import org.apache.calcite.rel.hint.HintStrategyTable;
 import org.apache.calcite.rel.type.RelDataType;
 import org.apache.calcite.rel.type.RelDataTypeField;
+import org.apache.calcite.rex.RexBuilder;
 import org.apache.calcite.rex.RexCall;
 import org.apache.calcite.rex.RexLiteral;
 import org.apache.calcite.rex.RexNode;
 import org.apache.calcite.rex.RexShuttle;
+import org.apache.calcite.rex.RexUtil;
 import org.apache.calcite.schema.ColumnStrategy;
 import org.apache.calcite.schema.SchemaPlus;
 import org.apache.calcite.sql.SqlExplainLevel;
 import org.apache.calcite.sql.SqlFunction;
+import org.apache.calcite.sql.SqlKind;
 import org.apache.calcite.sql.SqlNode;
 import org.apache.calcite.sql.type.BasicSqlType;
 import org.apache.calcite.sql.type.SqlTypeName;
@@ -744,9 +747,7 @@ public abstract class AbstractPlannerTest extends 
IgniteAbstractTest {
             // Hints are not serializable.
             clearHints(expected);
 
-            // TODO https://issues.apache.org/jira/browse/IGNITE-19162 Remove 
this rewriter
-            //  when the issue with sub-millisecond precision is resolved.
-            RelNode replaced = new 
RewriteTimeTimestampLiterals().visit((IgniteRel) expected);
+            RelNode replaced = new 
RewriteExpressionsToComparisonFormShuttle().visit((IgniteRel) expected);
             if (replaced != expected) {
                 expected = replaced;
             }
@@ -1158,11 +1159,18 @@ public abstract class AbstractPlannerTest extends 
IgniteAbstractTest {
     }
 
     /**
-     * Truncates TIME/TIMESTAMP literals to millis, because sub-millisecond 
values are lost during serilization,
-     * since calcite's runtime does not support sub-millisecond precision for 
these types.
+     * Rewrites all expressions so they match their deserialized form.
+     *
+     * <ul>
+     * <li>Truncates TIME/TIMESTAMP literals to millis, because 
sub-millisecond values are lost during serilization,
+     * since calcite's runtime does not support sub-millisecond precision for 
these types.</li>
+     * <li>Expands all calls to {@code SEARCH} operator) see See RelJson 
toJson(RexNode node).</li>
+     * <li>Flattens ANDs and ORs.</li>
+     * </ul>
      */
-    private static class RewriteTimeTimestampLiterals extends IgniteRelShuttle 
{
-
+    private static class RewriteExpressionsToComparisonFormShuttle extends 
IgniteRelShuttle {
+        // TODO https://issues.apache.org/jira/browse/IGNITE-19162 Remove this 
rewriter
+        //  when the issue with sub-millisecond precision is resolved.
         final RexShuttle rexVisitor = new RexShuttle() {
             @Override
             public RexNode visitLiteral(RexLiteral literal) {
@@ -1191,6 +1199,20 @@ public abstract class AbstractPlannerTest extends 
IgniteAbstractTest {
                     return super.visitLiteral(literal);
                 }
             }
+
+            @Override
+            public RexNode visitCall(RexCall call) {
+                RexNode newCall = super.visitCall(call);
+                RexBuilder rexBuilder = Commons.emptyCluster().getRexBuilder();
+
+                if (newCall.isA(SqlKind.SEARCH)) {
+                    return RexUtil.expandSearch(rexBuilder, null, newCall);
+                } else if (newCall.isA(SqlKind.AND) || 
newCall.isA(SqlKind.OR)) {
+                    return RexUtil.flatten(rexBuilder, newCall);
+                } else {
+                    return newCall;
+                }
+            }
         };
 
         @Override
diff --git 
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/CastResolutionTest.java
 
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/CastResolutionTest.java
index 01cba2520c2..c05521fde05 100644
--- 
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/CastResolutionTest.java
+++ 
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/CastResolutionTest.java
@@ -62,7 +62,10 @@ public class CastResolutionTest extends AbstractPlannerTest {
 
     private static final Set<String> FRACTIONAL_NAMES = 
FRACTIONAL_TYPES.stream().map(SqlTypeName::getName).collect(Collectors.toSet());
 
-    private static final Set<String> EXACT_NUMERIC = 
EXACT_TYPES.stream().map(SqlTypeName::getName).collect(Collectors.toSet());
+    private static final Set<String> EXACT_NUMERIC = EXACT_TYPES.stream()
+            .filter(t -> !SqlTypeName.UNSIGNED_TYPES.contains(t))
+            .map(SqlTypeName::getName)
+            .collect(Collectors.toSet());
 
     private static final Set<String> CHAR_NAMES = 
CHAR_TYPES.stream().map(SqlTypeName::getName).collect(Collectors.toSet());
 
diff --git 
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/CorrelatedSubqueryPlannerTest.java
 
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/CorrelatedSubqueryPlannerTest.java
index 446d2c1f142..cab4fc6775a 100644
--- 
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/CorrelatedSubqueryPlannerTest.java
+++ 
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/CorrelatedSubqueryPlannerTest.java
@@ -196,13 +196,14 @@ public class CorrelatedSubqueryPlannerTest extends 
AbstractPlannerTest {
 
             List<LogicalCorrelate> correlates = findNodes(rel, 
byClass(LogicalCorrelate.class));
 
-            assertEquals(4, correlates.size());
+            // TODO https://issues.apache.org/jira/browse/IGNITE-27403 
investigate changes in this test.
+            assertEquals(2, correlates.size());
 
             // There are collisions by correlation id.
             assertEquals(correlates.get(0).getCorrelationId(), 
correlates.get(1).getCorrelationId());
-            assertEquals(correlates.get(0).getCorrelationId(), 
correlates.get(2).getCorrelationId());
-            assertEquals(correlates.get(0).getCorrelationId(), 
correlates.get(3).getCorrelationId());
 
+            // TODO https://issues.apache.org/jira/browse/IGNITE-27403 
investigate changes in this test.
+            // Cannot decorrelate further
             rel = planner.replaceCorrelatesCollisions(rel);
 
             correlates = findNodes(rel, byClass(LogicalCorrelate.class));
diff --git 
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/DynamicParametersTest.java
 
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/DynamicParametersTest.java
index 3881f96f932..8f0211d227b 100644
--- 
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/DynamicParametersTest.java
+++ 
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/DynamicParametersTest.java
@@ -70,8 +70,9 @@ public class DynamicParametersTest extends 
AbstractPlannerTest {
     public Stream<DynamicTest> testArithExprs() {
         return Stream.of(
                 sql("SELECT 1 + ?", 
1).parameterTypes(nullable(NativeTypes.INT32)).ok(),
-                sql("SELECT NULL + ?", 
1).parameterTypes(nullable(NativeTypes.INT32)).project("null:INTEGER"),
-                sql("SELECT ? + NULL", 
1).parameterTypes(nullable(NativeTypes.INT32)).project("null:INTEGER"),
+                // TODO https://issues.apache.org/jira/browse/IGNITE-27395 
SELECT NULL + ?int is not simplified to NULL
+                sql("SELECT NULL + ?", 
1).parameterTypes(nullable(NativeTypes.INT32)).project("+(null:NULL, ?0)"),
+                sql("SELECT ? + NULL", 
1).parameterTypes(nullable(NativeTypes.INT32)).project("+(?0, null)"),
 
                 sql("SELECT 1 + ?", 
"1").parameterTypes(nullable(NativeTypes.STRING))
                         .fails("Cannot apply '+' to arguments of type 
'<INTEGER> + <VARCHAR>'"),
@@ -120,7 +121,7 @@ public class DynamicParametersTest extends 
AbstractPlannerTest {
         return Stream.of(
                 sql("SELECT ? IN ('1', '2')", 
1).parameterTypes(nullable(NativeTypes.INT32))
                         .fails("Values passed to IN operator must have 
compatible types"),
-                sql("SELECT ? IN (1, 2)", 
1).parameterTypes(nullable(NativeTypes.INT32)).project("OR(=(?0, 1), =(?0, 
2))"),
+                sql("SELECT ? IN (1, 2)", 
1).parameterTypes(nullable(NativeTypes.INT32)).project("SEARCH(?0, Sarg[1, 
2])"),
 
                 sql("SELECT ? IN (1)", Unspecified.UNKNOWN)
                         .fails("Unable to determine type of a dynamic 
parameter"),
@@ -468,7 +469,7 @@ public class DynamicParametersTest extends 
AbstractPlannerTest {
                 checkStatement()
                         .sql("SELECT COALESCE(?, ?)", null, null)
                         .parameterTypes(nullable(null), nullable(null))
-                        .project("CASE(IS NOT NULL(?0), ?0, ?1)"),
+                        .project("CASE(IS NOT NULL(?0), CAST(?0):NULL, ?1)"),
 
                 checkStatement()
                         .sql("SELECT COALESCE(?, 1)", Unspecified.UNKNOWN)
diff --git 
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/ImplicitCastsTest.java
 
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/ImplicitCastsTest.java
index 64f06f3d969..88b7a83dba7 100644
--- 
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/ImplicitCastsTest.java
+++ 
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/ImplicitCastsTest.java
@@ -112,6 +112,7 @@ public class ImplicitCastsTest extends AbstractPlannerTest {
     private static Stream<Arguments> joinColumnTypes() {
 
         List<RelDataType> numericTypes = SqlTypeName.NUMERIC_TYPES.stream()
+                .filter(t -> !SqlTypeName.UNSIGNED_TYPES.contains(t))
                 // Real/Float got mixed up.
                 .filter(t -> t != SqlTypeName.FLOAT)
                 .map(TYPE_FACTORY::createSqlType)
diff --git 
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/IndexSearchBoundsPlannerTest.java
 
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/IndexSearchBoundsPlannerTest.java
index 06df65c41b6..363eac3d610 100644
--- 
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/IndexSearchBoundsPlannerTest.java
+++ 
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/IndexSearchBoundsPlannerTest.java
@@ -339,10 +339,18 @@ public class IndexSearchBoundsPlannerTest extends 
AbstractPlannerTest {
         );
 
         // Implicit cast of 2 to VARCHAR.
-        assertBounds("SELECT * FROM TEST WHERE C1 = 1 AND C2 IN (2::VARCHAR, 
'3')",
-                exact(1),
-                multi(exact("2"), exact("3"))
-        );
+        // TODO https://issues.apache.org/jira/browse/IGNITE-27391
+        assertPlan("SELECT * FROM TEST WHERE C1 = 1 AND C2 IN (2::VARCHAR, 
'3')", 
+                List.of(publicSchema), 
nodeOrAnyChild(isInstanceOf(IgniteIndexScan.class)
+                        .and(scan -> {
+                            boolean boundsMatch = 
matchBounds(scan.searchBounds(), exact(1));
+                            String condition = scan.condition() != null ? 
scan.condition().toString() : null;
+                            String expected = 
+                                    "AND(=($t0, 1), OR(=(CAST($t1):VARCHAR 
CHARACTER SET \"UTF-8\", _UTF-8'2'), =($t1, _UTF-8'3')))";
+                            boolean conditionMatch = Objects.equals(condition, 
expected);
+                            return boundsMatch && conditionMatch;
+                        })), List.of(),
+                "LogicalTableScanConverterRule", "UnionConverterRule");
     }
 
     /** Tests bounds with dynamic parameters. */
diff --git 
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/datatypes/NumericInTypeCoercionTest.java
 
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/datatypes/NumericInTypeCoercionTest.java
index 2442a547510..38ca01d2e4a 100644
--- 
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/datatypes/NumericInTypeCoercionTest.java
+++ 
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/planner/datatypes/NumericInTypeCoercionTest.java
@@ -20,8 +20,12 @@ package 
org.apache.ignite.internal.sql.engine.planner.datatypes;
 import static 
org.apache.ignite.internal.sql.engine.prepare.IgniteSqlValidator.DECIMAL_DYNAMIC_PARAM_PRECISION;
 import static 
org.apache.ignite.internal.sql.engine.prepare.IgniteSqlValidator.DECIMAL_DYNAMIC_PARAM_SCALE;
 
+import java.text.DecimalFormat;
 import java.util.List;
+import java.util.Map;
 import java.util.function.Predicate;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
 import java.util.stream.Stream;
 import org.apache.calcite.rex.RexNode;
 import org.apache.ignite.internal.sql.engine.framework.TestBuilders;
@@ -32,6 +36,7 @@ import org.apache.ignite.internal.sql.engine.rel.IgniteValues;
 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.util.SqlTestUtils;
+import org.apache.ignite.internal.type.DecimalNativeType;
 import org.apache.ignite.internal.type.NativeType;
 import org.apache.ignite.internal.type.NativeTypes;
 import org.apache.ignite.sql.ColumnType;
@@ -2710,16 +2715,97 @@ public class NumericInTypeCoercionTest extends 
BaseTypeCoercionTest {
                         .build()
         );
 
-        // SHORT values can intersect with a DECIMAL with a 5 digits in 
integer parts, so for SHORT (INT16) we need to generate values
-        // take it into consideration.
-        boolean closerToBound = numericPair.first().spec() == ColumnType.INT16;
-
-        String value = "(" + generateLiteral(numericPair.second(), 
closerToBound) + ")";
+        String value = "(" + generateLiteralForPair(numericPair, true) + ")";
 
         Predicate<IgniteTableScan> matcher = checkPlan(first, second);
         assertPlan("SELECT c1 FROM T1 WHERE c1 IN " + value, schema, matcher);
     }
 
+    private static String generateLiteralForPair(NumericPair numericPair, 
boolean literalIsInRange) {
+        NativeType columnType = numericPair.first();
+        NativeType literalType = numericPair.second();
+
+        Map<ColumnType, Integer> precisionPerType = Map.of(
+                ColumnType.INT8, 3,
+                ColumnType.INT16, 5,
+                ColumnType.INT32, 10,
+                ColumnType.INT64, 19,
+                ColumnType.FLOAT, 10,
+                ColumnType.DOUBLE, 19
+        );
+
+        Integer columnDigits = precisionPerType.get(columnType.spec());
+        int columnFractions = 0;
+
+        if (columnType instanceof DecimalNativeType) {
+            DecimalNativeType decimal = (DecimalNativeType) columnType;
+            columnDigits = decimal.precision();
+            columnFractions = decimal.scale();
+            columnDigits -= columnFractions;
+        } else if (isFloatingPointType(columnType)) {
+            columnFractions = 2;
+        }
+
+        Integer literalDigits = precisionPerType.get(literalType.spec());
+        int literalFractions = 0;
+        if (literalType instanceof DecimalNativeType) {
+            DecimalNativeType decimal = (DecimalNativeType) literalType;
+            literalDigits = decimal.precision();
+            literalFractions = decimal.scale();
+            literalDigits -= literalFractions;
+        } else if (isFloatingPointType(literalType)) {
+            literalFractions = 2;
+        }
+
+        int numDigits;
+        int numFractions;
+
+        if (literalIsInRange) {
+            numDigits = Math.min(columnDigits, literalDigits);
+            numFractions = Math.min(columnFractions, literalFractions);
+        } else {
+            numDigits = Math.max(columnDigits, literalDigits) + 1;
+            numFractions = Math.max(columnFractions, literalFractions);
+        }
+
+        String intPart = IntStream.rangeClosed(1, numDigits)
+                .mapToObj(String::valueOf)
+                .collect(Collectors.joining(""))
+                .substring(0, numDigits);
+
+        String strVal;
+        if (numFractions > 0) {
+            String fracPart = IntStream.rangeClosed(1, numFractions)
+                    .mapToObj(String::valueOf)
+                    .collect(Collectors.joining(""))
+                    .substring(0, numFractions);
+
+            strVal = intPart + "." + fracPart;
+        } else {
+            strVal = intPart;
+        }
+
+        Object litVal;
+        if (isFloatingPointType(literalType)) {
+            // Format floats and double
+            String format = "0." + "#".repeat(numDigits + numFractions) + 
"E0";    
+            DecimalFormat decimalFormat = new DecimalFormat(format);
+            if (literalType.spec() == ColumnType.FLOAT) {
+                litVal = decimalFormat.format(Float.parseFloat(strVal));
+            } else {
+                litVal = decimalFormat.format(Double.parseDouble(strVal));
+            }
+        } else {
+            litVal = strVal;
+        }
+        return SqlTestUtils.makeLiteral(litVal, literalType);
+    }
+
+    private static boolean isFloatingPointType(NativeType type1) {
+        ColumnType secondType = type1.spec();
+        return secondType == ColumnType.FLOAT || secondType == 
ColumnType.DOUBLE;
+    }
+
     @ParameterizedTest
     @MethodSource("inOperandsLiteralsOutOfRange")
     public void literalsOutOfRange(
@@ -2736,17 +2822,15 @@ public class NumericInTypeCoercionTest extends 
BaseTypeCoercionTest {
 
         // SHORT values can intersect with a DECIMAL with a 5 digits in 
integer parts, so for SHORT (INT16) we need to generate values
         // take it into consideration.
-        boolean closerToBound = numericPair.first().spec() == ColumnType.INT16;
-
-        String value = "(" +  generateLiteral(numericPair.second(), 
closerToBound) + ")";
+        String value = "(" + generateLiteralForPair(numericPair, false) + ")";
 
         Predicate<IgniteValues> matcher = isInstanceOf(IgniteValues.class);
         assertPlan("SELECT c1 FROM T1 WHERE c1 IN " + value, schema, matcher);
     }
 
     /**
-     * This test ensures that combination of {@link 
#inOperandsLiteralsWithinRange()} and {@link #inOperandsLiteralsOutOfRange()}
-     * doesn't miss any type pair from {@link NumericPair}.
+     * This test ensures that combination of {@link 
#inOperandsLiteralsWithinRange()} and {@link #inOperandsLiteralsOutOfRange()} 
doesn't
+     * miss any type pair from {@link NumericPair}.
      */
     @Test
     void inOperandsLiteralsIncludeAllPairs() {
diff --git 
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/prepare/ddl/DdlSqlToCommandConverterTest.java
 
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/prepare/ddl/DdlSqlToCommandConverterTest.java
index e4ff3591205..5afb6934c60 100644
--- 
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/prepare/ddl/DdlSqlToCommandConverterTest.java
+++ 
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/prepare/ddl/DdlSqlToCommandConverterTest.java
@@ -64,6 +64,7 @@ import java.util.concurrent.atomic.AtomicReference;
 import java.util.function.Function;
 import java.util.function.Supplier;
 import java.util.regex.Pattern;
+import java.util.stream.Collectors;
 import java.util.stream.Stream;
 import org.apache.calcite.rel.type.RelDataType;
 import org.apache.calcite.sql.SqlDdl;
@@ -116,6 +117,10 @@ import org.mockito.Mockito;
 public class DdlSqlToCommandConverterTest extends 
AbstractDdlSqlToCommandConverterTest {
     private static final Integer TEST_ZONE_ID = 100;
 
+    private static final List<SqlTypeName> SIGNED_NUMERIC_TYPES = 
NUMERIC_TYPES.stream()
+            .filter(t -> !SqlTypeName.UNSIGNED_TYPES.contains(t))
+            .collect(Collectors.toList());
+
     @BeforeEach
     void setUp() {
         Supplier<TableStatsStalenessConfiguration> statStalenessProperties = 
() -> new TableStatsStalenessConfiguration(
@@ -379,7 +384,7 @@ public class DdlSqlToCommandConverterTest extends 
AbstractDdlSqlToCommandConvert
         List<DynamicTest> testItems = new ArrayList<>();
         PlanningContext ctx = createContext();
 
-        for (SqlTypeName numType : NUMERIC_TYPES) {
+        for (SqlTypeName numType : SIGNED_NUMERIC_TYPES) {
             for (SqlTypeName intervalType : INTERVAL_TYPES) {
                 RelDataType initialNumType = 
Commons.typeFactory().createSqlType(numType);
                 Object value = 
SqlTestUtils.generateValueByType(initialNumType);
@@ -399,7 +404,7 @@ public class DdlSqlToCommandConverterTest extends 
AbstractDdlSqlToCommandConvert
         PlanningContext ctx = createContext();
 
         for (SqlTypeName intervalType : INTERVAL_TYPES) {
-            for (SqlTypeName numType : NUMERIC_TYPES) {
+            for (SqlTypeName numType : SIGNED_NUMERIC_TYPES) {
                 String value = makeUsableIntervalValue(intervalType.getName());
 
                 fillTestCase(numType.getName(), value, testItems, false, ctx);
@@ -504,7 +509,7 @@ public class DdlSqlToCommandConverterTest extends 
AbstractDdlSqlToCommandConvert
 
         String[] numbers = {"100.4", "100.6", "100", "'100'", "'100.1'"};
 
-        List<SqlTypeName> typesWithoutDecimal = new ArrayList<>(NUMERIC_TYPES);
+        List<SqlTypeName> typesWithoutDecimal = new 
ArrayList<>(SIGNED_NUMERIC_TYPES);
         typesWithoutDecimal.remove(DECIMAL);
 
         for (String value : numbers) {
@@ -559,7 +564,7 @@ public class DdlSqlToCommandConverterTest extends 
AbstractDdlSqlToCommandConvert
         String[] values = {"'01:01:02'", "'2020-01-02 01:01:01'", 
"'2020-01-02'", "true", "'true'", "x'01'", "INTERVAL '1' DAY"};
 
         for (String value : values) {
-            for (SqlTypeName numericType : NUMERIC_TYPES) {
+            for (SqlTypeName numericType : SIGNED_NUMERIC_TYPES) {
                 fillTestCase(numericType.getName(), value, testItems, false, 
ctx);
             }
         }
diff --git 
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/sql/SqlReservedWordsTest.java
 
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/sql/SqlReservedWordsTest.java
index a722691dab0..213a95bbd6d 100644
--- 
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/sql/SqlReservedWordsTest.java
+++ 
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/sql/SqlReservedWordsTest.java
@@ -219,6 +219,7 @@ public class SqlReservedWordsTest extends 
AbstractParserTest {
             "USER",
             "USING",
             "UUID",
+            "UNSIGNED",
             "VALUE",
             "VALUES",
             "VARIANT",
diff --git 
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/util/QueryCheckerTest.java
 
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/util/QueryCheckerTest.java
index 682bb305faf..3d59c2f2668 100644
--- 
a/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/util/QueryCheckerTest.java
+++ 
b/modules/sql-engine/src/test/java/org/apache/ignite/internal/sql/engine/util/QueryCheckerTest.java
@@ -86,7 +86,7 @@ public class QueryCheckerTest extends BaseIgniteAbstractTest {
                 .mapToObj(i -> List.of("N1"))
                 .collect(Collectors.toList()));
         CLUSTER.setDataProvider("T1", 
TestBuilders.tableScan(DataProvider.fromCollection(
-                List.of(new Object[]{1, 1, 1, 1, 1}, new Object[]{2, 2, 1, 1, 
1})
+                List.of(new Object[]{1, 1, 1, 1, 1}, new Object[]{2, 2, 2, 2, 
2})
         )));
     }
 
diff --git a/modules/sql-engine/src/test/resources/tpcds/plan/q15.plan 
b/modules/sql-engine/src/test/resources/tpcds/plan/q15.plan
index b3ef27d27b1..62d381538cf 100644
--- a/modules/sql-engine/src/test/resources/tpcds/plan/q15.plan
+++ b/modules/sql-engine/src/test/resources/tpcds/plan/q15.plan
@@ -12,7 +12,7 @@ Sort
         projection: [CA_ZIP, CS_SALES_PRICE]
         est: (rows=111896)
       HashJoin
-          predicate: AND(=(CS_BILL_CUSTOMER_SK, C_CUSTOMER_SK), 
OR(=(SUBSTR(CA_ZIP, 1, 5), _UTF-8'85669'), =(SUBSTR(CA_ZIP, 1, 5), 
_UTF-8'86197'), =(SUBSTR(CA_ZIP, 1, 5), _UTF-8'88274'), =(SUBSTR(CA_ZIP, 1, 5), 
_UTF-8'83405'), =(SUBSTR(CA_ZIP, 1, 5), _UTF-8'86475'), =(SUBSTR(CA_ZIP, 1, 5), 
_UTF-8'85392'), =(SUBSTR(CA_ZIP, 1, 5), _UTF-8'85460'), =(SUBSTR(CA_ZIP, 1, 5), 
_UTF-8'80348'), =(SUBSTR(CA_ZIP, 1, 5), _UTF-8'81792'), SEARCH(CA_STATE, 
Sarg[_UTF-8'CA':VARCHAR(2) CHARACTER SET "UTF-8" [...]
+          predicate: AND(=(CS_BILL_CUSTOMER_SK, C_CUSTOMER_SK), 
OR(SEARCH(SUBSTR(CA_ZIP, 1, 5), Sarg[_UTF-8'80348':VARCHAR(10) CHARACTER SET 
"UTF-8", _UTF-8'81792':VARCHAR(10) CHARACTER SET "UTF-8", 
_UTF-8'83405':VARCHAR(10) CHARACTER SET "UTF-8", _UTF-8'85392':VARCHAR(10) 
CHARACTER SET "UTF-8", _UTF-8'85460':VARCHAR(10) CHARACTER SET "UTF-8", 
_UTF-8'85669':VARCHAR(10) CHARACTER SET "UTF-8", _UTF-8'86197':VARCHAR(10) 
CHARACTER SET "UTF-8", _UTF-8'86475':VARCHAR(10) CHARACTER SET "UTF-8", [...]
           type: inner
           est: (rows=111896)
         HashJoin
diff --git a/modules/sql-engine/src/test/resources/tpcds/plan/q45.plan 
b/modules/sql-engine/src/test/resources/tpcds/plan/q45.plan
index ee142c0d998..d729a0b3b2f 100644
--- a/modules/sql-engine/src/test/resources/tpcds/plan/q45.plan
+++ b/modules/sql-engine/src/test/resources/tpcds/plan/q45.plan
@@ -12,7 +12,7 @@ Limit
         projection: [CA_ZIP, CA_COUNTY, WS_SALES_PRICE]
         est: (rows=10786141)
       Filter
-          predicate: OR(=(SUBSTR(CA_ZIP, 1, 5), _UTF-8'85669'), 
=(SUBSTR(CA_ZIP, 1, 5), _UTF-8'86197'), =(SUBSTR(CA_ZIP, 1, 5), _UTF-8'88274'), 
=(SUBSTR(CA_ZIP, 1, 5), _UTF-8'83405'), =(SUBSTR(CA_ZIP, 1, 5), _UTF-8'86475'), 
=(SUBSTR(CA_ZIP, 1, 5), _UTF-8'85392'), =(SUBSTR(CA_ZIP, 1, 5), _UTF-8'85460'), 
=(SUBSTR(CA_ZIP, 1, 5), _UTF-8'80348'), =(SUBSTR(CA_ZIP, 1, 5), _UTF-8'81792'), 
IS NOT NULL(i))
+          predicate: OR(SEARCH(SUBSTR(CA_ZIP, 1, 5), 
Sarg[_UTF-8'80348':VARCHAR(10) CHARACTER SET "UTF-8", _UTF-8'81792':VARCHAR(10) 
CHARACTER SET "UTF-8", _UTF-8'83405':VARCHAR(10) CHARACTER SET "UTF-8", 
_UTF-8'85392':VARCHAR(10) CHARACTER SET "UTF-8", _UTF-8'85460':VARCHAR(10) 
CHARACTER SET "UTF-8", _UTF-8'85669':VARCHAR(10) CHARACTER SET "UTF-8", 
_UTF-8'86197':VARCHAR(10) CHARACTER SET "UTF-8", _UTF-8'86475':VARCHAR(10) 
CHARACTER SET "UTF-8", _UTF-8'88274':VARCHAR(10) CHARACTER SET "U [...]
           est: (rows=10786141)
         HashJoin
             predicate: =(I_ITEM_ID, I_ITEM_ID$0)
diff --git a/modules/sql-engine/src/test/resources/tpcds/plan/q50.plan 
b/modules/sql-engine/src/test/resources/tpcds/plan/q50.plan
index 9d93f05588f..02aab08763f 100644
--- a/modules/sql-engine/src/test/resources/tpcds/plan/q50.plan
+++ b/modules/sql-engine/src/test/resources/tpcds/plan/q50.plan
@@ -9,7 +9,7 @@ Sort
       est: (rows=28459)
     Project
         fieldNames: [S_STORE_NAME, S_COMPANY_ID, S_STREET_NUMBER, 
S_STREET_NAME, S_STREET_TYPE, S_SUITE_NUMBER, S_CITY, S_COUNTY, S_STATE, S_ZIP, 
$f10, $f11, $f12, $f13, $f14]
-        projection: [S_STORE_NAME, S_COMPANY_ID, S_STREET_NUMBER, 
S_STREET_NAME, S_STREET_TYPE, S_SUITE_NUMBER, S_CITY, S_COUNTY, S_STATE, S_ZIP, 
CASE(<=(-(SR_RETURNED_DATE_SK, SS_SOLD_DATE_SK), 30), 1, 0), 
CASE(AND(>(-(SR_RETURNED_DATE_SK, SS_SOLD_DATE_SK), 30), 
<=(-(SR_RETURNED_DATE_SK, SS_SOLD_DATE_SK), 60)), 1, 0), 
CASE(AND(>(-(SR_RETURNED_DATE_SK, SS_SOLD_DATE_SK), 60), 
<=(-(SR_RETURNED_DATE_SK, SS_SOLD_DATE_SK), 90)), 1, 0), 
CASE(AND(>(-(SR_RETURNED_DATE_SK, SS_SOLD_DATE_SK), 90),  [...]
+        projection: [S_STORE_NAME, S_COMPANY_ID, S_STREET_NUMBER, 
S_STREET_NAME, S_STREET_TYPE, S_SUITE_NUMBER, S_CITY, S_COUNTY, S_STATE, S_ZIP, 
CASE(<=(-(SR_RETURNED_DATE_SK, SS_SOLD_DATE_SK), 30), 1, 0), 
CASE(SEARCH(-(SR_RETURNED_DATE_SK, SS_SOLD_DATE_SK), Sarg[(30..60]]), 1, 0), 
CASE(SEARCH(-(SR_RETURNED_DATE_SK, SS_SOLD_DATE_SK), Sarg[(60..90]]), 1, 0), 
CASE(SEARCH(-(SR_RETURNED_DATE_SK, SS_SOLD_DATE_SK), Sarg[(90..120]]), 1, 0), 
CASE(>(-(SR_RETURNED_DATE_SK, SS_SOLD_DATE_SK), 120), 1, 0)]
         est: (rows=31882)
       HashJoin
           predicate: =(SS_STORE_SK, S_STORE_SK)
diff --git a/modules/sql-engine/src/test/resources/tpcds/plan/q62.plan 
b/modules/sql-engine/src/test/resources/tpcds/plan/q62.plan
index ab5c0227e2b..24d69c6a993 100644
--- a/modules/sql-engine/src/test/resources/tpcds/plan/q62.plan
+++ b/modules/sql-engine/src/test/resources/tpcds/plan/q62.plan
@@ -9,7 +9,7 @@ Sort
       est: (rows=87765)
     Project
         fieldNames: [EXPR$0, SM_TYPE, WEB_NAME, $f3, $f4, $f5, $f6, $f7]
-        projection: [SUBSTR(W_WAREHOUSE_NAME, 1, 20), SM_TYPE, WEB_NAME, 
CASE(<=(-(WS_SHIP_DATE_SK, WS_SOLD_DATE_SK), 30), 1, 0), 
CASE(AND(>(-(WS_SHIP_DATE_SK, WS_SOLD_DATE_SK), 30), <=(-(WS_SHIP_DATE_SK, 
WS_SOLD_DATE_SK), 60)), 1, 0), CASE(AND(>(-(WS_SHIP_DATE_SK, WS_SOLD_DATE_SK), 
60), <=(-(WS_SHIP_DATE_SK, WS_SOLD_DATE_SK), 90)), 1, 0), 
CASE(AND(>(-(WS_SHIP_DATE_SK, WS_SOLD_DATE_SK), 90), <=(-(WS_SHIP_DATE_SK, 
WS_SOLD_DATE_SK), 120)), 1, 0), CASE(>(-(WS_SHIP_DATE_SK, WS_SOLD_DATE_SK), 
[...]
+        projection: [SUBSTR(W_WAREHOUSE_NAME, 1, 20), SM_TYPE, WEB_NAME, 
CASE(<=(-(WS_SHIP_DATE_SK, WS_SOLD_DATE_SK), 30), 1, 0), 
CASE(SEARCH(-(WS_SHIP_DATE_SK, WS_SOLD_DATE_SK), Sarg[(30..60]]), 1, 0), 
CASE(SEARCH(-(WS_SHIP_DATE_SK, WS_SOLD_DATE_SK), Sarg[(60..90]]), 1, 0), 
CASE(SEARCH(-(WS_SHIP_DATE_SK, WS_SOLD_DATE_SK), Sarg[(90..120]]), 1, 0), 
CASE(>(-(WS_SHIP_DATE_SK, WS_SOLD_DATE_SK), 120), 1, 0)]
         est: (rows=179846)
       HashJoin
           predicate: =(WS_WAREHOUSE_SK, W_WAREHOUSE_SK)
diff --git a/modules/sql-engine/src/test/resources/tpcds/plan/q64.plan 
b/modules/sql-engine/src/test/resources/tpcds/plan/q64.plan
index c663026fbf3..7a99a7e3fc8 100644
--- a/modules/sql-engine/src/test/resources/tpcds/plan/q64.plan
+++ b/modules/sql-engine/src/test/resources/tpcds/plan/q64.plan
@@ -180,7 +180,7 @@ Sort
                                               est: (rows=2250)
                                             TableScan
                                                 table: PUBLIC.ITEM
-                                                predicate: AND(SEARCH(I_COLOR, 
Sarg[_UTF-8'azure':VARCHAR(20) CHARACTER SET "UTF-8", _UTF-8'blush':VARCHAR(20) 
CHARACTER SET "UTF-8", _UTF-8'gainsboro':VARCHAR(20) CHARACTER SET "UTF-8", 
_UTF-8'hot':VARCHAR(20) CHARACTER SET "UTF-8", _UTF-8'lemon':VARCHAR(20) 
CHARACTER SET "UTF-8", _UTF-8'misty':VARCHAR(20) CHARACTER SET 
"UTF-8"]:VARCHAR(20) CHARACTER SET "UTF-8"), >=(I_CURRENT_PRICE, 80.00), 
SEARCH(CAST(I_CURRENT_PRICE):DECIMAL(12, 2), Sar [...]
+                                                predicate: AND(SEARCH(I_COLOR, 
Sarg[_UTF-8'azure':VARCHAR(20) CHARACTER SET "UTF-8", _UTF-8'blush':VARCHAR(20) 
CHARACTER SET "UTF-8", _UTF-8'gainsboro':VARCHAR(20) CHARACTER SET "UTF-8", 
_UTF-8'hot':VARCHAR(20) CHARACTER SET "UTF-8", _UTF-8'lemon':VARCHAR(20) 
CHARACTER SET "UTF-8", _UTF-8'misty':VARCHAR(20) CHARACTER SET 
"UTF-8"]:VARCHAR(20) CHARACTER SET "UTF-8"), >=(I_CURRENT_PRICE, 80.00), 
SEARCH(CAST(I_CURRENT_PRICE):DECIMAL(12, 2), Sar [...]
                                                 fieldNames: [I_ITEM_SK, 
I_CURRENT_PRICE, I_COLOR, I_PRODUCT_NAME]
                                                 est: (rows=2250)
                                         Filter
@@ -413,7 +413,7 @@ Sort
                                               est: (rows=2250)
                                             TableScan
                                                 table: PUBLIC.ITEM
-                                                predicate: AND(SEARCH(I_COLOR, 
Sarg[_UTF-8'azure':VARCHAR(20) CHARACTER SET "UTF-8", _UTF-8'blush':VARCHAR(20) 
CHARACTER SET "UTF-8", _UTF-8'gainsboro':VARCHAR(20) CHARACTER SET "UTF-8", 
_UTF-8'hot':VARCHAR(20) CHARACTER SET "UTF-8", _UTF-8'lemon':VARCHAR(20) 
CHARACTER SET "UTF-8", _UTF-8'misty':VARCHAR(20) CHARACTER SET 
"UTF-8"]:VARCHAR(20) CHARACTER SET "UTF-8"), >=(I_CURRENT_PRICE, 80.00), 
SEARCH(CAST(I_CURRENT_PRICE):DECIMAL(12, 2), Sar [...]
+                                                predicate: AND(SEARCH(I_COLOR, 
Sarg[_UTF-8'azure':VARCHAR(20) CHARACTER SET "UTF-8", _UTF-8'blush':VARCHAR(20) 
CHARACTER SET "UTF-8", _UTF-8'gainsboro':VARCHAR(20) CHARACTER SET "UTF-8", 
_UTF-8'hot':VARCHAR(20) CHARACTER SET "UTF-8", _UTF-8'lemon':VARCHAR(20) 
CHARACTER SET "UTF-8", _UTF-8'misty':VARCHAR(20) CHARACTER SET 
"UTF-8"]:VARCHAR(20) CHARACTER SET "UTF-8"), >=(I_CURRENT_PRICE, 80.00), 
SEARCH(CAST(I_CURRENT_PRICE):DECIMAL(12, 2), Sar [...]
                                                 fieldNames: [I_ITEM_SK, 
I_CURRENT_PRICE, I_COLOR, I_PRODUCT_NAME]
                                                 est: (rows=2250)
                                         Filter
diff --git a/modules/sql-engine/src/test/resources/tpcds/plan/q78.plan 
b/modules/sql-engine/src/test/resources/tpcds/plan/q78.plan
index 48856fdbfbd..07699e582b6 100644
--- a/modules/sql-engine/src/test/resources/tpcds/plan/q78.plan
+++ b/modules/sql-engine/src/test/resources/tpcds/plan/q78.plan
@@ -7,7 +7,7 @@ Sort
       projection: [SS_CUSTOMER_SK, ROUND(/(SS_QTY, +(CASE(IS NOT NULL(WS_QTY), 
CAST(WS_QTY):BIGINT NOT NULL, 0:BIGINT), CASE(IS NOT NULL(CS_QTY), 
CAST(CS_QTY):BIGINT NOT NULL, 0:BIGINT))), 2), SS_QTY, SS_WC, SS_SP, +(CASE(IS 
NOT NULL(WS_QTY), CAST(WS_QTY):BIGINT NOT NULL, 0:BIGINT), CASE(IS NOT 
NULL(CS_QTY), CAST(CS_QTY):BIGINT NOT NULL, 0:BIGINT)), +(CASE(IS NOT 
NULL(WS_WC), CAST(WS_WC):DECIMAL(14, 2) NOT NULL, 0.00:DECIMAL(14, 2)), CASE(IS 
NOT NULL(CS_WC), CAST(CS_WC):DECIMAL(14, 2) NO [...]
       est: (rows=5169421725)
     Filter
-        predicate: OR(CASE(IS NOT NULL(WS_QTY), >(CAST(WS_QTY):BIGINT NOT 
NULL, 0), false), CASE(IS NOT NULL(CS_QTY), >(CAST(CS_QTY):BIGINT NOT NULL, 0), 
false))
+        predicate: OR(>(CAST(WS_QTY):BIGINT NOT NULL, 0), 
>(CAST(CS_QTY):BIGINT NOT NULL, 0))
         est: (rows=5169421725)
       MergeJoin
           predicate: AND(=(CS_SOLD_YEAR, SS_SOLD_YEAR), =(CS_ITEM_SK, 
SS_ITEM_SK), =(CS_CUSTOMER_SK, SS_CUSTOMER_SK))
diff --git a/modules/sql-engine/src/test/resources/tpcds/plan/q8.plan 
b/modules/sql-engine/src/test/resources/tpcds/plan/q8.plan
index cf3561a60b9..405ff63bd96 100644
--- a/modules/sql-engine/src/test/resources/tpcds/plan/q8.plan
+++ b/modules/sql-engine/src/test/resources/tpcds/plan/q8.plan
@@ -67,16 +67,16 @@ Limit
                   est: (rows=832)
                 TableScan
                     table: PUBLIC.CUSTOMER_ADDRESS
-                    predicate: OR(=(SUBSTR(CA_ZIP, 1, 5), _UTF-8'47602'), 
=(SUBSTR(CA_ZIP, 1, 5), _UTF-8'16704'), =(SUBSTR(CA_ZIP, 1, 5), _UTF-8'35863'), 
=(SUBSTR(CA_ZIP, 1, 5), _UTF-8'28577'), =(SUBSTR(CA_ZIP, 1, 5), _UTF-8'83910'), 
=(SUBSTR(CA_ZIP, 1, 5), _UTF-8'36201'), =(SUBSTR(CA_ZIP, 1, 5), _UTF-8'58412'), 
=(SUBSTR(CA_ZIP, 1, 5), _UTF-8'48162'), =(SUBSTR(CA_ZIP, 1, 5), _UTF-8'28055'), 
=(SUBSTR(CA_ZIP, 1, 5), _UTF-8'41419'), =(SUBSTR(CA_ZIP, 1, 5), _UTF-8'80332'), 
=(SUBSTR(CA_ZIP, 1 [...]
+                    predicate: SEARCH(SUBSTR(CA_ZIP, 1, 5), 
Sarg[_UTF-8'10298':VARCHAR(10) CHARACTER SET "UTF-8", _UTF-8'10374':VARCHAR(10) 
CHARACTER SET "UTF-8", _UTF-8'10425':VARCHAR(10) CHARACTER SET "UTF-8", 
_UTF-8'11340':VARCHAR(10) CHARACTER SET "UTF-8", _UTF-8'11489':VARCHAR(10) 
CHARACTER SET "UTF-8", _UTF-8'11618':VARCHAR(10) CHARACTER SET "UTF-8", 
_UTF-8'11652':VARCHAR(10) CHARACTER SET "UTF-8", _UTF-8'11686':VARCHAR(10) 
CHARACTER SET "UTF-8", _UTF-8'11855':VARCHAR(10) CHARACTER [...]
                     fieldNames: [CA_ZIP]
                     projection: [SUBSTR(CA_ZIP, 1, 5)]
                     est: (rows=50000)
                 Exchange
-                    distribution: hash by [CA_ZIP]
+                    distribution: random
                     est: (rows=1665)
                   Project
                       fieldNames: [CA_ZIP]
-                      projection: [CA_ZIP]
+                      projection: [SUBSTR(CA_ZIP, 1, 5)]
                       est: (rows=1665)
                     Filter
                         predicate: >(CNT, 10)
@@ -100,7 +100,7 @@ Limit
                                 est: (rows=3330)
                               Project
                                   fieldNames: [CA_ZIP]
-                                  projection: [SUBSTR(CA_ZIP, 1, 5)]
+                                  projection: [CA_ZIP]
                                   est: (rows=33300)
                                 HashJoin
                                     predicate: =(CA_ADDRESS_SK, 
C_CURRENT_ADDR_SK)
diff --git a/modules/sql-engine/src/test/resources/tpcds/plan/q99.plan 
b/modules/sql-engine/src/test/resources/tpcds/plan/q99.plan
index a2e0190149c..2688302c3f1 100644
--- a/modules/sql-engine/src/test/resources/tpcds/plan/q99.plan
+++ b/modules/sql-engine/src/test/resources/tpcds/plan/q99.plan
@@ -9,7 +9,7 @@ Sort
       est: (rows=175869)
     Project
         fieldNames: [EXPR$0, SM_TYPE, CC_NAME, $f3, $f4, $f5, $f6, $f7]
-        projection: [SUBSTR(W_WAREHOUSE_NAME, 1, 20), SM_TYPE, CC_NAME, 
CASE(<=(-(CS_SHIP_DATE_SK, CS_SOLD_DATE_SK), 30), 1, 0), 
CASE(AND(>(-(CS_SHIP_DATE_SK, CS_SOLD_DATE_SK), 30), <=(-(CS_SHIP_DATE_SK, 
CS_SOLD_DATE_SK), 60)), 1, 0), CASE(AND(>(-(CS_SHIP_DATE_SK, CS_SOLD_DATE_SK), 
60), <=(-(CS_SHIP_DATE_SK, CS_SOLD_DATE_SK), 90)), 1, 0), 
CASE(AND(>(-(CS_SHIP_DATE_SK, CS_SOLD_DATE_SK), 90), <=(-(CS_SHIP_DATE_SK, 
CS_SOLD_DATE_SK), 120)), 1, 0), CASE(>(-(CS_SHIP_DATE_SK, CS_SOLD_DATE_SK),  
[...]
+        projection: [SUBSTR(W_WAREHOUSE_NAME, 1, 20), SM_TYPE, CC_NAME, 
CASE(<=(-(CS_SHIP_DATE_SK, CS_SOLD_DATE_SK), 30), 1, 0), 
CASE(SEARCH(-(CS_SHIP_DATE_SK, CS_SOLD_DATE_SK), Sarg[(30..60]]), 1, 0), 
CASE(SEARCH(-(CS_SHIP_DATE_SK, CS_SOLD_DATE_SK), Sarg[(60..90]]), 1, 0), 
CASE(SEARCH(-(CS_SHIP_DATE_SK, CS_SOLD_DATE_SK), Sarg[(90..120]]), 1, 0), 
CASE(>(-(CS_SHIP_DATE_SK, CS_SOLD_DATE_SK), 120), 1, 0)]
         est: (rows=360387)
       HashJoin
           predicate: =(CS_WAREHOUSE_SK, W_WAREHOUSE_SK)
diff --git a/modules/sql-engine/src/test/resources/tpch/plan/q22.plan 
b/modules/sql-engine/src/test/resources/tpch/plan/q22.plan
index 68dece05424..a5e44808e5a 100644
--- a/modules/sql-engine/src/test/resources/tpch/plan/q22.plan
+++ b/modules/sql-engine/src/test/resources/tpch/plan/q22.plan
@@ -31,7 +31,7 @@ Sort
                   est: (rows=150000)
                 TableScan
                     table: PUBLIC.CUSTOMER
-                    predicate: OR(=(SUBSTR(C_PHONE, 1, 2), _UTF-8'13'), 
=(SUBSTR(C_PHONE, 1, 2), _UTF-8'31'), =(SUBSTR(C_PHONE, 1, 2), _UTF-8'23'), 
=(SUBSTR(C_PHONE, 1, 2), _UTF-8'29'), =(SUBSTR(C_PHONE, 1, 2), _UTF-8'30'), 
=(SUBSTR(C_PHONE, 1, 2), _UTF-8'18'), =(SUBSTR(C_PHONE, 1, 2), _UTF-8'17'))
+                    predicate: SEARCH(SUBSTR(C_PHONE, 1, 2), 
Sarg[_UTF-8'13':VARCHAR(15) CHARACTER SET "UTF-8", _UTF-8'17':VARCHAR(15) 
CHARACTER SET "UTF-8", _UTF-8'18':VARCHAR(15) CHARACTER SET "UTF-8", 
_UTF-8'23':VARCHAR(15) CHARACTER SET "UTF-8", _UTF-8'29':VARCHAR(15) CHARACTER 
SET "UTF-8", _UTF-8'30':VARCHAR(15) CHARACTER SET "UTF-8", 
_UTF-8'31':VARCHAR(15) CHARACTER SET "UTF-8"]:VARCHAR(15) CHARACTER SET "UTF-8")
                     fieldNames: [C_CUSTKEY, C_PHONE, C_ACCTBAL]
                     est: (rows=150000)
               Project
@@ -59,7 +59,7 @@ Sort
                           est: (rows=1)
                         TableScan
                             table: PUBLIC.CUSTOMER
-                            predicate: AND(>(C_ACCTBAL, 0.00), 
OR(=(SUBSTR(C_PHONE, 1, 2), _UTF-8'13'), =(SUBSTR(C_PHONE, 1, 2), _UTF-8'31'), 
=(SUBSTR(C_PHONE, 1, 2), _UTF-8'23'), =(SUBSTR(C_PHONE, 1, 2), _UTF-8'29'), 
=(SUBSTR(C_PHONE, 1, 2), _UTF-8'30'), =(SUBSTR(C_PHONE, 1, 2), _UTF-8'18'), 
=(SUBSTR(C_PHONE, 1, 2), _UTF-8'17')))
+                            predicate: AND(>(C_ACCTBAL, 0.00), 
SEARCH(SUBSTR(C_PHONE, 1, 2), Sarg[_UTF-8'13':VARCHAR(15) CHARACTER SET 
"UTF-8", _UTF-8'17':VARCHAR(15) CHARACTER SET "UTF-8", _UTF-8'18':VARCHAR(15) 
CHARACTER SET "UTF-8", _UTF-8'23':VARCHAR(15) CHARACTER SET "UTF-8", 
_UTF-8'29':VARCHAR(15) CHARACTER SET "UTF-8", _UTF-8'30':VARCHAR(15) CHARACTER 
SET "UTF-8", _UTF-8'31':VARCHAR(15) CHARACTER SET "UTF-8"]:VARCHAR(15) 
CHARACTER SET "UTF-8"))
                             fieldNames: [C_ACCTBAL]
                             est: (rows=75000)
           ReduceHashAggregate

Reply via email to