This is an automated email from the ASF dual-hosted git repository. amashenkov pushed a commit to branch ignite-17203 in repository https://gitbox.apache.org/repos/asf/ignite-3.git
The following commit(s) were added to refs/heads/ignite-17203 by this push: new 461eb4b20 Fix type conversion. 461eb4b20 is described below commit 461eb4b2048f56efe19c8b1268d83fd0bec755e0 Author: Andrew V. Mashenkov <andrey.mashen...@gmail.com> AuthorDate: Fri Jul 1 15:18:11 2022 +0300 Fix type conversion. --- .../ignite/schema/definition/ColumnType.java | 38 +++++++--- .../ignite/internal/sql/engine/ItMetadataTest.java | 74 ++++++++++---------- .../apache/ignite/internal/schema/NativeTypes.java | 6 +- .../ignite/internal/schema/TemporalNativeType.java | 3 +- .../SchemaConfigurationConverter.java | 56 --------------- .../ignite/internal/schema/NativeTypeTest.java | 17 +++-- .../ignite/internal/schema/TemporalTypesTest.java | 4 +- .../sql/engine/exec/ddl/DdlCommandHandler.java | 9 +-- .../sql/engine/type/IgniteTypeFactory.java | 80 ++++++++++++++++------ .../internal/sql/engine/type/IgniteTypeSystem.java | 58 +++++++++++++++- .../internal/table/MutableRowTupleAdapterTest.java | 14 ++-- 11 files changed, 202 insertions(+), 157 deletions(-) diff --git a/modules/api/src/main/java/org/apache/ignite/schema/definition/ColumnType.java b/modules/api/src/main/java/org/apache/ignite/schema/definition/ColumnType.java index 47b7747fb..13f9d3633 100644 --- a/modules/api/src/main/java/org/apache/ignite/schema/definition/ColumnType.java +++ b/modules/api/src/main/java/org/apache/ignite/schema/definition/ColumnType.java @@ -175,14 +175,14 @@ public class ColumnType { /** * Returns timezone-free type representing a time of day in hours, minutes, seconds, and fractional seconds with the default precision - * of 6 (microseconds). + * of 0 (seconds). * * @return Native type. - * @see TemporalColumnType#DEFAULT_PRECISION + * @see TemporalColumnType#DEFAULT_TIME_PRECISION * @see #time(int) */ public static TemporalColumnType time() { - return new TemporalColumnType(ColumnTypeSpec.TIME, TemporalColumnType.DEFAULT_PRECISION); + return new TemporalColumnType(ColumnTypeSpec.TIME, TemporalColumnType.DEFAULT_TIME_PRECISION); } /** @@ -203,14 +203,14 @@ public class ColumnType { } /** - * Returns timezone-free datetime encoded as (date, time) with the default time precision of 6 (microseconds). + * Returns timezone-free datetime encoded as (date, time) with the default time precision of 0 (seconds). * * @return Native type. - * @see TemporalColumnType#DEFAULT_PRECISION + * @see TemporalColumnType#DEFAULT_TIME_PRECISION * @see #datetime(int) */ public static TemporalColumnType datetime() { - return new TemporalColumnType(ColumnTypeSpec.DATETIME, TemporalColumnType.DEFAULT_PRECISION); + return new TemporalColumnType(ColumnTypeSpec.DATETIME, TemporalColumnType.DEFAULT_TIME_PRECISION); } /** @@ -236,11 +236,11 @@ public class ColumnType { * (microseconds). * * @return Native type. - * @see TemporalColumnType#DEFAULT_PRECISION + * @see TemporalColumnType#DEFAULT_TIMESTAMP_PRECISION * @see #timestamp(int) */ public static TemporalColumnType timestamp() { - return new TemporalColumnType(ColumnTypeSpec.TIMESTAMP, TemporalColumnType.DEFAULT_PRECISION); + return new TemporalColumnType(ColumnTypeSpec.TIMESTAMP, TemporalColumnType.DEFAULT_TIMESTAMP_PRECISION); } /** @@ -460,8 +460,26 @@ public class ColumnType { * Column type of variable length. */ public static class TemporalColumnType extends ColumnType { - /** Default temporal type precision: microseconds. */ - public static final int DEFAULT_PRECISION = 6; + /** + * Default TIME type precision: microseconds. + * + * SQL99 part 2 section 6.1 syntax rule 30 + */ + public static final int DEFAULT_TIMESTAMP_PRECISION = 6; + + /** + * Default TIMESTAMP type precision: seconds. + * + * SQL99 part 2 section 6.1 syntax rule 30 + */ + public static final int DEFAULT_TIME_PRECISION = 0; + + /** + * Max TIME precision. + * + * SQL99 part 2 section 6.1 syntax rule 31 + */ + public static final int MAX_TIME_PRECISION = 9; /** Fractional seconds precision. */ private final int precision; diff --git a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItMetadataTest.java b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItMetadataTest.java index 07d30ca0f..40821f874 100644 --- a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItMetadataTest.java +++ b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItMetadataTest.java @@ -129,11 +129,11 @@ public class ItMetadataTest extends AbstractBasicIntegrationTest { + "INT_C INT, " + "LONG_C BIGINT, " + "NUMBER_C NUMERIC, " - + "NUMBER_C2 NUMERIC(5), " - + "NUMBER_C3 NUMERIC(10,3), " + + "NUMBER_C2 NUMERIC(38), " + + "NUMBER_C3 NUMERIC(38,37), " + "DECIMAL_C DECIMAL, " - + "DECIMAL_C2 DECIMAL(5), " - + "DECIMAL_C3 DECIMAL(10,3), " + + "DECIMAL_C2 DECIMAL(38), " + + "DECIMAL_C3 DECIMAL(38,37), " // Approximate numeric types + "FLOAT_C FLOAT, " @@ -143,7 +143,7 @@ public class ItMetadataTest extends AbstractBasicIntegrationTest { // Character string types + "CHAR_C CHAR, " - + "CHAR_C2 CHAR(125), " + + "CHAR_C2 CHAR(65536), " + "VARCHAR_C VARCHAR, " + "VARCHAR_C2 VARCHAR(125), " @@ -152,9 +152,9 @@ public class ItMetadataTest extends AbstractBasicIntegrationTest { // + "BIT_C2 BIT(10), " // TODO: from ANSI`92. Not supported by Calcite parser. // + "BIT_C3 BIT VARYING(10), " // TODO: from ANSI`92. Not supported by Calcite parser. + "BINARY_C BINARY, " // Added in ANSI`99 - + "BINARY_C2 BINARY(80), " + + "BINARY_C2 BINARY(65536), " // + "VARBINARY_C VARBINARY, " // TODO: from ANSI`99. Not supported by Calcite parser. -// + "VARBINARY_C2 VARBINARY(80) " // TODO: from ANSI`99. Not supported by Calcite parser. +// + "VARBINARY_C2 VARBINARY(125) " // TODO: from ANSI`99. Not supported by Calcite parser. // Datetime types + "DATE_C DATE, " @@ -164,12 +164,12 @@ public class ItMetadataTest extends AbstractBasicIntegrationTest { + "TIME_LTZ_C2 TIME(9) WITH LOCAL TIME ZONE, " // Not part of any standard // + "TIME_TZ_C TIME WITH TIMEZONE, " // TODO: from ANSI`92. Not supported by Calcite parser. // + "TIME_TZ_C2 TIME(9) WITH TIMEZONE, " // TODO: from ANSI`92. Not supported by Calcite parser. - + "TIMESTAMP_C TIMESTAMP, " - + "TIMESTAMP_C2 TIMESTAMP(9), " - + "TIMESTAMP_LTZ_C TIMESTAMP WITH LOCAL TIME ZONE, " // Not part of any standard - + "TIMESTAMP_LTZ_C2 TIMESTAMP(9) WITH LOCAL TIME ZONE, " // Not part of any standard -// + "TIMESTAMP_TZ_C TIMESTAMP WITH TIME ZONE, " // TODO: from ANSI`92. Not supported by Calcite parser. -// + "TIMESTAMP_TZ_C2 TIMESTAMP(9) WITH TIME ZONE, " // TODO: from ANSI`92. Not supported by Calcite parser. + + "DATETIME_C TIMESTAMP, " + + "DATETIME_C2 TIMESTAMP(9), " + + "TIMESTAMP_C TIMESTAMP WITH LOCAL TIME ZONE, " // Not part of any standard + + "TIMESTAMP_C2 TIMESTAMP(9) WITH LOCAL TIME ZONE, " // Not part of any standard +// + "TIMESTAMP_C TIMESTAMP WITH TIME ZONE, " // TODO: from ANSI`92. Not supported by Calcite parser. +// + "TIMESTAMP_C2 TIMESTAMP(9) WITH TIME ZONE, " // TODO: from ANSI`92. Not supported by Calcite parser. // Interval types // TODO: Ignite doesn't support interval types. @@ -193,56 +193,54 @@ public class ItMetadataTest extends AbstractBasicIntegrationTest { assertQuery("select * from metadata_table") .columnMetadata( new MetadataMatcher().name("ID").nullable(false), -// new MetadataMatcher().name("BOOLEAN_C") +// new MetadataMatcher().name("BOOLEAN_C"), // Exact numeric types new MetadataMatcher().name("TINY_C").type(SqlColumnType.INT8).precision(3).scale(0), new MetadataMatcher().name("SMALL_C").type(SqlColumnType.INT16).precision(5).scale(0), new MetadataMatcher().name("INT_C").type(SqlColumnType.INT32).precision(10).scale(0), new MetadataMatcher().name("LONG_C").type(SqlColumnType.INT64).precision(19).scale(0), - new MetadataMatcher().name("NUMBER_C").type(SqlColumnType.DECIMAL).precision(0x7FFF).scale(0), - new MetadataMatcher().name("NUMBER_C2").type(SqlColumnType.DECIMAL).precision(5).scale(0), - new MetadataMatcher().name("NUMBER_C3").type(SqlColumnType.DECIMAL).precision(10).scale(3), + new MetadataMatcher().name("NUMBER_C").type(SqlColumnType.DECIMAL).precision(0x7FFF).scale(0), + new MetadataMatcher().name("NUMBER_C2").type(SqlColumnType.DECIMAL).precision(38).scale(0), + new MetadataMatcher().name("NUMBER_C3").type(SqlColumnType.DECIMAL).precision(38).scale(37), new MetadataMatcher().name("DECIMAL_C").type(SqlColumnType.DECIMAL).precision(0x7FFF).scale(0), - new MetadataMatcher().name("DECIMAL_C2").type(SqlColumnType.DECIMAL).precision(5).scale(0), - new MetadataMatcher().name("DECIMAL_C3").type(SqlColumnType.DECIMAL).precision(10).scale(3), + new MetadataMatcher().name("DECIMAL_C2").type(SqlColumnType.DECIMAL).precision(38).scale(0), + new MetadataMatcher().name("DECIMAL_C3").type(SqlColumnType.DECIMAL).precision(38).scale(37), // Approximate numeric types new MetadataMatcher().name("FLOAT_C").type(SqlColumnType.FLOAT).precision(7).scale(UNDEFINED_SCALE), -// new MetadataMatcher().name("FLOAT_C2").precision(4).scale(ColumnMetadata.UNDEFINED_SCALE), +// new MetadataMatcher().name("FLOAT_C2").precision(4).scale(ColumnMetadata.UNDEFINED_SCALE), new MetadataMatcher().name("REAL_C").type(SqlColumnType.FLOAT).precision(7).scale(UNDEFINED_SCALE), new MetadataMatcher().name("DOUBLE_C").type(SqlColumnType.DOUBLE).precision(15).scale(UNDEFINED_SCALE), // Character string types new MetadataMatcher().name("CHAR_C").type(SqlColumnType.STRING).precision(1).scale(UNDEFINED_SCALE), - new MetadataMatcher().name("CHAR_C2").type(SqlColumnType.STRING).precision(125).scale(UNDEFINED_SCALE), - new MetadataMatcher().name("VARCHAR_C").type(SqlColumnType.STRING).precision(2 << 15).scale(UNDEFINED_SCALE), + new MetadataMatcher().name("CHAR_C2").type(SqlColumnType.STRING).precision(65536).scale(UNDEFINED_SCALE), + new MetadataMatcher().name("VARCHAR_C").type(SqlColumnType.STRING).precision(65536).scale(UNDEFINED_SCALE), new MetadataMatcher().name("VARCHAR_C2").type(SqlColumnType.STRING).precision(125).scale(UNDEFINED_SCALE), // Binary string types -// new MetadataMatcher().name("BIT_C"), -// new MetadataMatcher().name("BIT_C2"), -// new MetadataMatcher().name("BIT_C3"), +// new MetadataMatcher().name("BIT_C"), +// new MetadataMatcher().name("BIT_C2"), +// new MetadataMatcher().name("BIT_C3"), new MetadataMatcher().name("BINARY_C").type(SqlColumnType.BYTE_ARRAY).precision(1).scale(UNDEFINED_SCALE), - new MetadataMatcher().name("BINARY_C2").type(SqlColumnType.BYTE_ARRAY).precision(80).scale(UNDEFINED_SCALE), -// new MetadataMatcher().name("VARBINARY_C"), -// new MetadataMatcher().name("VARBINARY_C2"), + new MetadataMatcher().name("BINARY_C2").type(SqlColumnType.BYTE_ARRAY).precision(65536).scale(UNDEFINED_SCALE), +// new MetadataMatcher().name("VARBINARY_C").type(SqlColumnType.BYTE_ARRAY).precision(65536).scale(UNDEFINED_SCALE), +// new MetadataMatcher().name("VARBINARY_C2").type(SqlColumnType.BYTE_ARRAY).precision(125).scale(UNDEFINED_SCALE), // Datetime types new MetadataMatcher().name("DATE_C").type(SqlColumnType.DATE).precision(0).scale(UNDEFINED_SCALE), - new MetadataMatcher().name("TIME_C").type(SqlColumnType.TIME).precision(3).scale(UNDEFINED_SCALE), - // TODO: Add IGNITE dialect to support time/timestamp precision > 3 - new MetadataMatcher().name("TIME_C2").type(SqlColumnType.TIME)/*.precision(9)*/.scale(UNDEFINED_SCALE), - new MetadataMatcher().name("TIME_LTZ_C").type(SqlColumnType.TIME).precision(3).scale(UNDEFINED_SCALE), - new MetadataMatcher().name("TIME_LTZ_C2").type(SqlColumnType.TIME)/*.precision(9)*/.scale(UNDEFINED_SCALE), + new MetadataMatcher().name("TIME_C").type(SqlColumnType.TIME).precision(0).scale(UNDEFINED_SCALE), + new MetadataMatcher().name("TIME_C2").type(SqlColumnType.TIME).precision(9).scale(UNDEFINED_SCALE), + new MetadataMatcher().name("TIME_LTZ_C").type(SqlColumnType.TIME).precision(0).scale(UNDEFINED_SCALE), + new MetadataMatcher().name("TIME_LTZ_C2").type(SqlColumnType.TIME).precision(9).scale(UNDEFINED_SCALE), // new MetadataMatcher().name("TIME_TZ_C").type(SqlColumnType.TIME), // new MetadataMatcher().name("TIME_TZ_C2").type(SqlColumnType.TIME), - new MetadataMatcher().name("TIMESTAMP_C").type(SqlColumnType.DATETIME).precision(3).scale(UNDEFINED_SCALE), - new MetadataMatcher().name("TIMESTAMP_C2").type(SqlColumnType.DATETIME)/*.precision(9)*/.scale(UNDEFINED_SCALE), - new MetadataMatcher().name("TIMESTAMP_LTZ_C").type(SqlColumnType.TIMESTAMP).precision(3).scale(UNDEFINED_SCALE), - new MetadataMatcher().name("TIMESTAMP_LTZ_C2").type(SqlColumnType.TIMESTAMP)/*.precision(9)*/.scale( - UNDEFINED_SCALE), + new MetadataMatcher().name("DATETIME_C").type(SqlColumnType.DATETIME).precision(0).scale(UNDEFINED_SCALE), + new MetadataMatcher().name("DATETIME_C2").type(SqlColumnType.DATETIME).precision(9).scale(UNDEFINED_SCALE), + new MetadataMatcher().name("TIMESTAMP_C").type(SqlColumnType.TIMESTAMP).precision(6).scale(UNDEFINED_SCALE), + new MetadataMatcher().name("TIMESTAMP_C2").type(SqlColumnType.TIMESTAMP).precision(9).scale(UNDEFINED_SCALE), // new MetadataMatcher().name("TIMESTAMP_TZ_C").type(SqlColumnType.TIMESTAMP), // new MetadataMatcher().name("TIMESTAMP_TZ_C2").type(SqlColumnType.TIMESTAMP), diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/NativeTypes.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/NativeTypes.java index 916b05aba..36840ad96 100644 --- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/NativeTypes.java +++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/NativeTypes.java @@ -147,7 +147,7 @@ public class NativeTypes { * @see #time(int) */ public static NativeType time() { - return TemporalNativeType.time(ColumnType.TemporalColumnType.DEFAULT_PRECISION); + return TemporalNativeType.time(ColumnType.TemporalColumnType.DEFAULT_TIME_PRECISION); } /** @@ -167,7 +167,7 @@ public class NativeTypes { * @see #datetime(int) */ public static NativeType datetime() { - return TemporalNativeType.datetime(ColumnType.TemporalColumnType.DEFAULT_PRECISION); + return TemporalNativeType.datetime(ColumnType.TemporalColumnType.DEFAULT_TIME_PRECISION); } /** @@ -187,7 +187,7 @@ public class NativeTypes { * @see #timestamp(int) */ public static NativeType timestamp() { - return TemporalNativeType.timestamp(ColumnType.TemporalColumnType.DEFAULT_PRECISION); + return TemporalNativeType.timestamp(ColumnType.TemporalColumnType.DEFAULT_TIMESTAMP_PRECISION); } /** diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/TemporalNativeType.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/TemporalNativeType.java index 011b37f9b..e249bf06b 100644 --- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/TemporalNativeType.java +++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/TemporalNativeType.java @@ -18,6 +18,7 @@ package org.apache.ignite.internal.schema; import org.apache.ignite.internal.tostring.S; +import org.apache.ignite.schema.definition.ColumnType.TemporalColumnType; /** * Temporal native type. @@ -71,7 +72,7 @@ public class TemporalNativeType extends NativeType { private TemporalNativeType(NativeTypeSpec typeSpec, int size, int precision) { super(typeSpec, size); - if (precision < 0 || precision > 9) { + if (precision < 0 || precision > TemporalColumnType.MAX_TIME_PRECISION) { throw new IllegalArgumentException("Unsupported fractional seconds precision: " + precision); } diff --git a/modules/schema/src/main/java/org/apache/ignite/internal/schema/configuration/SchemaConfigurationConverter.java b/modules/schema/src/main/java/org/apache/ignite/internal/schema/configuration/SchemaConfigurationConverter.java index 7dee7e71c..a9444b6dc 100644 --- a/modules/schema/src/main/java/org/apache/ignite/internal/schema/configuration/SchemaConfigurationConverter.java +++ b/modules/schema/src/main/java/org/apache/ignite/internal/schema/configuration/SchemaConfigurationConverter.java @@ -516,60 +516,4 @@ public class SchemaConfigurationConverter { public static TableChange dropColumn(String columnName, TableChange tblChange) { return tblChange.changeColumns(colChg -> colChg.delete(columnName)); } - - /** - * Gets ColumnType type for given class. - * - * @param cls Class. - * @return ColumnType type or null. - */ - public static ColumnType columnType(Class<?> cls) { - assert cls != null; - - // Primitives. - if (cls == byte.class) { - return ColumnType.INT8; - } else if (cls == short.class) { - return ColumnType.INT16; - } else if (cls == int.class) { - return ColumnType.INT32; - } else if (cls == long.class) { - return ColumnType.INT64; - } else if (cls == float.class) { - return ColumnType.FLOAT; - } else if (cls == double.class) { - return ColumnType.DOUBLE; - } else if (cls == Byte.class) { // Boxed primitives. - return ColumnType.INT8; - } else if (cls == Short.class) { - return ColumnType.INT16; - } else if (cls == Integer.class) { - return ColumnType.INT32; - } else if (cls == Long.class) { - return ColumnType.INT64; - } else if (cls == Float.class) { - return ColumnType.FLOAT; - } else if (cls == Double.class) { - return ColumnType.DOUBLE; - } else if (cls == LocalDate.class) { // Temporal types. - return ColumnType.DATE; - } else if (cls == LocalTime.class) { - return ColumnType.time(ColumnType.TemporalColumnType.DEFAULT_PRECISION); - } else if (cls == LocalDateTime.class) { - return ColumnType.datetime(ColumnType.TemporalColumnType.DEFAULT_PRECISION); - } else if (cls == Instant.class) { - return ColumnType.timestamp(ColumnType.TemporalColumnType.DEFAULT_PRECISION); - } else if (cls == String.class) { // Other types - return ColumnType.string(); - } else if (cls == UUID.class) { - return ColumnType.UUID; - } else if (cls == BigInteger.class) { - return ColumnType.numberOf(); - } else if (cls == BigDecimal.class) { - return ColumnType.decimalOf(); - } - - throw new IllegalArgumentException("Type " + cls.getName() + " is not supported."); - } - } diff --git a/modules/schema/src/test/java/org/apache/ignite/internal/schema/NativeTypeTest.java b/modules/schema/src/test/java/org/apache/ignite/internal/schema/NativeTypeTest.java index 4855787e3..5e1c24662 100644 --- a/modules/schema/src/test/java/org/apache/ignite/internal/schema/NativeTypeTest.java +++ b/modules/schema/src/test/java/org/apache/ignite/internal/schema/NativeTypeTest.java @@ -105,20 +105,19 @@ public class NativeTypeTest { } /** - * ValidateTemporalTypesLength. - * TODO Documentation https://issues.apache.org/jira/browse/IGNITE-15859 + * Validate data size of datetime types. */ @Test public void validateTemporalTypesLength() { assertEquals(3, DATE.sizeInBytes()); - assertEquals(6, time().sizeInBytes()); + assertEquals(4, time().sizeInBytes()); assertEquals(4, time(0).sizeInBytes()); assertEquals(4, time(3).sizeInBytes()); assertEquals(6, time(4).sizeInBytes()); assertEquals(6, time(9).sizeInBytes()); - assertEquals(9, datetime().sizeInBytes()); + assertEquals(7, datetime().sizeInBytes()); assertEquals(7, datetime(0).sizeInBytes()); assertEquals(7, datetime(3).sizeInBytes()); assertEquals(9, datetime(4).sizeInBytes()); @@ -129,8 +128,8 @@ public class NativeTypeTest { assertEquals(12, timestamp(1).sizeInBytes()); assertEquals(12, timestamp(9).sizeInBytes()); - assertEquals(0, datetime().compareTo(datetime(6))); - assertEquals(0, time().compareTo(time(6))); + assertEquals(0, datetime().compareTo(datetime(0))); + assertEquals(0, time().compareTo(time(0))); assertEquals(0, timestamp().compareTo(timestamp(6))); } @@ -174,9 +173,9 @@ public class NativeTypeTest { assertEquals(BYTES, from(ColumnType.blobOf())); assertEquals(STRING, from(ColumnType.string())); - assertEquals(time(), from(ColumnType.time(ColumnType.TemporalColumnType.DEFAULT_PRECISION))); - assertEquals(datetime(), from(ColumnType.datetime(ColumnType.TemporalColumnType.DEFAULT_PRECISION))); - assertEquals(timestamp(), from(ColumnType.timestamp(ColumnType.TemporalColumnType.DEFAULT_PRECISION))); + assertEquals(time(), from(ColumnType.time(ColumnType.TemporalColumnType.DEFAULT_TIME_PRECISION))); + assertEquals(datetime(), from(ColumnType.datetime(ColumnType.TemporalColumnType.DEFAULT_TIME_PRECISION))); + assertEquals(timestamp(), from(ColumnType.timestamp(ColumnType.TemporalColumnType.DEFAULT_TIMESTAMP_PRECISION))); for (int i = 1; i < 800; i += 100) { assertEquals(blobOf(i), from(ColumnType.blobOf(i))); diff --git a/modules/schema/src/test/java/org/apache/ignite/internal/schema/TemporalTypesTest.java b/modules/schema/src/test/java/org/apache/ignite/internal/schema/TemporalTypesTest.java index db5f83b9a..423480ef4 100644 --- a/modules/schema/src/test/java/org/apache/ignite/internal/schema/TemporalTypesTest.java +++ b/modules/schema/src/test/java/org/apache/ignite/internal/schema/TemporalTypesTest.java @@ -60,11 +60,11 @@ public class TemporalTypesTest { checkTime(TemporalNativeType.time(i), LocalTime.MIN); } - checkTime(TemporalNativeType.time(ColumnType.TemporalColumnType.DEFAULT_PRECISION), LocalTime.MAX.truncatedTo(ChronoUnit.MICROS)); + checkTime(TemporalNativeType.time(ColumnType.TemporalColumnType.DEFAULT_TIME_PRECISION), LocalTime.MAX.truncatedTo(ChronoUnit.SECONDS)); checkTime(TemporalNativeType.time(9), LocalTime.MAX); assertThrows(AssertionError.class, - () -> checkTime(TemporalNativeType.time(ColumnType.TemporalColumnType.DEFAULT_PRECISION), LocalTime.MAX)); + () -> checkTime(TemporalNativeType.time(ColumnType.TemporalColumnType.DEFAULT_TIME_PRECISION), LocalTime.MAX)); assertThrows(AssertionError.class, () -> checkTime(TemporalNativeType.time(0), LocalTime.MAX)); assertThrows(AssertionError.class, () -> checkTime(TemporalNativeType.time(8), LocalTime.MAX)); } diff --git a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/ddl/DdlCommandHandler.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/ddl/DdlCommandHandler.java index 64af405e7..b95f845d5 100644 --- a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/ddl/DdlCommandHandler.java +++ b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/ddl/DdlCommandHandler.java @@ -44,7 +44,6 @@ import org.apache.ignite.internal.sql.engine.prepare.ddl.DdlCommand; import org.apache.ignite.internal.sql.engine.prepare.ddl.DropIndexCommand; import org.apache.ignite.internal.sql.engine.prepare.ddl.DropTableCommand; import org.apache.ignite.internal.sql.engine.type.IgniteTypeFactory; -import org.apache.ignite.internal.sql.engine.util.Commons; import org.apache.ignite.internal.storage.DataStorageManager; import org.apache.ignite.internal.table.distributed.TableManager; import org.apache.ignite.internal.util.IgniteObjectName; @@ -122,14 +121,12 @@ public class DdlCommandHandler { pkeyDef.withColumns(IgniteObjectName.quoteNames(cmd.primaryKeyColumns())); pkeyDef.withColocationColumns(IgniteObjectName.quoteNames(cmd.colocationColumns())); - final IgniteTypeFactory typeFactory = Commons.typeFactory(); - final List<org.apache.ignite.schema.definition.ColumnDefinition> colsInner = new ArrayList<>(); for (ColumnDefinition col : cmd.columns()) { ColumnDefinitionBuilder col0 = SchemaBuilders.column( IgniteObjectName.quote(col.name()), - typeFactory.columnType(col.type()) + IgniteTypeFactory.relDataTypeToColumnType(col.type()) ) .asNullable(col.nullable()) .withDefaultValueExpression(col.defaultValue()); @@ -320,12 +317,10 @@ public class DdlCommandHandler { }).collect(Collectors.toList()); } - final IgniteTypeFactory typeFactory = Commons.typeFactory(); - for (ColumnDefinition col : colsDef0) { ColumnDefinitionBuilder col0 = SchemaBuilders.column( IgniteObjectName.quote(col.name()), - typeFactory.columnType(col.type()) + IgniteTypeFactory.relDataTypeToColumnType(col.type()) ) .asNullable(col.nullable()) .withDefaultValueExpression(col.defaultValue()); diff --git a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/type/IgniteTypeFactory.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/type/IgniteTypeFactory.java index 893515d53..423af903b 100644 --- a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/type/IgniteTypeFactory.java +++ b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/type/IgniteTypeFactory.java @@ -22,7 +22,6 @@ import static org.apache.ignite.internal.util.CollectionUtils.first; import java.lang.reflect.Type; import java.math.BigDecimal; -import java.math.BigInteger; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.time.Duration; @@ -45,7 +44,6 @@ 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.ignite.internal.schema.configuration.SchemaConfigurationConverter; import org.apache.ignite.schema.definition.ColumnType; /** @@ -163,30 +161,72 @@ public class IgniteTypeFactory extends JavaTypeFactoryImpl { } /** - * Gets ColumnType type for given class. + * Gets ColumnType type for RelDataType class. * * @param relType Rel type. * @return ColumnType type or null. */ - public ColumnType columnType(RelDataType relType) { + public static ColumnType relDataTypeToColumnType(RelDataType relType) { assert relType != null; + assert relType instanceof BasicSqlType + || relType instanceof IntervalSqlType : "Not supported yet."; // Implement Class->ColumnType mapping if failed. - Type javaType = getResultClass(relType); - - if (javaType == byte[].class) { - return relType.getPrecision() == PRECISION_NOT_SPECIFIED ? ColumnType.blobOf() : - ColumnType.blobOf(relType.getPrecision()); - } else if (javaType == String.class) { - return relType.getPrecision() == PRECISION_NOT_SPECIFIED ? ColumnType.string() : - ColumnType.stringOf(relType.getPrecision()); - } else if (javaType == BigInteger.class) { - return relType.getPrecision() == PRECISION_NOT_SPECIFIED ? ColumnType.numberOf() : - ColumnType.numberOf(relType.getPrecision()); - } else if (javaType == BigDecimal.class) { - return relType.getPrecision() == PRECISION_NOT_SPECIFIED ? ColumnType.decimalOf() : - ColumnType.decimalOf(relType.getPrecision(), relType.getScale()); - } else { - return SchemaConfigurationConverter.columnType((Class<?>) javaType); + switch (relType.getSqlTypeName()) { + case BOOLEAN: + throw new IllegalArgumentException("Type is not supported yet."); + case TINYINT: + return ColumnType.INT8; + case SMALLINT: + return ColumnType.INT16; + case INTEGER: + return ColumnType.INT32; + case BIGINT: + return ColumnType.INT64; + case DECIMAL: + return relType.getPrecision() == PRECISION_NOT_SPECIFIED ? ColumnType.decimalOf() : + ColumnType.decimalOf(relType.getPrecision(), relType.getScale()); + case FLOAT: + case REAL: + return ColumnType.FLOAT; + case DOUBLE: + return ColumnType.DOUBLE; + case DATE: + return ColumnType.DATE; + case TIME: + case TIME_WITH_LOCAL_TIME_ZONE: + return relType.getPrecision() == PRECISION_NOT_SPECIFIED ? ColumnType.time() : + ColumnType.time(relType.getPrecision()); + case TIMESTAMP: + return relType.getPrecision() == PRECISION_NOT_SPECIFIED ? ColumnType.datetime() : + ColumnType.datetime(relType.getPrecision()); + case TIMESTAMP_WITH_LOCAL_TIME_ZONE: + return relType.getPrecision() == PRECISION_NOT_SPECIFIED ? ColumnType.timestamp() : + ColumnType.timestamp(relType.getPrecision()); + case INTERVAL_YEAR: + case INTERVAL_YEAR_MONTH: + case INTERVAL_MONTH: + throw new IllegalArgumentException("Type is not supported yet."); + case INTERVAL_DAY: + case INTERVAL_DAY_HOUR: + case INTERVAL_DAY_MINUTE: + case INTERVAL_DAY_SECOND: + case INTERVAL_HOUR: + case INTERVAL_HOUR_MINUTE: + case INTERVAL_HOUR_SECOND: + case INTERVAL_MINUTE: + case INTERVAL_MINUTE_SECOND: + case INTERVAL_SECOND: + throw new IllegalArgumentException("Type is not supported yet."); + case VARCHAR: + case CHAR: + return relType.getPrecision() == PRECISION_NOT_SPECIFIED ? ColumnType.string() : + ColumnType.stringOf(relType.getPrecision()); + case BINARY: + case VARBINARY: + return relType.getPrecision() == PRECISION_NOT_SPECIFIED ? ColumnType.blobOf() : + ColumnType.blobOf(relType.getPrecision()); + default: + throw new IllegalArgumentException("Type is not supported yet."); } } diff --git a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/type/IgniteTypeSystem.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/type/IgniteTypeSystem.java index f65f74a58..86d8344c4 100644 --- a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/type/IgniteTypeSystem.java +++ b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/type/IgniteTypeSystem.java @@ -25,6 +25,7 @@ import org.apache.calcite.rel.type.RelDataTypeSystem; import org.apache.calcite.rel.type.RelDataTypeSystemImpl; import org.apache.calcite.sql.type.BasicSqlType; import org.apache.calcite.sql.type.SqlTypeName; +import org.apache.ignite.schema.definition.ColumnType.TemporalColumnType; /** * Ignite type system. @@ -44,29 +45,80 @@ public class IgniteTypeSystem extends RelDataTypeSystemImpl implements Serializa return Short.MAX_VALUE; } + /** {@inheritDoc} */ + @Override + public int getMaxPrecision(SqlTypeName typeName) { + switch (typeName) { + case TIME: + case TIME_WITH_LOCAL_TIME_ZONE: + case TIMESTAMP: + case TIMESTAMP_WITH_LOCAL_TIME_ZONE: + return TemporalColumnType.MAX_TIME_PRECISION; + default: + return super.getMaxPrecision(typeName); + } + } + + /** {@inheritDoc} */ + @Override + public int getDefaultPrecision(SqlTypeName typeName) { + switch (typeName) { + case TIMESTAMP: // DATETIME + return TemporalColumnType.DEFAULT_TIME_PRECISION; + case TIMESTAMP_WITH_LOCAL_TIME_ZONE: // TIMESTAMP + return TemporalColumnType.DEFAULT_TIMESTAMP_PRECISION; + default: + return super.getDefaultPrecision(typeName); + } + } + /** {@inheritDoc} */ @Override public RelDataType deriveSumType(RelDataTypeFactory typeFactory, RelDataType argumentType) { RelDataType sumType; + // This method is used to derive types for aggregate functions only. + // We allow type widening for aggregates to prevent unwanted number overflow. + // + // SQL`99 part 2 section 9.3 syntax rule 3: + // Shortly, the standard says both, the return type and the argument type, must be of the same kind, + // but doesn't restrict them being exactly of the same type. if (argumentType instanceof BasicSqlType) { switch (argumentType.getSqlTypeName()) { case INTEGER: case TINYINT: case SMALLINT: - sumType = typeFactory.createSqlType(SqlTypeName.BIGINT); + sumType = typeFactory.createTypeWithNullability( + // TODO: can we cache the type? + typeFactory.createSqlType( + SqlTypeName.BIGINT, + typeFactory.getTypeSystem().getMaxPrecision(SqlTypeName.BIGINT), + typeFactory.getTypeSystem().getMaxScale(SqlTypeName.BIGINT) + ), argumentType.isNullable()); break; case BIGINT: case DECIMAL: - sumType = typeFactory.createSqlType(SqlTypeName.DECIMAL); + sumType = typeFactory.createTypeWithNullability( + // TODO: can we cache the type? + typeFactory.createSqlType( + SqlTypeName.DECIMAL, + typeFactory.getTypeSystem().getMaxPrecision(SqlTypeName.DECIMAL), + typeFactory.getTypeSystem().getMaxScale(SqlTypeName.DECIMAL) + ), argumentType.isNullable()); break; case REAL: case FLOAT: case DOUBLE: - sumType = typeFactory.createSqlType(SqlTypeName.DOUBLE); + sumType = typeFactory.createTypeWithNullability( + // TODO: can we cache the type? + typeFactory.createSqlType( + SqlTypeName.DOUBLE, + typeFactory.getTypeSystem().getMaxPrecision(SqlTypeName.DOUBLE), + typeFactory.getTypeSystem().getMaxScale(SqlTypeName.DOUBLE) + ), argumentType.isNullable()); break; diff --git a/modules/table/src/test/java/org/apache/ignite/internal/table/MutableRowTupleAdapterTest.java b/modules/table/src/test/java/org/apache/ignite/internal/table/MutableRowTupleAdapterTest.java index 04b3d25c7..dfcbbf9a0 100644 --- a/modules/table/src/test/java/org/apache/ignite/internal/table/MutableRowTupleAdapterTest.java +++ b/modules/table/src/test/java/org/apache/ignite/internal/table/MutableRowTupleAdapterTest.java @@ -543,18 +543,16 @@ public class MutableRowTupleAdapterTest { assertEquals(val1, val2); } - @SuppressWarnings("unchecked") private <T extends Temporal> T truncateToDefaultPrecision(T temporal) { - return (T) temporal.with(NANO_OF_SECOND, truncateToDefaultPrecision(temporal.get(NANO_OF_SECOND))); - } + int precision = temporal instanceof Instant ? ColumnType.TemporalColumnType.DEFAULT_TIMESTAMP_PRECISION + : ColumnType.TemporalColumnType.DEFAULT_TIME_PRECISION; - private int truncateToDefaultPrecision(int nanos) { - int factor = tailFactorForDefaultPrecision(); - return nanos / factor * factor; + return (T) temporal.with(NANO_OF_SECOND, + truncatePrecision(temporal.get(NANO_OF_SECOND), tailFactor(precision))); } - private int tailFactorForDefaultPrecision() { - return tailFactor(ColumnType.TemporalColumnType.DEFAULT_PRECISION); + private int truncatePrecision(int nanos, int factor) { + return nanos / factor * factor; } private int tailFactor(int precision) {