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

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

commit 817b78c07d755fb36870ec2d3278a191c635a4d1
Author: Evgeniy Stanilovskiy <[email protected]>
AuthorDate: Wed Oct 15 13:11:52 2025 +0300

    IGNITE-26694 Sql. Fix performance drop after IGNITE-26592 (#6767)
---
 .../internal/sql/engine/prepare/CacheKey.java      |  10 +-
 .../sql/engine/prepare/IgniteSqlValidator.java     |  74 ++++++--
 .../sql/engine/prepare/PlanningContext.java        |  12 +-
 .../sql/engine/prepare/PrepareServiceImpl.java     | 188 ++++++++-------------
 .../sql/engine/planner/AbstractPlannerTest.java    |  14 +-
 5 files changed, 155 insertions(+), 143 deletions(-)

diff --git 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/CacheKey.java
 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/CacheKey.java
index 34bd665f990..1693025d11d 100644
--- 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/CacheKey.java
+++ 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/CacheKey.java
@@ -18,7 +18,7 @@
 package org.apache.ignite.internal.sql.engine.prepare;
 
 import java.util.Arrays;
-import org.apache.calcite.rel.type.RelDataType;
+import org.apache.ignite.sql.ColumnType;
 
 /**
  * CacheKey.
@@ -26,13 +26,15 @@ import org.apache.calcite.rel.type.RelDataType;
  * context could be schema name, dynamic parameters, and so on...
  */
 public class CacheKey {
+    static final ColumnType[] EMPTY_CLASS_ARRAY = {};
+
     private final int catalogVersion;
 
     private final String schemaName;
 
     private final String query;
 
-    private final RelDataType[] paramTypes;
+    private final ColumnType[] paramTypes;
 
     private int hashCode = 0;
 
@@ -44,7 +46,7 @@ public class CacheKey {
      * @param query      Query string.
      * @param paramTypes Types of all dynamic parameters, no any type can be 
{@code null}.
      */
-    public CacheKey(int catalogVersion, String schemaName, String query, 
RelDataType[] paramTypes) {
+    public CacheKey(int catalogVersion, String schemaName, String query, 
ColumnType[] paramTypes) {
         this.catalogVersion = catalogVersion;
         this.schemaName = schemaName;
         this.query = query;
@@ -59,7 +61,7 @@ public class CacheKey {
         return schemaName;
     }
 
-    RelDataType[] paramTypes() {
+    ColumnType[] paramTypes() {
         return paramTypes;
     }
 
diff --git 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/IgniteSqlValidator.java
 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/IgniteSqlValidator.java
index 536045da070..6a90d5b6c68 100644
--- 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/IgniteSqlValidator.java
+++ 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/IgniteSqlValidator.java
@@ -162,13 +162,13 @@ public class IgniteSqlValidator extends SqlValidatorImpl {
      * @param parametersTypes Dynamic parameters types
      */
     public IgniteSqlValidator(SqlOperatorTable opTab, CalciteCatalogReader 
catalogReader,
-            IgniteTypeFactory typeFactory, SqlValidator.Config config, 
Int2ObjectMap<RelDataType> parametersTypes) {
+            IgniteTypeFactory typeFactory, SqlValidator.Config config, 
Int2ObjectMap<ColumnType> parametersTypes) {
         super(opTab, catalogReader, typeFactory, config);
 
         this.dynamicParameters = new 
Int2ObjectArrayMap<>(parametersTypes.size());
-        for (Int2ObjectMap.Entry<RelDataType> param : 
parametersTypes.int2ObjectEntrySet()) {
-            RelDataType relType = param.getValue();
-            dynamicParameters.put(param.getIntKey(), new 
DynamicParamState(relType));
+        for (Int2ObjectMap.Entry<ColumnType> param : 
parametersTypes.int2ObjectEntrySet()) {
+            ColumnType colType = param.getValue();
+            dynamicParameters.put(param.getIntKey(), new 
DynamicParamState(colType));
         }
     }
 
@@ -735,7 +735,7 @@ public class IgniteSqlValidator extends SqlValidatorImpl {
 
             // Validate value, if present.
             if (!isUnspecified(dynamicParam)) {
-                RelDataType paramType = getDynamicParamType(dynamicParam);
+                ColumnType paramType = getDynamicParamType(dynamicParam);
 
                 if (paramType == null) {
                     throw newValidationError(n, 
IgniteResource.INSTANCE.illegalFetchLimit(nodeName));
@@ -1467,15 +1467,12 @@ public class IgniteSqlValidator extends 
SqlValidatorImpl {
 
             return unknownType;
         } else {
-            RelDataType parameterType = getDynamicParamType(dynamicParam);
-            if (parameterType == null) {
-                parameterType = typeFactory.createSqlType(SqlTypeName.NULL);
-            }
+            ColumnType parameterType = getDynamicParamType(dynamicParam);
 
             // Dynamic parameters are always nullable.
             // Otherwise it seem to cause "Conversion to relational algebra 
failed to preserve datatypes" errors
             // in some cases.
-            RelDataType nullableType = 
typeFactory.createTypeWithNullability(parameterType, true);
+            RelDataType nullableType = 
typeFactory.createTypeWithNullability(relTypeFromDynamicParamType(parameterType),
 true);
 
             setDynamicParamType(dynamicParam, nullableType);
 
@@ -1507,13 +1504,13 @@ public class IgniteSqlValidator extends 
SqlValidatorImpl {
      * this method throws {@link IllegalArgumentException}.
      */
     @Nullable
-    private RelDataType getDynamicParamType(SqlDynamicParam dynamicParam) {
+    private ColumnType getDynamicParamType(SqlDynamicParam dynamicParam) {
         int paramIndex = dynamicParam.getIndex();
 
         if (isUnspecified(dynamicParam)) {
             throw new IllegalArgumentException(format("Value of dynamic 
parameter#{} is not specified", paramIndex));
         } else {
-            return dynamicParameters.get(paramIndex).relType;
+            return dynamicParameters.get(paramIndex).colType;
         }
     }
 
@@ -1578,7 +1575,7 @@ public class IgniteSqlValidator extends SqlValidatorImpl {
 
     private static final class DynamicParamState {
 
-        final RelDataType relType;
+        final ColumnType colType;
 
         final boolean hasType;
 
@@ -1595,13 +1592,13 @@ public class IgniteSqlValidator extends 
SqlValidatorImpl {
          */
         RelDataType resolvedType;
 
-        private DynamicParamState(@Nullable RelDataType relType) {
-            this.relType = relType;
+        private DynamicParamState(@Nullable ColumnType colType) {
+            this.colType = colType;
             this.hasType = true;
         }
 
         private DynamicParamState() {
-            this.relType = null;
+            this.colType = null;
             this.hasType = false;
         }
     }
@@ -1615,4 +1612,49 @@ public class IgniteSqlValidator extends SqlValidatorImpl 
{
         GROUP,
         OTHER
     }
+
+    private RelDataType relTypeFromDynamicParamType(@Nullable ColumnType type) 
{
+        if (type == null) {
+            return typeFactory.createSqlType(SqlTypeName.NULL);
+        }
+
+        switch (type) {
+            case NULL:
+                return typeFactory.createSqlType(SqlTypeName.NULL);
+            case BOOLEAN:
+                return typeFactory.createSqlType(SqlTypeName.BOOLEAN);
+            case INT8:
+                return typeFactory.createSqlType(SqlTypeName.TINYINT);
+            case INT16:
+                return typeFactory.createSqlType(SqlTypeName.SMALLINT);
+            case INT32:
+                return typeFactory.createSqlType(SqlTypeName.INTEGER);
+            case INT64:
+                return typeFactory.createSqlType(SqlTypeName.BIGINT);
+            case FLOAT:
+                return typeFactory.createSqlType(SqlTypeName.REAL);
+            case DOUBLE:
+                return typeFactory.createSqlType(SqlTypeName.DOUBLE);
+            case DATE:
+                return typeFactory.createSqlType(SqlTypeName.DATE);
+            case TIME:
+                return typeFactory.createSqlType(SqlTypeName.TIME, 
TEMPORAL_DYNAMIC_PARAM_PRECISION);
+            case DATETIME:
+                return typeFactory.createSqlType(SqlTypeName.TIMESTAMP, 
TEMPORAL_DYNAMIC_PARAM_PRECISION);
+            case TIMESTAMP:
+                return 
typeFactory.createSqlType(SqlTypeName.TIMESTAMP_WITH_LOCAL_TIME_ZONE, 
TEMPORAL_DYNAMIC_PARAM_PRECISION);
+            case BYTE_ARRAY:
+                return typeFactory.createSqlType(SqlTypeName.VARBINARY, 
PRECISION_NOT_SPECIFIED);
+            case STRING:
+                return typeFactory.createSqlType(SqlTypeName.VARCHAR, 
PRECISION_NOT_SPECIFIED);
+            case UUID:
+                return typeFactory.createSqlType(SqlTypeName.UUID);
+            case DECIMAL:
+                return typeFactory.createSqlType(
+                        SqlTypeName.DECIMAL, DECIMAL_DYNAMIC_PARAM_PRECISION, 
DECIMAL_DYNAMIC_PARAM_SCALE
+                );
+            default:
+                throw new AssertionError("Unknown type " + type);
+        }
+    }
 }
diff --git 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/PlanningContext.java
 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/PlanningContext.java
index d8c0a5c7917..e7e6dbbebd5 100644
--- 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/PlanningContext.java
+++ 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/PlanningContext.java
@@ -54,7 +54,6 @@ import org.apache.calcite.rel.metadata.MetadataDef;
 import org.apache.calcite.rel.metadata.MetadataHandler;
 import org.apache.calcite.rel.metadata.RelMetadataProvider;
 import org.apache.calcite.rel.metadata.UnboundMetadata;
-import org.apache.calcite.rel.type.RelDataType;
 import org.apache.calcite.rel.type.RelDataTypeFactory;
 import org.apache.calcite.rex.RexBuilder;
 import org.apache.calcite.schema.SchemaPlus;
@@ -72,6 +71,7 @@ import 
org.apache.ignite.internal.sql.engine.metadata.cost.IgniteCostFactory;
 import org.apache.ignite.internal.sql.engine.rex.IgniteRexBuilder;
 import org.apache.ignite.internal.sql.engine.schema.IgniteDataSource;
 import org.apache.ignite.internal.sql.engine.type.IgniteTypeFactory;
+import org.apache.ignite.sql.ColumnType;
 import org.jetbrains.annotations.Nullable;
 
 /**
@@ -173,7 +173,7 @@ public final class PlanningContext implements Context {
     /** Flag indicated if planning has been canceled due to timeout. */
     private volatile boolean timeouted;
 
-    private final Int2ObjectMap<RelDataType> parameters;
+    private final Int2ObjectMap<ColumnType> parameters;
 
     private @Nullable CalciteCatalogReader catalogReader;
 
@@ -188,7 +188,7 @@ public final class PlanningContext implements Context {
             FrameworkConfig config,
             String qry,
             long plannerTimeout,
-            Int2ObjectMap<RelDataType> parameters,
+            Int2ObjectMap<ColumnType> parameters,
             boolean explicitTx,
             int catalogVersion,
             @Nullable String defaultSchemaName
@@ -218,7 +218,7 @@ public final class PlanningContext implements Context {
     }
 
     /** Get query parameters. */
-    public Int2ObjectMap<RelDataType> parameters() {
+    public Int2ObjectMap<ColumnType> parameters() {
         return parameters;
     }
 
@@ -411,7 +411,7 @@ public final class PlanningContext implements Context {
 
         private long plannerTimeout;
 
-        private Int2ObjectMap<RelDataType> parameters = 
Int2ObjectMaps.emptyMap();
+        private Int2ObjectMap<ColumnType> parameters = 
Int2ObjectMaps.emptyMap();
 
         private boolean explicitTx;
 
@@ -449,7 +449,7 @@ public final class PlanningContext implements Context {
         }
 
         /** Values of dynamic parameters to assist with type inference. */
-        public Builder parameters(Int2ObjectMap<RelDataType> parameters) {
+        public Builder parameters(Int2ObjectMap<ColumnType> parameters) {
             this.parameters = parameters;
             return this;
         }
diff --git 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/PrepareServiceImpl.java
 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/PrepareServiceImpl.java
index 0d5a0645acd..1ad111be8a8 100644
--- 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/PrepareServiceImpl.java
+++ 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/prepare/PrepareServiceImpl.java
@@ -17,15 +17,12 @@
 
 package org.apache.ignite.internal.sql.engine.prepare;
 
-import static org.apache.calcite.rel.type.RelDataType.PRECISION_NOT_SPECIFIED;
-import static org.apache.calcite.sql.type.SqlTypeName.INTEGER;
 import static 
org.apache.ignite.internal.metrics.sources.ThreadPoolMetricSource.THREAD_POOLS_METRICS_SOURCE_NAME;
-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 static 
org.apache.ignite.internal.sql.engine.prepare.IgniteSqlValidator.TEMPORAL_DYNAMIC_PARAM_PRECISION;
+import static 
org.apache.ignite.internal.sql.engine.prepare.CacheKey.EMPTY_CLASS_ARRAY;
 import static 
org.apache.ignite.internal.sql.engine.prepare.PlannerHelper.optimize;
 import static 
org.apache.ignite.internal.sql.engine.util.Commons.FRAMEWORK_CONFIG;
 import static 
org.apache.ignite.internal.sql.engine.util.Commons.fastQueryOptimizationEnabled;
+import static org.apache.ignite.internal.sql.engine.util.TypeUtils.columnType;
 import static 
org.apache.ignite.internal.thread.ThreadOperation.NOTHING_ALLOWED;
 import static 
org.apache.ignite.internal.util.CompletableFutures.isCompletedSuccessfully;
 import static 
org.apache.ignite.internal.util.CompletableFutures.nullCompletedFuture;
@@ -33,12 +30,7 @@ import static 
org.apache.ignite.lang.ErrorGroups.Sql.EXECUTION_CANCELLED_ERR;
 
 import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
 import it.unimi.dsi.fastutil.ints.IntSet;
-import java.math.BigDecimal;
 import java.time.Duration;
-import java.time.Instant;
-import java.time.LocalDate;
-import java.time.LocalDateTime;
-import java.time.LocalTime;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -69,7 +61,6 @@ import org.apache.calcite.sql.SqlKind;
 import org.apache.calcite.sql.SqlLiteral;
 import org.apache.calcite.sql.SqlNode;
 import org.apache.calcite.sql.SqlNodeList;
-import org.apache.calcite.sql.type.SqlTypeName;
 import org.apache.calcite.tools.Frameworks;
 import org.apache.calcite.util.Pair;
 import org.apache.ignite.internal.lang.SqlExceptionMapperUtil;
@@ -104,7 +95,6 @@ import 
org.apache.ignite.internal.sql.engine.sql.IgniteSqlExplainMode;
 import org.apache.ignite.internal.sql.engine.sql.IgniteSqlKill;
 import org.apache.ignite.internal.sql.engine.sql.ParsedResult;
 import 
org.apache.ignite.internal.sql.engine.statistic.StatisticUpdatesNotifier;
-import org.apache.ignite.internal.sql.engine.type.IgniteTypeFactory;
 import org.apache.ignite.internal.sql.engine.util.Cloner;
 import org.apache.ignite.internal.sql.engine.util.Commons;
 import org.apache.ignite.internal.sql.engine.util.TypeUtils;
@@ -113,8 +103,12 @@ import 
org.apache.ignite.internal.sql.engine.util.cache.CacheFactory;
 import org.apache.ignite.internal.sql.metrics.SqlPlanCacheMetricSource;
 import org.apache.ignite.internal.storage.DataStorageManager;
 import org.apache.ignite.internal.thread.IgniteThreadFactory;
+import org.apache.ignite.internal.type.NativeType;
+import org.apache.ignite.internal.type.NativeTypes;
 import org.apache.ignite.internal.util.ExceptionUtils;
+import org.apache.ignite.lang.ErrorGroups.Common;
 import org.apache.ignite.lang.ErrorGroups.Sql;
+import org.apache.ignite.lang.IgniteException;
 import org.apache.ignite.sql.ColumnMetadata;
 import org.apache.ignite.sql.ColumnType;
 import org.apache.ignite.sql.ResultSetMetadata;
@@ -122,7 +116,6 @@ import org.apache.ignite.sql.SqlException;
 import org.apache.ignite.table.QualifiedName;
 import org.apache.ignite.table.QualifiedNameHelper;
 import org.jetbrains.annotations.Nullable;
-import org.jetbrains.annotations.TestOnly;
 
 /**
  * An implementation of the {@link PrepareService} that uses a Calcite-based 
query planner to validate and optimize a given query.
@@ -306,15 +299,7 @@ public class PrepareServiceImpl implements PrepareService {
         long timestamp = operationContext.operationTime().longValue();
         int catalogVersion = schemaManager.catalogVersion(timestamp);
 
-        RelDataType[] paramTypes = new 
RelDataType[operationContext.parameters().length];
-
-        int idx = 0;
-        for (Object param : operationContext.parameters()) {
-            RelDataType relType = deriveTypeFromDynamicParamValue(param);
-            paramTypes[idx++] = relType;
-        }
-
-        CacheKey key = new CacheKey(catalogVersion, schemaName, 
parsedResult.normalizedQuery(), paramTypes);
+        CacheKey key = createCacheKey(parsedResult.normalizedQuery(), 
catalogVersion, schemaName, operationContext.parameters());
 
         CompletableFuture<PlanInfo> planFuture = cache.get(key);
 
@@ -346,7 +331,7 @@ public class PrepareServiceImpl implements PrepareService {
                 .plannerTimeout(plannerTimeout)
                 .catalogVersion(catalogVersion)
                 .defaultSchemaName(schemaName)
-                .parameters(Commons.arrayToMap(paramTypes))
+                .parameters(Commons.arrayToMap(key.paramTypes()))
                 .explicitTx(explicitTx)
                 .build();
 
@@ -358,6 +343,31 @@ public class PrepareServiceImpl implements PrepareService {
         );
     }
 
+    private static CacheKey createCacheKey(
+            String query, int catalogVersion, String schemaName, Object[] 
params
+    ) {
+        ColumnType[] paramTypes = new ColumnType[params.length];
+
+        int idx = 0;
+        for (Object param : params) {
+            ColumnType columnType;
+            if (param != null) {
+                @Nullable NativeType type = NativeTypes.fromObject(param);
+
+                if (type == null) {
+                    throw new IgniteException(Common.INTERNAL_ERR, 
"Unsupported native type: " + param.getClass());
+                }
+
+                columnType = type.spec();
+            } else {
+                columnType = null;
+            }
+            paramTypes[idx++] = columnType;
+        }
+
+        return new CacheKey(catalogVersion, schemaName, query, paramTypes);
+    }
+
     private SchemaPlus getDefaultSchema(int catalogVersion, String schemaName) 
{
         IgniteSchemas rootSchema = schemaManager.schemas(catalogVersion);
         assert rootSchema != null : "Root schema does not exist";
@@ -509,14 +519,38 @@ public class PrepareServiceImpl implements PrepareService 
{
             }
 
             // Use parameter metadata to compute a cache key.
-            CacheKey cacheKey =
-                    createCacheKey(stmt.parsedResult.normalizedQuery(), 
ctx.catalogVersion(), ctx.schemaName(), stmt.parameterType);
+            CacheKey cacheKey = 
createCacheKeyFromParameterMetadata(stmt.parsedResult.normalizedQuery(), 
ctx.catalogVersion(),
+                    ctx.schemaName(), stmt.parameterMetadata);
 
             return cache.get(cacheKey, k -> CompletableFuture.supplyAsync(() 
-> buildQueryPlan(stmt, ctx,
                     () -> cache.invalidate(cacheKey)), planningPool));
         });
     }
 
+    private static CacheKey createCacheKeyFromParameterMetadata(
+            String query,
+            int catalogVersion,
+            String schemaName,
+            ParameterMetadata parameterMetadata
+    ) {
+        ColumnType[] paramTypes;
+
+        List<ParameterType> parameterTypes = 
parameterMetadata.parameterTypes();
+        if (parameterTypes.isEmpty()) {
+            paramTypes = EMPTY_CLASS_ARRAY;
+        } else {
+            ColumnType[] result = new ColumnType[parameterTypes.size()];
+
+            for (int i = 0; i < parameterTypes.size(); i++) {
+                result[i] = parameterTypes.get(i).columnType();
+            }
+
+            paramTypes = result;
+        }
+
+        return new CacheKey(catalogVersion, schemaName, query, paramTypes);
+    }
+
     private CompletableFuture<Void> rebuildQueryPlan(
             ParsedResult parsedResult,
             PlanningContext ctx,
@@ -552,7 +586,9 @@ public class PrepareServiceImpl implements PrepareService {
             // Validate
             ValidationResult validated = 
planner.validateAndGetTypeMetadata(sqlNode);
 
-            return new ValidStatement<>(parsedResult, validated, 
planner.getParameterRowType());
+            ParameterMetadata parameterMetadata = 
createParameterMetadata(planner.getParameterRowType());
+
+            return new ValidStatement<>(parsedResult, validated, 
parameterMetadata);
         }, planningPool);
     }
 
@@ -566,8 +602,6 @@ public class PrepareServiceImpl implements PrepareService {
         IgniteRel optimizedRel = relWithMetadata.rel;
         QueryPlan fastPlan = tryOptimizeFast(stmt, ctx);
 
-        ParameterMetadata parameterMetadata = 
createParameterMetadata(stmt.parameterType);
-
         ResultSetMetadata resultSetMetadata = 
resultSetMetadata(validated.dataType(), validated.origins(), 
validated.aliases());
 
         int catalogVersion = ctx.catalogVersion();
@@ -580,7 +614,7 @@ public class PrepareServiceImpl implements PrepareService {
                     catalogVersion,
                     kvGet,
                     resultSetMetadata,
-                    parameterMetadata,
+                    stmt.parameterMetadata,
                     relWithMetadata.paMetadata,
                     relWithMetadata.ppMetadata
             );
@@ -593,7 +627,7 @@ public class PrepareServiceImpl implements PrepareService {
                 SqlQueryType.QUERY,
                 optimizedRel,
                 resultSetMetadata,
-                parameterMetadata,
+                stmt.parameterMetadata,
                 catalogVersion,
                 relWithMetadata.numSources,
                 fastPlan,
@@ -744,8 +778,8 @@ public class PrepareServiceImpl implements PrepareService {
 
         return validateDml(parsedResult, sqlNode, ctx).thenCompose(stmt -> {
             // Use parameter metadata to compute a cache key.
-            CacheKey cacheKey =
-                    createCacheKey(stmt.parsedResult.normalizedQuery(), 
ctx.catalogVersion(), ctx.schemaName(), stmt.parameterType);
+            CacheKey cacheKey = 
createCacheKeyFromParameterMetadata(stmt.parsedResult.normalizedQuery(), 
ctx.catalogVersion(),
+                    ctx.schemaName(), stmt.parameterMetadata);
 
             return cache.get(cacheKey, k -> CompletableFuture.supplyAsync(() 
-> buildDmlPlan(stmt, ctx,
                     () -> cache.invalidate(cacheKey)), planningPool));
@@ -756,7 +790,6 @@ public class PrepareServiceImpl implements PrepareService {
         IgnitePlanner planner = ctx.planner();
 
         SqlNode validatedNode = stmt.value.sqlNode();
-        ParameterMetadata parameterMetadata = 
createParameterMetadata(stmt.parameterType);
 
         RelWithMetadata relWithMetadata = doOptimize(ctx, validatedNode, 
planner, onTimeoutAction);
         IgniteRel optimizedRel = relWithMetadata.rel;
@@ -772,7 +805,7 @@ public class PrepareServiceImpl implements PrepareService {
                     catalogVersion,
                     kvModify,
                     DML_METADATA,
-                    parameterMetadata,
+                    stmt.parameterMetadata,
                     relWithMetadata.paMetadata,
                     relWithMetadata.ppMetadata
             );
@@ -782,7 +815,7 @@ public class PrepareServiceImpl implements PrepareService {
                     SqlQueryType.DML,
                     optimizedRel,
                     DML_METADATA,
-                    parameterMetadata,
+                    stmt.parameterMetadata,
                     catalogVersion,
                     relWithMetadata.numSources,
                     null,
@@ -816,8 +849,9 @@ public class PrepareServiceImpl implements PrepareService {
             SqlNode validatedNode = planner.validate(sqlNode);
             ValidationResult validatedResult = new 
ValidationResult(validatedNode);
 
+            ParameterMetadata parameterMetadata = 
createParameterMetadata(planner.getParameterRowType());
             // No need whole ParsedResult
-            return new ValidStatement<>(parsedResult, validatedResult, 
planner.getParameterRowType());
+            return new ValidStatement<>(parsedResult, validatedResult, 
parameterMetadata);
         }, planningPool);
     }
 
@@ -858,7 +892,7 @@ public class PrepareServiceImpl implements PrepareService {
                 planningContext.catalogVersion(),
                 (IgniteSelectCount) fastOptRel,
                 resultSetMetadata,
-                createParameterMetadata(stmt.parameterType)
+                stmt.parameterMetadata
         );
 
         logPlan(stmt.parsedResult.originalQuery(), plan);
@@ -866,21 +900,6 @@ public class PrepareServiceImpl implements PrepareService {
         return plan;
     }
 
-    private static CacheKey createCacheKey(
-            String normalizedQuery,
-            int catalogVersion,
-            String schemaName,
-            RelDataType parameterRowType
-    ) {
-        RelDataType[] paramTypes = new 
RelDataType[parameterRowType.getFieldCount()];
-
-        for (int i = 0; i < parameterRowType.getFieldCount(); i++) {
-            paramTypes[i] = parameterRowType.getFieldList().get(i).getType();
-        }
-
-        return new CacheKey(catalogVersion, schemaName, normalizedQuery, 
paramTypes);
-    }
-
     private static IntSet resolveSources(IgniteRel rel) {
         IntSet tables = new IntOpenHashSet();
 
@@ -933,7 +952,7 @@ public class PrepareServiceImpl implements PrepareService {
 
                         ColumnMetadataImpl fldMeta = new ColumnMetadataImpl(
                                 alias != null ? alias : fld.getName(),
-                                TypeUtils.columnType(fld.getType()),
+                                columnType(fld.getType()),
                                 fld.getType().getPrecision(),
                                 fld.getType().getScale(),
                                 fld.getType().isNullable(),
@@ -1204,12 +1223,12 @@ public class PrepareServiceImpl implements 
PrepareService {
     private static class ValidStatement<T> {
         final ParsedResult parsedResult;
         final T value;
-        final RelDataType parameterType;
+        final ParameterMetadata parameterMetadata;
 
-        private ValidStatement(ParsedResult parsedResult, T value, RelDataType 
parameterType) {
+        private ValidStatement(ParsedResult parsedResult, T value, 
ParameterMetadata parameterMetadata) {
             this.parsedResult = parsedResult;
             this.value = value;
-            this.parameterType = parameterType;
+            this.parameterMetadata = parameterMetadata;
         }
 
         ParsedResult parsedResult() {
@@ -1318,61 +1337,4 @@ public class PrepareServiceImpl implements 
PrepareService {
             return new PlanInfo(plan, null, IntSet.of());
         }
     }
-
-    @TestOnly
-    @Nullable
-    public static RelDataType 
deriveTypeFromDynamicParamValueTestOnly(@Nullable Object value) {
-        return deriveTypeFromDynamicParamValue(value);
-    }
-
-    @Nullable
-    private static RelDataType deriveTypeFromDynamicParamValue(@Nullable 
Object value) {
-        if (value == null) {
-            return null;
-        }
-
-        IgniteTypeFactory typeFactory = Commons.typeFactory();
-
-        Class<?> cls = value.getClass();
-
-        if (cls == Character.class) {
-            cls = String.class;
-        }
-
-        if (cls == Boolean.class) {
-            return typeFactory.createSqlType(SqlTypeName.BOOLEAN);
-        } else if (cls == Byte.class) {
-            return typeFactory.createSqlType(SqlTypeName.TINYINT);
-        } else if (cls == Short.class) {
-            return typeFactory.createSqlType(SqlTypeName.SMALLINT);
-        } else if (cls == Integer.class) {
-            return typeFactory.createSqlType(INTEGER);
-        } else if (cls == Long.class) {
-            return typeFactory.createSqlType(SqlTypeName.BIGINT);
-        } else if (cls == Float.class) {
-            return typeFactory.createSqlType(SqlTypeName.REAL);
-        } else if (cls == Double.class) {
-            return typeFactory.createSqlType(SqlTypeName.DOUBLE);
-        } else if (cls == LocalDate.class) {
-            return typeFactory.createSqlType(SqlTypeName.DATE);
-        } else if (cls == LocalTime.class) {
-            return typeFactory.createSqlType(SqlTypeName.TIME, 
TEMPORAL_DYNAMIC_PARAM_PRECISION);
-        } else if (cls == LocalDateTime.class) {
-            return typeFactory.createSqlType(SqlTypeName.TIMESTAMP, 
TEMPORAL_DYNAMIC_PARAM_PRECISION);
-        } else if (cls == Instant.class) {
-            return 
typeFactory.createSqlType(SqlTypeName.TIMESTAMP_WITH_LOCAL_TIME_ZONE, 
TEMPORAL_DYNAMIC_PARAM_PRECISION);
-        } else if (cls == byte[].class) {
-            return typeFactory.createSqlType(SqlTypeName.VARBINARY, 
PRECISION_NOT_SPECIFIED);
-        } else if (cls == String.class) {
-            return typeFactory.createSqlType(SqlTypeName.VARCHAR, 
PRECISION_NOT_SPECIFIED);
-        } else if (cls == UUID.class) {
-            return typeFactory.createSqlType(SqlTypeName.UUID);
-        } else if (cls == BigDecimal.class) {
-            return typeFactory.createSqlType(
-                    SqlTypeName.DECIMAL, DECIMAL_DYNAMIC_PARAM_PRECISION, 
DECIMAL_DYNAMIC_PARAM_SCALE
-            );
-        }
-
-        throw new AssertionError("Unknown type " + cls);
-    }
 }
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 254d1ad1716..6949462627c 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
@@ -19,7 +19,6 @@ package org.apache.ignite.internal.sql.engine.planner;
 
 import static org.apache.calcite.tools.Frameworks.newConfigBuilder;
 import static 
org.apache.ignite.internal.sql.engine.externalize.RelJsonWriter.toJson;
-import static 
org.apache.ignite.internal.sql.engine.prepare.PrepareServiceImpl.deriveTypeFromDynamicParamValueTestOnly;
 import static 
org.apache.ignite.internal.sql.engine.util.Commons.FRAMEWORK_CONFIG;
 import static org.apache.ignite.internal.util.CollectionUtils.first;
 import static org.apache.ignite.internal.util.CollectionUtils.nullOrEmpty;
@@ -123,7 +122,9 @@ import org.apache.ignite.internal.sql.engine.util.TypeUtils;
 import org.apache.ignite.internal.testframework.IgniteAbstractTest;
 import org.apache.ignite.internal.testframework.IgniteTestUtils;
 import org.apache.ignite.internal.type.NativeType;
+import org.apache.ignite.internal.type.NativeTypes;
 import org.apache.ignite.internal.util.Pair;
+import org.apache.ignite.sql.ColumnType;
 import org.jetbrains.annotations.Nullable;
 
 /**
@@ -253,11 +254,16 @@ public abstract class AbstractPlannerTest extends 
IgniteAbstractTest {
             String... disabledRules
     ) {
 
-        Int2ObjectArrayMap<RelDataType> paramsMap = new Int2ObjectArrayMap<>();
+        Int2ObjectArrayMap<ColumnType> dynamicParamTypes = new 
Int2ObjectArrayMap<>();
         for (int i = 0; i < params.size(); i++) {
             Object value = params.get(i);
             if (value != Unspecified.UNKNOWN) {
-                paramsMap.put(i, 
deriveTypeFromDynamicParamValueTestOnly(value));
+                if (value != null && value.getClass() == Character.class) {
+                    dynamicParamTypes.put(i, ColumnType.STRING);
+                } else {
+                    NativeType type = NativeTypes.fromObject(value);
+                    dynamicParamTypes.put(i, type == null ? null : 
type.spec());
+                }
             }
         }
 
@@ -286,7 +292,7 @@ public abstract class AbstractPlannerTest extends 
IgniteAbstractTest {
                 .catalogVersion(1)
                 .defaultSchemaName(defaultSchema.getName())
                 .query(sql)
-                .parameters(paramsMap)
+                .parameters(dynamicParamTypes)
                 // Assume that we use explicit transactions by default.
                 .explicitTx(true)
                 .build();

Reply via email to