diff --git a/be/src/util/date_func.cpp b/be/src/util/date_func.cpp index 2c0ebdd811..e324d68106 100644 --- a/be/src/util/date_func.cpp +++ b/be/src/util/date_func.cpp @@ -109,4 +109,25 @@ int32_t time_to_buffer_from_double(double time, char* buffer) { return buffer - begin; } +std::string time_to_buffer_from_double(double time) { + fmt::memory_buffer buffer; + if (time < 0) { + time = -time; + fmt::format_to(buffer, "-"); + } + if (time > 3020399) { + time = 3020399; + } + int64_t hour = (int64_t)(time / 3600); + int32_t minute = ((int32_t)(time / 60)) % 60; + int32_t second = ((int32_t)time) % 60; + if (hour >= 100) { + fmt::format_to(buffer, fmt::format("{}", hour)); + } else { + fmt::format_to(buffer, fmt::format("{:02d}", hour)); + } + fmt::format_to(buffer, fmt::format(":{:02d}:{:02d}", minute, second)); + return fmt::to_string(buffer); +} + } // namespace doris diff --git a/be/src/util/date_func.h b/be/src/util/date_func.h index e5843b64af..4378fd32e1 100644 --- a/be/src/util/date_func.h +++ b/be/src/util/date_func.h @@ -32,4 +32,6 @@ int32_t time_to_buffer_from_double(double time, char* buffer); uint32_t timestamp_from_date_v2(const std::string& date_str); uint64_t timestamp_from_datetime_v2(const std::string& date_str); +std::string time_to_buffer_from_double(double time); + } // namespace doris diff --git a/be/src/vec/CMakeLists.txt b/be/src/vec/CMakeLists.txt index 4426ba63a7..0d845b19dc 100644 --- a/be/src/vec/CMakeLists.txt +++ b/be/src/vec/CMakeLists.txt @@ -89,6 +89,7 @@ set(VEC_FILES data_types/data_type_date_time.cpp data_types/data_type_time_v2.cpp data_types/data_type_jsonb.cpp + data_types/data_type_time.cpp exec/vaggregation_node.cpp exec/varrow_scanner.cpp exec/vsort_node.cpp diff --git a/be/src/vec/data_types/data_type_factory.cpp b/be/src/vec/data_types/data_type_factory.cpp index 85dfc445ba..e622d979d5 100644 --- a/be/src/vec/data_types/data_type_factory.cpp +++ b/be/src/vec/data_types/data_type_factory.cpp @@ -20,6 +20,8 @@ #include "vec/data_types/data_type_factory.hpp" +#include "data_type_time.h" + namespace doris::vectorized { DataTypePtr DataTypeFactory::create_data_type(const doris::Field& col_desc) { @@ -92,6 +94,8 @@ DataTypePtr DataTypeFactory::create_data_type(const TypeDescriptor& col_desc, bo break; case TYPE_TIME: case TYPE_TIMEV2: + nested = std::make_shared(); + break; case TYPE_DOUBLE: nested = std::make_shared(); break; diff --git a/be/src/vec/data_types/data_type_time.cpp b/be/src/vec/data_types/data_type_time.cpp new file mode 100644 index 0000000000..caa4e0530c --- /dev/null +++ b/be/src/vec/data_types/data_type_time.cpp @@ -0,0 +1,52 @@ +// 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. +// This file is copied from +// https://github.com/ClickHouse/ClickHouse/blob/master/src/DataTypes/DataTypeDateTime.cpp +// and modified by Doris + +#include "vec/data_types/data_type_time.h" + +#include "util/date_func.h" +#include "vec/columns/columns_number.h" + +namespace doris::vectorized { + +bool DataTypeTime::equals(const IDataType& rhs) const { + return typeid(rhs) == typeid(*this); +} + +std::string DataTypeTime::to_string(const IColumn& column, size_t row_num) const { + Float64 float_val = + assert_cast(*column.convert_to_full_column_if_const().get()) + .get_data()[row_num]; + return time_to_buffer_from_double(float_val); +} + +void DataTypeTime::to_string(const IColumn& column, size_t row_num, BufferWritable& ostr) const { + Float64 float_val = + assert_cast(*column.convert_to_full_column_if_const().get()) + .get_data()[row_num]; + std::string time_val = time_to_buffer_from_double(float_val); + // DateTime to_string the end is /0 + ostr.write(time_val.data(), time_val.size()); +} + +MutableColumnPtr DataTypeTime::create_column() const { + return DataTypeNumberBase::create_column(); +} + +} // namespace doris::vectorized diff --git a/be/src/vec/data_types/data_type_time.h b/be/src/vec/data_types/data_type_time.h new file mode 100644 index 0000000000..b10c9d88d5 --- /dev/null +++ b/be/src/vec/data_types/data_type_time.h @@ -0,0 +1,53 @@ +// 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. +// This file is copied from +// https://github.com/ClickHouse/ClickHouse/blob/master/src/DataTypes/DataTypeDateTime.h +// and modified by Doris + +#pragma once + +#include "vec/data_types/data_type_number.h" +#include "vec/data_types/data_type_number_base.h" + +namespace doris::vectorized { + +class DataTypeTime final : public DataTypeNumberBase { +public: + DataTypeTime() = default; + + bool equals(const IDataType& rhs) const override; + + std::string to_string(const IColumn& column, size_t row_num) const override; + + void to_string(const IColumn& column, size_t row_num, BufferWritable& ostr) const override; + + MutableColumnPtr create_column() const override; + + bool can_be_used_as_version() const override { return true; } + bool is_summable() const override { return true; } + bool can_be_used_in_bit_operations() const override { return true; } + bool can_be_used_in_boolean_context() const override { return true; } + bool can_be_inside_nullable() const override { return true; } + + bool can_be_promoted() const override { return true; } + DataTypePtr promote_numeric_type() const override { + using PromotedType = DataTypeNumber>; + return std::make_shared(); + } +}; + +} // namespace doris::vectorized diff --git a/be/src/vec/functions/function_date_or_datetime_computation.h b/be/src/vec/functions/function_date_or_datetime_computation.h index 4900f1a48a..eba6d17fc7 100644 --- a/be/src/vec/functions/function_date_or_datetime_computation.h +++ b/be/src/vec/functions/function_date_or_datetime_computation.h @@ -27,6 +27,7 @@ #include "vec/data_types/data_type_date.h" #include "vec/data_types/data_type_date_time.h" #include "vec/data_types/data_type_number.h" +#include "vec/data_types/data_type_time.h" #include "vec/functions/function.h" #include "vec/functions/function_helpers.h" #include "vec/runtime/vdatetime_value.h" @@ -245,7 +246,7 @@ struct SubtractYearsImpl : SubtractIntervalImpl, DateType } \ }; DECLARE_DATE_FUNCTIONS(DateDiffImpl, datediff, DataTypeInt32, (ts0.daynr() - ts1.daynr())); -DECLARE_DATE_FUNCTIONS(TimeDiffImpl, timediff, DataTypeFloat64, ts0.second_diff(ts1)); +DECLARE_DATE_FUNCTIONS(TimeDiffImpl, timediff, DataTypeTime, ts0.second_diff(ts1)); #define TIME_DIFF_FUNCTION_IMPL(CLASS, NAME, UNIT) \ DECLARE_DATE_FUNCTIONS(CLASS, NAME, DataTypeInt64, datetime_diff(ts1, ts0)) @@ -798,7 +799,7 @@ struct CurrentDateImpl { template struct CurrentTimeImpl { - using ReturnType = DataTypeFloat64; + using ReturnType = DataTypeTime; static constexpr auto name = FunctionName::name; static Status execute(FunctionContext* context, Block& block, const ColumnNumbers& arguments, size_t result, size_t input_rows_count) { diff --git a/be/src/vec/functions/function_running_difference.h b/be/src/vec/functions/function_running_difference.h index b9b53892f9..85f17ad786 100644 --- a/be/src/vec/functions/function_running_difference.h +++ b/be/src/vec/functions/function_running_difference.h @@ -31,6 +31,7 @@ #include "vec/data_types/data_type_date_time.h" #include "vec/data_types/data_type_nullable.h" #include "vec/data_types/data_type_number.h" +#include "vec/data_types/data_type_time.h" #include "vec/data_types/data_type_time_v2.h" #include "vec/data_types/number_traits.h" #include "vec/functions/function.h" @@ -75,7 +76,7 @@ public: } else if (which.is_decimal()) { return_type = nested_type; } else if (which.is_date_time() || which.is_date_time_v2()) { - return_type = std::make_shared(); + return_type = std::make_shared(); } else if (which.is_date() || which.is_date_v2()) { return_type = std::make_shared(); } diff --git a/be/test/vec/function/function_running_difference_test.cpp b/be/test/vec/function/function_running_difference_test.cpp index 6b002097b7..0245db4523 100644 --- a/be/test/vec/function/function_running_difference_test.cpp +++ b/be/test/vec/function/function_running_difference_test.cpp @@ -55,7 +55,7 @@ TEST(FunctionRunningDifferenceTest, function_running_difference_test) { {{std::string("2019-07-18 12:00:06")}, (double)1.0}, {{std::string("2019-07-18 12:00:08")}, (double)2.0}, {{std::string("2019-07-18 12:00:10")}, (double)2.0}}; - check_function(func_name, input_types, data_set); + check_function(func_name, input_types, data_set); } { InputTypeSet input_types = {TypeIndex::Date}; diff --git a/be/test/vec/function/function_test_util.h b/be/test/vec/function/function_test_util.h index 2603d224a4..6083278d29 100644 --- a/be/test/vec/function/function_test_util.h +++ b/be/test/vec/function/function_test_util.h @@ -35,6 +35,7 @@ #include "vec/data_types/data_type_jsonb.h" #include "vec/data_types/data_type_number.h" #include "vec/data_types/data_type_string.h" +#include "vec/data_types/data_type_time.h" #include "vec/functions/simple_function_factory.h" namespace doris::vectorized { @@ -233,7 +234,8 @@ Status check_function(const std::string& func_name, const InputTypeSet& input_ty fn_ctx_return.type = doris_udf::FunctionContext::TYPE_BOOLEAN; } else if constexpr (std::is_same_v) { fn_ctx_return.type = doris_udf::FunctionContext::TYPE_INT; - } else if constexpr (std::is_same_v) { + } else if constexpr (std::is_same_v || + std::is_same_v) { fn_ctx_return.type = doris_udf::FunctionContext::TYPE_DOUBLE; } else if constexpr (std::is_same_v) { fn_ctx_return.type = doris_udf::FunctionContext::TYPE_DATETIME; @@ -293,7 +295,8 @@ Status check_function(const std::string& func_name, const InputTypeSet& input_ty const auto& column_data = field.get>().get_value(); EXPECT_EQ(expect_data.value, column_data.value) << " at row " << i; } else if constexpr (std::is_same_v || - std::is_same_v) { + std::is_same_v || + std::is_same_v) { const auto& column_data = field.get(); EXPECT_DOUBLE_EQ(expect_data, column_data) << " at row " << i; } else { diff --git a/be/test/vec/function/function_time_test.cpp b/be/test/vec/function/function_time_test.cpp index 18455a4566..8a68a608b8 100644 --- a/be/test/vec/function/function_time_test.cpp +++ b/be/test/vec/function/function_time_test.cpp @@ -186,7 +186,7 @@ TEST(VTimestampFunctionsTest, timediff_test) { {{std::string("2019-00-18 12:00:00"), std::string("2019-07-18 13:01:02")}, Null()}, {{std::string("2019-07-18 12:00:00"), std::string("2019-07-00 13:01:02")}, Null()}}; - check_function(func_name, input_types, data_set); + check_function(func_name, input_types, data_set); } TEST(VTimestampFunctionsTest, date_format_test) { @@ -849,7 +849,7 @@ TEST(VTimestampFunctionsTest, timediff_v2_test) { {{std::string("2019-00-18"), std::string("2019-07-18")}, Null()}, {{std::string("2019-07-18"), std::string("2019-07-00")}, Null()}}; - check_function(func_name, input_types, data_set); + check_function(func_name, input_types, data_set); } { @@ -860,7 +860,7 @@ TEST(VTimestampFunctionsTest, timediff_v2_test) { {{std::string("2019-00-18"), std::string("2019-07-18")}, Null()}, {{std::string("2019-07-18"), std::string("2019-07-00")}, Null()}}; - check_function(func_name, input_types, data_set); + check_function(func_name, input_types, data_set); } { @@ -871,7 +871,7 @@ TEST(VTimestampFunctionsTest, timediff_v2_test) { {{std::string("2019-00-18"), std::string("2019-07-18")}, Null()}, {{std::string("2019-07-18"), std::string("2019-07-00")}, Null()}}; - check_function(func_name, input_types, data_set); + check_function(func_name, input_types, data_set); } { @@ -883,7 +883,7 @@ TEST(VTimestampFunctionsTest, timediff_v2_test) { {{std::string("2019-00-18 00:00:00"), std::string("2019-07-18")}, Null()}, {{std::string("2019-07-18 00:00:00"), std::string("2019-07-00")}, Null()}}; - check_function(func_name, input_types, data_set); + check_function(func_name, input_types, data_set); } { @@ -895,7 +895,7 @@ TEST(VTimestampFunctionsTest, timediff_v2_test) { {{std::string("2019-00-18"), std::string("2019-07-18 00:00:00")}, Null()}, {{std::string("2019-07-18"), std::string("2019-07-00 00:00:00")}, Null()}}; - check_function(func_name, input_types, data_set); + check_function(func_name, input_types, data_set); } { InputTypeSet input_types = {TypeIndex::DateTimeV2, TypeIndex::DateTimeV2}; @@ -906,7 +906,7 @@ TEST(VTimestampFunctionsTest, timediff_v2_test) { {{std::string("2019-00-18 00:00:00"), std::string("2019-07-18 00:00:00")}, Null()}, {{std::string("2019-07-18 00:00:00"), std::string("2019-07-00 00:00:00")}, Null()}}; - check_function(func_name, input_types, data_set); + check_function(func_name, input_types, data_set); } { @@ -918,7 +918,7 @@ TEST(VTimestampFunctionsTest, timediff_v2_test) { {{std::string("2019-00-18 00:00:00"), std::string("2019-07-18")}, Null()}, {{std::string("2019-07-18 00:00:00"), std::string("2019-07-00")}, Null()}}; - check_function(func_name, input_types, data_set); + check_function(func_name, input_types, data_set); } { @@ -930,7 +930,7 @@ TEST(VTimestampFunctionsTest, timediff_v2_test) { {{std::string("2019-00-18"), std::string("2019-07-18 00:00:00")}, Null()}, {{std::string("2019-07-18"), std::string("2019-07-00 00:00:00")}, Null()}}; - check_function(func_name, input_types, data_set); + check_function(func_name, input_types, data_set); } { @@ -942,7 +942,7 @@ TEST(VTimestampFunctionsTest, timediff_v2_test) { {{std::string("2019-00-18 00:00:00"), std::string("2019-07-18 00:00:00")}, Null()}, {{std::string("2019-07-18 00:00:00"), std::string("2019-07-00 00:00:00")}, Null()}}; - check_function(func_name, input_types, data_set); + check_function(func_name, input_types, data_set); } { @@ -957,7 +957,7 @@ TEST(VTimestampFunctionsTest, timediff_v2_test) { {{std::string("2019-07-18 00:00:00.123"), std::string("2019-07-00 00:00:00")}, Null()}}; - check_function(func_name, input_types, data_set); + check_function(func_name, input_types, data_set); } } diff --git a/gensrc/script/doris_builtins_functions.py b/gensrc/script/doris_builtins_functions.py index 30af7b6f85..329e306685 100755 --- a/gensrc/script/doris_builtins_functions.py +++ b/gensrc/script/doris_builtins_functions.py @@ -2424,8 +2424,8 @@ visible_functions = [ [['running_difference'], 'DECIMAL128', ['DECIMAL128'], '', '', '', 'vec', ''], [['running_difference'], 'INT', ['DATE'], '', '', '', 'vec', ''], [['running_difference'], 'INT', ['DATEV2'], '', '', '', 'vec', ''], - [['running_difference'], 'DOUBLE', ['DATETIME'], '', '', '', 'vec', ''], - [['running_difference'], 'DOUBLE', ['DATETIMEV2'], '', '', '', 'vec', ''], + [['running_difference'], 'TIME', ['DATETIME'], '', '', '', 'vec', ''], + [['running_difference'], 'TIMEV2', ['DATETIMEV2'], '', '', '', 'vec', ''], # Longtext function [['substr', 'substring'], 'STRING', ['STRING', 'INT'], diff --git a/regression-test/data/query_p0/sql_functions/math_functions/test_running_difference.out b/regression-test/data/query_p0/sql_functions/math_functions/test_running_difference.out index 4399a055d8..fc0dbc5fe1 100644 --- a/regression-test/data/query_p0/sql_functions/math_functions/test_running_difference.out +++ b/regression-test/data/query_p0/sql_functions/math_functions/test_running_difference.out @@ -33,12 +33,12 @@ 2022-11-08 8 -- !test_running_difference_7 -- -2022-03-12T10:41 0.0 -2022-03-12T10:41:02 2.0 -2022-03-12T10:41:03 1.0 -2022-03-12T10:41:03 0.0 -2022-03-12T10:42:01 58.0 -2022-03-12T11:05:04 1383.0 +2022-03-12T10:41 00:00:00 +2022-03-12T10:41:02 00:00:02 +2022-03-12T10:41:03 00:00:01 +2022-03-12T10:41:03 00:00:00 +2022-03-12T10:42:01 00:00:58 +2022-03-12T11:05:04 00:23:03 -- !test_running_difference_8 -- \N \N