This is an automated email from the ASF dual-hosted git repository.
eldenmoon pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/master by this push:
new 55b99a7eda9 [fix](point-query) Fix point query ignoring session
timezone for functions like from_unixtime (#60913)
55b99a7eda9 is described below
commit 55b99a7eda9f26d34623212b77e8a77f6d009235
Author: lihangyu <[email protected]>
AuthorDate: Tue Mar 3 18:12:33 2026 +0800
[fix](point-query) Fix point query ignoring session timezone for functions
like from_unixtime (#60913)
Point queries on unique key tables with row store incorrectly used the
default timezone (Asia/Shanghai) instead of the session timezone when
evaluating timezone-sensitive functions like from_unixtime(). This was
because PTabletKeyLookupRequest did not carry timezone information, and
the RuntimeState created in Reusable::init() always used the default
timezone.
The fix adds a time_zone field to PTabletKeyLookupRequest, sets it from
the session variable in FE PointQueryExecutor, and applies it to the
RuntimeState in BE PointQueryExecutor::init().
Changes:
- gensrc/proto: Add time_zone field to PTabletKeyLookupRequest
- FE: Send session timezone in PointQueryExecutor.getNextInternal()
- BE: Add RuntimeState::set_timezone() and use it in
PointQueryExecutor::init()
- Add regression test for point query timezone handling
---
be/src/runtime/runtime_state.h | 5 ++
be/src/service/point_query_executor.cpp | 4 ++
.../org/apache/doris/qe/PointQueryExecutor.java | 6 ++
gensrc/proto/internal_service.proto | 2 +
.../point_query_p0/test_point_query_timezone.out | 15 +++++
.../test_point_query_timezone.groovy | 71 ++++++++++++++++++++++
6 files changed, 103 insertions(+)
diff --git a/be/src/runtime/runtime_state.h b/be/src/runtime/runtime_state.h
index e07ad2a8a7e..126c8f4f617 100644
--- a/be/src/runtime/runtime_state.h
+++ b/be/src/runtime/runtime_state.h
@@ -47,6 +47,7 @@
#include "runtime/workload_group/workload_group.h"
#include "util/debug_util.h"
#include "util/runtime_profile.h"
+#include "util/timezone_utils.h"
#include "vec/runtime/vector_search_user_params.h"
namespace doris {
@@ -181,6 +182,10 @@ public:
// if possible, use timezone_obj() rather than timezone()
const std::string& timezone() const { return _timezone; }
const cctz::time_zone& timezone_obj() const { return _timezone_obj; }
+ void set_timezone(const std::string& timezone) {
+ _timezone = timezone;
+ TimezoneUtils::find_cctz_time_zone(_timezone, _timezone_obj);
+ }
const std::string& lc_time_names() const { return _lc_time_names; }
const std::string& user() const { return _user; }
const TUniqueId& query_id() const { return _query_id; }
diff --git a/be/src/service/point_query_executor.cpp
b/be/src/service/point_query_executor.cpp
index a8f8eadd1f2..4b908e70c6c 100644
--- a/be/src/service/point_query_executor.cpp
+++ b/be/src/service/point_query_executor.cpp
@@ -319,6 +319,10 @@ Status PointQueryExecutor::init(const
PTabletKeyLookupRequest* request,
*_tablet->tablet_schema(), 1));
}
}
+ // Set timezone from request for functions like from_unixtime()
+ if (request->has_time_zone() && !request->time_zone().empty()) {
+ _reusable->runtime_state()->set_timezone(request->time_zone());
+ }
if (request->has_version() && request->version() >= 0) {
_version = request->version();
}
diff --git
a/fe/fe-core/src/main/java/org/apache/doris/qe/PointQueryExecutor.java
b/fe/fe-core/src/main/java/org/apache/doris/qe/PointQueryExecutor.java
index 5925b428a16..8ddf2487313 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/qe/PointQueryExecutor.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/qe/PointQueryExecutor.java
@@ -278,6 +278,12 @@ public class PointQueryExecutor implements CoordInterface {
.setOutputExpr(shortCircuitQueryContext.serializedOutputExpr)
.setQueryOptions(shortCircuitQueryContext.serializedQueryOptions)
.setIsBinaryRow(ConnectContext.get().command ==
MysqlCommand.COM_STMT_EXECUTE);
+ // Set timezone for functions like from_unixtime
+ String timeZone =
ConnectContext.get().getSessionVariable().getTimeZone();
+ if ("CST".equals(timeZone)) {
+ timeZone = "Asia/Shanghai";
+ }
+ requestBuilder.setTimeZone(timeZone);
if (snapshotVisibleVersions != null &&
!snapshotVisibleVersions.isEmpty()) {
requestBuilder.setVersion(snapshotVisibleVersions.get(0));
}
diff --git a/gensrc/proto/internal_service.proto
b/gensrc/proto/internal_service.proto
index f2c0475791e..808a70e327a 100644
--- a/gensrc/proto/internal_service.proto
+++ b/gensrc/proto/internal_service.proto
@@ -381,6 +381,8 @@ message PTabletKeyLookupRequest {
optional int64 version = 7;
// serilized from TQueryOptions
optional bytes query_options = 8;
+ // timezone string, e.g. "America/Mexico_City"
+ optional string time_zone = 9;
}
message PTabletKeyLookupResponse {
diff --git a/regression-test/data/point_query_p0/test_point_query_timezone.out
b/regression-test/data/point_query_p0/test_point_query_timezone.out
new file mode 100644
index 00000000000..b0c47ea961d
--- /dev/null
+++ b/regression-test/data/point_query_p0/test_point_query_timezone.out
@@ -0,0 +1,15 @@
+-- This file is automatically generated. You should know what you did if you
want to edit this
+-- !full_scan --
+job_001 2024-01-31 18:00:00.000000
+job_002 2024-02-01 18:00:00.000000
+
+-- !point_query --
+job_001 2024-01-31 18:00:00.000000
+
+-- !full_scan_tokyo --
+job_001 2024-02-01 09:00:00.000000
+job_002 2024-02-02 09:00:00.000000
+
+-- !point_query_tokyo --
+job_001 2024-02-01 09:00:00.000000
+
diff --git
a/regression-test/suites/point_query_p0/test_point_query_timezone.groovy
b/regression-test/suites/point_query_p0/test_point_query_timezone.groovy
new file mode 100644
index 00000000000..927552e8f3c
--- /dev/null
+++ b/regression-test/suites/point_query_p0/test_point_query_timezone.groovy
@@ -0,0 +1,71 @@
+// 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.
+
+// Test point query timezone handling (cir_19478)
+// Point queries on unique key tables with row store should respect
+// session timezone for functions like from_unixtime()
+suite("test_point_query_timezone") {
+ def tableName = "test_point_query_timezone_tbl"
+
+ sql """ DROP TABLE IF EXISTS ${tableName} """
+ sql """
+ CREATE TABLE ${tableName} (
+ `job_id` VARCHAR(50) NOT NULL,
+ `capture_time` BIGINT NOT NULL,
+ `event_time` BIGINT NULL
+ ) ENGINE=OLAP
+ UNIQUE KEY(`job_id`, `capture_time`)
+ DISTRIBUTED BY HASH(`job_id`) BUCKETS 1
+ PROPERTIES (
+ "replication_allocation" = "tag.location.default: 1",
+ "store_row_column" = "true",
+ "enable_unique_key_merge_on_write" = "true"
+ )
+ """
+
+ sql """ INSERT INTO ${tableName} VALUES ('job_001', 1706745600000,
1706745600000) """
+ sql """ INSERT INTO ${tableName} VALUES ('job_002', 1706832000000,
1706832000000) """
+
+ // Verify it's a short-circuit (point) query
+ explain {
+ sql("SELECT * FROM ${tableName} WHERE job_id = 'job_001' AND
capture_time = 1706745600000")
+ contains "SHORT-CIRCUIT"
+ }
+
+ // Test with America/Mexico_City timezone (UTC-6)
+ // 1706745600 = 2024-02-01 00:00:00 UTC = 2024-01-31 18:00:00 Mexico_City
+ sql """ SET time_zone = 'America/Mexico_City' """
+
+ // Full table scan - should use session timezone
+ qt_full_scan """ SELECT job_id, from_unixtime(event_time/1000) AS t FROM
${tableName} ORDER BY job_id """
+
+ // Point query - should also use session timezone (this was the bug)
+ qt_point_query """ SELECT job_id, from_unixtime(event_time/1000) AS t FROM
${tableName} WHERE job_id = 'job_001' AND capture_time = 1706745600000 """
+
+ // Test with Asia/Tokyo timezone (UTC+9)
+ // 1706745600 = 2024-02-01 00:00:00 UTC = 2024-02-01 09:00:00 Tokyo
+ sql """ SET time_zone = 'Asia/Tokyo' """
+
+ qt_full_scan_tokyo """ SELECT job_id, from_unixtime(event_time/1000) AS t
FROM ${tableName} ORDER BY job_id """
+
+ qt_point_query_tokyo """ SELECT job_id, from_unixtime(event_time/1000) AS
t FROM ${tableName} WHERE job_id = 'job_001' AND capture_time = 1706745600000
"""
+
+ // Reset timezone
+ sql """ SET time_zone = 'Asia/Shanghai' """
+
+ sql """ DROP TABLE IF EXISTS ${tableName} """
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]