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();
