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]

Reply via email to