Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -408,7 +408,15 @@ Status DataTypeDateSerDe<T>::from_olap_string(const std::string& str, Field& fie
// Exception!
if (!CastToDateOrDatetime::from_string_non_strict_mode<IsDatetime>(
StringRef(str), res, options.timezone, params)) [[unlikely]] {
return Status::InvalidArgument("parse date or datetime fail, string: '{}'", str);
// Keep the same datelike Field-parser convention as DateV2/DateTimeV2: invalid OLAP
// strings fall back to the type-specific minimum. VecDateTimeValue stores DateV1 and
// DateTimeV1 values, whose minimum valid date is FIRST_DAY.
res = VecDateTimeValue::FIRST_DAY;
if constexpr (IsDatetime) {
res.to_datetime();
} else {
res.cast_to_date();
}
}
field = Field::create_field<T>(std::move(res));
return Status::OK();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ Status DataTypeDateTimeV2SerDe::from_olap_string(const std::string& str, Field&
std::string date_format = "%Y-%m-%d %H:%i:%s.%f";

if (!res.from_date_format_str(date_format.data(), date_format.size(), str.data(), str.size())) {
// On parse failure, fall back to MIN_DATETIME_V2, the packed lower-bound DateTimeV2 value.
res = DateV2Value<DateTimeV2ValueType>(MIN_DATETIME_V2);
}
field = Field::create_field<TYPE_DATETIMEV2>(std::move(res));
Expand Down
1 change: 1 addition & 0 deletions be/src/vec/data_types/serde/data_type_datev2_serde.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@ Status DataTypeDateV2SerDe::from_olap_string(const std::string& str, Field& fiel
((time_tm.tm_year + 1900) << 9) | ((time_tm.tm_mon + 1) << 5) | time_tm.tm_mday;
res = DateV2Value<DateV2ValueType>(value);
} else {
// On parse failure, fall back to MIN_DATE_V2, the packed lower-bound DateV2 value.
res = DateV2Value<DateV2ValueType>(MIN_DATE_V2);
}
field = Field::create_field<TYPE_DATEV2>(std::move(res));
Expand Down
43 changes: 42 additions & 1 deletion be/test/olap/olap_type_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,11 @@
#include "gtest/gtest_pred_impl.h"
#include "olap/olap_common.h"
#include "olap/types.h"
#include "vec/core/field.h"
#include "vec/data_types/data_type_factory.hpp"
#include "vec/data_types/serde/data_type_serde.h"
#include "vec/functions/cast/cast_to_string.h"
#include "vec/runtime/vdatetime_value.h"

namespace doris {

Expand All @@ -39,6 +43,16 @@ class OlapTypeTest : public testing::Test {
}
};

static void expect_from_olap_string_default(const vectorized::DataTypePtr& data_type,
const std::string& input,
const vectorized::Field& expected_field) {
vectorized::Field field;
vectorized::DataTypeSerDe::FormatOptions options;
auto status = data_type->get_serde()->from_olap_string(input, field, options);
ASSERT_TRUE(status.ok()) << data_type->get_name() << " failed: " << status.to_string();
EXPECT_EQ(field, expected_field) << data_type->get_name();
}

// deserialize float string serialized by old version of Doris
TEST_F(OlapTypeTest, deser_float_old) {
std::vector<float> normal_input_values = {
Expand Down Expand Up @@ -576,4 +590,31 @@ TEST_F(OlapTypeTest, ser_deser_double) {
<< ", diff_ratio: " << fmt::format("{:.17g}", diff_ratio);
}
}
} // namespace doris

TEST_F(OlapTypeTest, datelike_from_olap_string_parse_failure_defaults) {
const std::string invalid = "not-a-valid-datelike-value";

auto datev1_default = VecDateTimeValue::FIRST_DAY;
datev1_default.cast_to_date();
expect_from_olap_string_default(
vectorized::DataTypeFactory::instance().create_data_type(TYPE_DATE, false), invalid,
vectorized::Field::create_field<TYPE_DATE>(datev1_default));

auto datetimev1_default = VecDateTimeValue::FIRST_DAY;
datetimev1_default.to_datetime();
expect_from_olap_string_default(
vectorized::DataTypeFactory::instance().create_data_type(TYPE_DATETIME, false), invalid,
vectorized::Field::create_field<TYPE_DATETIME>(datetimev1_default));

expect_from_olap_string_default(
vectorized::DataTypeFactory::instance().create_data_type(TYPE_DATEV2, false), invalid,
vectorized::Field::create_field<TYPE_DATEV2>(
DateV2Value<DateV2ValueType>(MIN_DATE_V2)));

expect_from_olap_string_default(
vectorized::DataTypeFactory::instance().create_data_type(TYPE_DATETIMEV2, false),
invalid,
vectorized::Field::create_field<TYPE_DATETIMEV2>(
DateV2Value<DateTimeV2ValueType>(MIN_DATETIME_V2)));
}
} // namespace doris
Loading