Skip to content

Commit d514b34

Browse files
committed
[Feature](function) Support function TIME_FORMAT
1 parent bf2e1c2 commit d514b34

File tree

10 files changed

+788
-134
lines changed

10 files changed

+788
-134
lines changed

be/src/vec/functions/date_time_transforms.h

Lines changed: 2 additions & 133 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include "udf/udf.h"
3232
#include "util/binary_cast.hpp"
3333
#include "vec/columns/column_decimal.h"
34+
#include "vec/columns/column.h"
3435
#include "vec/columns/column_nullable.h"
3536
#include "vec/columns/column_string.h"
3637
#include "vec/columns/column_vector.h"
@@ -43,6 +44,7 @@
4344
#include "vec/data_types/data_type_decimal.h"
4445
#include "vec/data_types/data_type_string.h"
4546
#include "vec/functions/date_format_type.h"
47+
#include "vec/runtime/time_value.h"
4648
#include "vec/runtime/vdatetime_value.h"
4749
#include "vec/utils/util.hpp"
4850

@@ -431,139 +433,6 @@ struct FromUnixTimeDecimalImpl {
431433
}
432434
};
433435

434-
// Base template for optimized time field(HOUR, MINUTE, SECOND, MS) extraction from Unix timestamp
435-
// Uses lookup_offset to avoid expensive civil_second construction
436-
template <typename Impl>
437-
class FunctionTimeFieldFromUnixtime : public IFunction {
438-
public:
439-
static constexpr auto name = Impl::name;
440-
static FunctionPtr create() { return std::make_shared<FunctionTimeFieldFromUnixtime<Impl>>(); }
441-
442-
String get_name() const override { return name; }
443-
444-
size_t get_number_of_arguments() const override { return 1; }
445-
446-
DataTypePtr get_return_type_impl(const ColumnsWithTypeAndName& arguments) const override {
447-
// microsecond_from_unixtime returns Int32, others (hour/minute/second) return Int8
448-
if constexpr (Impl::ArgType == PrimitiveType::TYPE_DECIMAL64) {
449-
return make_nullable(std::make_shared<DataTypeInt32>());
450-
} else {
451-
return make_nullable(std::make_shared<DataTypeInt8>());
452-
}
453-
}
454-
455-
// (UTC 9999-12-31 23:59:59) - 24 * 3600
456-
static const int64_t TIMESTAMP_VALID_MAX = 253402243199L;
457-
458-
Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
459-
uint32_t result, size_t input_rows_count) const override {
460-
using ArgColType = PrimitiveTypeTraits<Impl::ArgType>::ColumnType;
461-
using ResColType = std::conditional_t<Impl::ArgType == PrimitiveType::TYPE_DECIMAL64,
462-
ColumnInt32, ColumnInt8>;
463-
using ResItemType = typename ResColType::value_type;
464-
auto res = ResColType::create();
465-
466-
const auto* ts_col =
467-
assert_cast<const ArgColType*>(block.get_by_position(arguments[0]).column.get());
468-
if constexpr (Impl::ArgType == PrimitiveType::TYPE_DECIMAL64) {
469-
// microsecond_from_unixtime only
470-
const auto scale = static_cast<int32_t>(ts_col->get_scale());
471-
472-
for (int i = 0; i < input_rows_count; ++i) {
473-
const auto seconds = ts_col->get_intergral_part(i);
474-
const auto fraction = ts_col->get_fractional_part(i);
475-
476-
if (seconds < 0 || seconds > TIMESTAMP_VALID_MAX) {
477-
return Status::InvalidArgument(
478-
"The input value of TimeFiled(from_unixtime()) must between 0 and "
479-
"253402243199L");
480-
}
481-
482-
ResItemType value = Impl::extract_field(fraction, scale);
483-
res->insert_value(value);
484-
}
485-
} else {
486-
auto ctz = context->state()->timezone_obj();
487-
for (int i = 0; i < input_rows_count; ++i) {
488-
auto date = ts_col->get_element(i);
489-
490-
if (date < 0 || date > TIMESTAMP_VALID_MAX) {
491-
return Status::InvalidArgument(
492-
"The input value of TimeFiled(from_unixtime()) must between 0 and "
493-
"253402243199L");
494-
}
495-
496-
ResItemType value = Impl::extract_field(date, ctz);
497-
res->insert_value(value);
498-
}
499-
}
500-
block.replace_by_position(result, std::move(res));
501-
return Status::OK();
502-
}
503-
};
504-
505-
struct HourFromUnixtimeImpl {
506-
static constexpr PrimitiveType ArgType = PrimitiveType::TYPE_BIGINT;
507-
static constexpr auto name = "hour_from_unixtime";
508-
509-
static int8_t extract_field(int64_t local_time, const cctz::time_zone& ctz) {
510-
static const auto epoch = std::chrono::time_point_cast<cctz::sys_seconds>(
511-
std::chrono::system_clock::from_time_t(0));
512-
cctz::time_point<cctz::sys_seconds> t = epoch + cctz::seconds(local_time);
513-
int offset = ctz.lookup_offset(t).offset;
514-
local_time += offset;
515-
516-
static const libdivide::divider<int64_t> fast_div_3600(3600);
517-
static const libdivide::divider<int64_t> fast_div_86400(86400);
518-
519-
int64_t remainder;
520-
if (LIKELY(local_time >= 0)) {
521-
remainder = local_time - local_time / fast_div_86400 * 86400;
522-
} else {
523-
remainder = local_time % 86400;
524-
if (remainder < 0) {
525-
remainder += 86400;
526-
}
527-
}
528-
return static_cast<int8_t>(remainder / fast_div_3600);
529-
}
530-
};
531-
532-
struct MinuteFromUnixtimeImpl {
533-
static constexpr PrimitiveType ArgType = PrimitiveType::TYPE_BIGINT;
534-
static constexpr auto name = "minute_from_unixtime";
535-
536-
static int8_t extract_field(int64_t local_time, const cctz::time_zone& /*ctz*/) {
537-
static const libdivide::divider<int64_t> fast_div_60(60);
538-
static const libdivide::divider<int64_t> fast_div_3600(3600);
539-
540-
local_time = local_time - local_time / fast_div_3600 * 3600;
541-
542-
return static_cast<int8_t>(local_time / fast_div_60);
543-
}
544-
};
545-
546-
struct SecondFromUnixtimeImpl {
547-
static constexpr PrimitiveType ArgType = PrimitiveType::TYPE_BIGINT;
548-
static constexpr auto name = "second_from_unixtime";
549-
550-
static int8_t extract_field(int64_t local_time, const cctz::time_zone& /*ctz*/) {
551-
return static_cast<int8_t>(local_time % 60);
552-
}
553-
};
554-
555-
struct MicrosecondFromUnixtimeImpl {
556-
static constexpr PrimitiveType ArgType = PrimitiveType::TYPE_DECIMAL64;
557-
static constexpr auto name = "microsecond_from_unixtime";
558-
559-
static int32_t extract_field(int64_t fraction, int scale) {
560-
if (scale < 6) {
561-
fraction *= common::exp10_i64(6 - scale);
562-
}
563-
return static_cast<int32_t>(fraction);
564-
}
565-
};
566-
567436
#include "common/compile_check_end.h"
568437
} // namespace doris::vectorized
569438

be/src/vec/functions/function_datetime_string_to_string.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ using FunctionFromUnixTimeNewDecimalOneArg =
3737
FunctionDateTimeStringToString<FromUnixTimeDecimalImpl<false>>;
3838
using FunctionFromUnixTimeNewDecimalTwoArg =
3939
FunctionDateTimeStringToString<FromUnixTimeDecimalImpl<true>>;
40+
using FunctionTimeFormatDate = FunctionTimeFormat<TYPE_DATEV2>;
41+
using FunctionTimeFormatDateTime = FunctionTimeFormat<TYPE_DATETIMEV2>;
42+
using FunctionTimeFormatTime = FunctionTimeFormat<TYPE_TIMEV2>;
4043

4144
void register_function_date_time_string_to_string(SimpleFunctionFactory& factory) {
4245
factory.register_function<FunctionDateFormatV2>();
@@ -47,6 +50,9 @@ void register_function_date_time_string_to_string(SimpleFunctionFactory& factory
4750
factory.register_function<FunctionFromUnixTimeNewDecimalOneArg>();
4851
factory.register_function<FunctionFromUnixTimeNewDecimalTwoArg>();
4952
factory.register_function<FunctionDateTimeV2DateFormat>();
53+
factory.register_function<FunctionTimeFormatDate>();
54+
factory.register_function<FunctionTimeFormatDateTime>();
55+
factory.register_function<FunctionTimeFormatTime>();
5056
}
5157

5258
} // namespace doris::vectorized

0 commit comments

Comments
 (0)