This is an automated email from the ASF dual-hosted git repository.
zstan 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 4dee07f045c IGNITE-26694 Sql. Fix performance drop after IGNITE-26592
(#6767)
4dee07f045c is described below
commit 4dee07f045c66c4a6beb5b168b12447a1627587c
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/ItLimitOffsetTest.java | 2 +-
.../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 +-
6 files changed, 156 insertions(+), 144 deletions(-)
diff --git
a/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItLimitOffsetTest.java
b/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItLimitOffsetTest.java
index b0a21bb5f14..d7175490a74 100644
---
a/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItLimitOffsetTest.java
+++
b/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItLimitOffsetTest.java
@@ -48,7 +48,7 @@ public class ItLimitOffsetTest extends BaseSqlIntegrationTest
{
/** Tests correctness of fetch / offset params. */
@Test
- public void testInvalidLimitOffset() throws InterruptedException {
+ public void testInvalidLimitOffset() {
BigDecimal moreThanUpperLong = new BigDecimal(Long.MAX_VALUE).add(new
BigDecimal(1));
// cache the plan with concrete type param
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();