Skip to content
Merged
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
88 changes: 88 additions & 0 deletions be/src/vec/functions/function_other_types_to_date.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
#include "vec/columns/column_string.h"
#include "vec/columns/column_vector.h"
#include "vec/common/assert_cast.h"
#include "vec/common/pod_array.h"
#include "vec/common/pod_array_fwd.h"
#include "vec/common/string_ref.h"
#include "vec/core/block.h"
Expand All @@ -62,6 +63,7 @@
#include "vec/functions/datetime_errors.h"
#include "vec/functions/function.h"
#include "vec/functions/simple_function_factory.h"
#include "vec/runtime/time_value.h"
#include "vec/runtime/vdatetime_value.h"
#include "vec/utils/util.hpp"

Expand Down Expand Up @@ -379,6 +381,91 @@ struct MakeDateImpl {
}
};

struct MakeTimeImpl {
static constexpr auto name = "maketime";
using DateValueType = PrimitiveTypeTraits<PrimitiveType::TYPE_TIMEV2>::CppType;
using NativeType = PrimitiveTypeTraits<PrimitiveType::TYPE_TIMEV2>::CppNativeType;
static bool is_variadic() { return false; }
static size_t get_number_of_arguments() { return 3; }
static DataTypes get_variadic_argument_types() { return {}; }
static DataTypePtr get_return_type_impl(const DataTypes& arguments) {
return make_nullable(std::make_shared<DataTypeTimeV2>());
}

static Status execute(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
uint32_t result, size_t input_rows_count) {
DCHECK_EQ(arguments.size(), 3);
auto res_col = ColumnTimeV2::create(input_rows_count);
auto res_null_map = ColumnUInt8::create(input_rows_count, 0);
auto& res_data = res_col->get_data();

ColumnPtr arg_col[3];
bool is_const[3];
for (int i = 0; i < arguments.size(); ++i) {
std::tie(arg_col[i], is_const[i]) =
unpack_if_const(block.get_by_position(arguments[i]).column);
}

const auto& hour_data = assert_cast<const ColumnInt64*>(arg_col[0].get())->get_data();
const auto& min_data = assert_cast<const ColumnInt64*>(arg_col[1].get())->get_data();
if (const auto* sec_col = check_and_get_column<ColumnFloat64>(arg_col[2].get())) {
for (int i = 0; i < input_rows_count; ++i) {
int64_t hour = hour_data[index_check_const(i, is_const[0])];
int64_t minute = min_data[index_check_const(i, is_const[1])];
double sec = sec_col->get_element(index_check_const(i, is_const[2]));
if (!check_and_set_time_value(hour, minute, sec)) {
res_data[i] = 0;
res_null_map->get_data()[i] = 1;
continue;
}
execute_single(hour, minute, sec, res_data, i);
}
} else {
const auto& sec_data = assert_cast<const ColumnInt64*>(arg_col[2].get())->get_data();
for (int i = 0; i < input_rows_count; ++i) {
int64_t hour = hour_data[index_check_const(i, is_const[0])];
int64_t minute = min_data[index_check_const(i, is_const[1])];
double sec = static_cast<double>(sec_data[index_check_const(i, is_const[2])]);
if (!check_and_set_time_value(hour, minute, sec)) {
res_data[i] = 0;
res_null_map->get_data()[i] = 1;
continue;
}
execute_single(hour, minute, sec, res_data, i);
}
}

block.replace_by_position(
result, ColumnNullable::create(std::move(res_col), std::move(res_null_map)));
return Status::OK();
}

private:
static bool check_and_set_time_value(int64_t& hour, int64_t& minute, double& sec) {
static constexpr int MAX_HOUR_FOR_MAKETIME = 838;
if (minute < 0 || minute >= 60 || sec < 0 || sec >= 60) {
return false;
}

// Avoid overflow in `execute_single`
// the case {838, 59, 59.999999} will be slove in `TimeValue::from_double_with_limit`
if (std::abs(hour) > MAX_HOUR_FOR_MAKETIME) {
hour = hour > 0 ? MAX_HOUR_FOR_MAKETIME : -MAX_HOUR_FOR_MAKETIME;
minute = sec = 59;
}
return true;
}

static void execute_single(int64_t hour, int64_t minute, double sec,
PaddedPODArray<double>& res_data, size_t row) {
// Round sec to 6 decimal places (microsecond precision)
double total_sec =
std::abs(hour) * 3600 + minute * 60 + std::round(sec * 1000000.0) / 1000000.0;

res_data[row] = TimeValue::from_double_with_limit(total_sec * (hour < 0 ? -1 : 1));
}
};

struct DateTruncState {
using Callback_function = std::function<void(const ColumnPtr&, ColumnPtr& res, size_t)>;
Callback_function callback_function;
Expand Down Expand Up @@ -1360,6 +1447,7 @@ void register_function_timestamp(SimpleFunctionFactory& factory) {
factory.register_function<FunctionStrToDate>();
factory.register_function<FunctionStrToDatetime>();
factory.register_function<FunctionMakeDate>();
factory.register_function<FunctionOtherTypesToDateType<MakeTimeImpl>>();
factory.register_function<FromDays>();
factory.register_function<FunctionDateTruncDateV2>();
factory.register_function<FunctionDateTruncDatetimeV2>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,7 @@
import org.apache.doris.nereids.trees.expressions.functions.scalar.LtrimIn;
import org.apache.doris.nereids.trees.expressions.functions.scalar.MakeDate;
import org.apache.doris.nereids.trees.expressions.functions.scalar.MakeSet;
import org.apache.doris.nereids.trees.expressions.functions.scalar.MakeTime;
import org.apache.doris.nereids.trees.expressions.functions.scalar.MapContainsEntry;
import org.apache.doris.nereids.trees.expressions.functions.scalar.MapContainsKey;
import org.apache.doris.nereids.trees.expressions.functions.scalar.MapContainsValue;
Expand Down Expand Up @@ -843,6 +844,7 @@ public class BuiltinScalarFunctions implements FunctionHelper {
scalar(LtrimIn.class, "ltrim_in"),
scalar(MakeDate.class, "makedate"),
scalar(MakeSet.class, "make_set"),
scalar(MakeTime.class, "maketime"),
scalar(MapContainsEntry.class, "map_contains_entry"),
scalar(MapContainsKey.class, "map_contains_key"),
scalar(MapContainsValue.class, "map_contains_value"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
import org.apache.doris.nereids.types.DateV2Type;
import org.apache.doris.nereids.types.DecimalV3Type;
import org.apache.doris.nereids.types.StringType;
import org.apache.doris.nereids.types.TimeV2Type;
import org.apache.doris.nereids.util.DateUtils;
import org.apache.doris.qe.ConnectContext;

Expand Down Expand Up @@ -711,6 +712,34 @@ public static Expression makeDate(IntegerLiteral year, IntegerLiteral dayOfYear)
: new NullLiteral(DateV2Type.INSTANCE);
}

/**
* time transformation function: maketime
*/
@ExecFunction(name = "maketime")
public static Expression makeTime(BigIntLiteral hour, BigIntLiteral minute, DoubleLiteral second) {
long hourValue = hour.getValue();
long minuteValue = minute.getValue();
double secondValue = second.getValue();

if (minuteValue < 0 || minuteValue >= 60 || secondValue < 0 || secondValue >= 60) {
return new NullLiteral(TimeV2Type.INSTANCE);
}
if (Math.abs(hourValue) > 838) {
hourValue = hourValue > 0 ? 838 : -838;
minuteValue = 59;
secondValue = 59;
} else if (Math.abs(hourValue) == 838 && secondValue > 59) {
secondValue = 59;
}

double totalSeconds = Math.abs(hourValue) * 3600 + minuteValue * 60
+ Math.round(secondValue * 1000000.0) / 1000000.0;
if (hourValue < 0) {
totalSeconds = -totalSeconds;
}
return new TimeV2Literal(totalSeconds);
}

/**
* date transformation function: str_to_date
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// 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.

package org.apache.doris.nereids.trees.expressions.functions.scalar;

import org.apache.doris.catalog.FunctionSignature;
import org.apache.doris.nereids.trees.expressions.Expression;
import org.apache.doris.nereids.trees.expressions.functions.AlwaysNullable;
import org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature;
import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor;
import org.apache.doris.nereids.types.BigIntType;
import org.apache.doris.nereids.types.DoubleType;
import org.apache.doris.nereids.types.TimeV2Type;

import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;

import java.util.List;

/**
* ScalarFunction 'maketime'.
*/
public class MakeTime extends ScalarFunction implements ExplicitlyCastableSignature, AlwaysNullable {
public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
FunctionSignature.ret(TimeV2Type.INSTANCE)
.args(BigIntType.INSTANCE, BigIntType.INSTANCE, BigIntType.INSTANCE),
FunctionSignature.ret(TimeV2Type.MAX)
.args(BigIntType.INSTANCE, BigIntType.INSTANCE, DoubleType.INSTANCE)

);

/**
* constructor with 2 arguments.
*/
public MakeTime(Expression arg0, Expression arg1, Expression arg2) {
super("maketime", arg0, arg1, arg2);
}

/** constructor for withChildren and reuse signature */
private MakeTime(ScalarFunctionParams functionParams) {
super(functionParams);
}

/**
* withChildren.
*/
@Override
public MakeTime withChildren(List<Expression> children) {
Preconditions.checkArgument(children.size() == 3);
return new MakeTime(getFunctionParams(children));
}

@Override
public List<FunctionSignature> getSignatures() {
return SIGNATURES;
}

@Override
public <R, C> R accept(ExpressionVisitor<R, C> visitor, C context) {
return visitor.visitMakeTime(this, context);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,7 @@
import org.apache.doris.nereids.trees.expressions.functions.scalar.LtrimIn;
import org.apache.doris.nereids.trees.expressions.functions.scalar.MakeDate;
import org.apache.doris.nereids.trees.expressions.functions.scalar.MakeSet;
import org.apache.doris.nereids.trees.expressions.functions.scalar.MakeTime;
import org.apache.doris.nereids.trees.expressions.functions.scalar.MapContainsEntry;
import org.apache.doris.nereids.trees.expressions.functions.scalar.MapContainsKey;
import org.apache.doris.nereids.trees.expressions.functions.scalar.MapContainsValue;
Expand Down Expand Up @@ -2618,6 +2619,10 @@ default R visitMakeSet(MakeSet makeSet, C context) {
return visitScalarFunction(makeSet, context);
}

default R visitMakeTime(MakeTime makeTime, C context) {
return visitScalarFunction(makeTime, context);
}

default R visitExportSet(ExportSet exportSet, C context) {
return visitScalarFunction(exportSet, context);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1970,3 +1970,29 @@ da fanadur
-- !yearweek_5 --
202352

-- !maketime_test_1 --
12:15:30.000000
111:00:23.123457
838:59:59.000000
-838:59:59.000000
\N
\N
\N
\N
\N
\N
\N

-- !maketime_test_2 --
12:15:25
111:00:25
838:59:59
-838:59:59
\N
14:51:25
\N
\N
01:02:25
\N
07:23:25

Loading
Loading