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
25 changes: 23 additions & 2 deletions be/src/vec/functions/function_date_or_datetime_computation.h
Original file line number Diff line number Diff line change
Expand Up @@ -838,10 +838,31 @@ struct CurrentTimeImpl {
static Status execute(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
uint32_t result, size_t input_rows_count) {
auto col_to = ColumnTimeV2::create();
VecDateTimeValue dtv;
DateV2Value<DateTimeV2ValueType> dtv;
dtv.from_unixtime(context->state()->timestamp_ms() / 1000,
context->state()->timezone_obj());
auto time = TimeValue::make_time(dtv.hour(), dtv.minute(), dtv.second());
double time;
if (arguments.size() == 1) {
// the precision must be const, which is checked in fe.
const auto* col = assert_cast<const ColumnInt8*>(
block.get_by_position(arguments[0]).column.get());
uint8_t precision = col->get_element(0);
if (precision <= 6) {
dtv.from_unixtime(context->state()->timestamp_ms() / 1000,
context->state()->nano_seconds(),
context->state()->timezone_obj(), precision);
time = TimeValue::make_time(dtv.hour(), dtv.minute(), dtv.second(),
dtv.microsecond());
} else {
return Status::InvalidArgument(
"The precision in function CURTIME should be between 0 and 6, but got {}",
precision);
}
} else {
dtv.from_unixtime(context->state()->timestamp_ms() / 1000,
context->state()->timezone_obj());
time = TimeValue::make_time(dtv.hour(), dtv.minute(), dtv.second());
}
col_to->insert_value(time);
block.get_by_position(result).column =
ColumnConst::create(std::move(col_to), input_rows_count);
Expand Down
83 changes: 83 additions & 0 deletions be/test/vec/function/function_time_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1558,4 +1558,87 @@ TEST(VTimestampFunctionsTest, time) {
static_cast<void>(check_function<DataTypeTimeV2, true>(func_name, input_types, data_set));
}

TEST(VTimestampFunctionsTest, curtime_test) {
std::string func_name = "curtime";

// Test curtime without precision
{
InputTypeSet input_types = {};
Block block;
ColumnsWithTypeAndName arguments;

auto return_type = std::make_shared<DataTypeTimeV2>(0);
FunctionBasePtr func =
SimpleFunctionFactory::instance().get_function(func_name, arguments, return_type);
EXPECT_TRUE(func != nullptr);

auto fn_ctx_return = std::make_shared<DataTypeTimeV2>(0);
std::vector<DataTypePtr> arg_types = {};
FunctionUtils fn_utils(fn_ctx_return, arg_types, false);
auto* fn_ctx = fn_utils.get_fn_ctx();

EXPECT_TRUE(func->open(fn_ctx, FunctionContext::FRAGMENT_LOCAL).ok());
EXPECT_TRUE(func->open(fn_ctx, FunctionContext::THREAD_LOCAL).ok());

block.insert({nullptr, return_type, "result"});
ColumnNumbers args;
auto st = func->execute(fn_ctx, block, args, 0, 1);
EXPECT_TRUE(st.ok());

auto result_col = block.get_by_position(0).column;
EXPECT_TRUE(result_col);
if (const auto* const_col = check_and_get_column<ColumnConst>(result_col.get())) {
auto time_value = const_col->get_field().get<double>();
EXPECT_GE(time_value, 0.0);
EXPECT_LE(time_value, 24.0 * 3600 * 1000000);
}

EXPECT_TRUE(func->close(fn_ctx, FunctionContext::THREAD_LOCAL).ok());
EXPECT_TRUE(func->close(fn_ctx, FunctionContext::FRAGMENT_LOCAL).ok());
}

// Test curtime with precision
{
InputTypeSet input_types = {PrimitiveType::TYPE_TINYINT};
Block block;

auto precision_col = ColumnInt8::create();
precision_col->insert_value(3);
auto precision_type = std::make_shared<DataTypeInt8>();
block.insert({std::move(precision_col), precision_type, "precision"});

ColumnsWithTypeAndName arguments;
arguments.push_back(block.get_by_position(0));

auto return_type = std::make_shared<DataTypeTimeV2>(3);
FunctionBasePtr func =
SimpleFunctionFactory::instance().get_function(func_name, arguments, return_type);
EXPECT_TRUE(func != nullptr);

auto fn_ctx_return = std::make_shared<DataTypeTimeV2>(3);
std::vector<DataTypePtr> arg_types = {precision_type};
FunctionUtils fn_utils(fn_ctx_return, arg_types, false);
auto* fn_ctx = fn_utils.get_fn_ctx();

EXPECT_TRUE(func->open(fn_ctx, FunctionContext::FRAGMENT_LOCAL).ok());
EXPECT_TRUE(func->open(fn_ctx, FunctionContext::THREAD_LOCAL).ok());

block.insert({nullptr, return_type, "result"});
ColumnNumbers args = {0};
auto st = func->execute(fn_ctx, block, args, 1, 1);
EXPECT_TRUE(st.ok());

auto result_col = block.get_by_position(1).column;
EXPECT_TRUE(result_col);
if (const auto* const_col = check_and_get_column<ColumnConst>(result_col.get())) {
auto time_value = const_col->get_field().get<double>();
EXPECT_GE(time_value, 0.0);
EXPECT_LE(time_value, 24.0 * 3600 * 1000000);
}

EXPECT_TRUE(func->close(fn_ctx, FunctionContext::THREAD_LOCAL).ok());
EXPECT_TRUE(func->close(fn_ctx, FunctionContext::FRAGMENT_LOCAL).ok());
}
}

} // namespace doris::vectorized
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import org.apache.doris.nereids.trees.expressions.literal.DateV2Literal;
import org.apache.doris.nereids.trees.expressions.literal.IntegerLiteral;
import org.apache.doris.nereids.trees.expressions.literal.TimeV2Literal;
import org.apache.doris.nereids.trees.expressions.literal.TinyIntLiteral;
import org.apache.doris.nereids.util.DateUtils;

import java.time.LocalDateTime;
Expand Down Expand Up @@ -95,11 +96,21 @@ public static Expression curTime() {
return TimeV2Literal.fromJavaDateType(LocalDateTime.now(DateUtils.getTimeZone()));
}

@ExecFunction(name = "curtime")
public static Expression curTime(TinyIntLiteral precision) {
return TimeV2Literal.fromJavaDateType(LocalDateTime.now(DateUtils.getTimeZone()), precision.getValue());
}

@ExecFunction(name = "current_time")
public static Expression currentTime() {
return TimeV2Literal.fromJavaDateType(LocalDateTime.now(DateUtils.getTimeZone()));
}

@ExecFunction(name = "current_time")
public static Expression currentTime(TinyIntLiteral precision) {
return TimeV2Literal.fromJavaDateType(LocalDateTime.now(DateUtils.getTimeZone()), precision.getValue());
}

/**
* date transformation function: unix_timestamp
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,16 @@
package org.apache.doris.nereids.trees.expressions.functions.scalar;

import org.apache.doris.catalog.FunctionSignature;
import org.apache.doris.nereids.exceptions.AnalysisException;
import org.apache.doris.nereids.trees.expressions.Expression;
import org.apache.doris.nereids.trees.expressions.functions.AlwaysNotNullable;
import org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature;
import org.apache.doris.nereids.trees.expressions.functions.ComputeSignature;
import org.apache.doris.nereids.trees.expressions.functions.ImplicitlyCastableSignature;
import org.apache.doris.nereids.trees.expressions.literal.TinyIntLiteral;
import org.apache.doris.nereids.trees.expressions.shape.LeafExpression;
import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor;
import org.apache.doris.nereids.types.TimeV2Type;
import org.apache.doris.nereids.types.TinyIntType;

import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
Expand All @@ -34,10 +38,11 @@
* ScalarFunction 'current_time'. This class is generated by GenerateFunction.
*/
public class CurrentTime extends ScalarFunction
implements LeafExpression, ExplicitlyCastableSignature, AlwaysNotNullable {
implements LeafExpression, ImplicitlyCastableSignature, AlwaysNotNullable, ComputeSignature {

public static final List<FunctionSignature> SIGNATURES = ImmutableList.of(
FunctionSignature.ret(TimeV2Type.INSTANCE).args()
FunctionSignature.ret(TimeV2Type.INSTANCE).args(),
FunctionSignature.ret(TimeV2Type.INSTANCE).args(TinyIntType.INSTANCE)
);

/**
Expand All @@ -47,17 +52,51 @@ public CurrentTime() {
super("current_time");
}

/**
* constructor with 1 argument.
*/
public CurrentTime(Expression arg) {
super("current_time", arg);
}

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

@Override
public FunctionSignature computeSignature(FunctionSignature signature) {
if (arity() == 1 && child(0) instanceof TinyIntLiteral) {
byte precision = ((TinyIntLiteral) child(0)).getValue();
if (precision < 0 || precision > 6) {
throw new IllegalArgumentException("The precision must be between 0 and 6");
}
return FunctionSignature.ret(TimeV2Type.of(precision)).args(TinyIntType.INSTANCE);
}

return super.computeSignature(signature);
}

@Override
public Expression withChildren(List<Expression> children) {
Preconditions.checkArgument(children.isEmpty());
Preconditions.checkArgument(children.isEmpty() || children.size() == 1);
return new CurrentTime(getFunctionParams(children));
}

@Override
public void checkLegalityAfterRewrite() {
if (arity() == 1) {
if (!child(0).isLiteral()) {
throw new AnalysisException("CURTIME only accepts literal as precision.");
}
}
}

@Override
public void checkLegalityBeforeTypeCoercion() {
checkLegalityAfterRewrite();
}

@Override
public List<FunctionSignature> getSignatures() {
return SIGNATURES;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,18 @@ public static Expression fromJavaDateType(LocalDateTime dateTime) {
return new TimeV2Literal(dateTime.getHour(), dateTime.getMinute(), dateTime.getSecond(), 0, 0, false);
}

/**
* construct with precision
*/
public static Expression fromJavaDateType(LocalDateTime dateTime, int precision) {
if (isDateOutOfRange(dateTime)) {
throw new AnalysisException("datetime out of range" + dateTime.toString());
}
int value = (int) Math.pow(10, TimeV2Type.MAX_SCALE - precision);
return new TimeV2Literal(dateTime.getHour(), dateTime.getMinute(), dateTime.getSecond(),
(dateTime.getNano() / 1000) / value * value, precision, false);
}

public LocalDateTime toJavaDateType() {
return LocalDateTime.of(0, 1, 1, ((int) getHour()), ((int) getMinute()), ((int) getSecond()),
(int) getMicroSecond() * 1000);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,22 @@ suite("test_date_function") {
// TIME CURTIME()
def curtime_result = sql """ SELECT CURTIME() """
assertTrue(curtime_result[0].size() == 1)
def curtime_with_arg = sql """ SELECT CAST(CURTIME(3) AS STRING) """
assertTrue(curtime_with_arg[0].size() == 1)
assertTrue(curtime_with_arg[0][0].contains('.'))

curtime_with_arg = sql """ SELECT CAST(CURTIME(0) AS STRING) """
assertTrue(curtime_with_arg[0].size() == 1)
assertFalse(curtime_with_arg[0][0].contains('.'))

test {
sql """ SELECT CURTIME(114514);"""
exception "Can not find the compatibility function signature: current_time(INT)"
}
test {
sql """ SELECT CURTIME(7); """
exception "The precision must be between 0 and 6"
}

sql """ insert into ${tableName} values ("2010-11-30 23:59:59") """
// DATE_ADD
Expand Down
Loading