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

ptupitsyn 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 6871bba01b IGNITE-21568 Java thin: Pass client time zone to server 
(#3737)
6871bba01b is described below

commit 6871bba01b3643cf6e0b45cde7d2f69151b6a835
Author: Pavel Tupitsyn <ptupit...@apache.org>
AuthorDate: Mon May 13 11:26:09 2024 +0300

    IGNITE-21568 Java thin: Pass client time zone to server (#3737)
---
 .../handler/requests/sql/ClientSqlProperties.java  | 10 +++++++-
 .../ignite/internal/client/sql/ClientSql.java      |  9 ++++---
 .../internal/client/sql/ClientStatement.java       | 28 ++++++++++++----------
 .../client/sql/ClientStatementBuilder.java         | 11 ++++++---
 .../org/apache/ignite/client/ClientSqlTest.java    |  3 +++
 .../org/apache/ignite/client/fakes/FakeCursor.java |  2 ++
 .../cpp/ignite/client/detail/sql/sql_impl.cpp      |  1 +
 .../platforms/cpp/ignite/odbc/query/data_query.cpp |  1 +
 .../dotnet/Apache.Ignite.Tests/FakeServer.cs       |  4 +++-
 .../dotnet/Apache.Ignite.Tests/Sql/SqlTests.cs     |  2 +-
 .../dotnet/Apache.Ignite/Internal/Sql/Sql.cs       |  2 ++
 .../ignite/internal/sql/api/ItSqlApiBaseTest.java  | 25 +++++++++++++++++++
 12 files changed, 77 insertions(+), 21 deletions(-)

diff --git 
a/modules/client-handler/src/main/java/org/apache/ignite/client/handler/requests/sql/ClientSqlProperties.java
 
b/modules/client-handler/src/main/java/org/apache/ignite/client/handler/requests/sql/ClientSqlProperties.java
index 785a973153..015f90d9dd 100644
--- 
a/modules/client-handler/src/main/java/org/apache/ignite/client/handler/requests/sql/ClientSqlProperties.java
+++ 
b/modules/client-handler/src/main/java/org/apache/ignite/client/handler/requests/sql/ClientSqlProperties.java
@@ -17,12 +17,13 @@
 
 package org.apache.ignite.client.handler.requests.sql;
 
-import javax.annotation.Nullable;
+import java.time.ZoneId;
 import org.apache.ignite.internal.client.proto.ClientMessageUnpacker;
 import org.apache.ignite.internal.sql.api.IgniteSqlImpl;
 import org.apache.ignite.internal.sql.engine.QueryProperty;
 import org.apache.ignite.internal.sql.engine.property.SqlProperties;
 import org.apache.ignite.internal.sql.engine.property.SqlPropertiesHelper;
+import org.jetbrains.annotations.Nullable;
 
 class ClientSqlProperties {
     private final @Nullable String schema;
@@ -33,11 +34,14 @@ class ClientSqlProperties {
 
     private final long idleTimeout;
 
+    private final @Nullable String timeZoneId;
+
     ClientSqlProperties(ClientMessageUnpacker in) {
         schema = in.tryUnpackNil() ? null : in.unpackString();
         pageSize = in.tryUnpackNil() ? IgniteSqlImpl.DEFAULT_PAGE_SIZE : 
in.unpackInt();
         queryTimeout = in.tryUnpackNil() ? 0 : in.unpackLong();
         idleTimeout = in.tryUnpackNil() ? 0 : in.unpackLong();
+        timeZoneId = in.tryUnpackNil() ? null : in.unpackString();
 
         // Skip properties - not used by SQL engine.
         in.unpackInt(); // Number of properties.
@@ -68,6 +72,10 @@ class ClientSqlProperties {
             builder.set(QueryProperty.DEFAULT_SCHEMA, schema);
         }
 
+        if (timeZoneId != null) {
+            builder.set(QueryProperty.TIME_ZONE_ID, ZoneId.of(timeZoneId));
+        }
+
         return builder.build();
     }
 }
diff --git 
a/modules/client/src/main/java/org/apache/ignite/internal/client/sql/ClientSql.java
 
b/modules/client/src/main/java/org/apache/ignite/internal/client/sql/ClientSql.java
index 74095a4c8b..acfb230519 100644
--- 
a/modules/client/src/main/java/org/apache/ignite/internal/client/sql/ClientSql.java
+++ 
b/modules/client/src/main/java/org/apache/ignite/internal/client/sql/ClientSql.java
@@ -20,6 +20,7 @@ package org.apache.ignite.internal.client.sql;
 import static org.apache.ignite.internal.client.table.ClientTable.writeTx;
 import static org.apache.ignite.internal.util.ExceptionUtils.unwrapCause;
 
+import java.time.ZoneId;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Objects;
@@ -75,7 +76,7 @@ public class ClientSql implements IgniteSql {
     /** {@inheritDoc} */
     @Override
     public Statement createStatement(String query) {
-        return new ClientStatement(query, null, null, null);
+        return new ClientStatement(query, null, null, null, null);
     }
 
     /** {@inheritDoc} */
@@ -177,7 +178,7 @@ public class ClientSql implements IgniteSql {
             @Nullable Object... arguments) {
         Objects.requireNonNull(query);
 
-        ClientStatement statement = new ClientStatement(query, null, null, 
null);
+        ClientStatement statement = new ClientStatement(query, null, null, 
null, null);
 
         return executeAsync(transaction, statement, arguments);
     }
@@ -200,7 +201,7 @@ public class ClientSql implements IgniteSql {
             @Nullable Object... arguments) {
         Objects.requireNonNull(query);
 
-        ClientStatement statement = new ClientStatement(query, null, null, 
null);
+        ClientStatement statement = new ClientStatement(query, null, null, 
null, null);
 
         return executeAsync(transaction, mapper, statement, arguments);
     }
@@ -228,6 +229,7 @@ public class ClientSql implements IgniteSql {
             w.out().packLongNullable(clientStatement.queryTimeoutNullable());
 
             w.out().packLongNullable(0L); // defaultSessionTimeout
+            w.out().packString(clientStatement.timeZoneId().getId());
 
             packProperties(w, null);
 
@@ -286,6 +288,7 @@ public class ClientSql implements IgniteSql {
             w.out().packNil(); // pageSize
             w.out().packNil(); // queryTimeout
             w.out().packNil(); // sessionTimeout
+            w.out().packString(ZoneId.systemDefault().getId());
 
             packProperties(w, null);
 
diff --git 
a/modules/client/src/main/java/org/apache/ignite/internal/client/sql/ClientStatement.java
 
b/modules/client/src/main/java/org/apache/ignite/internal/client/sql/ClientStatement.java
index 42256f572b..de5ec90114 100644
--- 
a/modules/client/src/main/java/org/apache/ignite/internal/client/sql/ClientStatement.java
+++ 
b/modules/client/src/main/java/org/apache/ignite/internal/client/sql/ClientStatement.java
@@ -18,10 +18,10 @@
 package org.apache.ignite.internal.client.sql;
 
 import java.time.ZoneId;
-import java.time.ZoneOffset;
 import java.util.Objects;
 import java.util.concurrent.TimeUnit;
 import org.apache.ignite.sql.Statement;
+import org.jetbrains.annotations.Nullable;
 
 /**
  * Client SQL statement.
@@ -31,13 +31,16 @@ public class ClientStatement implements Statement {
     private final String query;
 
     /** Default schema. */
-    private final String defaultSchema;
+    private final @Nullable String defaultSchema;
 
     /** Query timeout. */
-    private final Long queryTimeoutMs;
+    private final @Nullable Long queryTimeoutMs;
 
     /** Page size. */
-    private final Integer pageSize;
+    private final @Nullable Integer pageSize;
+
+    /** Time-zone ID. */
+    private final ZoneId timeZoneId;
 
     /**
      * Constructor.
@@ -48,17 +51,19 @@ public class ClientStatement implements Statement {
      * @param pageSize Page size.
      */
     @SuppressWarnings("AssignmentOrReturnOfFieldWithMutableType")
-    public ClientStatement(
+    ClientStatement(
             String query,
-            String defaultSchema,
-            Long queryTimeoutMs,
-            Integer pageSize) {
+            @Nullable String defaultSchema,
+            @Nullable Long queryTimeoutMs,
+            @Nullable Integer pageSize,
+            @Nullable ZoneId timeZoneId) {
         Objects.requireNonNull(query);
 
         this.query = query;
         this.defaultSchema = defaultSchema;
         this.queryTimeoutMs = queryTimeoutMs;
         this.pageSize = pageSize;
+        this.timeZoneId = timeZoneId != null ? timeZoneId : 
ZoneId.systemDefault();
     }
 
     /** {@inheritDoc} */
@@ -80,7 +85,7 @@ public class ClientStatement implements Statement {
      *
      * @return Query timeout.
      */
-    public Long queryTimeoutNullable() {
+    @Nullable Long queryTimeoutNullable() {
         return queryTimeoutMs;
     }
 
@@ -93,8 +98,7 @@ public class ClientStatement implements Statement {
     /** {@inheritDoc} */
     @Override
     public ZoneId timeZoneId() {
-        // TODO: https://issues.apache.org/jira/browse/IGNITE-21568
-        return ZoneOffset.UTC;
+        return timeZoneId;
     }
 
     /** {@inheritDoc} */
@@ -108,7 +112,7 @@ public class ClientStatement implements Statement {
      *
      * @return Page size.
      */
-    public Integer pageSizeNullable() {
+    @Nullable Integer pageSizeNullable() {
         return pageSize;
     }
 
diff --git 
a/modules/client/src/main/java/org/apache/ignite/internal/client/sql/ClientStatementBuilder.java
 
b/modules/client/src/main/java/org/apache/ignite/internal/client/sql/ClientStatementBuilder.java
index a61d763e7c..0ed4dbfbb1 100644
--- 
a/modules/client/src/main/java/org/apache/ignite/internal/client/sql/ClientStatementBuilder.java
+++ 
b/modules/client/src/main/java/org/apache/ignite/internal/client/sql/ClientStatementBuilder.java
@@ -39,6 +39,9 @@ public class ClientStatementBuilder implements 
Statement.StatementBuilder {
     /** Page size. */
     private Integer pageSize;
 
+    /** Time-zone ID. */
+    private ZoneId timeZoneId;
+
     /** {@inheritDoc} */
     @Override
     public StatementBuilder query(String query) {
@@ -75,8 +78,9 @@ public class ClientStatementBuilder implements 
Statement.StatementBuilder {
 
     @Override
     public StatementBuilder timeZoneId(ZoneId timeZoneId) {
-        // TODO: https://issues.apache.org/jira/browse/IGNITE-21568
-        throw new UnsupportedOperationException("Not implemented yet");
+        this.timeZoneId = timeZoneId;
+
+        return this;
     }
 
     /** {@inheritDoc} */
@@ -86,6 +90,7 @@ public class ClientStatementBuilder implements 
Statement.StatementBuilder {
                 query,
                 defaultSchema,
                 queryTimeoutMs,
-                pageSize);
+                pageSize,
+                timeZoneId);
     }
 }
diff --git 
a/modules/client/src/test/java/org/apache/ignite/client/ClientSqlTest.java 
b/modules/client/src/test/java/org/apache/ignite/client/ClientSqlTest.java
index 9f9a5f77af..71419406e1 100644
--- a/modules/client/src/test/java/org/apache/ignite/client/ClientSqlTest.java
+++ b/modules/client/src/test/java/org/apache/ignite/client/ClientSqlTest.java
@@ -33,6 +33,7 @@ import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.LocalTime;
 import java.time.Period;
+import java.time.ZoneId;
 import java.util.BitSet;
 import java.util.Map;
 import java.util.UUID;
@@ -84,6 +85,7 @@ public class ClientSqlTest extends AbstractClientTableTest {
                 .defaultSchema("SCHEMA2")
                 .queryTimeout(124, TimeUnit.SECONDS)
                 .pageSize(235)
+                .timeZoneId(ZoneId.of("Europe/London"))
                 .build();
 
         AsyncResultSet<SqlRow> resultSet = client.sql().executeAsync(null, 
statement).join();
@@ -94,6 +96,7 @@ public class ClientSqlTest extends AbstractClientTableTest {
         assertEquals("SCHEMA2", props.get("schema"));
         assertEquals("124000", props.get("timeout"));
         assertEquals("235", props.get("pageSize"));
+        assertEquals("Europe/London", props.get("timeZoneId"));
     }
 
     @Test
diff --git 
a/modules/client/src/test/java/org/apache/ignite/client/fakes/FakeCursor.java 
b/modules/client/src/test/java/org/apache/ignite/client/fakes/FakeCursor.java
index 159099f5c6..2493f4d277 100644
--- 
a/modules/client/src/test/java/org/apache/ignite/client/fakes/FakeCursor.java
+++ 
b/modules/client/src/test/java/org/apache/ignite/client/fakes/FakeCursor.java
@@ -19,6 +19,7 @@ package org.apache.ignite.client.fakes;
 
 import static 
org.apache.ignite.internal.sql.engine.QueryProperty.DEFAULT_SCHEMA;
 import static 
org.apache.ignite.internal.sql.engine.QueryProperty.QUERY_TIMEOUT;
+import static org.apache.ignite.internal.sql.engine.QueryProperty.TIME_ZONE_ID;
 import static 
org.apache.ignite.internal.util.CompletableFutures.nullCompletedFuture;
 
 import java.math.BigDecimal;
@@ -61,6 +62,7 @@ public class FakeCursor implements 
AsyncSqlCursor<InternalSqlRow> {
 
             rows.add(getRow("schema", properties.get(DEFAULT_SCHEMA)));
             rows.add(getRow("timeout", 
String.valueOf(properties.get(QUERY_TIMEOUT))));
+            rows.add(getRow("timeZoneId", 
String.valueOf(properties.get(TIME_ZONE_ID))));
         } else if ("SELECT META".equals(qry)) {
             columns.add(new FakeColumnMetadata("BOOL", ColumnType.BOOLEAN));
             columns.add(new FakeColumnMetadata("INT8", ColumnType.INT8));
diff --git a/modules/platforms/cpp/ignite/client/detail/sql/sql_impl.cpp 
b/modules/platforms/cpp/ignite/client/detail/sql/sql_impl.cpp
index db7c5520be..7f15a72144 100644
--- a/modules/platforms/cpp/ignite/client/detail/sql/sql_impl.cpp
+++ b/modules/platforms/cpp/ignite/client/detail/sql/sql_impl.cpp
@@ -29,6 +29,7 @@ void write_statement(protocol::writer &writer, const 
sql_statement &statement) {
     writer.write(statement.page_size());
     writer.write(std::int64_t(statement.timeout().count()));
     writer.write_nil(); // Session timeout (unused, session is closed by the 
server immediately).
+    writer.write_nil(); // TODO: IGNITE-21605 Time zone id.
 
     const auto &properties = statement.properties();
     auto props_num = std::int32_t(properties.size());
diff --git a/modules/platforms/cpp/ignite/odbc/query/data_query.cpp 
b/modules/platforms/cpp/ignite/odbc/query/data_query.cpp
index 0eae298056..00b46b9e1c 100644
--- a/modules/platforms/cpp/ignite/odbc/query/data_query.cpp
+++ b/modules/platforms/cpp/ignite/odbc/query/data_query.cpp
@@ -274,6 +274,7 @@ sql_result data_query::make_request_execute() {
             
writer.write(m_connection.get_configuration().get_page_size().get_value());
             writer.write(std::int64_t(m_connection.get_timeout()) * 1000);
             writer.write_nil(); // Session timeout (unused, session is closed 
by the server immediately).
+            writer.write_nil(); // TODO: IGNITE-21605 Time zone id.
 
             // Properties are not used for now.
             writer.write(0);
diff --git a/modules/platforms/dotnet/Apache.Ignite.Tests/FakeServer.cs 
b/modules/platforms/dotnet/Apache.Ignite.Tests/FakeServer.cs
index 13a1ac3058..68d696f94c 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Tests/FakeServer.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Tests/FakeServer.cs
@@ -441,6 +441,7 @@ namespace Apache.Ignite.Tests
             props["timeoutMs"] = timeoutMs;
 
             props["sessionTimeoutMs"] = reader.TryReadNil() ? (long?)null : 
reader.ReadInt64();
+            props["timeZoneId"] = reader.TryReadNil() ? null : 
reader.ReadString();
 
             // ReSharper restore RedundantCast
             var propCount = reader.ReadInt32();
@@ -550,7 +551,8 @@ namespace Apache.Ignite.Tests
                 ["schema"] = reader.TryReadNil() ? null : reader.ReadString(),
                 ["pageSize"] = reader.TryReadNil() ? null : reader.ReadInt32(),
                 ["timeoutMs"] = reader.TryReadNil() ? null : 
reader.ReadInt64(),
-                ["sessionTimeoutMs"] = reader.TryReadNil() ? null : 
reader.ReadInt64()
+                ["sessionTimeoutMs"] = reader.TryReadNil() ? null : 
reader.ReadInt64(),
+                ["timeZoneId"] = reader.TryReadNil() ? null : 
reader.ReadString()
             };
 
             var propCount = reader.ReadInt32();
diff --git a/modules/platforms/dotnet/Apache.Ignite.Tests/Sql/SqlTests.cs 
b/modules/platforms/dotnet/Apache.Ignite.Tests/Sql/SqlTests.cs
index d3f98d5336..c51560b9a2 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Tests/Sql/SqlTests.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Tests/Sql/SqlTests.cs
@@ -402,7 +402,7 @@ namespace Apache.Ignite.Tests.Sql
             var props = rows.ToDictionary(x => (string)x["NAME"]!, x => 
(string)x["VAL"]!);
 
             Assert.IsTrue(res.HasRowSet);
-            Assert.AreEqual(8, props.Count);
+            Assert.AreEqual(9, props.Count);
 
             Assert.AreEqual("schema-1", props["schema"]);
             Assert.AreEqual("987", props["pageSize"]);
diff --git a/modules/platforms/dotnet/Apache.Ignite/Internal/Sql/Sql.cs 
b/modules/platforms/dotnet/Apache.Ignite/Internal/Sql/Sql.cs
index 9b21a8a547..565b4835b3 100644
--- a/modules/platforms/dotnet/Apache.Ignite/Internal/Sql/Sql.cs
+++ b/modules/platforms/dotnet/Apache.Ignite/Internal/Sql/Sql.cs
@@ -238,6 +238,8 @@ namespace Apache.Ignite.Internal.Sql
             w.Write(statement.PageSize);
             w.Write((long)statement.Timeout.TotalMilliseconds);
             w.WriteNil(); // Session timeout (unused, session is closed by the 
server immediately).
+            w.WriteNil(); // TODO: IGNITE-21604 Time zone id.
+
             WriteProperties(statement, ref w);
             w.Write(statement.Query);
             w.WriteObjectCollectionAsBinaryTuple(args);
diff --git 
a/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/api/ItSqlApiBaseTest.java
 
b/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/api/ItSqlApiBaseTest.java
index 66b3da2a91..ff6ee40c92 100644
--- 
a/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/api/ItSqlApiBaseTest.java
+++ 
b/modules/sql-engine/src/integrationTest/java/org/apache/ignite/internal/sql/api/ItSqlApiBaseTest.java
@@ -29,6 +29,8 @@ import static 
org.junit.jupiter.api.Assertions.assertInstanceOf;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
+import java.time.LocalDateTime;
+import java.time.ZoneId;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Set;
@@ -56,6 +58,7 @@ import org.apache.ignite.sql.SqlBatchException;
 import org.apache.ignite.sql.SqlException;
 import org.apache.ignite.sql.SqlRow;
 import org.apache.ignite.sql.Statement;
+import org.apache.ignite.sql.Statement.StatementBuilder;
 import org.apache.ignite.table.Table;
 import org.apache.ignite.tx.Transaction;
 import org.apache.ignite.tx.TransactionOptions;
@@ -840,6 +843,28 @@ public abstract class ItSqlApiBaseTest extends 
BaseSqlIntegrationTest {
         assertEquals(1, result.result().get(0).intValue(0));
     }
 
+    @ParameterizedTest
+    @ValueSource(strings = {"", "UTC", "Europe/Athens", "America/New_York", 
"Asia/Tokyo"})
+    public void testTimeZoneId(String timeZoneId) {
+        ZoneId zoneId = timeZoneId.isEmpty() ? ZoneId.systemDefault() : 
ZoneId.of(timeZoneId);
+
+        StatementBuilder builder = igniteSql().statementBuilder()
+                .query("SELECT CURRENT_TIMESTAMP")
+                .timeZoneId(zoneId);
+
+        ResultSet<SqlRow> resultSet = igniteSql().execute(null, 
builder.build());
+        SqlRow row = resultSet.next();
+
+        LocalDateTime ts = row.value(0);
+        assertNotNull(ts);
+
+        float tsMillis = 
ts.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
+        float nowMillis = 
LocalDateTime.now(zoneId).atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
+        float deltaMillis = 5000;
+
+        assertEquals(nowMillis, tsMillis, deltaMillis);
+    }
+
     protected ResultSet<SqlRow> executeForRead(IgniteSql sql, String query, 
Object... args) {
         return executeForRead(sql, null, query, args);
     }

Reply via email to