You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by am...@apache.org on 2022/06/30 14:15:21 UTC

[ignite-3] branch ignite-17203 updated: Add test.

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 b7aed5aa3 Add test.
b7aed5aa3 is described below

commit b7aed5aa36ec0b3b09020ab9dc970e274357115d
Author: Andrew V. Mashenkov <an...@gmail.com>
AuthorDate: Thu Jun 30 17:15:13 2022 +0300

    Add test.
---
 .../ignite/internal/sql/engine/ItMetadataTest.java | 159 ++++++++++++++++++
 .../internal/sql/engine/util/MetadataMatcher.java  | 185 +++++++++++++++++++++
 .../internal/sql/engine/util/QueryChecker.java     |  36 +++-
 .../ignite/internal/sql/engine/util/TypeUtils.java |  19 ++-
 4 files changed, 395 insertions(+), 4 deletions(-)

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 769c9853e..07d30ca0f 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
@@ -19,13 +19,16 @@ package org.apache.ignite.internal.sql.engine;
 
 import static java.util.stream.Collectors.joining;
 import static java.util.stream.Stream.generate;
+import static org.apache.ignite.sql.ColumnMetadata.UNDEFINED_SCALE;
 
 import java.time.Duration;
 import java.time.Period;
 import org.apache.ignite.internal.schema.configuration.SchemaConfigurationConverter;
+import org.apache.ignite.internal.sql.engine.util.MetadataMatcher;
 import org.apache.ignite.schema.SchemaBuilders;
 import org.apache.ignite.schema.definition.ColumnType;
 import org.apache.ignite.schema.definition.TableDefinition;
+import org.apache.ignite.sql.SqlColumnType;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Test;
@@ -42,6 +45,11 @@ public class ItMetadataTest extends AbstractBasicIntegrationTest {
         createAndPopulateTable();
     }
 
+    @Override
+    protected int nodes() {
+        return 1;
+    }
+
     @Test
     public void trimColumnNames() {
         String var300 = generate(() -> "X").limit(300).collect(joining());
@@ -107,4 +115,155 @@ public class ItMetadataTest extends AbstractBasicIntegrationTest {
                 .columnNames("DOUBLE_C", "LONG_C", "STRING_C", "INT_C")
                 .check();
     }
+
+    @Test
+    public void metadata() {
+        CLUSTER_NODES.get(0).sql().createSession()
+                .execute(null, "CREATE TABLE METADATA_TABLE ("
+                                + "ID INT PRIMARY KEY, "
+//                                + "BOOLEAN_C BOOLEAN, "  //TODO: from ANSI`99. Not supported by Ignite.
+
+                                // Exact numeric types
+                                + "TINY_C TINYINT, " // TINYINT is not a part of any SQL standard.
+                                + "SMALL_C SMALLINT, "
+                                + "INT_C INT, "
+                                + "LONG_C BIGINT, "
+                                + "NUMBER_C NUMERIC, "
+                                + "NUMBER_C2 NUMERIC(5), "
+                                + "NUMBER_C3 NUMERIC(10,3), "
+                                + "DECIMAL_C DECIMAL, "
+                                + "DECIMAL_C2 DECIMAL(5), "
+                                + "DECIMAL_C3 DECIMAL(10,3), "
+
+                                // Approximate numeric types
+                                + "FLOAT_C FLOAT, "
+//                              + "FLOAT_C2 FLOAT(4), " // TODO: from ANSI`92. Not supported by Calcite parser.
+                                + "REAL_C REAL, "
+                                + "DOUBLE_C DOUBLE, "
+
+                                // Character string types
+                                + "CHAR_C CHAR, "
+                                + "CHAR_C2 CHAR(125), "
+                                + "VARCHAR_C VARCHAR, "
+                                + "VARCHAR_C2 VARCHAR(125), "
+
+                                // Binary string types
+//                              + "BIT_C BIT, " // TODO: from ANSI`92. Not supported by Calcite parser.
+//                              + "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), "
+//                              + "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.
+
+                                // Datetime types
+                                + "DATE_C DATE, "
+                                + "TIME_C TIME, "
+                                + "TIME_C2 TIME(9), "
+                                + "TIME_LTZ_C TIME WITH LOCAL TIME ZONE, " // Not part of any standard
+                                + "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.
+
+                                // Interval types
+                                // TODO: Ignite doesn't support interval types.
+//                              + "INTERVAL_YEAR_C INTERVAL YEAR, "
+//                              + "INTERVAL_MONTH_C INTERVAL MONTH, "
+//                              + "INTERVAL_DAY_C INTERVAL DAY, "
+//                              + "INTERVAL_HOUR_C INTERVAL HOUR, "
+//                              + "INTERVAL_SEC_C INTERVAL SECOND, "
+//                              + "INTERVAL_SEC_C2 INTERVAL SECOND(9), "
+
+                                // Custom types
+//                              + "UUID_C UUID, " //TODO: custom types are not supported yet.
+//                              + "BITSET_C BITMASK(8) " //TODO: custom types are not supported yet. Map to BIT(n) ?
+
+                                // Nullability constraint
+                                + "NULLABLE_C INT, "
+                                + "NON_NULL_C INT NOT NULL "
+                                + ")"
+                );
+
+        assertQuery("select * from metadata_table")
+                .columnMetadata(
+                        new MetadataMatcher().name("ID").nullable(false),
+//                        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("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),
+
+                        // 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("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("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("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"),
+
+                        // 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_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("TIMESTAMP_TZ_C").type(SqlColumnType.TIMESTAMP),
+//                      new MetadataMatcher().name("TIMESTAMP_TZ_C2").type(SqlColumnType.TIMESTAMP),
+
+                        // Interval types
+                        // TODO: Ignite doesn't support interval types.
+//                      new MetadataMatcher().name("INTERVAL_YEAR_C"),
+//                      new MetadataMatcher().name("INTERVAL_MONTH_C"),
+//                      new MetadataMatcher().name("INTERVAL_DAY_C"),
+//                      new MetadataMatcher().name("INTERVAL_HOUR_C"),
+//                      new MetadataMatcher().name("INTERVAL_MINUTE_C"),
+//                      new MetadataMatcher().name("INTERVAL_SEC_C"),
+//                      new MetadataMatcher().name("INTERVAL_SEC_C2"),
+
+                        // Custom types
+//                      new MetadataMatcher().name("UUID_C"),
+//                      new MetadataMatcher().name("BITSET_C"),
+
+                        // Nullability constraint
+                        new MetadataMatcher().name("NULLABLE_C").nullable(true),
+                        new MetadataMatcher().name("NON_NULL_C").nullable(false)
+                )
+                .check();
+    }
 }
diff --git a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/util/MetadataMatcher.java b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/util/MetadataMatcher.java
new file mode 100644
index 000000000..ad292a32e
--- /dev/null
+++ b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/util/MetadataMatcher.java
@@ -0,0 +1,185 @@
+/*
+ * 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.sql.engine.util;
+
+import static org.junit.jupiter.api.Assertions.assertAll;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertSame;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.ignite.internal.sql.SqlColumnTypeConverter;
+import org.apache.ignite.internal.tostring.S;
+import org.apache.ignite.sql.ColumnMetadata;
+import org.apache.ignite.sql.ColumnMetadata.ColumnOrigin;
+import org.apache.ignite.sql.SqlColumnType;
+import org.junit.jupiter.api.function.Executable;
+
+/**
+ * Column metadata checker.
+ */
+public class MetadataMatcher {
+    /** Marker object. */
+    private static final Object NO_CHECK = new Object() {
+        @Override
+        public String toString() {
+            return "<non_checkable>";
+        }
+    };
+
+    /** Name of the result's column. */
+    private Object name = NO_CHECK;
+
+    /** Type of the result's column. */
+    private Object type = NO_CHECK;
+
+    /** Column precision. */
+    private Object precision = NO_CHECK;
+
+    /** Column scale. */
+    private Object scale = NO_CHECK;
+
+    /** Nullable flag of the result's column. */
+    private Object nullable = NO_CHECK;
+
+    /** Origin of the result's column. */
+    private Object origin = NO_CHECK;
+
+    /**
+     * Sets column name.
+     *
+     * @return This.
+     */
+    public MetadataMatcher name(String name) {
+        this.name = name;
+
+        return this;
+    }
+
+    /**
+     * Sets column SQL type.
+     *
+     * @return This.
+     */
+    public MetadataMatcher type(SqlColumnType type) {
+        this.type = type;
+
+        return this;
+    }
+
+    /**
+     * Sets column precision.
+     *
+     * @return This.
+     */
+    public MetadataMatcher precision(int precision) {
+        this.precision = precision;
+
+        return this;
+    }
+
+    /**
+     * Sets column scale.
+     *
+     * @return This.
+     */
+    public MetadataMatcher scale(int scale) {
+        this.scale = scale;
+
+        return this;
+    }
+
+    /**
+     * Sets column nullability flag.
+     *
+     * @return This.
+     */
+    public MetadataMatcher nullable(boolean nullable) {
+        this.nullable = nullable;
+
+        return this;
+    }
+
+    /**
+     * Sets column origins.
+     *
+     * @return This.
+     */
+    public MetadataMatcher origin(ColumnOrigin origin) {
+        this.origin = origin;
+
+        return this;
+    }
+
+    /**
+     * Checks metadata.
+     *
+     * @param actualMeta Metadata to check.
+     */
+    void check(ColumnMetadata actualMeta) {
+        List<Executable> matchers = new ArrayList<>();
+
+        if (name != NO_CHECK) {
+            matchers.add(() -> assertEquals(name, actualMeta.name(), "name"));
+        }
+
+        if (type != NO_CHECK) {
+            SqlColumnType type0 = (SqlColumnType) type;
+            matchers.add(() -> assertSame(type0, actualMeta.type(), "type"));
+            matchers.add(() -> assertSame(SqlColumnTypeConverter.columnTypeToClass(type0), actualMeta.valueClass(), "value class"));
+        }
+
+        if (precision != NO_CHECK) {
+            matchers.add(() -> assertEquals(precision, actualMeta.precision(), "precision"));
+        }
+
+        if (scale != NO_CHECK) {
+            matchers.add(() -> assertEquals(scale, actualMeta.scale(), "scale"));
+        }
+
+        if (nullable != NO_CHECK) {
+            matchers.add(() -> assertEquals(nullable, actualMeta.nullable(), "nullable"));
+        }
+
+        if (origin != NO_CHECK) {
+            if (origin == null) {
+                matchers.add(() -> assertNull(actualMeta.origin(), "origin"));
+            } else {
+                ColumnOrigin expected = (ColumnOrigin) origin;
+                ColumnOrigin actual = actualMeta.origin();
+
+                matchers.add(() -> {
+                    assertNotNull(actual, "origin");
+                    assertEquals(expected.schemaName(), actual.schemaName(), " origin schema");
+                    assertEquals(expected.tableName(), actual.tableName(), " origin table");
+                    assertEquals(expected.columnName(), actual.columnName(), " origin column");
+                });
+            }
+        }
+
+        assertAll("Mismatch:\n expected = " + this + ",\n actual = " + actualMeta, matchers);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public String toString() {
+        return S.toString(MetadataMatcher.class, this);
+    }
+}
diff --git a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/util/QueryChecker.java b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/util/QueryChecker.java
index 1af6711c8..b42e553e8 100644
--- a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/util/QueryChecker.java
+++ b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/util/QueryChecker.java
@@ -23,6 +23,8 @@ import static org.apache.ignite.internal.util.ArrayUtils.nullOrEmpty;
 import static org.hamcrest.CoreMatchers.equalTo;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertIterableEquals;
 import static org.junit.jupiter.api.Assertions.fail;
 
 import java.lang.reflect.Type;
@@ -33,6 +35,7 @@ import java.util.Collections;
 import java.util.Comparator;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Objects;
 import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 import org.apache.ignite.internal.sql.SqlColumnTypeConverter;
@@ -41,6 +44,7 @@ import org.apache.ignite.internal.util.CollectionUtils;
 import org.apache.ignite.sql.ColumnMetadata;
 import org.hamcrest.CoreMatchers;
 import org.hamcrest.Matcher;
+import org.hamcrest.Matchers;
 import org.hamcrest.core.SubstringMatcher;
 import org.jetbrains.annotations.Nullable;
 
@@ -242,6 +246,8 @@ public abstract class QueryChecker {
 
     private List<Type> expectedColumnTypes;
 
+    private List<MetadataMatcher> metadataMatchers;
+
     private boolean ordered;
 
     private Object[] params = OBJECT_EMPTY_ARRAY;
@@ -321,6 +327,17 @@ public abstract class QueryChecker {
         return this;
     }
 
+    /**
+     * Sets columns metadata.
+     *
+     * @return This.
+     */
+    public QueryChecker columnMetadata(MetadataMatcher... matchers) {
+        metadataMatchers = Arrays.asList(matchers);
+
+        return this;
+    }
+
     /**
      * Sets plan.
      *
@@ -360,6 +377,8 @@ public abstract class QueryChecker {
 
         var cur = cursors.get(0).join();
 
+        var res = CursorUtils.getAllFromCursor(cur);
+
         if (expectedColumnNames != null) {
             List<String> colNames = cur.metadata().columns().stream()
                     .map(ColumnMetadata::name)
@@ -377,7 +396,21 @@ public abstract class QueryChecker {
             assertThat("Column types don't match", colTypes, equalTo(expectedColumnTypes));
         }
 
-        var res = CursorUtils.getAllFromCursor(cur);
+        if (metadataMatchers != null) {
+            List<ColumnMetadata> columnMetadata = cur.metadata().columns();
+
+            Iterator<ColumnMetadata> valueIterator = columnMetadata.iterator();
+            Iterator<MetadataMatcher> matcherIterator = metadataMatchers.iterator();
+
+            while(matcherIterator.hasNext() && valueIterator.hasNext()) {
+                MetadataMatcher matcher = matcherIterator.next();
+                ColumnMetadata actualElement = valueIterator.next();
+
+                matcher.check(actualElement);
+            }
+
+            assertFalse(matcherIterator.hasNext(), "Column metadata doesn't match");
+        }
 
         if (expectedResult != null) {
             if (!ordered) {
@@ -477,4 +510,5 @@ public abstract class QueryChecker {
             return 0;
         }
     }
+
 }
diff --git a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/util/TypeUtils.java b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/util/TypeUtils.java
index 16b1804b4..b8620b0c5 100644
--- a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/util/TypeUtils.java
+++ b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/util/TypeUtils.java
@@ -46,6 +46,7 @@ import org.apache.calcite.sql.type.SqlTypeUtil;
 import org.apache.ignite.internal.schema.DecimalNativeType;
 import org.apache.ignite.internal.schema.NativeType;
 import org.apache.ignite.internal.schema.NumberNativeType;
+import org.apache.ignite.internal.schema.TemporalNativeType;
 import org.apache.ignite.internal.schema.VarlenNativeType;
 import org.apache.ignite.internal.sql.engine.exec.ExecutionContext;
 import org.apache.ignite.internal.sql.engine.exec.RowHandler;
@@ -411,11 +412,23 @@ public class TypeUtils {
             case DATE:
                 return factory.createSqlType(SqlTypeName.DATE);
             case TIME:
-                return factory.createSqlType(SqlTypeName.TIME);
+                assert nativeType instanceof TemporalNativeType;
+
+                var time = (TemporalNativeType) nativeType;
+
+                return factory.createSqlType(SqlTypeName.TIME, time.precision());
             case TIMESTAMP:
-                return factory.createSqlType(SqlTypeName.TIMESTAMP_WITH_LOCAL_TIME_ZONE);
+                assert nativeType instanceof TemporalNativeType;
+
+                var ts = (TemporalNativeType) nativeType;
+
+                return factory.createSqlType(SqlTypeName.TIMESTAMP_WITH_LOCAL_TIME_ZONE, ts.precision());
             case DATETIME:
-                return factory.createSqlType(SqlTypeName.TIMESTAMP);
+                assert nativeType instanceof TemporalNativeType;
+
+                var dt = (TemporalNativeType) nativeType;
+
+                return factory.createSqlType(SqlTypeName.TIMESTAMP, dt.precision());
             default:
                 throw new IllegalStateException("Unexpected native type " + nativeType);
         }