This is an automated email from the ASF dual-hosted git repository.
ivandasch pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ignite.git
The following commit(s) were added to refs/heads/master by this push:
new b7b53690410 IGNITE-17599 SQL Calcite: Support insertion of
LocalDateTime, LocalDate and LocalTime (#10399)
b7b53690410 is described below
commit b7b53690410ec72a23fbc28a31e08fd21f881e80
Author: Ivan Daschinskiy <[email protected]>
AuthorDate: Tue Nov 29 21:11:32 2022 +0300
IGNITE-17599 SQL Calcite: Support insertion of LocalDateTime, LocalDate and
LocalTime (#10399)
* IGNITE-17599 SQL Calcite: Support insertion of LocalDateTime, LocalDate
and LocalTime
* Review fixes
* Add additional tests.
---
.../query/calcite/externalize/RelJsonReader.java | 3 +
.../query/calcite/type/IgniteTypeFactory.java | 11 +-
.../processors/query/calcite/util/TypeUtils.java | 50 +++-
.../integration/LocalDateTimeSupportTest.java | 288 +++++++++++++++++++++
.../ignite/testsuites/IntegrationTestSuite.java | 2 +
.../processors/query/GridQueryIndexing.java | 13 -
.../processors/query/QueryTypeDescriptorImpl.java | 11 +-
.../internal/processors/query/QueryUtils.java | 18 +-
.../processors/query/DummyQueryIndexing.java | 5 -
.../internal/processors/query/h2/H2Utils.java | 40 ---
.../processors/query/h2/IgniteH2Indexing.java | 17 --
.../h2/H2ColumnTypeConversionCheckSelfTest.java | 57 ----
.../IgniteBinaryCacheQueryTestSuite3.java | 2 -
13 files changed, 369 insertions(+), 148 deletions(-)
diff --git
a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/externalize/RelJsonReader.java
b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/externalize/RelJsonReader.java
index 522ec373125..d740af19174 100644
---
a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/externalize/RelJsonReader.java
+++
b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/externalize/RelJsonReader.java
@@ -243,6 +243,9 @@ public class RelJsonReader {
/** {@inheritDoc} */
@Override public List<RexNode> getExpressionList(String tag) {
List<Object> jsonNodes = (List)jsonRel.get(tag);
+ if (jsonNodes == null)
+ return null;
+
List<RexNode> nodes = new ArrayList<>();
for (Object jsonNode : jsonNodes)
nodes.add(relJson.toRex(this, jsonNode));
diff --git
a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/type/IgniteTypeFactory.java
b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/type/IgniteTypeFactory.java
index 94c9cd6f96a..d2ca9a6b3ca 100644
---
a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/type/IgniteTypeFactory.java
+++
b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/type/IgniteTypeFactory.java
@@ -23,6 +23,7 @@ import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.sql.Timestamp;
import java.time.Duration;
+import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.Period;
@@ -40,6 +41,7 @@ import org.apache.calcite.sql.SqlUtil;
import org.apache.calcite.sql.parser.SqlParserPos;
import org.apache.calcite.sql.type.BasicSqlType;
import org.apache.calcite.sql.type.IntervalSqlType;
+import org.apache.calcite.sql.type.SqlTypeName;
import org.apache.ignite.internal.util.typedef.F;
/**
@@ -265,6 +267,12 @@ public class IgniteTypeFactory extends JavaTypeFactoryImpl
{
return
createTypeWithNullability(createSqlIntervalType(INTERVAL_QUALIFIER_DAY_TIME),
true);
else if (clazz == Period.class)
return
createTypeWithNullability(createSqlIntervalType(INTERVAL_QUALIFIER_YEAR_MONTH),
true);
+ else if (clazz == LocalDateTime.class)
+ return
createTypeWithNullability(createSqlType(SqlTypeName.TIMESTAMP), true);
+ else if (clazz == LocalDate.class)
+ return
createTypeWithNullability(createSqlType(SqlTypeName.DATE), true);
+ else if (clazz == LocalTime.class)
+ return
createTypeWithNullability(createSqlType(SqlTypeName.TIME), true);
else {
RelDataType relType = createCustomType(clazz);
@@ -301,7 +309,8 @@ public class IgniteTypeFactory extends JavaTypeFactoryImpl {
/** {@inheritDoc} */
@Override public RelDataType createType(Type type) {
- if (type == Duration.class || type == Period.class)
+ if (type == Duration.class || type == Period.class || type ==
LocalDateTime.class || type == LocalTime.class
+ || type == LocalDate.class)
return createJavaType((Class<?>)type);
RelDataType customType = createCustomType(type, false);
diff --git
a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/util/TypeUtils.java
b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/util/TypeUtils.java
index a01b6d90d2f..4455f4a387f 100644
---
a/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/util/TypeUtils.java
+++
b/modules/calcite/src/main/java/org/apache/ignite/internal/processors/query/calcite/util/TypeUtils.java
@@ -23,7 +23,12 @@ import java.sql.Date;
import java.sql.Time;
import java.sql.Timestamp;
import java.time.Duration;
+import java.time.Instant;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
import java.time.Period;
+import java.time.ZoneOffset;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
@@ -59,6 +64,7 @@ import org.apache.calcite.util.Pair;
import org.apache.calcite.util.TimeString;
import org.apache.calcite.util.TimestampString;
import org.apache.ignite.IgniteException;
+import
org.apache.ignite.internal.cache.query.index.sorted.inline.types.DateValueUtils;
import org.apache.ignite.internal.processors.query.IgniteSQLException;
import
org.apache.ignite.internal.processors.query.calcite.exec.ExecutionContext;
import org.apache.ignite.internal.processors.query.calcite.exec.RowHandler;
@@ -81,6 +87,9 @@ public class TypeUtils {
java.sql.Date.class,
java.sql.Time.class,
java.sql.Timestamp.class,
+ LocalDateTime.class,
+ LocalDate.class,
+ LocalTime.class,
Duration.class,
Period.class,
byte[].class
@@ -316,13 +325,19 @@ public class TypeUtils {
if (val == null)
return null;
else if (storageType == java.sql.Date.class)
- return (int)(SqlFunctions.toLong((java.util.Date)val,
DataContext.Variable.TIME_ZONE.get(ctx)) / DateTimeUtils.MILLIS_PER_DAY);
+ return (int)(toLong(ctx, val) / DateTimeUtils.MILLIS_PER_DAY);
+ else if (storageType == LocalDate.class)
+ return (int)(toLong(ctx, val) / DateTimeUtils.MILLIS_PER_DAY);
else if (storageType == java.sql.Time.class)
- return (int)(SqlFunctions.toLong((java.util.Date)val,
DataContext.Variable.TIME_ZONE.get(ctx)) % DateTimeUtils.MILLIS_PER_DAY);
- else if (storageType == Timestamp.class)
- return SqlFunctions.toLong((java.util.Date)val,
DataContext.Variable.TIME_ZONE.get(ctx));
+ return (int)(toLong(ctx, val) % DateTimeUtils.MILLIS_PER_DAY);
+ else if (storageType == LocalTime.class)
+ return (int)(toLong(ctx, val) % DateTimeUtils.MILLIS_PER_DAY);
+ else if (storageType == Timestamp.class || storageType ==
LocalDateTime.class)
+ return toLong(ctx, val);
else if (storageType == java.util.Date.class)
- return SqlFunctions.toLong((java.util.Date)val,
DataContext.Variable.TIME_ZONE.get(ctx));
+ return toLong(ctx, val);
+ else if (storageType == java.util.Date.class)
+ return toLong(ctx, val);
else if (storageType == Duration.class) {
return TimeUnit.SECONDS.toMillis(((Duration)val).getSeconds())
+ TimeUnit.NANOSECONDS.toMillis(((Duration)val).getNano());
@@ -348,16 +363,41 @@ public class TypeUtils {
return val;
}
+ /** Converts temporal objects to long.
+ *
+ * @param ctx Data context.
+ * @param val Temporal value.
+ * @return Millis value.
+ */
+ private static long toLong(DataContext ctx, Object val) {
+ if (val instanceof LocalDateTime)
+ return
SqlFunctions.toLong(DateValueUtils.convertToTimestamp((LocalDateTime)val),
DataContext.Variable.TIME_ZONE.get(ctx));
+
+ if (val instanceof LocalDate)
+ return
SqlFunctions.toLong(DateValueUtils.convertToSqlDate((LocalDate)val),
DataContext.Variable.TIME_ZONE.get(ctx));
+
+ if (val instanceof LocalTime)
+ return
SqlFunctions.toLong(DateValueUtils.convertToSqlTime((LocalTime)val),
DataContext.Variable.TIME_ZONE.get(ctx));
+
+ return SqlFunctions.toLong((java.util.Date)val,
DataContext.Variable.TIME_ZONE.get(ctx));
+ }
+
/** */
public static Object fromInternal(DataContext ctx, Object val, Type
storageType) {
if (val == null)
return null;
else if (storageType == java.sql.Date.class && val instanceof Integer)
return new java.sql.Date(fromLocalTs(ctx, (Integer)val *
DateTimeUtils.MILLIS_PER_DAY));
+ else if (storageType == LocalDate.class && val instanceof Integer)
+ return new java.sql.Date(fromLocalTs(ctx, (Integer)val *
DateTimeUtils.MILLIS_PER_DAY)).toLocalDate();
else if (storageType == java.sql.Time.class && val instanceof Integer)
return new java.sql.Time(fromLocalTs(ctx, (Integer)val));
+ else if (storageType == LocalTime.class && val instanceof Integer)
+ return
Instant.ofEpochMilli((Integer)val).atZone(ZoneOffset.UTC).toLocalTime();
else if (storageType == Timestamp.class && val instanceof Long)
return new Timestamp(fromLocalTs(ctx, (Long)val));
+ else if (storageType == LocalDateTime.class && val instanceof Long)
+ return new Timestamp(fromLocalTs(ctx,
(Long)val)).toLocalDateTime();
else if (storageType == java.util.Date.class && val instanceof Long)
return new java.util.Date(fromLocalTs(ctx, (Long)val));
else if (storageType == Duration.class && val instanceof Long)
diff --git
a/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/LocalDateTimeSupportTest.java
b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/LocalDateTimeSupportTest.java
new file mode 100644
index 00000000000..2b10ea90388
--- /dev/null
+++
b/modules/calcite/src/test/java/org/apache/ignite/internal/processors/query/calcite/integration/LocalDateTimeSupportTest.java
@@ -0,0 +1,288 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.ignite.internal.processors.query.calcite.integration;
+
+import java.sql.Timestamp;
+import java.time.Instant;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.Month;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Date;
+import java.util.List;
+import java.util.function.Function;
+import org.apache.ignite.cache.QueryEntity;
+import org.apache.ignite.configuration.CacheConfiguration;
+import org.apache.ignite.configuration.IgniteConfiguration;
+import org.apache.ignite.internal.util.typedef.G;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import static java.util.Collections.singletonList;
+import static
org.apache.ignite.internal.cache.query.index.sorted.inline.types.DateValueUtils.convertToSqlDate;
+import static
org.apache.ignite.internal.cache.query.index.sorted.inline.types.DateValueUtils.convertToSqlTime;
+import static
org.apache.ignite.internal.cache.query.index.sorted.inline.types.DateValueUtils.convertToTimestamp;
+
+/** */
+@RunWith(Parameterized.class)
+public class LocalDateTimeSupportTest extends AbstractBasicIntegrationTest {
+ /** */
+ @Parameterized.Parameter()
+ public boolean isValidationEnabled;
+
+ /** */
+ @Parameterized.Parameter(1)
+ public String sqlType;
+
+ /** */
+ @Parameterized.Parameter(2)
+ public Class<?> colType;
+
+ /** */
+ @Parameterized.Parameter(3)
+ public Class<?> objType;
+
+ /** */
+ @Parameterized.Parameter(4)
+ public Function<Object, Object> sqlTypeConverter;
+
+ /** */
+ @Parameterized.Parameter(5)
+ public boolean isOldDate;
+
+ /** */
+ @Parameterized.Parameters(name = "isValidationEnabled={0}, sqlType={1},
columnCls={2}, testObjCls={3}, beforeGregorian={5}")
+ public static Collection<Object[]> parameters() {
+ Collection<Object[]> params = new ArrayList<>();
+
+ for (boolean isOldDate: Arrays.asList(true, false)) {
+ for (boolean isV : Arrays.asList(true, false)) {
+ params.add(new Object[] {
+ isV, "TIMESTAMP", null, LocalDateTime.class, f(ts ->
convertToTimestamp((LocalDateTime)ts)), isOldDate
+ });
+ params.add(new Object[] {
+ isV, "TIMESTAMP", null, Date.class, f(ts -> new
Timestamp(((Date)ts).getTime())), isOldDate
+ });
+ params.add(new Object[] {
+ isV, "TIMESTAMP", null, java.sql.Date.class, f(ts -> new
Timestamp(((Date)ts).getTime())), isOldDate
+ });
+
+ for (Class<?> testObjCls : Arrays.asList(Timestamp.class,
LocalDateTime.class, Date.class, java.sql.Date.class)) {
+ params.add(new Object[] {
+ isV, null, Timestamp.class, testObjCls, f(ts -> {
+ if (ts instanceof LocalDateTime)
+ return convertToTimestamp((LocalDateTime)ts);
+ return ts;
+ }),
+ isOldDate
+ });
+
+ params.add(new Object[] {
+ isV, null, Date.class, testObjCls, f(ts -> {
+ if (testObjCls == LocalDateTime.class)
+ return new
Date(convertToTimestamp((LocalDateTime)ts).getTime());
+ else if (testObjCls == Timestamp.class)
+ return new Date(((Timestamp)ts).getTime());
+ return ts;
+ }),
+ isOldDate
+ });
+
+ params.add(new Object[] {
+ isV, null, LocalDateTime.class, testObjCls, f(ts -> {
+ if (testObjCls == Timestamp.class)
+ return ((Timestamp)ts).toLocalDateTime();
+ else if (testObjCls == java.util.Date.class)
+ return new
Timestamp(((Date)ts).getTime()).toLocalDateTime();
+ else if (testObjCls == java.sql.Date.class)
+ return
((java.sql.Date)ts).toLocalDate().atStartOfDay();
+ else
+ return ts;
+ }),
+ isOldDate
+ });
+ }
+
+ params.add(new Object[] {
+ isV, "DATE", null, LocalDate.class, f(d ->
convertToSqlDate((LocalDate)d)), isOldDate
+ });
+
+ for (Class<?> testObjCls : Arrays.asList(LocalDate.class,
java.sql.Date.class)) {
+ params.add(new Object[] {
+ isV, null, java.sql.Date.class, testObjCls, f(ts -> {
+ if (testObjCls == LocalDate.class)
+ return convertToSqlDate((LocalDate)ts);
+ return ts;
+ }),
+ isOldDate
+ });
+
+ params.add(new Object[] {
+ isV, null, LocalDate.class, testObjCls, f(ts -> {
+ if (testObjCls == java.sql.Date.class)
+ return ((java.sql.Date)ts).toLocalDate();
+ return ts;
+ }),
+ isOldDate
+ });
+ }
+
+ params.add(new Object[] {
+ isV, "TIME", null, LocalTime.class, f(t ->
convertToSqlTime((LocalTime)t)), isOldDate
+ });
+
+ for (Class<?> testObjCls : Arrays.asList(LocalTime.class,
java.sql.Time.class)) {
+ params.add(new Object[] {
+ isV, null, java.sql.Time.class, testObjCls, f(ts -> {
+ if (testObjCls == LocalTime.class)
+ return convertToSqlTime((LocalTime)ts);
+ return ts;
+ }),
+ isOldDate
+ });
+
+ params.add(new Object[] {
+ isV, null, LocalTime.class, testObjCls, f(ts -> {
+ if (testObjCls == java.sql.Time.class)
+ return ((java.sql.Time)ts).toLocalTime();
+ return ts;
+ }),
+ isOldDate
+ });
+ }
+ }
+ }
+
+ return params;
+ }
+
+ /** {@inheritDoc} */
+ @Override protected IgniteConfiguration getConfiguration(String
igniteInstanceName) throws Exception {
+ IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName);
+
+ cfg.getSqlConfiguration().setValidationEnabled(isValidationEnabled);
+
+ return cfg;
+ }
+
+ /** {@inheritDoc} */
+ @Override public void beforeTest() throws Exception {
+ if (!G.allGrids().isEmpty())
+ return;
+
+ startGrids(nodeCount());
+
+ client = startClientGrid("client");
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void afterTest() throws Exception {
+ stopAllGrids();
+ }
+
+ /** */
+ @Test
+ public void testTemporalTypes() {
+ createTable();
+
+ executeSql("CREATE INDEX DATA_IDX ON DATA(data DESC);");
+
+ Object testObj = generateTestObject(objType, isOldDate);
+
+ executeSql("INSERT INTO DATA(_key, id, data) values(?, ?, ?)", 0, 0,
testObj);
+
+ grid(0).cache(DEFAULT_CACHE_NAME).put(1, new Data(1, testObj));
+
+ grid(0).cache(DEFAULT_CACHE_NAME).put(2, grid(0).binary().toBinary(new
Data(2, testObj)));
+
+ List<List<?>> selectData = executeSql("SELECT data FROM DATA");
+
+ Object sqlObj = sqlTypeConverter.apply(testObj);
+
+ selectData.forEach(d -> assertEquals(sqlObj, d.get(0)));
+ }
+
+ /** */
+ private void createTable() {
+ if (sqlType != null) {
+ executeSql("CREATE TABLE DATA (id INT PRIMARY KEY, data " +
sqlType + ") WITH" +
+ " \"KEY_TYPE=java.lang.Integer" +
+ ", VALUE_TYPE=" + Data.class.getName() +
+ ", CACHE_NAME=default\"");
+ }
+ else {
+ QueryEntity projEntity = new QueryEntity();
+ projEntity.setKeyType(Integer.class.getName());
+ projEntity.setValueType(Data.class.getName());
+ projEntity.addQueryField("id", Integer.class.getName(), null);
+ projEntity.addQueryField("data", colType.getName(), null);
+
+ projEntity.setTableName("DATA");
+
+ grid(0).createCache(new CacheConfiguration<>(DEFAULT_CACHE_NAME)
+ .setQueryEntities(singletonList(projEntity))
+ .setSqlSchema("PUBLIC"));
+ }
+ }
+
+ /** */
+ private static Object generateTestObject(Class<?> cls, boolean isOldDate) {
+ LocalDateTime oldDateTime = LocalDateTime.of(1042, Month.APRIL, 1, 12,
45, 0);
+ LocalDate oldDate = LocalDate.of(1042, Month.APRIL, 1);
+ if (cls == LocalDateTime.class)
+ return isOldDate ? oldDateTime : LocalDateTime.now();
+ else if (cls == LocalTime.class)
+ return LocalTime.now();
+ else if (cls == LocalDate.class)
+ return isOldDate ? oldDate : LocalDate.now();
+ else if (cls == Date.class)
+ return isOldDate ? new
Date(convertToTimestamp(oldDateTime).getTime()) : Date.from(Instant.now());
+ else if (cls == java.sql.Date.class)
+ return isOldDate ? java.sql.Date.valueOf(oldDate) :
java.sql.Date.valueOf(LocalDate.now());
+ else if (cls == java.sql.Time.class)
+ return java.sql.Time.valueOf(LocalTime.now());
+ else if (cls == java.sql.Timestamp.class)
+ return isOldDate ? convertToTimestamp(oldDateTime) :
java.sql.Timestamp.valueOf(LocalDateTime.now());
+ else
+ throw new IllegalStateException();
+ }
+
+ /** */
+ private static <T, R> Function<Object, Object> f(Function<T, R> f) {
+ return (Function<Object, Object>)f;
+ }
+
+ /** */
+ public static class Data {
+ /** */
+ public int id;
+
+ /** */
+ public Object data;
+
+ /** */
+ public Data(int id, Object data) {
+ this.id = id;
+ this.data = data;
+ }
+ }
+}
diff --git
a/modules/calcite/src/test/java/org/apache/ignite/testsuites/IntegrationTestSuite.java
b/modules/calcite/src/test/java/org/apache/ignite/testsuites/IntegrationTestSuite.java
index 9a11cac9cf7..44a6113e9bf 100644
---
a/modules/calcite/src/test/java/org/apache/ignite/testsuites/IntegrationTestSuite.java
+++
b/modules/calcite/src/test/java/org/apache/ignite/testsuites/IntegrationTestSuite.java
@@ -39,6 +39,7 @@ import
org.apache.ignite.internal.processors.query.calcite.integration.JoinInteg
import
org.apache.ignite.internal.processors.query.calcite.integration.KeepBinaryIntegrationTest;
import
org.apache.ignite.internal.processors.query.calcite.integration.KillCommandDdlIntegrationTest;
import
org.apache.ignite.internal.processors.query.calcite.integration.KillQueryCommandDdlIntegrationTest;
+import
org.apache.ignite.internal.processors.query.calcite.integration.LocalDateTimeSupportTest;
import
org.apache.ignite.internal.processors.query.calcite.integration.MemoryQuotasIntegrationTest;
import
org.apache.ignite.internal.processors.query.calcite.integration.MetadataIntegrationTest;
import
org.apache.ignite.internal.processors.query.calcite.integration.QueryEngineConfigurationIntegrationTest;
@@ -111,6 +112,7 @@ import org.junit.runners.Suite;
KeepBinaryIntegrationTest.class,
QueryMetadataIntegrationTest.class,
MemoryQuotasIntegrationTest.class,
+ LocalDateTimeSupportTest.class
})
public class IntegrationTestSuite {
}
diff --git
a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryIndexing.java
b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryIndexing.java
index c8c91394e96..273a3d73289 100644
---
a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryIndexing.java
+++
b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/GridQueryIndexing.java
@@ -275,17 +275,4 @@ public interface GridQueryIndexing {
* @throws IgniteCheckedException On bean registration error.
*/
public void registerMxBeans(IgniteMBeansManager mbMgr) throws
IgniteCheckedException;
-
- /**
- * Checks if object of the specified class can be stored in the specified
table column by the query engine.
- *
- * @param schemaName Schema name.
- * @param tblName Table name.
- * @param colName Name of the column.
- * @param cls Class to perform check on.
- * @return Whether object of the specified class can be successfully
stored and accessed from the SQL column by the
- * query engine.
- * @throws IgniteSQLException if table or column with specified name was
not found.
- */
- public boolean isConvertibleToColumnType(String schemaName, String
tblName, String colName, Class<?> cls);
}
diff --git
a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/QueryTypeDescriptorImpl.java
b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/QueryTypeDescriptorImpl.java
index 4da4d68b249..78a9d509767 100644
---
a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/QueryTypeDescriptorImpl.java
+++
b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/QueryTypeDescriptorImpl.java
@@ -635,7 +635,7 @@ public class QueryTypeDescriptorImpl implements
GridQueryTypeDescriptor {
isKey ? NULL_KEY : NULL_VALUE);
}
- if (validateTypes && propVal != null &&
!isCompatibleWithPropertyType(propVal, prop.name(), prop.type())) {
+ if (validateTypes && propVal != null &&
!isCompatibleWithPropertyType(propVal, prop.type())) {
throw new IgniteSQLException("Type for a column '" +
prop.name() + "' is not compatible with table definition." +
" Expected '" + prop.type().getSimpleName() + "', actual
type '" + typeName(propVal) + "'");
}
@@ -702,7 +702,7 @@ public class QueryTypeDescriptorImpl implements
GridQueryTypeDescriptor {
if (propVal == null)
continue;
- if (!isCompatibleWithPropertyType(propVal, idxField,
propType)) {
+ if (!isCompatibleWithPropertyType(propVal, propType)) {
throw new IgniteSQLException("Type for a column '" +
idxField + "' is not compatible with index definition." +
" Expected '" + prop.type().getSimpleName() + "',
actual type '" + typeName(propVal) + "'");
}
@@ -714,17 +714,14 @@ public class QueryTypeDescriptorImpl implements
GridQueryTypeDescriptor {
* Checks if the specified object is compatible with the type of the
column through which this object will be accessed.
*
* @param val Object to check.
- * @param colName Name of the column to which current property corresponds.
* @param expColType Type of the column based on Query Property info.
*/
- private boolean isCompatibleWithPropertyType(Object val, String colName,
Class<?> expColType) {
+ private boolean isCompatibleWithPropertyType(Object val, Class<?>
expColType) {
if (!(val instanceof BinaryObject) || val instanceof BinaryArray) {
if (U.box(expColType).isAssignableFrom(U.box(val.getClass())))
return true;
- GridQueryIndexing indexing =
coCtx.kernalContext().query().getIndexing();
-
- if (indexing != null &&
indexing.isConvertibleToColumnType(schemaName, tableName(), colName,
val.getClass()))
+ if (QueryUtils.isConvertibleTypes(val, expColType))
return true;
return expColType.isArray()
diff --git
a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/QueryUtils.java
b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/QueryUtils.java
index d9270156dd3..ecf9eaf28da 100644
---
a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/QueryUtils.java
+++
b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/QueryUtils.java
@@ -38,7 +38,6 @@ import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
-
import org.apache.ignite.IgniteCheckedException;
import org.apache.ignite.IgniteException;
import org.apache.ignite.IgniteSystemProperties;
@@ -1748,6 +1747,23 @@ public class QueryUtils {
return DEFAULT_DELIM;
}
+ /** */
+ public static boolean isConvertibleTypes(Object val, Class<?> expCls) {
+ if (val == null)
+ return true;
+
+ if (expCls == java.sql.Date.class || expCls ==
java.time.LocalDate.class)
+ return val instanceof java.sql.Date || val instanceof
java.time.LocalDate;
+
+ if (expCls == java.sql.Time.class || expCls ==
java.time.LocalTime.class)
+ return val instanceof java.sql.Time || val instanceof
java.time.LocalTime;
+
+ if (expCls == java.sql.Timestamp.class || expCls ==
java.util.Date.class || expCls == java.time.LocalDateTime.class)
+ return val instanceof java.time.LocalDateTime || val instanceof
java.util.Date;
+
+ return false;
+ }
+
/**
* Private constructor.
*/
diff --git
a/modules/core/src/test/java/org/apache/ignite/internal/processors/query/DummyQueryIndexing.java
b/modules/core/src/test/java/org/apache/ignite/internal/processors/query/DummyQueryIndexing.java
index f1206050285..37f8f8ff12f 100644
---
a/modules/core/src/test/java/org/apache/ignite/internal/processors/query/DummyQueryIndexing.java
+++
b/modules/core/src/test/java/org/apache/ignite/internal/processors/query/DummyQueryIndexing.java
@@ -202,9 +202,4 @@ public class DummyQueryIndexing implements
GridQueryIndexing {
@Override public void registerMxBeans(IgniteMBeansManager mbMgr) {
}
-
- /** {@inheritDoc} */
- @Override public boolean isConvertibleToColumnType(String schemaName,
String tblName, String colName, Class<?> cls) {
- return false;
- }
}
diff --git
a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/H2Utils.java
b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/H2Utils.java
index d5144301e5c..bfc03a5f190 100644
---
a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/H2Utils.java
+++
b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/H2Utils.java
@@ -30,20 +30,14 @@ import java.sql.SQLException;
import java.sql.Time;
import java.sql.Timestamp;
import java.sql.Types;
-import java.time.LocalDate;
-import java.time.LocalDateTime;
-import java.time.LocalTime;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
-import java.util.HashMap;
-import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
-import java.util.Set;
import java.util.UUID;
import javax.cache.CacheException;
import org.apache.ignite.IgniteCheckedException;
@@ -154,21 +148,6 @@ public class H2Utils {
/** Quotation character. */
private static final char ESC_CH = '\"';
- /** Types that can be implicitly converted to H2 column type. */
- private static final Map<Integer, Set<Class<?>>> CONVERTABLE_TYPES = new
HashMap<Integer, Set<Class<?>>>() {
- {
- put(Value.TIMESTAMP, new HashSet<Class<?>>() {
- {
- add(LocalDateTime.class);
- add(java.util.Date.class);
- add(java.sql.Date.class);
- }
- });
- put(Value.TIME, Collections.singleton(LocalTime.class));
- put(Value.DATE, Collections.singleton(LocalDate.class));
- }
- };
-
/**
* @param c1 First column.
* @param c2 Second column.
@@ -535,33 +514,14 @@ public class H2Utils {
return false;
}
- /**
- * @param cls The class whose convertibility is to be tested.
- * @param colType Column target type.
- * @return Whether specified class can be implicitly converted to the
specified type.
- * @see #wrap(CacheObjectValueContext, Object, int)
- */
- public static boolean isConvertableToColumnType(Class<?> cls, int colType)
{
- assert cls != null;
-
- if (DataType.getTypeClassName(colType).equals(cls.getName()))
- return true;
-
- Set<Class<?>> types = CONVERTABLE_TYPES.get(colType);
-
- return types != null && types.contains(cls);
- }
-
/**
* Wraps object to respective {@link Value}.
*
- * Note, implicit type conversions must be also included into {@link
#CONVERTABLE_TYPES}.
*
* @param obj Object.
* @param type Value type.
* @return Value.
* @throws IgniteCheckedException If failed.
- * @see #isConvertableToColumnType(Class, int)
*/
@SuppressWarnings("ConstantConditions")
public static Value wrap(CacheObjectValueContext coCtx, Object obj, int
type) throws IgniteCheckedException {
diff --git
a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
index dbf55a4aef2..7b700a776c1 100644
---
a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
+++
b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
@@ -153,7 +153,6 @@ import org.h2.api.ErrorCode;
import org.h2.api.JavaObjectSerializer;
import org.h2.engine.Session;
import org.h2.engine.SysProperties;
-import org.h2.message.DbException;
import org.h2.util.JdbcUtils;
import org.h2.value.CompareMode;
import org.jetbrains.annotations.Nullable;
@@ -1805,22 +1804,6 @@ public class IgniteH2Indexing implements
GridQueryIndexing {
);
}
- /** {@inheritDoc} */
- @Override public boolean isConvertibleToColumnType(String schemaName,
String tblName, String colName, Class<?> cls) {
- GridH2Table table = schemaMgr.dataTable(schemaName, tblName);
-
- if (table == null)
- throw new IgniteSQLException("Table was not found [schemaName=" +
schemaName + ", tableName=" + tblName + ']');
-
- try {
- return H2Utils.isConvertableToColumnType(cls,
table.getColumn(colName).getType());
- }
- catch (DbException e) {
- throw new IgniteSQLException("Colum with specified name was not
found for the table [schemaName=" + schemaName +
- ", tableName=" + tblName + ", colName=" + colName + ']', e);
- }
- }
-
/** {@inheritDoc} */
@Override public boolean isStreamableInsertStatement(String schemaName,
SqlFieldsQuery qry) throws SQLException {
QueryParserResult parsed = parser.parse(schemaName, qry, true);
diff --git
a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/H2ColumnTypeConversionCheckSelfTest.java
b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/H2ColumnTypeConversionCheckSelfTest.java
deleted file mode 100644
index ed73d1edc7b..00000000000
---
a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/H2ColumnTypeConversionCheckSelfTest.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.ignite.internal.processors.query.h2;
-
-import java.sql.Timestamp;
-import java.time.LocalDate;
-import java.time.LocalDateTime;
-import java.time.LocalTime;
-import org.apache.ignite.cache.query.SqlFieldsQuery;
-import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
-import org.junit.Test;
-
-/** */
-public class H2ColumnTypeConversionCheckSelfTest extends
GridCommonAbstractTest {
- /** */
- @Test
- public void testConversions() throws Exception {
- startGrid(0);
-
- grid(0).context().query().querySqlFields(
- new SqlFieldsQuery("CREATE TABLE TBL (id INT PRIMARY KEY,
timestamp TIMESTAMP, date DATE, time TIME)"), false);
-
- assertTrue(isConvertible("TIMESTAMP", Timestamp.class));
- assertTrue(isConvertible("TIMESTAMP", java.sql.Date.class));
- assertTrue(isConvertible("TIMESTAMP", java.util.Date.class));
- assertTrue(isConvertible("TIMESTAMP", LocalDateTime.class));
- assertFalse(isConvertible("TIMESTAMP", Integer.class));
-
- assertTrue(isConvertible("DATE", java.sql.Date.class));
- assertTrue(isConvertible("DATE", LocalDate.class));
- assertFalse(isConvertible("DATE", Integer.class));
-
- assertTrue(isConvertible("TIME", java.sql.Time.class));
- assertTrue(isConvertible("TIME", LocalTime.class));
- assertFalse(isConvertible("TIME", Integer.class));
- }
-
- /** */
- private boolean isConvertible(String colName, Class<?> cls) {
- return
grid(0).context().query().getIndexing().isConvertibleToColumnType("PUBLIC",
"TBL", colName, cls);
- }
-}
diff --git
a/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteBinaryCacheQueryTestSuite3.java
b/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteBinaryCacheQueryTestSuite3.java
index f5f95b6c64a..93eefe1bf72 100644
---
a/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteBinaryCacheQueryTestSuite3.java
+++
b/modules/indexing/src/test/java/org/apache/ignite/testsuites/IgniteBinaryCacheQueryTestSuite3.java
@@ -136,7 +136,6 @@ import
org.apache.ignite.internal.processors.query.SqlQueryIndexWithDifferentTyp
import org.apache.ignite.internal.processors.query.SqlSystemViewsSelfTest;
import org.apache.ignite.internal.processors.query.h2.GridIndexRebuildSelfTest;
import org.apache.ignite.internal.processors.query.h2.GridIndexRebuildTest;
-import
org.apache.ignite.internal.processors.query.h2.H2ColumnTypeConversionCheckSelfTest;
import
org.apache.ignite.internal.processors.query.h2.QueryParserMetricsHolderSelfTest;
import
org.apache.ignite.internal.processors.query.h2.RowCountTableStatisticsSurvivesNodeRestartTest;
import
org.apache.ignite.internal.processors.query.h2.RowCountTableStatisticsUsageTest;
@@ -372,7 +371,6 @@ import org.junit.runners.Suite;
InlineIndexKeyTypeRegistryTest.class,
IgniteQueryConvertibleTypesValidationTest.class,
- H2ColumnTypeConversionCheckSelfTest.class,
IgniteStatisticsTestSuite.class,