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(¶ms);
+ 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(¶ms);
+ 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>(¶ms);
+ 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]