This is an automated email from the ASF dual-hosted git repository. yiguolei 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 c108554f14 [function](date function) add new date function 'to_monday' #13707 c108554f14 is described below commit c108554f14ee9be0cdf73cd69f8698e42874dd91 Author: lsy3993 <110876560+lsy3...@users.noreply.github.com> AuthorDate: Fri Oct 28 08:41:16 2022 +0800 [function](date function) add new date function 'to_monday' #13707 --- be/src/vec/functions/function_timestamp.cpp | 122 +++++++++++++++++++++ .../sql-functions/date-time-functions/to_monday.md | 46 ++++++++ docs/sidebars.json | 1 + .../sql-functions/date-time-functions/to_monday.md | 45 ++++++++ gensrc/script/doris_builtins_functions.py | 8 ++ .../datetime_functions/test_date_function.out | 7 ++ .../datetime_functions/test_date_function.groovy | 27 +++++ 7 files changed, 256 insertions(+) diff --git a/be/src/vec/functions/function_timestamp.cpp b/be/src/vec/functions/function_timestamp.cpp index 63fb1d900c..f941408dc8 100644 --- a/be/src/vec/functions/function_timestamp.cpp +++ b/be/src/vec/functions/function_timestamp.cpp @@ -717,6 +717,124 @@ struct LastDayImpl { } }; +template <typename DateType> +struct MondayImpl { + static constexpr auto name = "to_monday"; + + static Status execute_impl(FunctionContext* context, Block& block, + const ColumnNumbers& arguments, size_t result, + size_t input_rows_count) { + auto null_map = ColumnUInt8::create(input_rows_count, 0); + ColumnPtr res_column; + ColumnPtr argument_column = + block.get_by_position(arguments[0]).column->convert_to_full_column_if_const(); + if constexpr (std::is_same_v<DateType, DataTypeDateTime> || + std::is_same_v<DateType, DataTypeDate>) { + auto data_col = assert_cast<const ColumnVector<Int64>*>(argument_column.get()); + res_column = ColumnInt64::create(input_rows_count); + execute_straight<VecDateTimeValue, Int64, Int64>( + input_rows_count, null_map->get_data(), data_col->get_data(), + static_cast<ColumnVector<Int64>*>(res_column->assume_mutable().get()) + ->get_data()); + + } else if constexpr (std::is_same_v<DateType, DataTypeDateV2>) { + auto data_col = assert_cast<const ColumnVector<UInt32>*>(argument_column.get()); + res_column = ColumnVector<UInt32>::create(input_rows_count); + execute_straight<DateV2Value<DateV2ValueType>, UInt32, UInt32>( + input_rows_count, null_map->get_data(), data_col->get_data(), + static_cast<ColumnVector<UInt32>*>(res_column->assume_mutable().get()) + ->get_data()); + + } else if constexpr (std::is_same_v<DateType, DataTypeDateTimeV2>) { + auto data_col = assert_cast<const ColumnVector<UInt64>*>(argument_column.get()); + res_column = ColumnVector<UInt32>::create(input_rows_count); + execute_straight<DateV2Value<DateTimeV2ValueType>, UInt32, UInt64>( + input_rows_count, null_map->get_data(), data_col->get_data(), + static_cast<ColumnVector<UInt32>*>(res_column->assume_mutable().get()) + ->get_data()); + } + block.replace_by_position( + result, ColumnNullable::create(std::move(res_column), std::move(null_map))); + return Status::OK(); + } + + template <typename DateValueType, typename ReturnType, typename InputDateType> + static void execute_straight(size_t input_rows_count, NullMap& null_map, + const PaddedPODArray<InputDateType>& data_col, + PaddedPODArray<ReturnType>& res_data) { + for (int i = 0; i < input_rows_count; i++) { + if constexpr (std::is_same_v<DateValueType, VecDateTimeValue>) { + const auto& cur_data = data_col[i]; + auto ts_value = binary_cast<Int64, VecDateTimeValue>(cur_data); + if (!ts_value.is_valid_date()) { + null_map[i] = 1; + continue; + } + if (is_special_day(ts_value.year(), ts_value.month(), ts_value.day())) { + ts_value.set_time(ts_value.year(), ts_value.month(), 1, 0, 0, 0); + ts_value.set_type(TIME_DATE); + res_data[i] = binary_cast<VecDateTimeValue, Int64>(ts_value); + continue; + } + + // day_of_week, from 1(Mon) to 7(Sun) + int day_of_week = ts_value.weekday() + 1; + int gap_of_monday = day_of_week - 1; + TimeInterval interval(DAY, gap_of_monday, true); + ts_value.template date_add_interval<DAY>(interval); + ts_value.set_type(TIME_DATE); + res_data[i] = binary_cast<VecDateTimeValue, Int64>(ts_value); + + } else if constexpr (std::is_same_v<DateValueType, DateV2Value<DateV2ValueType>>) { + const auto& cur_data = data_col[i]; + auto ts_value = binary_cast<UInt32, DateValueType>(cur_data); + if (!ts_value.is_valid_date()) { + null_map[i] = 1; + continue; + } + if (is_special_day(ts_value.year(), ts_value.month(), ts_value.day())) { + ts_value.template set_time_unit<TimeUnit::DAY>(1); + res_data[i] = binary_cast<DateValueType, UInt32>(ts_value); + continue; + } + + // day_of_week, from 1(Mon) to 7(Sun) + int day_of_week = ts_value.weekday() + 1; + int gap_of_monday = day_of_week - 1; + TimeInterval interval(DAY, gap_of_monday, true); + ts_value.template date_add_interval<DAY>(interval); + res_data[i] = binary_cast<DateValueType, UInt32>(ts_value); + } else { + const auto& cur_data = data_col[i]; + auto ts_value = binary_cast<UInt64, DateValueType>(cur_data); + if (!ts_value.is_valid_date()) { + null_map[i] = 1; + continue; + } + if (is_special_day(ts_value.year(), ts_value.month(), ts_value.day())) { + ts_value.set_time(ts_value.year(), ts_value.month(), 1, 0, 0, 0, 0); + UInt64 cast_value = binary_cast<DateValueType, UInt64>(ts_value); + DataTypeDateTimeV2::cast_to_date_v2(cast_value, res_data[i]); + continue; + } + // day_of_week, from 1(Mon) to 7(Sun) + int day_of_week = ts_value.weekday() + 1; + int gap_of_monday = day_of_week - 1; + TimeInterval interval(DAY, gap_of_monday, true); + ts_value.template date_add_interval<DAY>(interval); + ts_value.set_time(ts_value.year(), ts_value.month(), ts_value.day(), 0, 0, 0, 0); + UInt64 cast_value = binary_cast<DateValueType, UInt64>(ts_value); + DataTypeDateTimeV2::cast_to_date_v2(cast_value, res_data[i]); + } + } + } + + // specially, 1970-01-01, 1970-01-02, 1970-01-03 and 1970-01-04 return 1970-01-01 + static bool is_special_day(int year, int month, int day) { + return year == 1970 && month == 1 && day > 0 && day < 5; + } +}; + template <typename Impl> class FunctionOtherTypesToDateType : public IFunction { public: @@ -771,6 +889,10 @@ void register_function_timestamp(SimpleFunctionFactory& factory) { factory.register_function<FunctionDateOrDateTimeToDate<LastDayImpl, DataTypeDate>>(); factory.register_function<FunctionDateOrDateTimeToDate<LastDayImpl, DataTypeDateV2>>(); factory.register_function<FunctionDateOrDateTimeToDate<LastDayImpl, DataTypeDateTimeV2>>(); + factory.register_function<FunctionDateOrDateTimeToDate<MondayImpl, DataTypeDateV2>>(); + factory.register_function<FunctionDateOrDateTimeToDate<MondayImpl, DataTypeDateTimeV2>>(); + factory.register_function<FunctionDateOrDateTimeToDate<MondayImpl, DataTypeDate>>(); + factory.register_function<FunctionDateOrDateTimeToDate<MondayImpl, DataTypeDateTime>>(); } } // namespace doris::vectorized diff --git a/docs/en/docs/sql-manual/sql-functions/date-time-functions/to_monday.md b/docs/en/docs/sql-manual/sql-functions/date-time-functions/to_monday.md new file mode 100644 index 0000000000..dde3f877aa --- /dev/null +++ b/docs/en/docs/sql-manual/sql-functions/date-time-functions/to_monday.md @@ -0,0 +1,46 @@ +--- +{ + "title": "to_monday", + "language": "en" +} +--- + +<!-- +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. +--> + +## to_monday +### Description +#### Syntax + +`DATE to_monday(DATETIME date)` + +Round a date or datetime down to the nearest Monday, return type is Date or DateV2. +Specially, input 1970-01-01, 1970-01-02, 1970-01-03 and 1970-01-04 will return '1970-01-01' + +### example + +``` +MySQL [(none)]> select to_monday('2022-09-10'); ++----------------------------------+ +| to_monday('2022-09-10 00:00:00') | ++----------------------------------+ +| 2022-09-05 | ++----------------------------------+ +``` + +### keywords + MONDAY diff --git a/docs/sidebars.json b/docs/sidebars.json index 4cf82d482b..6d515f636d 100644 --- a/docs/sidebars.json +++ b/docs/sidebars.json @@ -294,6 +294,7 @@ "sql-manual/sql-functions/date-time-functions/second", "sql-manual/sql-functions/date-time-functions/from_days", "sql-manual/sql-functions/date-time-functions/last_day", + "sql-manual/sql-functions/date-time-functions/to_monday", "sql-manual/sql-functions/date-time-functions/from_unixtime", "sql-manual/sql-functions/date-time-functions/unix_timestamp", "sql-manual/sql-functions/date-time-functions/utc_timestamp", diff --git a/docs/zh-CN/docs/sql-manual/sql-functions/date-time-functions/to_monday.md b/docs/zh-CN/docs/sql-manual/sql-functions/date-time-functions/to_monday.md new file mode 100644 index 0000000000..55f6e46b05 --- /dev/null +++ b/docs/zh-CN/docs/sql-manual/sql-functions/date-time-functions/to_monday.md @@ -0,0 +1,45 @@ +--- +{ + "title": "to_monday", + "language": "en" +} +--- + +<!-- +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. +--> + +## to_monday +### Description +#### Syntax + +`DATE to_monday(DATETIME date)` + +将日期或带时间的日期向下舍入到最近的星期一。作为一种特殊情况,日期参数 1970-01-01、1970-01-02、1970-01-03 和 1970-01-04 返回日期 1970-01-01 + +### example + +``` +MySQL [(none)]> select to_monday('2022-09-10'); ++----------------------------------+ +| to_monday('2022-09-10 00:00:00') | ++----------------------------------+ +| 2022-09-05 | ++----------------------------------+ +``` + +### keywords + MONDAY diff --git a/gensrc/script/doris_builtins_functions.py b/gensrc/script/doris_builtins_functions.py index 8e9b447cde..444cf48716 100755 --- a/gensrc/script/doris_builtins_functions.py +++ b/gensrc/script/doris_builtins_functions.py @@ -532,6 +532,14 @@ visible_functions = [ [['last_day'], 'DATEV2', ['DATEV2'], '_ZN5doris18TimestampFunctions8last_dayEPN9doris_udf15FunctionContextERKNS1_11DateTimeValE', '', '', 'vec', 'ALWAYS_NULLABLE'], + [['to_monday'], 'DATEV2', ['DATETIMEV2'], + '', '', '', 'vec', 'ALWAYS_NULLABLE'], + [['to_monday'], 'DATEV2', ['DATEV2'], + '','', '', 'vec', 'ALWAYS_NULLABLE'], + [['to_monday'], 'DATE', ['DATETIME'], + '', '', '', 'vec', 'ALWAYS_NULLABLE'], + [['to_monday'], 'DATE', ['DATE'], + '','', '', 'vec', 'ALWAYS_NULLABLE'], [['to_days'], 'INT', ['DATE'], '_ZN5doris18TimestampFunctions7to_daysEPN9doris_udf15FunctionContextERKNS1_11DateTimeValE', '', '', 'vec', 'ALWAYS_NULLABLE'], diff --git a/regression-test/data/query_p0/sql_functions/datetime_functions/test_date_function.out b/regression-test/data/query_p0/sql_functions/datetime_functions/test_date_function.out index b465af0658..847060d35b 100644 --- a/regression-test/data/query_p0/sql_functions/datetime_functions/test_date_function.out +++ b/regression-test/data/query_p0/sql_functions/datetime_functions/test_date_function.out @@ -541,3 +541,10 @@ true 2022-01-31 2022-01-31 2022-02-28 2022-02-28 +-- !sql -- +\N \N \N \N +1970-01-01 1970-01-01 1970-01-01 1970-01-01 +2000-01-31 2000-01-31 2000-01-31 2000-01-31 +2021-12-27 2021-12-27 2021-12-27 2021-12-27 +2022-02-28 2022-02-28 2022-02-28 2022-02-28 + diff --git a/regression-test/suites/query_p0/sql_functions/datetime_functions/test_date_function.groovy b/regression-test/suites/query_p0/sql_functions/datetime_functions/test_date_function.groovy index 7ff926157f..b63de704e1 100644 --- a/regression-test/suites/query_p0/sql_functions/datetime_functions/test_date_function.groovy +++ b/regression-test/suites/query_p0/sql_functions/datetime_functions/test_date_function.groovy @@ -477,4 +477,31 @@ suite("test_date_function") { select last_day(birth), last_day(birth1) from ${tableName}; """ sql """ DROP TABLE IF EXISTS ${tableName}; """ + + // test to_monday + sql """ SET enable_vectorized_engine = TRUE; """ + sql """ DROP TABLE IF EXISTS ${tableName}; """ + sql """ + CREATE TABLE IF NOT EXISTS ${tableName} ( + birth date, + birth1 datev2, + birth2 datetime, + birth3 datetimev2) + UNIQUE KEY(birth, birth1, birth2, birth3) + DISTRIBUTED BY HASH (birth) BUCKETS 1 + PROPERTIES( "replication_allocation" = "tag.location.default: 1"); + """ + sql """ + insert into ${tableName} values + ('2022-01-01', '2022-01-01', '2022-01-01 00:00:00', '2022-01-01 00:00:00'), + ('2000-02-01', '2000-02-01', '2000-02-01 00:00:00', '2000-02-01 00:00:00.123'), + ('2022-02-29', '2022-02-29', '2022-02-29 00:00:00', '2022-02-29 00:00:00'), + ('2022-02-28', '2022-02-28', '2022-02-28 23:59:59', '2022-02-28 23:59:59'), + ('1970-01-02', '1970-01-02', '1970-01-02 01:02:03', '1970-01-02 02:03:04');""" + qt_sql """ + select to_monday(birth), to_monday(birth1), + to_monday(birth2), to_monday(birth3) + from ${tableName}; + """ + sql """ DROP TABLE IF EXISTS ${tableName}; """ } --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org For additional commands, e-mail: commits-h...@doris.apache.org