This is an automated email from the ASF dual-hosted git repository.

zstan pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/ignite-3.git


The following commit(s) were added to refs/heads/main by this push:
     new 8f660aac53 IGNITE-19068 Sql. Support sql engine representation for kv 
api timestamp type - Fixes #1905.
8f660aac53 is described below

commit 8f660aac53560c3a89306bce2823a567e4451092
Author: zstan <[email protected]>
AuthorDate: Mon Apr 10 09:27:13 2023 +0300

    IGNITE-19068 Sql. Support sql engine representation for kv api timestamp 
type - Fixes #1905.
    
    Signed-off-by: zstan <[email protected]>
---
 .../ignite/internal/sql/api/ItCommonApiTest.java   | 72 ++++++++++++++++
 .../internal/sql/engine/ItDataTypesTest.java       | 26 +++---
 .../sql/types/timestamp/test_timestamp.test        | 97 ++++++++++++++++++++++
 modules/sql-engine/src/main/codegen/config.fmpp    |  2 +-
 .../ignite/internal/sql/engine/util/TypeUtils.java |  7 ++
 5 files changed, 190 insertions(+), 14 deletions(-)

diff --git 
a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/api/ItCommonApiTest.java
 
b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/api/ItCommonApiTest.java
index d5ea1dfe52..cb9046be23 100644
--- 
a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/api/ItCommonApiTest.java
+++ 
b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/api/ItCommonApiTest.java
@@ -18,20 +18,33 @@
 package org.apache.ignite.internal.sql.api;
 
 import static 
org.apache.ignite.internal.testframework.IgniteTestUtils.assertThrowsWithCause;
+import static org.apache.ignite.internal.testframework.IgniteTestUtils.await;
 import static 
org.apache.ignite.internal.testframework.IgniteTestUtils.waitForCondition;
 import static org.apache.ignite.lang.ErrorGroups.Sql;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertThrows;
 
+import java.time.Instant;
+import java.time.LocalDateTime;
 import java.util.concurrent.TimeUnit;
+import org.apache.ignite.Ignite;
 import org.apache.ignite.internal.app.IgniteImpl;
+import 
org.apache.ignite.internal.schema.testutils.SchemaConfigurationConverter;
+import org.apache.ignite.internal.schema.testutils.builder.SchemaBuilders;
+import org.apache.ignite.internal.schema.testutils.definition.ColumnType;
+import 
org.apache.ignite.internal.schema.testutils.definition.ColumnType.TemporalColumnType;
+import org.apache.ignite.internal.schema.testutils.definition.TableDefinition;
 import org.apache.ignite.internal.sql.engine.ClusterPerClassIntegrationTest;
 import org.apache.ignite.internal.sql.engine.SqlQueryProcessor;
 import org.apache.ignite.internal.sql.engine.exec.ExecutionCancelledException;
+import org.apache.ignite.internal.table.distributed.TableManager;
 import org.apache.ignite.sql.IgniteSql;
 import org.apache.ignite.sql.ResultSet;
 import org.apache.ignite.sql.Session;
 import org.apache.ignite.sql.SqlException;
+import org.apache.ignite.sql.SqlRow;
+import org.apache.ignite.table.Table;
+import org.apache.ignite.table.Tuple;
 import org.junit.jupiter.api.Test;
 
 /** Test common SQL API. */
@@ -95,4 +108,63 @@ public class ItCommonApiTest extends 
ClusterPerClassIntegrationTest {
         // second session could start new query
         ses2.execute(null, "SELECT 2 + 2").close();
     }
+
+    /** Check timestamp type operations correctness using sql and kv api. */
+    @Test
+    public void checkTimestampOperations() {
+        String kvTblName = "tbl_all_columns_sql";
+        String schemaName = "PUBLIC";
+        String keyCol = "key";
+        int maxTimePrecision = TemporalColumnType.MAX_TIME_PRECISION;
+
+        Ignite node = CLUSTER_NODES.get(0);
+
+        // TODO: https://issues.apache.org/jira/browse/IGNITE-19162 Trim all 
less than millisecond information from timestamp
+        //String tsStr = "2023-03-29T08:22:33.005007Z";
+        String tsStr = "2023-03-29T08:22:33.005Z";
+
+        Instant ins = Instant.parse(tsStr);
+
+        sql("CREATE TABLE timestamps(id INTEGER PRIMARY KEY, i TIMESTAMP(9))");
+
+        TableDefinition schTblAllSql = SchemaBuilders.tableBuilder(schemaName, 
kvTblName).columns(
+                SchemaBuilders.column(keyCol, ColumnType.INT64).build(),
+                SchemaBuilders.column("time", 
ColumnType.time(maxTimePrecision)).asNullable(true).build(),
+                SchemaBuilders.column("timestamp", 
ColumnType.timestamp(maxTimePrecision)).asNullable(true).build(),
+                SchemaBuilders.column("datetime", 
ColumnType.datetime(maxTimePrecision)).asNullable(true).build()
+        ).withPrimaryKey(keyCol).build();
+
+        await(((TableManager) 
node.tables()).createTableAsync(schTblAllSql.name(), tblCh ->
+                SchemaConfigurationConverter.convert(schTblAllSql, tblCh)
+        ));
+
+        Table tbl = node.tables().table(kvTblName);
+
+        Tuple rec = Tuple.create()
+                .set("KEY", 1L)
+                .set("TIMESTAMP", ins)
+                .set("DATETIME", LocalDateTime.of(2023, 1, 18, 18, 9, 29));
+
+        tbl.recordView().insert(null, rec);
+
+        // TODO: https://issues.apache.org/jira/browse/IGNITE-19161 Can`t 
insert timestamp representing in ISO_INSTANT format
+        tsStr = tsStr.replace("T", " ").substring(0, tsStr.length() - 1);
+
+        sql("INSERT INTO timestamps VALUES (101, TIMESTAMP '" + tsStr + "')");
+
+        try (Session ses = node.sql().createSession()) {
+            // for projection pop up
+            ResultSet<SqlRow> res = ses.execute(null, "SELECT i, id FROM 
timestamps");
+
+            String srtRepr = ins.toString();
+
+            assertEquals(srtRepr.substring(0, srtRepr.length() - 1), 
res.next().datetimeValue(0).toString());
+
+            String query = "select \"KEY\", \"TIME\", \"DATETIME\", 
\"TIMESTAMP\" from TBL_ALL_COLUMNS_SQL ORDER BY KEY";
+
+            res = ses.execute(null, query);
+
+            assertEquals(ins, res.next().timestampValue(3));
+        }
+    }
 }
diff --git 
a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItDataTypesTest.java
 
b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItDataTypesTest.java
index b9ad11ace9..dc0194edd2 100644
--- 
a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItDataTypesTest.java
+++ 
b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItDataTypesTest.java
@@ -53,7 +53,7 @@ public class ItDataTypesTest extends 
ClusterPerClassIntegrationTest {
     public void testUnicodeStrings() {
         sql("CREATE TABLE string_table(key int primary key, val varchar)");
 
-        String[] values = new String[]{"Кирилл", "Müller", "我是谁", "ASCII"};
+        String[] values = {"Кирилл", "Müller", "我是谁", "ASCII"};
 
         int key = 0;
 
@@ -170,9 +170,9 @@ public class ItDataTypesTest extends 
ClusterPerClassIntegrationTest {
      */
     @Test
     public void testDateTime() {
-        assertQuery("select date 
'1992-01-19'").returns(sqlDate("1992-01-19")).check();
-        assertQuery("select date '1992-01-18' + interval (1) 
days").returns(sqlDate("1992-01-19")).check();
-        assertQuery("select date '1992-01-18' + interval (24) 
hours").returns(sqlDate("1992-01-19")).check();
+        assertQuery("SELECT date 
'1992-01-19'").returns(sqlDate("1992-01-19")).check();
+        assertQuery("SELECT date '1992-01-18' + interval (1) 
days").returns(sqlDate("1992-01-19")).check();
+        assertQuery("SELECT date '1992-01-18' + interval (24) 
hours").returns(sqlDate("1992-01-19")).check();
         assertQuery("SELECT timestamp '1992-01-18 02:30:00' + interval (25) 
hours")
                 .returns(sqlDateTime("1992-01-19T03:30:00")).check();
         assertQuery("SELECT timestamp '1992-01-18 02:30:00' + interval (23) 
hours")
@@ -180,9 +180,9 @@ public class ItDataTypesTest extends 
ClusterPerClassIntegrationTest {
         assertQuery("SELECT timestamp '1992-01-18 02:30:00' + interval (24) 
hours")
                 .returns(sqlDateTime("1992-01-19T02:30:00.000")).check();
 
-        assertQuery("select date 
'1992-03-29'").returns(sqlDate("1992-03-29")).check();
-        assertQuery("select date '1992-03-28' + interval (1) 
days").returns(sqlDate("1992-03-29")).check();
-        assertQuery("select date '1992-03-28' + interval (24) 
hours").returns(sqlDate("1992-03-29")).check();
+        assertQuery("SELECT date 
'1992-03-29'").returns(sqlDate("1992-03-29")).check();
+        assertQuery("SELECT date '1992-03-28' + interval (1) 
days").returns(sqlDate("1992-03-29")).check();
+        assertQuery("SELECT date '1992-03-28' + interval (24) 
hours").returns(sqlDate("1992-03-29")).check();
         assertQuery("SELECT timestamp '1992-03-28 02:30:00' + interval (25) 
hours")
                 .returns(sqlDateTime("1992-03-29T03:30:00.000")).check();
         assertQuery("SELECT timestamp '1992-03-28 02:30:00' + interval (23) 
hours")
@@ -190,9 +190,9 @@ public class ItDataTypesTest extends 
ClusterPerClassIntegrationTest {
         assertQuery("SELECT timestamp '1992-03-28 02:30:00' + interval (24) 
hours")
                 .returns(sqlDateTime("1992-03-29T02:30:00.000")).check();
 
-        assertQuery("select date 
'1992-09-27'").returns(sqlDate("1992-09-27")).check();
-        assertQuery("select date '1992-09-26' + interval (1) 
days").returns(sqlDate("1992-09-27")).check();
-        assertQuery("select date '1992-09-26' + interval (24) 
hours").returns(sqlDate("1992-09-27")).check();
+        assertQuery("SELECT date 
'1992-09-27'").returns(sqlDate("1992-09-27")).check();
+        assertQuery("SELECT date '1992-09-26' + interval (1) 
days").returns(sqlDate("1992-09-27")).check();
+        assertQuery("SELECT date '1992-09-26' + interval (24) 
hours").returns(sqlDate("1992-09-27")).check();
         assertQuery("SELECT timestamp '1992-09-26 02:30:00' + interval (25) 
hours")
                 .returns(sqlDateTime("1992-09-27T03:30:00.000")).check();
         assertQuery("SELECT timestamp '1992-09-26 02:30:00' + interval (23) 
hours")
@@ -200,9 +200,9 @@ public class ItDataTypesTest extends 
ClusterPerClassIntegrationTest {
         assertQuery("SELECT timestamp '1992-09-26 02:30:00' + interval (24) 
hours")
                 .returns(sqlDateTime("1992-09-27T02:30:00.000")).check();
 
-        assertQuery("select date 
'2021-11-07'").returns(sqlDate("2021-11-07")).check();
-        assertQuery("select date '2021-11-06' + interval (1) 
days").returns(sqlDate("2021-11-07")).check();
-        assertQuery("select date '2021-11-06' + interval (24) 
hours").returns(sqlDate("2021-11-07")).check();
+        assertQuery("SELECT date 
'2021-11-07'").returns(sqlDate("2021-11-07")).check();
+        assertQuery("SELECT date '2021-11-06' + interval (1) 
days").returns(sqlDate("2021-11-07")).check();
+        assertQuery("SELECT date '2021-11-06' + interval (24) 
hours").returns(sqlDate("2021-11-07")).check();
         assertQuery("SELECT timestamp '2021-11-06 01:30:00' + interval (25) 
hours")
                 .returns(sqlDateTime("2021-11-07T02:30:00.000")).check();
         // Check string representation here, since after timestamp calculation 
we have '2021-11-07T01:30:00.000-0800'
diff --git 
a/modules/runner/src/integrationTest/sql/types/timestamp/test_timestamp.test 
b/modules/runner/src/integrationTest/sql/types/timestamp/test_timestamp.test
new file mode 100644
index 0000000000..e0f3278abd
--- /dev/null
+++ b/modules/runner/src/integrationTest/sql/types/timestamp/test_timestamp.test
@@ -0,0 +1,97 @@
+# name: test/sql/types/timestamp/test_timestamp.test
+# description: Test TIMESTAMP type
+# group: [timestamp]
+
+statement ok
+PRAGMA enable_verification
+
+statement ok
+CREATE TABLE IF NOT EXISTS timestamp (t TIMESTAMP);
+
+statement ok
+INSERT INTO timestamp VALUES ('2008-01-01 00:00:01'), ('2007-01-01 00:00:01'), 
('2008-02-01 00:00:01'), ('2008-01-02 00:00:01'), ('2008-01-01 10:00:00'), 
('2008-01-01 00:10:00'), ('2008-01-01 00:00:10')
+
+query T
+SELECT timestamp '2017-07-23 13:10:11';
+----
+2017-07-23T13:10:11
+
+# other trailing, preceding, or middle gunk is not accepted
+statement error
+SELECT timestamp '    2017-07-23     13:10:11    AA';
+
+statement error
+SELECT timestamp 'AA2017-07-23 13:10:11';
+
+statement error
+SELECT timestamp '2017-07-23A13:10:11';
+
+query T
+SELECT t FROM timestamp ORDER BY t LIMIT 1;
+----
+2007-01-01T00:00:01
+
+query T
+SELECT MIN(t) FROM timestamp;
+----
+2007-01-01T00:00:01
+
+query T
+SELECT MAX(t) FROM timestamp;
+----
+2008-02-01T00:00:01
+
+statement error
+SELECT SUM(t) FROM timestamp
+
+statement error
+SELECT AVG(t) FROM timestamp
+
+statement error
+SELECT t+t FROM timestamp
+
+statement error
+SELECT t*t FROM timestamp
+
+statement error
+SELECT t/t FROM timestamp
+
+statement error
+SELECT t%t FROM timestamp
+
+query I
+SELECT YEAR(TIMESTAMP '1992-01-01 01:01:01');
+----
+1992
+
+query I
+SELECT YEAR(TIMESTAMP '1992-01-01 01:01:01'::DATE);
+----
+1992
+
+query T
+SELECT (TIMESTAMP '1992-01-01 01:01:01')::DATE;
+----
+1992-01-01
+
+query T
+SELECT (TIMESTAMP '1992-01-01 01:01:01')::TIME;
+----
+01:01:01
+
+query T
+SELECT t::DATE FROM timestamp WHERE EXTRACT(YEAR from t)=2007 ORDER BY 1
+----
+2007-01-01
+
+query T
+SELECT t::TIME FROM timestamp WHERE EXTRACT(YEAR from t)=2007 ORDER BY 1
+----
+00:00:01
+
+query T
+SELECT (DATE '1992-01-01')::TIMESTAMP;
+----
+1992-01-01T00:00
+
+
diff --git a/modules/sql-engine/src/main/codegen/config.fmpp 
b/modules/sql-engine/src/main/codegen/config.fmpp
index 5ae4d19b38..10d3ee9b57 100644
--- a/modules/sql-engine/src/main/codegen/config.fmpp
+++ b/modules/sql-engine/src/main/codegen/config.fmpp
@@ -511,7 +511,7 @@ data: {
       "TEMPORARY"
 #     "THEN"
 #     "TIME"
-#     "TIMESTAMP"
+      "TIMESTAMP"
       "TIMEZONE_HOUR"
       "TIMEZONE_MINUTE"
       "TINYINT"
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 04a85cfe89..8d375052bd 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
@@ -22,6 +22,7 @@ import static 
org.apache.ignite.internal.sql.engine.util.Commons.transform;
 import java.lang.reflect.Type;
 import java.math.BigDecimal;
 import java.time.Duration;
+import java.time.Instant;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.LocalTime;
@@ -264,6 +265,10 @@ public class TypeUtils {
             var dt = (LocalDateTime) val;
 
             return TimeUnit.SECONDS.toMillis(dt.toEpochSecond(ZoneOffset.UTC)) 
+ TimeUnit.NANOSECONDS.toMillis(dt.getNano());
+        } else if (storageType == Instant.class) {
+            var timeStamp = (Instant) val;
+
+            return timeStamp.toEpochMilli();
         } else if (storageType == Duration.class) {
             return TimeUnit.SECONDS.toMillis(((Duration) val).getSeconds())
                     + TimeUnit.NANOSECONDS.toMillis(((Duration) 
val).getNano());
@@ -312,6 +317,8 @@ public class TypeUtils {
         } else if (storageType == LocalDateTime.class && (val instanceof 
Long)) {
             return 
LocalDateTime.ofEpochSecond(TimeUnit.MILLISECONDS.toSeconds((Long) val),
                     (int) TimeUnit.MILLISECONDS.toNanos((Long) val % 1000), 
ZoneOffset.UTC);
+        } else if (storageType == Instant.class && val instanceof Long) {
+            return Instant.ofEpochMilli((long) val);
         } else if (storageType == Duration.class && val instanceof Long) {
             return Duration.ofMillis((Long) val);
         } else if (storageType == Period.class && val instanceof Integer) {

Reply via email to