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

korlov 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 e22683ef88 IGNITE-22780 Sql. Fix cast from VARCHAR to TS WITH LOCAL TZ 
(#4116)
e22683ef88 is described below

commit e22683ef880eb8626669777bb4a4385c0cc694c8
Author: korlov42 <[email protected]>
AuthorDate: Fri Jul 19 17:07:46 2024 +0300

    IGNITE-22780 Sql. Fix cast from VARCHAR to TS WITH LOCAL TZ (#4116)
---
 .../engine/ItCastToTsWithLocalTimeZoneTest.java    | 596 +++++++++++++++++++++
 .../sql/engine/exec/exp/RexToLixTranslator.java    |   5 +-
 2 files changed, 600 insertions(+), 1 deletion(-)

diff --git 
a/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItCastToTsWithLocalTimeZoneTest.java
 
b/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItCastToTsWithLocalTimeZoneTest.java
new file mode 100644
index 0000000000..517a99c903
--- /dev/null
+++ 
b/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/engine/ItCastToTsWithLocalTimeZoneTest.java
@@ -0,0 +1,596 @@
+/*
+ * 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;
+
+import java.time.Instant;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.ZoneId;
+import java.time.ZoneOffset;
+import org.apache.ignite.internal.sql.BaseSqlIntegrationTest;
+import org.apache.ignite.internal.testframework.WithSystemProperty;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Set of tests to ensure correctness of CAST expression to TIMESTAMP WITH 
TIME ZONE for
+ * type pairs supported by cast specification.
+ */
+@WithSystemProperty(key = "IMPLICIT_PK_ENABLED", value = "true")
+public class ItCastToTsWithLocalTimeZoneTest extends BaseSqlIntegrationTest {
+    @BeforeAll
+    static void createTable() {
+        sql("CREATE TABLE test (val TIMESTAMP WITH LOCAL TIME ZONE)");
+        sql("CREATE TABLE src (id INT PRIMARY KEY, s VARCHAR(100), ts 
TIMESTAMP, d DATE, t TIME)");
+    }
+
+    @AfterAll
+    static void dropTable() {
+        sql("DROP TABLE IF EXISTS test");
+        sql("DROP TABLE IF EXISTS src");
+    }
+
+    @AfterEach
+    void clearTable() {
+        sql("DELETE FROM test");
+        sql("DELETE FROM src");
+    }
+
+    @Test
+    void implicitCastOfLiteralsOnInsert() {
+        {
+            ZoneId zone = ZoneOffset.ofHours(4);
+
+            assertQuery("INSERT INTO test VALUES ('1970-01-01 
12:00:00')").withTimeZoneId(zone).check();
+            assertQuery("INSERT INTO test VALUES (timestamp '1970-01-01 
13:00:00')").withTimeZoneId(zone).check();
+            assertQuery("INSERT INTO test VALUES (date 
'1970-01-01')").withTimeZoneId(zone).check();
+            assertQuery("INSERT INTO test VALUES (time 
'12:00:00')").withTimeZoneId(zone).check();
+        }
+
+        {
+            ZoneId zone = ZoneOffset.ofHours(8);
+
+            assertQuery("INSERT INTO test VALUES ('1970-01-01 
14:00:00')").withTimeZoneId(zone).check();
+            assertQuery("INSERT INTO test VALUES (timestamp '1970-01-01 
15:00:00')").withTimeZoneId(zone).check();
+            assertQuery("INSERT INTO test VALUES (date 
'1970-01-01')").withTimeZoneId(zone).check();
+            assertQuery("INSERT INTO test VALUES (time 
'14:00:00')").withTimeZoneId(zone).check();
+        }
+
+        assertQuery("SELECT * FROM test")
+                .returns(Instant.parse("1970-01-01T08:00:00Z"))
+                .returns(Instant.parse("1970-01-01T09:00:00Z"))
+                .returns(Instant.parse("1969-12-31T20:00:00Z"))
+                .returns(Instant.parse(LocalDate.now() + "T08:00:00Z"))
+                .returns(Instant.parse("1970-01-01T06:00:00Z"))
+                .returns(Instant.parse("1970-01-01T07:00:00Z"))
+                .returns(Instant.parse("1969-12-31T16:00:00Z"))
+                .returns(Instant.parse(LocalDate.now() + "T06:00:00Z"))
+                .check();
+    }
+
+    @Test
+    void explicitCastOfLiteralsOnInsert() {
+        {
+            ZoneId zone = ZoneOffset.ofHours(4);
+
+            assertQuery("INSERT INTO test VALUES (CAST('1970-01-01 12:00:00' 
as TIMESTAMP WITH LOCAL TIME ZONE))")
+                    .withTimeZoneId(zone)
+                    .check();
+            assertQuery("INSERT INTO test VALUES (CAST(timestamp '1970-01-01 
13:00:00' as TIMESTAMP WITH LOCAL TIME ZONE))")
+                    .withTimeZoneId(zone)
+                    .check();
+            assertQuery("INSERT INTO test VALUES (CAST(date '1970-01-01' as 
TIMESTAMP WITH LOCAL TIME ZONE))")
+                    .withTimeZoneId(zone)
+                    .check();
+            assertQuery("INSERT INTO test VALUES (CAST(time '12:00:00' as 
TIMESTAMP WITH LOCAL TIME ZONE))")
+                    .withTimeZoneId(zone)
+                    .check();
+        }
+
+        {
+            ZoneId zone = ZoneOffset.ofHours(8);
+
+            assertQuery("INSERT INTO test VALUES (CAST('1970-01-01 14:00:00' 
as TIMESTAMP WITH LOCAL TIME ZONE))")
+                    .withTimeZoneId(zone)
+                    .check();
+            assertQuery("INSERT INTO test VALUES (CAST(timestamp '1970-01-01 
15:00:00' as TIMESTAMP WITH LOCAL TIME ZONE))")
+                    .withTimeZoneId(zone)
+                    .check();
+            assertQuery("INSERT INTO test VALUES (CAST(date '1970-01-01' as 
TIMESTAMP WITH LOCAL TIME ZONE))")
+                    .withTimeZoneId(zone)
+                    .check();
+            assertQuery("INSERT INTO test VALUES (CAST(time '14:00:00' as 
TIMESTAMP WITH LOCAL TIME ZONE))")
+                    .withTimeZoneId(zone)
+                    .check();
+        }
+
+        assertQuery("SELECT * FROM test")
+                .returns(Instant.parse("1970-01-01T08:00:00Z"))
+                .returns(Instant.parse("1970-01-01T09:00:00Z"))
+                .returns(Instant.parse("1969-12-31T20:00:00Z"))
+                .returns(Instant.parse(LocalDate.now() + "T08:00:00Z"))
+                .returns(Instant.parse("1970-01-01T06:00:00Z"))
+                .returns(Instant.parse("1970-01-01T07:00:00Z"))
+                .returns(Instant.parse("1969-12-31T16:00:00Z"))
+                .returns(Instant.parse(LocalDate.now() + "T06:00:00Z"))
+                .check();
+    }
+
+    @Test
+    void explicitCastOfLiteralsOnSelect() {
+        {
+            ZoneId zone = ZoneOffset.ofHours(4);
+
+            assertQuery("SELECT CAST('1970-01-01 12:00:00' as TIMESTAMP WITH 
LOCAL TIME ZONE)")
+                    .withTimeZoneId(zone)
+                    .returns(Instant.parse("1970-01-01T08:00:00Z"))
+                    .check();
+            assertQuery("SELECT CAST(timestamp '1970-01-01 13:00:00' as 
TIMESTAMP WITH LOCAL TIME ZONE)")
+                    .withTimeZoneId(zone)
+                    .returns(Instant.parse("1970-01-01T09:00:00Z"))
+                    .check();
+            assertQuery("SELECT CAST(date '1970-01-01' as TIMESTAMP WITH LOCAL 
TIME ZONE)")
+                    .withTimeZoneId(zone)
+                    .returns(Instant.parse("1969-12-31T20:00:00Z"))
+                    .check();
+            assertQuery("SELECT CAST(time '12:00:00' as TIMESTAMP WITH LOCAL 
TIME ZONE)")
+                    .withTimeZoneId(zone)
+                    .returns(Instant.parse(LocalDate.now() + "T08:00:00Z"))
+                    .check();
+        }
+
+        {
+            ZoneId zone = ZoneOffset.ofHours(8);
+
+            assertQuery("SELECT CAST('1970-01-01 14:00:00' as TIMESTAMP WITH 
LOCAL TIME ZONE)")
+                    .withTimeZoneId(zone)
+                    .returns(Instant.parse("1970-01-01T06:00:00Z"))
+                    .check();
+            assertQuery("SELECT CAST(timestamp '1970-01-01 15:00:00' as 
TIMESTAMP WITH LOCAL TIME ZONE)")
+                    .withTimeZoneId(zone)
+                    .returns(Instant.parse("1970-01-01T07:00:00Z"))
+                    .check();
+            assertQuery("SELECT CAST(date '1970-01-01' as TIMESTAMP WITH LOCAL 
TIME ZONE)")
+                    .withTimeZoneId(zone)
+                    .returns(Instant.parse("1969-12-31T16:00:00Z"))
+                    .check();
+            assertQuery("SELECT CAST(time '14:00:00' as TIMESTAMP WITH LOCAL 
TIME ZONE)")
+                    .withTimeZoneId(zone)
+                    .returns(Instant.parse(LocalDate.now() + "T06:00:00Z"))
+                    .check();
+        }
+    }
+
+    @Test
+    void explicitCastOfLiteralsOnMultiInsert() {
+        {
+            ZoneId zone = ZoneOffset.ofHours(4);
+
+            assertQuery("INSERT INTO test VALUES " 
+                    + "(CAST('1970-01-01 12:00:00' as TIMESTAMP WITH LOCAL 
TIME ZONE))," 
+                    + "(CAST(timestamp '1970-01-01 13:00:00' as TIMESTAMP WITH 
LOCAL TIME ZONE))," 
+                    + "(CAST(date '1970-01-01' as TIMESTAMP WITH LOCAL TIME 
ZONE))," 
+                    + "(CAST(time '12:00:00' as TIMESTAMP WITH LOCAL TIME 
ZONE))")
+                    .withTimeZoneId(zone).check();
+        }
+
+        {
+            ZoneId zone = ZoneOffset.ofHours(8);
+
+            assertQuery("INSERT INTO test VALUES " 
+                    + "(CAST('1970-01-01 14:00:00' as TIMESTAMP WITH LOCAL 
TIME ZONE))," 
+                    + "(CAST(timestamp '1970-01-01 15:00:00' as TIMESTAMP WITH 
LOCAL TIME ZONE))," 
+                    + "(CAST(date '1970-01-01' as TIMESTAMP WITH LOCAL TIME 
ZONE))," 
+                    + "(CAST(time '14:00:00' as TIMESTAMP WITH LOCAL TIME 
ZONE))")
+                    .withTimeZoneId(zone).check();
+        }
+
+        assertQuery("SELECT * FROM test")
+                .returns(Instant.parse("1970-01-01T08:00:00Z"))
+                .returns(Instant.parse("1970-01-01T09:00:00Z"))
+                .returns(Instant.parse("1969-12-31T20:00:00Z"))
+                .returns(Instant.parse(LocalDate.now() + "T08:00:00Z"))
+                .returns(Instant.parse("1970-01-01T06:00:00Z"))
+                .returns(Instant.parse("1970-01-01T07:00:00Z"))
+                .returns(Instant.parse("1969-12-31T16:00:00Z"))
+                .returns(Instant.parse(LocalDate.now() + "T06:00:00Z"))
+                .check();
+    }
+
+    @Test
+    @Disabled("https://issues.apache.org/jira/browse/IGNITE-22779";)
+    void implicitCastOfDynParamsOnInsert() {
+        {
+            ZoneId zone = ZoneOffset.ofHours(4);
+
+            assertQuery("INSERT INTO test VALUES (?)")
+                    .withTimeZoneId(zone)
+                    .withParam("1970-01-01 12:00:00")
+                    .check();
+            assertQuery("INSERT INTO test VALUES (?)")
+                    .withTimeZoneId(zone)
+                    .withParam(LocalDateTime.parse("1970-01-01T13:00:00"))
+                    .check();
+            assertQuery("INSERT INTO test VALUES (?)")
+                    .withTimeZoneId(zone)
+                    .withParam(LocalDate.parse("1970-01-01"))
+                    .check();
+            assertQuery("INSERT INTO test VALUES (?)")
+                    .withTimeZoneId(zone)
+                    .withParam(LocalTime.parse("12:00:00"))
+                    .check();
+        }
+
+        {
+            ZoneId zone = ZoneOffset.ofHours(8);
+
+            assertQuery("INSERT INTO test VALUES (?)")
+                    .withTimeZoneId(zone)
+                    .withParam("1970-01-01 14:00:00")
+                    .check();
+            assertQuery("INSERT INTO test VALUES (?)")
+                    .withTimeZoneId(zone)
+                    .withParam(LocalDateTime.parse("1970-01-01T15:00:00"))
+                    .check();
+            assertQuery("INSERT INTO test VALUES (?)")
+                    .withTimeZoneId(zone)
+                    .withParam(LocalDate.parse("1970-01-01"))
+                    .check();
+            assertQuery("INSERT INTO test VALUES (?)")
+                    .withTimeZoneId(zone)
+                    .withParam(LocalTime.parse("14:00:00"))
+                    .check();
+        }
+
+        assertQuery("SELECT * FROM test")
+                .returns(Instant.parse("1970-01-01T08:00:00Z"))
+                .returns(Instant.parse("1970-01-01T09:00:00Z"))
+                .returns(Instant.parse("1969-12-31T20:00:00Z"))
+                .returns(Instant.parse(LocalDate.now() + "T08:00:00Z"))
+                .returns(Instant.parse("1970-01-01T06:00:00Z"))
+                .returns(Instant.parse("1970-01-01T07:00:00Z"))
+                .returns(Instant.parse("1969-12-31T16:00:00Z"))
+                .returns(Instant.parse(LocalDate.now() + "T06:00:00Z"))
+                .check();
+    }
+
+    @Test
+    void implicitCastOfSourceTableOnInsert() {
+        sql("INSERT INTO src VALUES " 
+                + "(1, '1970-01-01 12:00:00', timestamp '1970-01-01 13:00:00', 
date '1970-01-01', time '12:00:00')," 
+                + "(2, '1970-01-01 14:00:00', timestamp '1970-01-01 15:00:00', 
date '1970-01-01', time '14:00:00')"
+        );
+
+        {
+            ZoneId zone = ZoneOffset.ofHours(4);
+
+            assertQuery("INSERT INTO test SELECT s FROM src WHERE id = 1")
+                    .withTimeZoneId(zone)
+                    .check();
+            assertQuery("INSERT INTO test SELECT ts FROM src WHERE id = 1")
+                    .withTimeZoneId(zone)
+                    .check();
+            assertQuery("INSERT INTO test SELECT d FROM src WHERE id = 1")
+                    .withTimeZoneId(zone)
+                    .check();
+            assertQuery("INSERT INTO test SELECT t FROM src WHERE id = 1")
+                    .withTimeZoneId(zone)
+                    .check();
+        }
+
+        {
+            ZoneId zone = ZoneOffset.ofHours(8);
+
+            assertQuery("INSERT INTO test SELECT s FROM src WHERE id = 2")
+                    .withTimeZoneId(zone)
+                    .check();
+            assertQuery("INSERT INTO test SELECT ts FROM src WHERE id = 2")
+                    .withTimeZoneId(zone)
+                    .check();
+            assertQuery("INSERT INTO test SELECT d FROM src WHERE id = 2")
+                    .withTimeZoneId(zone)
+                    .check();
+            assertQuery("INSERT INTO test SELECT t FROM src WHERE id = 2")
+                    .withTimeZoneId(zone)
+                    .check();
+        }
+
+        assertQuery("SELECT * FROM test")
+                .returns(Instant.parse("1970-01-01T08:00:00Z"))
+                .returns(Instant.parse("1970-01-01T09:00:00Z"))
+                .returns(Instant.parse("1969-12-31T20:00:00Z"))
+                .returns(Instant.parse(LocalDate.now() + "T08:00:00Z"))
+                .returns(Instant.parse("1970-01-01T06:00:00Z"))
+                .returns(Instant.parse("1970-01-01T07:00:00Z"))
+                .returns(Instant.parse("1969-12-31T16:00:00Z"))
+                .returns(Instant.parse(LocalDate.now() + "T06:00:00Z"))
+                .check();
+    }
+
+    @Test
+    void explicitCastOfDynParamsOnInsert() {
+        {
+            ZoneId zone = ZoneOffset.ofHours(4);
+
+            assertQuery("INSERT INTO test VALUES (CAST(? as TIMESTAMP WITH 
LOCAL TIME ZONE))")
+                    .withTimeZoneId(zone)
+                    .withParam("1970-01-01 12:00:00")
+                    .check();
+            assertQuery("INSERT INTO test VALUES (CAST(? as TIMESTAMP WITH 
LOCAL TIME ZONE))")
+                    .withTimeZoneId(zone)
+                    .withParam(LocalDateTime.parse("1970-01-01T13:00:00"))
+                    .check();
+            assertQuery("INSERT INTO test VALUES (CAST(? as TIMESTAMP WITH 
LOCAL TIME ZONE))")
+                    .withTimeZoneId(zone)
+                    .withParam(LocalDate.parse("1970-01-01"))
+                    .check();
+            assertQuery("INSERT INTO test VALUES (CAST(? as TIMESTAMP WITH 
LOCAL TIME ZONE))")
+                    .withTimeZoneId(zone)
+                    .withParam(LocalTime.parse("12:00:00"))
+                    .check();
+        }
+
+        {
+            ZoneId zone = ZoneOffset.ofHours(8);
+
+            assertQuery("INSERT INTO test VALUES (CAST(? as TIMESTAMP WITH 
LOCAL TIME ZONE))")
+                    .withTimeZoneId(zone)
+                    .withParam("1970-01-01 14:00:00")
+                    .check();
+            assertQuery("INSERT INTO test VALUES (CAST(? as TIMESTAMP WITH 
LOCAL TIME ZONE))")
+                    .withTimeZoneId(zone)
+                    .withParam(LocalDateTime.parse("1970-01-01T15:00:00"))
+                    .check();
+            assertQuery("INSERT INTO test VALUES (CAST(? as TIMESTAMP WITH 
LOCAL TIME ZONE))")
+                    .withTimeZoneId(zone)
+                    .withParam(LocalDate.parse("1970-01-01"))
+                    .check();
+            assertQuery("INSERT INTO test VALUES (CAST(? as TIMESTAMP WITH 
LOCAL TIME ZONE))")
+                    .withTimeZoneId(zone)
+                    .withParam(LocalTime.parse("14:00:00"))
+                    .check();
+        }
+
+        assertQuery("SELECT * FROM test")
+                .returns(Instant.parse("1970-01-01T08:00:00Z"))
+                .returns(Instant.parse("1970-01-01T09:00:00Z"))
+                .returns(Instant.parse("1969-12-31T20:00:00Z"))
+                .returns(Instant.parse(LocalDate.now() + "T08:00:00Z"))
+                .returns(Instant.parse("1970-01-01T06:00:00Z"))
+                .returns(Instant.parse("1970-01-01T07:00:00Z"))
+                .returns(Instant.parse("1969-12-31T16:00:00Z"))
+                .returns(Instant.parse(LocalDate.now() + "T06:00:00Z"))
+                .check();
+    }
+
+    @Test
+    void explicitCastOfDynParamsOnSelect() {
+        {
+            ZoneId zone = ZoneOffset.ofHours(4);
+
+            assertQuery("SELECT CAST(? as TIMESTAMP WITH LOCAL TIME ZONE)")
+                    .withTimeZoneId(zone)
+                    .withParam("1970-01-01 12:00:00")
+                    .returns(Instant.parse("1970-01-01T08:00:00Z"))
+                    .check();
+            assertQuery("SELECT CAST(? as TIMESTAMP WITH LOCAL TIME ZONE)")
+                    .withTimeZoneId(zone)
+                    .withParam(LocalDateTime.parse("1970-01-01T13:00:00"))
+                    .returns(Instant.parse("1970-01-01T09:00:00Z"))
+                    .check();
+            assertQuery("SELECT CAST(? as TIMESTAMP WITH LOCAL TIME ZONE)")
+                    .withTimeZoneId(zone)
+                    .withParam(LocalDate.parse("1970-01-01"))
+                    .returns(Instant.parse("1969-12-31T20:00:00Z"))
+                    .check();
+            assertQuery("SELECT CAST(? as TIMESTAMP WITH LOCAL TIME ZONE)")
+                    .withTimeZoneId(zone)
+                    .withParam(LocalTime.parse("12:00:00"))
+                    .returns(Instant.parse(LocalDate.now() + "T08:00:00Z"))
+                    .check();
+        }
+
+        {
+            ZoneId zone = ZoneOffset.ofHours(8);
+
+            assertQuery("SELECT CAST(? as TIMESTAMP WITH LOCAL TIME ZONE)")
+                    .withTimeZoneId(zone)
+                    .withParam("1970-01-01 14:00:00")
+                    .returns(Instant.parse("1970-01-01T06:00:00Z"))
+                    .check();
+            assertQuery("SELECT CAST(? as TIMESTAMP WITH LOCAL TIME ZONE)")
+                    .withTimeZoneId(zone)
+                    .withParam(LocalDateTime.parse("1970-01-01T15:00:00"))
+                    .returns(Instant.parse("1970-01-01T07:00:00Z"))
+                    .check();
+            assertQuery("SELECT CAST(? as TIMESTAMP WITH LOCAL TIME ZONE)")
+                    .withTimeZoneId(zone)
+                    .withParam(LocalDate.parse("1970-01-01"))
+                    .returns(Instant.parse("1969-12-31T16:00:00Z"))
+                    .check();
+            assertQuery("SELECT CAST(? as TIMESTAMP WITH LOCAL TIME ZONE)")
+                    .withTimeZoneId(zone)
+                    .withParam(LocalTime.parse("14:00:00"))
+                    .returns(Instant.parse(LocalDate.now() + "T06:00:00Z"))
+                    .check();
+        }
+    }
+
+    @Test
+    void explicitCastOfDynParamsOnMultiInsert() {
+        {
+            ZoneId zone = ZoneOffset.ofHours(4);
+
+            assertQuery("INSERT INTO test VALUES " 
+                    + "(CAST(? as TIMESTAMP WITH LOCAL TIME ZONE))," 
+                    + "(CAST(? as TIMESTAMP WITH LOCAL TIME ZONE))," 
+                    + "(CAST(? as TIMESTAMP WITH LOCAL TIME ZONE))," 
+                    + "(CAST(? as TIMESTAMP WITH LOCAL TIME ZONE))")
+                    .withTimeZoneId(zone)
+                    .withParams(
+                            "1970-01-01 12:00:00",
+                            LocalDateTime.parse("1970-01-01T13:00:00"),
+                            LocalDate.parse("1970-01-01"),
+                            LocalTime.parse("12:00:00")
+                    )
+                    .check();
+        }
+
+        {
+            ZoneId zone = ZoneOffset.ofHours(8);
+
+            assertQuery("INSERT INTO test VALUES "
+                    + "(CAST(? as TIMESTAMP WITH LOCAL TIME ZONE)),"
+                    + "(CAST(? as TIMESTAMP WITH LOCAL TIME ZONE)),"
+                    + "(CAST(? as TIMESTAMP WITH LOCAL TIME ZONE)),"
+                    + "(CAST(? as TIMESTAMP WITH LOCAL TIME ZONE))")
+                    .withTimeZoneId(zone)
+                    .withParams(
+                            "1970-01-01 14:00:00",
+                            LocalDateTime.parse("1970-01-01T15:00:00"),
+                            LocalDate.parse("1970-01-01"),
+                            LocalTime.parse("14:00:00")
+                    )
+                    .check();
+        }
+
+        assertQuery("SELECT * FROM test")
+                .returns(Instant.parse("1970-01-01T08:00:00Z"))
+                .returns(Instant.parse("1970-01-01T09:00:00Z"))
+                .returns(Instant.parse("1969-12-31T20:00:00Z"))
+                .returns(Instant.parse(LocalDate.now() + "T08:00:00Z"))
+                .returns(Instant.parse("1970-01-01T06:00:00Z"))
+                .returns(Instant.parse("1970-01-01T07:00:00Z"))
+                .returns(Instant.parse("1969-12-31T16:00:00Z"))
+                .returns(Instant.parse(LocalDate.now() + "T06:00:00Z"))
+                .check();
+    }
+
+    @Test
+    void explicitCastOfSourceTableOnInsert() {
+        sql("INSERT INTO src VALUES "
+                + "(1, '1970-01-01 12:00:00', timestamp '1970-01-01 13:00:00', 
date '1970-01-01', time '12:00:00'),"
+                + "(2, '1970-01-01 14:00:00', timestamp '1970-01-01 15:00:00', 
date '1970-01-01', time '14:00:00')"
+        );
+
+        {
+            ZoneId zone = ZoneOffset.ofHours(4);
+
+            assertQuery("INSERT INTO test SELECT CAST(s as TIMESTAMP WITH 
LOCAL TIME ZONE) FROM src WHERE id = 1")
+                    .withTimeZoneId(zone)
+                    .check();
+            assertQuery("INSERT INTO test SELECT CAST(ts as TIMESTAMP WITH 
LOCAL TIME ZONE) FROM src WHERE id = 1")
+                    .withTimeZoneId(zone)
+                    .check();
+            assertQuery("INSERT INTO test SELECT CAST(d as TIMESTAMP WITH 
LOCAL TIME ZONE) FROM src WHERE id = 1")
+                    .withTimeZoneId(zone)
+                    .check();
+            assertQuery("INSERT INTO test SELECT CAST(t as TIMESTAMP WITH 
LOCAL TIME ZONE) FROM src WHERE id = 1")
+                    .withTimeZoneId(zone)
+                    .check();
+        }
+
+        {
+            ZoneId zone = ZoneOffset.ofHours(8);
+
+            assertQuery("INSERT INTO test SELECT CAST(s as TIMESTAMP WITH 
LOCAL TIME ZONE) FROM src WHERE id = 2")
+                    .withTimeZoneId(zone)
+                    .check();
+            assertQuery("INSERT INTO test SELECT CAST(ts as TIMESTAMP WITH 
LOCAL TIME ZONE) FROM src WHERE id = 2")
+                    .withTimeZoneId(zone)
+                    .check();
+            assertQuery("INSERT INTO test SELECT CAST(d as TIMESTAMP WITH 
LOCAL TIME ZONE) FROM src WHERE id = 2")
+                    .withTimeZoneId(zone)
+                    .check();
+            assertQuery("INSERT INTO test SELECT CAST(t as TIMESTAMP WITH 
LOCAL TIME ZONE) FROM src WHERE id = 2")
+                    .withTimeZoneId(zone)
+                    .check();
+        }
+
+        assertQuery("SELECT * FROM test")
+                .returns(Instant.parse("1970-01-01T08:00:00Z"))
+                .returns(Instant.parse("1970-01-01T09:00:00Z"))
+                .returns(Instant.parse("1969-12-31T20:00:00Z"))
+                .returns(Instant.parse(LocalDate.now() + "T08:00:00Z"))
+                .returns(Instant.parse("1970-01-01T06:00:00Z"))
+                .returns(Instant.parse("1970-01-01T07:00:00Z"))
+                .returns(Instant.parse("1969-12-31T16:00:00Z"))
+                .returns(Instant.parse(LocalDate.now() + "T06:00:00Z"))
+                .check();
+    }
+
+    @Test
+    void explicitCastOfSourceTableOnSelect() {
+        sql("INSERT INTO src VALUES "
+                + "(1, '1970-01-01 12:00:00', timestamp '1970-01-01 13:00:00', 
date '1970-01-01', time '12:00:00'),"
+                + "(2, '1970-01-01 14:00:00', timestamp '1970-01-01 15:00:00', 
date '1970-01-01', time '14:00:00')"
+        );
+
+        {
+            ZoneId zone = ZoneOffset.ofHours(4);
+
+            assertQuery("SELECT CAST(s as TIMESTAMP WITH LOCAL TIME ZONE) FROM 
src WHERE id = 1")
+                    .withTimeZoneId(zone)
+                    .returns(Instant.parse("1970-01-01T08:00:00Z"))
+                    .check();
+
+            assertQuery("SELECT CAST(ts as TIMESTAMP WITH LOCAL TIME ZONE) 
FROM src WHERE id = 1")
+                    .withTimeZoneId(zone)
+                    .returns(Instant.parse("1970-01-01T09:00:00Z"))
+                    .check();
+
+            assertQuery("SELECT CAST(d as TIMESTAMP WITH LOCAL TIME ZONE) FROM 
src WHERE id = 1")
+                    .withTimeZoneId(zone)
+                    .returns(Instant.parse("1969-12-31T20:00:00Z"))
+                    .check();
+
+            assertQuery("SELECT CAST(t as TIMESTAMP WITH LOCAL TIME ZONE) FROM 
src WHERE id = 1")
+                    .withTimeZoneId(zone)
+                    .returns(Instant.parse(LocalDate.now() + "T08:00:00Z"))
+                    .check();
+        }
+
+        {
+            ZoneId zone = ZoneOffset.ofHours(8);
+
+            assertQuery("SELECT CAST(s as TIMESTAMP WITH LOCAL TIME ZONE) FROM 
src WHERE id = 2")
+                    .withTimeZoneId(zone)
+                    .returns(Instant.parse("1970-01-01T06:00:00Z"))
+                    .check();
+
+            assertQuery("SELECT CAST(ts as TIMESTAMP WITH LOCAL TIME ZONE) 
FROM src WHERE id = 2")
+                    .withTimeZoneId(zone)
+                    .returns(Instant.parse("1970-01-01T07:00:00Z"))
+                    .check();
+
+            assertQuery("SELECT CAST(d as TIMESTAMP WITH LOCAL TIME ZONE) FROM 
src WHERE id = 2")
+                    .withTimeZoneId(zone)
+                    .returns(Instant.parse("1969-12-31T16:00:00Z"))
+                    .check();
+
+            assertQuery("SELECT CAST(t as TIMESTAMP WITH LOCAL TIME ZONE) FROM 
src WHERE id = 2")
+                    .withTimeZoneId(zone)
+                    .returns(Instant.parse(LocalDate.now() + "T06:00:00Z"))
+                    .check();
+        }
+    }
+}
diff --git 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/exp/RexToLixTranslator.java
 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/exp/RexToLixTranslator.java
index 9af6157beb..bb76746f44 100644
--- 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/exp/RexToLixTranslator.java
+++ 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/exec/exp/RexToLixTranslator.java
@@ -406,7 +406,10 @@ public class RexToLixTranslator implements 
RexVisitor<RexToLixTranslator.Result>
                         // Since this type implies a local timezone, its 
explicit indication seems redundant,
                         // so we prohibit the user from explicitly setting a 
timezone.
                         convert =
-                                
Expressions.call(BuiltInMethod.STRING_TO_TIMESTAMP.method, operand);
+                                Expressions.call(
+                                        
BuiltInMethod.TIMESTAMP_STRING_TO_TIMESTAMP_WITH_LOCAL_TIME_ZONE.method,
+                                        operand,
+                                        
Expressions.call(BuiltInMethod.TIME_ZONE.method, root));
                         break;
                     case DATE:
                         convert =

Reply via email to