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

yiguolei pushed a commit to branch branch-4.1
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/branch-4.1 by this push:
     new 6b0c7de64d2 [fix](be) Preserve DATE runtime filter types (#69963)
6b0c7de64d2 is described below

commit 6b0c7de64d2a6e65af86051db4ddf5cfadac7fc2
Author: Jerry Hu <[email protected]>
AuthorDate: Wed Nov 4 10:37:26 2026 +0800

    [fix](be) Preserve DATE runtime filter types (#69963)
    
    ### What problem does this PR solve?
    
    Issue Number: None
    
    Remote DATE runtime filters can also lose their DATE type when
    deserialized as DATETIME. Separately, a Variant schema-change regression
    used a value whose text representation depended on whether insertion
    happened before or after a DOUBLE-to-TEXT change.
    
    ### What is changed?
    
    - Decode remote DATE IN and MIN/MAX filter values as DATE, while
    preserving the existing DATETIME behavior.
---
 .../exec/runtime_filter/runtime_filter_wrapper.cpp | 25 ++++++-
 .../runtime_filter/runtime_filter_wrapper_test.cpp | 78 ++++++++++++++++++++++
 2 files changed, 101 insertions(+), 2 deletions(-)

diff --git a/be/src/exec/runtime_filter/runtime_filter_wrapper.cpp 
b/be/src/exec/runtime_filter/runtime_filter_wrapper.cpp
index 330bcb6895e..3afb517aff7 100644
--- a/be/src/exec/runtime_filter/runtime_filter_wrapper.cpp
+++ b/be/src/exec/runtime_filter/runtime_filter_wrapper.cpp
@@ -292,8 +292,18 @@ Status RuntimeFilterWrapper::_assign(const PInFilter& 
in_filter, bool contain_nu
         });
         break;
     }
-    case TYPE_DATETIME:
     case TYPE_DATE: {
+        batch_assign(in_filter, [](std::shared_ptr<HybridSetBase>& set, 
PColumnValue& column) {
+            const auto& string_val_ref = column.stringval();
+            VecDateTimeValue date_val;
+            CastParameters params;
+            
CastToDateOrDatetime::from_string_non_strict_mode<DatelikeTargetType::DATE>(
+                    {string_val_ref.c_str(), string_val_ref.length()}, 
date_val, nullptr, params);
+            set->insert(&date_val);
+        });
+        break;
+    }
+    case TYPE_DATETIME: {
         batch_assign(in_filter, [](std::shared_ptr<HybridSetBase>& set, 
PColumnValue& column) {
             const auto& string_val_ref = column.stringval();
             VecDateTimeValue datetime_val;
@@ -456,8 +466,19 @@ Status RuntimeFilterWrapper::_assign(const PMinMaxFilter& 
minmax_filter, bool co
         int64_t max_val = minmax_filter.max_val().longval();
         return _minmax_func->assign(&min_val, &max_val);
     }
-    case TYPE_DATETIME:
     case TYPE_DATE: {
+        const auto& min_val_ref = minmax_filter.min_val().stringval();
+        const auto& max_val_ref = minmax_filter.max_val().stringval();
+        VecDateTimeValue min_val;
+        VecDateTimeValue max_val;
+        CastParameters params;
+        
CastToDateOrDatetime::from_string_non_strict_mode<DatelikeTargetType::DATE>(
+                {min_val_ref.c_str(), min_val_ref.length()}, min_val, nullptr, 
params);
+        
CastToDateOrDatetime::from_string_non_strict_mode<DatelikeTargetType::DATE>(
+                {max_val_ref.c_str(), max_val_ref.length()}, max_val, nullptr, 
params);
+        return _minmax_func->assign(&min_val, &max_val);
+    }
+    case TYPE_DATETIME: {
         const auto& min_val_ref = minmax_filter.min_val().stringval();
         const auto& max_val_ref = minmax_filter.max_val().stringval();
         VecDateTimeValue min_val;
diff --git a/be/test/exec/runtime_filter/runtime_filter_wrapper_test.cpp 
b/be/test/exec/runtime_filter/runtime_filter_wrapper_test.cpp
index 44cde989ab0..80b0ee0eb23 100644
--- a/be/test/exec/runtime_filter/runtime_filter_wrapper_test.cpp
+++ b/be/test/exec/runtime_filter/runtime_filter_wrapper_test.cpp
@@ -20,10 +20,16 @@
 #include <glog/logging.h>
 #include <gtest/gtest.h>
 
+#include <tuple>
+
+#include "core/data_type/data_type_date.h"
 #include "core/data_type/data_type_number.h"
+#include "exec/runtime_filter/utils.h"
 #include "exprs/bloom_filter_func.h"
 #include "exprs/hybrid_set.h"
 #include "exprs/minmax_predicate.h"
+#include "exprs/vexpr.h"
+#include "exprs/vliteral.h"
 #include "testutil/column_helper.h"
 
 namespace doris {
@@ -248,6 +254,38 @@ TEST_F(RuntimeFilterWrapperTest, TestInAssign) {
 #undef APPLY_FOR_PRIMITIVE_BASE_TYPE
 }
 
+TEST_F(RuntimeFilterWrapperTest, TestDateInAssign) {
+    for (auto [column_type, value, expected_time_type] :
+         {std::tuple {TYPE_DATE, "2020-01-01", TimeType::TIME_DATE},
+          std::tuple {TYPE_DATETIME, "2020-01-01 01:02:03", 
TimeType::TIME_DATETIME}}) {
+        RuntimeFilterParams params {.filter_id = 0,
+                                    .filter_type = 
RuntimeFilterType::IN_FILTER,
+                                    .column_return_type = column_type,
+                                    .null_aware = false,
+                                    .max_in_num = 2};
+        RuntimeFilterWrapper producer(&params);
+        VecDateTimeValue probe = column_type == TYPE_DATE
+                                         ? VecDateTimeValue(0, 2, 0, 0, 0, 
2020, 1, 1)
+                                         : VecDateTimeValue(0, 3, 1, 2, 3, 
2020, 1, 1);
+        producer.hybrid_set()->insert(&probe);
+
+        PMergeFilterRequest request;
+        request.set_filter_type(PFilterType::IN_FILTER);
+        ASSERT_TRUE(producer.to_protobuf(request.mutable_in_filter()).ok());
+        ASSERT_EQ(request.in_filter().values_size(), 1);
+        EXPECT_EQ(request.in_filter().values(0).stringval(), value);
+
+        RuntimeFilterWrapper consumer(&params);
+        ASSERT_TRUE(consumer.assign(request, nullptr).ok());
+        EXPECT_EQ(probe.type(), expected_time_type);
+        EXPECT_TRUE(consumer.hybrid_set()->find(&probe));
+        VecDateTimeValue missing = column_type == TYPE_DATE
+                                           ? VecDateTimeValue(0, 2, 0, 0, 0, 
2020, 1, 2)
+                                           : VecDateTimeValue(0, 3, 1, 2, 3, 
2020, 1, 2);
+        EXPECT_FALSE(consumer.hybrid_set()->find(&missing));
+    }
+}
+
 TEST_F(RuntimeFilterWrapperTest, TestMinMaxAssign) {
     int32_t filter_id = 0;
     RuntimeFilterType filter_type = RuntimeFilterType::MINMAX_FILTER;
@@ -327,6 +365,46 @@ TEST_F(RuntimeFilterWrapperTest, TestMinMaxAssign) {
 #undef APPLY_FOR_PRIMITIVE_BASE_TYPE
 }
 
+TEST_F(RuntimeFilterWrapperTest, TestDateMinMaxAssign) {
+    for (auto [column_type, min_value, max_value, expected_time_type] :
+         {std::tuple {TYPE_DATE, "2020-01-01", "2020-01-02", 
TimeType::TIME_DATE},
+          std::tuple {TYPE_DATETIME, "2020-01-01 01:02:03", "2020-01-02 
04:05:06",
+                      TimeType::TIME_DATETIME}}) {
+        RuntimeFilterParams params {.filter_id = 0,
+                                    .filter_type = 
RuntimeFilterType::MINMAX_FILTER,
+                                    .column_return_type = column_type,
+                                    .null_aware = false};
+        auto wrapper = std::make_shared<RuntimeFilterWrapper>(&params);
+        PMergeFilterRequest request;
+        request.set_filter_type(PFilterType::MINMAX_FILTER);
+        
request.mutable_minmax_filter()->mutable_min_val()->set_stringval(min_value);
+        
request.mutable_minmax_filter()->mutable_max_val()->set_stringval(max_value);
+        ASSERT_TRUE(wrapper->assign(request, nullptr).ok());
+
+        const auto* min_date =
+                static_cast<const 
VecDateTimeValue*>(wrapper->minmax_func()->get_min());
+        const auto* max_date =
+                static_cast<const 
VecDateTimeValue*>(wrapper->minmax_func()->get_max());
+        EXPECT_EQ(min_date->type(), expected_time_type);
+        EXPECT_EQ(max_date->type(), expected_time_type);
+        char min_buffer[30];
+        char max_buffer[30];
+        min_date->to_string(min_buffer);
+        max_date->to_string(max_buffer);
+        EXPECT_STREQ(min_buffer, min_value);
+        EXPECT_STREQ(max_buffer, max_value);
+
+        if (column_type == TYPE_DATE) {
+            VExprSPtr literal;
+            ASSERT_TRUE(create_literal(std::make_shared<DataTypeDate>(), 
min_date, literal).ok());
+            ASSERT_TRUE(literal->is_literal());
+            EXPECT_EQ(literal->data_type()->get_primitive_type(), TYPE_DATE);
+            const auto& literal_column = static_cast<const 
VLiteral&>(*literal).get_column_ptr();
+            EXPECT_EQ((*literal_column)[0].get_type(), TYPE_DATE);
+        }
+    }
+}
+
 TEST_F(RuntimeFilterWrapperTest, TestBloom) {
     std::vector<int> data_vector(10);
     std::iota(data_vector.begin(), data_vector.end(), 0);


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to