[feature](function) support now/current_timestamp functions with precision (#12219)
* [feature](function) support now/current_timestamp functions with precision
This commit is contained in:
@ -107,9 +107,14 @@ RuntimeState::RuntimeState(const TQueryGlobals& query_globals)
|
||||
_is_cancelled(false),
|
||||
_per_fragment_instance_idx(0) {
|
||||
_query_options.batch_size = DEFAULT_BATCH_SIZE;
|
||||
if (query_globals.__isset.time_zone) {
|
||||
if (query_globals.__isset.time_zone && query_globals.__isset.nano_seconds) {
|
||||
_timezone = query_globals.time_zone;
|
||||
_timestamp_ms = query_globals.timestamp_ms;
|
||||
_nano_seconds = query_globals.nano_seconds;
|
||||
} else if (query_globals.__isset.time_zone) {
|
||||
_timezone = query_globals.time_zone;
|
||||
_timestamp_ms = query_globals.timestamp_ms;
|
||||
_nano_seconds = 0;
|
||||
} else if (!query_globals.now_string.empty()) {
|
||||
_timezone = TimezoneUtils::default_time_zone;
|
||||
DateTimeValue dt;
|
||||
@ -117,10 +122,12 @@ RuntimeState::RuntimeState(const TQueryGlobals& query_globals)
|
||||
int64_t timestamp;
|
||||
dt.unix_timestamp(×tamp, _timezone);
|
||||
_timestamp_ms = timestamp * 1000;
|
||||
_nano_seconds = 0;
|
||||
} else {
|
||||
//Unit test may set into here
|
||||
_timezone = TimezoneUtils::default_time_zone;
|
||||
_timestamp_ms = 0;
|
||||
_nano_seconds = 0;
|
||||
}
|
||||
TimezoneUtils::find_cctz_time_zone(_timezone, _timezone_obj);
|
||||
}
|
||||
@ -135,6 +142,7 @@ RuntimeState::RuntimeState()
|
||||
_query_options.batch_size = DEFAULT_BATCH_SIZE;
|
||||
_timezone = TimezoneUtils::default_time_zone;
|
||||
_timestamp_ms = 0;
|
||||
_nano_seconds = 0;
|
||||
TimezoneUtils::find_cctz_time_zone(_timezone, _timezone_obj);
|
||||
_exec_env = ExecEnv::GetInstance();
|
||||
}
|
||||
@ -161,9 +169,14 @@ Status RuntimeState::init(const TUniqueId& fragment_instance_id, const TQueryOpt
|
||||
const TQueryGlobals& query_globals, ExecEnv* exec_env) {
|
||||
_fragment_instance_id = fragment_instance_id;
|
||||
_query_options = query_options;
|
||||
if (query_globals.__isset.time_zone) {
|
||||
if (query_globals.__isset.time_zone && query_globals.__isset.nano_seconds) {
|
||||
_timezone = query_globals.time_zone;
|
||||
_timestamp_ms = query_globals.timestamp_ms;
|
||||
_nano_seconds = query_globals.nano_seconds;
|
||||
} else if (query_globals.__isset.time_zone) {
|
||||
_timezone = query_globals.time_zone;
|
||||
_timestamp_ms = query_globals.timestamp_ms;
|
||||
_nano_seconds = 0;
|
||||
} else if (!query_globals.now_string.empty()) {
|
||||
_timezone = TimezoneUtils::default_time_zone;
|
||||
DateTimeValue dt;
|
||||
@ -171,10 +184,12 @@ Status RuntimeState::init(const TUniqueId& fragment_instance_id, const TQueryOpt
|
||||
int64_t timestamp;
|
||||
dt.unix_timestamp(×tamp, _timezone);
|
||||
_timestamp_ms = timestamp * 1000;
|
||||
_nano_seconds = 0;
|
||||
} else {
|
||||
//Unit test may set into here
|
||||
_timezone = TimezoneUtils::default_time_zone;
|
||||
_timestamp_ms = 0;
|
||||
_nano_seconds = 0;
|
||||
}
|
||||
TimezoneUtils::find_cctz_time_zone(_timezone, _timezone_obj);
|
||||
|
||||
|
||||
@ -114,6 +114,7 @@ public:
|
||||
int num_scanner_threads() const { return _query_options.num_scanner_threads; }
|
||||
TQueryType::type query_type() const { return _query_options.query_type; }
|
||||
int64_t timestamp_ms() const { return _timestamp_ms; }
|
||||
int32_t nano_seconds() const { return _nano_seconds; }
|
||||
const std::string& timezone() const { return _timezone; }
|
||||
const cctz::time_zone& timezone_obj() const { return _timezone_obj; }
|
||||
const std::string& user() const { return _user; }
|
||||
@ -428,6 +429,7 @@ private:
|
||||
|
||||
//Query-global timestamp_ms
|
||||
int64_t _timestamp_ms;
|
||||
int32_t _nano_seconds;
|
||||
std::string _timezone;
|
||||
cctz::time_zone _timezone_obj;
|
||||
|
||||
|
||||
@ -90,9 +90,10 @@ std::string DataTypeDateTimeV2::to_string(const IColumn& column, size_t row_num)
|
||||
.get_data()[row_num];
|
||||
DateV2Value<DateTimeV2ValueType> val =
|
||||
binary_cast<UInt64, DateV2Value<DateTimeV2ValueType>>(int_val);
|
||||
std::stringstream ss;
|
||||
ss << val;
|
||||
return ss.str();
|
||||
|
||||
char buf[64];
|
||||
char* pos = val.to_string(buf, scale_);
|
||||
return std::string(buf, pos - buf - 1);
|
||||
}
|
||||
|
||||
void DataTypeDateTimeV2::to_string(const IColumn& column, size_t row_num,
|
||||
@ -104,7 +105,7 @@ void DataTypeDateTimeV2::to_string(const IColumn& column, size_t row_num,
|
||||
binary_cast<UInt64, DateV2Value<DateTimeV2ValueType>>(int_val);
|
||||
|
||||
char buf[64];
|
||||
char* pos = value.to_string(buf);
|
||||
char* pos = value.to_string(buf, scale_);
|
||||
// DateTime to_string the end is /0
|
||||
ostr.write(buf, pos - buf - 1);
|
||||
}
|
||||
|
||||
@ -205,12 +205,22 @@ struct LocalTimestampFunctionName {
|
||||
static constexpr auto name = "localtimestamp";
|
||||
};
|
||||
|
||||
using FunctionNow = FunctionCurrentDateOrDateTime<CurrentDateTimeImpl<NowFunctionName>>;
|
||||
using FunctionNow = FunctionCurrentDateOrDateTime<CurrentDateTimeImpl<NowFunctionName, false>>;
|
||||
using FunctionCurrentTimestamp =
|
||||
FunctionCurrentDateOrDateTime<CurrentDateTimeImpl<CurrentTimestampFunctionName>>;
|
||||
using FunctionLocalTime = FunctionCurrentDateOrDateTime<CurrentDateTimeImpl<LocalTimeFunctionName>>;
|
||||
FunctionCurrentDateOrDateTime<CurrentDateTimeImpl<CurrentTimestampFunctionName, false>>;
|
||||
using FunctionLocalTime =
|
||||
FunctionCurrentDateOrDateTime<CurrentDateTimeImpl<LocalTimeFunctionName, false>>;
|
||||
using FunctionLocalTimestamp =
|
||||
FunctionCurrentDateOrDateTime<CurrentDateTimeImpl<LocalTimestampFunctionName>>;
|
||||
FunctionCurrentDateOrDateTime<CurrentDateTimeImpl<LocalTimestampFunctionName, false>>;
|
||||
|
||||
using FunctionNowWithPrecision =
|
||||
FunctionCurrentDateOrDateTime<CurrentDateTimeImpl<NowFunctionName, true>>;
|
||||
using FunctionCurrentTimestampWithPrecision =
|
||||
FunctionCurrentDateOrDateTime<CurrentDateTimeImpl<CurrentTimestampFunctionName, true>>;
|
||||
using FunctionLocalTimeWithPrecision =
|
||||
FunctionCurrentDateOrDateTime<CurrentDateTimeImpl<LocalTimeFunctionName, true>>;
|
||||
using FunctionLocalTimestampWithPrecision =
|
||||
FunctionCurrentDateOrDateTime<CurrentDateTimeImpl<LocalTimestampFunctionName, true>>;
|
||||
|
||||
struct CurDateFunctionName {
|
||||
static constexpr auto name = "curdate";
|
||||
@ -337,6 +347,10 @@ void register_function_date_time_computation(SimpleFunctionFactory& factory) {
|
||||
factory.register_function<FunctionCurrentTimestamp>();
|
||||
factory.register_function<FunctionLocalTime>();
|
||||
factory.register_function<FunctionLocalTimestamp>();
|
||||
factory.register_function<FunctionNowWithPrecision>();
|
||||
factory.register_function<FunctionCurrentTimestampWithPrecision>();
|
||||
factory.register_function<FunctionLocalTimeWithPrecision>();
|
||||
factory.register_function<FunctionLocalTimestampWithPrecision>();
|
||||
factory.register_function(CurrentDateFunctionName::name,
|
||||
&createCurrentDateFunctionBuilderFunction);
|
||||
factory.register_function(CurDateFunctionName::name, &createCurDateFunctionBuilderFunction);
|
||||
|
||||
@ -579,6 +579,9 @@ public:
|
||||
template <typename FunctionImpl>
|
||||
class FunctionCurrentDateOrDateTime : public IFunction {
|
||||
public:
|
||||
static constexpr bool has_variadic_argument =
|
||||
!std::is_void_v<decltype(has_variadic_argument_types(std::declval<FunctionImpl>()))>;
|
||||
|
||||
static constexpr auto name = FunctionImpl::name;
|
||||
static FunctionPtr create() { return std::make_shared<FunctionCurrentDateOrDateTime>(); }
|
||||
|
||||
@ -590,51 +593,148 @@ public:
|
||||
return std::make_shared<typename FunctionImpl::ReturnType>();
|
||||
}
|
||||
|
||||
bool is_variadic() const override { return true; }
|
||||
|
||||
DataTypes get_variadic_argument_types_impl() const override {
|
||||
if constexpr (has_variadic_argument) return FunctionImpl::get_variadic_argument_types();
|
||||
return {};
|
||||
}
|
||||
|
||||
Status execute_impl(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
|
||||
size_t result, size_t input_rows_count) override {
|
||||
DCHECK(arguments.empty());
|
||||
return FunctionImpl::execute(context, block, result, input_rows_count);
|
||||
return FunctionImpl::execute(context, block, arguments, result, input_rows_count);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename FunctionName>
|
||||
template <typename FunctionName, bool WithPrecision>
|
||||
struct CurrentDateTimeImpl {
|
||||
using ReturnType = DataTypeDateTime;
|
||||
static constexpr auto name = FunctionName::name;
|
||||
static Status execute(FunctionContext* context, Block& block, size_t result,
|
||||
size_t input_rows_count) {
|
||||
WhichDataType which(remove_nullable(block.get_by_position(result).type));
|
||||
if (which.is_date_time_v2()) {
|
||||
return executeImpl<DateV2Value<DateTimeV2ValueType>, UInt64>(context, block, result,
|
||||
input_rows_count);
|
||||
} else if (which.is_date_v2()) {
|
||||
return executeImpl<DateV2Value<DateV2ValueType>, UInt32>(context, block, result,
|
||||
input_rows_count);
|
||||
using ReturnType = std::conditional_t<WithPrecision, DataTypeDateTimeV2, DataTypeDateTime>;
|
||||
|
||||
static DataTypes get_variadic_argument_types() {
|
||||
if constexpr (WithPrecision) {
|
||||
return {std::make_shared<DataTypeInt32>()};
|
||||
} else {
|
||||
return executeImpl<VecDateTimeValue, Int64>(context, block, result, input_rows_count);
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
static Status execute(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
|
||||
size_t result, size_t input_rows_count) {
|
||||
WhichDataType which(remove_nullable(block.get_by_position(result).type));
|
||||
if constexpr (WithPrecision) {
|
||||
DCHECK(which.is_date_time_v2() || which.is_date_v2());
|
||||
if (which.is_date_time_v2()) {
|
||||
return executeImpl<DateV2Value<DateTimeV2ValueType>, UInt64>(
|
||||
context, block, arguments, result, input_rows_count);
|
||||
} else {
|
||||
return executeImpl<DateV2Value<DateV2ValueType>, UInt32>(context, block, arguments,
|
||||
result, input_rows_count);
|
||||
}
|
||||
} else {
|
||||
if (which.is_date_time_v2()) {
|
||||
return executeImpl<DateV2Value<DateTimeV2ValueType>, UInt64>(
|
||||
context, block, arguments, result, input_rows_count);
|
||||
} else if (which.is_date_v2()) {
|
||||
return executeImpl<DateV2Value<DateV2ValueType>, UInt32>(context, block, arguments,
|
||||
result, input_rows_count);
|
||||
} else {
|
||||
return executeImpl<VecDateTimeValue, Int64>(context, block, arguments, result,
|
||||
input_rows_count);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename DateValueType, typename NativeType>
|
||||
static Status executeImpl(FunctionContext* context, Block& block, size_t result,
|
||||
static Status executeImpl(FunctionContext* context, Block& block,
|
||||
const ColumnNumbers& arguments, size_t result,
|
||||
size_t input_rows_count) {
|
||||
auto col_to = ColumnVector<NativeType>::create();
|
||||
DateValueType dtv;
|
||||
if (dtv.from_unixtime(context->impl()->state()->timestamp_ms() / 1000,
|
||||
context->impl()->state()->timezone_obj())) {
|
||||
if constexpr (std::is_same_v<DateValueType, VecDateTimeValue>) {
|
||||
reinterpret_cast<DateValueType*>(&dtv)->set_type(TIME_DATETIME);
|
||||
}
|
||||
auto date_packed_int = binary_cast<DateValueType, NativeType>(dtv);
|
||||
for (int i = 0; i < input_rows_count; i++) {
|
||||
col_to->insert_data(
|
||||
const_cast<const char*>(reinterpret_cast<char*>(&date_packed_int)), 0);
|
||||
if constexpr (WithPrecision) {
|
||||
if (const ColumnConst* const_column = check_and_get_column<ColumnConst>(
|
||||
block.get_by_position(arguments[0]).column)) {
|
||||
int scale = const_column->get_int(0);
|
||||
if (dtv.from_unixtime(context->impl()->state()->timestamp_ms() / 1000,
|
||||
context->impl()->state()->nano_seconds(),
|
||||
context->impl()->state()->timezone_obj(), scale)) {
|
||||
if constexpr (std::is_same_v<DateValueType, VecDateTimeValue>) {
|
||||
reinterpret_cast<DateValueType*>(&dtv)->set_type(TIME_DATETIME);
|
||||
}
|
||||
auto date_packed_int = binary_cast<DateValueType, NativeType>(dtv);
|
||||
for (int i = 0; i < input_rows_count; i++) {
|
||||
col_to->insert_data(
|
||||
const_cast<const char*>(reinterpret_cast<char*>(&date_packed_int)),
|
||||
0);
|
||||
}
|
||||
} else {
|
||||
auto invalid_val = 0;
|
||||
for (int i = 0; i < input_rows_count; i++) {
|
||||
col_to->insert_data(
|
||||
const_cast<const char*>(reinterpret_cast<char*>(&invalid_val)), 0);
|
||||
}
|
||||
}
|
||||
} else if (const ColumnNullable* nullable_column = check_and_get_column<ColumnNullable>(
|
||||
block.get_by_position(arguments[0]).column)) {
|
||||
const auto& null_map = nullable_column->get_null_map_data();
|
||||
const auto& nested_column = nullable_column->get_nested_column_ptr();
|
||||
for (int i = 0; i < input_rows_count; i++) {
|
||||
if (!null_map[i] &&
|
||||
dtv.from_unixtime(context->impl()->state()->timestamp_ms() / 1000,
|
||||
context->impl()->state()->nano_seconds(),
|
||||
context->impl()->state()->timezone_obj(),
|
||||
nested_column->get64(i))) {
|
||||
if constexpr (std::is_same_v<DateValueType, VecDateTimeValue>) {
|
||||
reinterpret_cast<DateValueType*>(&dtv)->set_type(TIME_DATETIME);
|
||||
}
|
||||
auto date_packed_int = binary_cast<DateValueType, NativeType>(dtv);
|
||||
col_to->insert_data(
|
||||
const_cast<const char*>(reinterpret_cast<char*>(&date_packed_int)),
|
||||
0);
|
||||
} else {
|
||||
auto invalid_val = 0;
|
||||
col_to->insert_data(
|
||||
const_cast<const char*>(reinterpret_cast<char*>(&invalid_val)), 0);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
auto& int_column = block.get_by_position(arguments[0]).column;
|
||||
for (int i = 0; i < input_rows_count; i++) {
|
||||
if (dtv.from_unixtime(context->impl()->state()->timestamp_ms() / 1000,
|
||||
context->impl()->state()->nano_seconds(),
|
||||
context->impl()->state()->timezone_obj(),
|
||||
int_column->get64(i))) {
|
||||
if constexpr (std::is_same_v<DateValueType, VecDateTimeValue>) {
|
||||
reinterpret_cast<DateValueType*>(&dtv)->set_type(TIME_DATETIME);
|
||||
}
|
||||
auto date_packed_int = binary_cast<DateValueType, NativeType>(dtv);
|
||||
col_to->insert_data(
|
||||
const_cast<const char*>(reinterpret_cast<char*>(&date_packed_int)),
|
||||
0);
|
||||
} else {
|
||||
auto invalid_val = 0;
|
||||
col_to->insert_data(
|
||||
const_cast<const char*>(reinterpret_cast<char*>(&invalid_val)), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
auto invalid_val = 0;
|
||||
for (int i = 0; i < input_rows_count; i++) {
|
||||
col_to->insert_data(const_cast<const char*>(reinterpret_cast<char*>(&invalid_val)),
|
||||
0);
|
||||
if (dtv.from_unixtime(context->impl()->state()->timestamp_ms() / 1000,
|
||||
context->impl()->state()->timezone_obj())) {
|
||||
if constexpr (std::is_same_v<DateValueType, VecDateTimeValue>) {
|
||||
reinterpret_cast<DateValueType*>(&dtv)->set_type(TIME_DATETIME);
|
||||
}
|
||||
auto date_packed_int = binary_cast<DateValueType, NativeType>(dtv);
|
||||
for (int i = 0; i < input_rows_count; i++) {
|
||||
col_to->insert_data(
|
||||
const_cast<const char*>(reinterpret_cast<char*>(&date_packed_int)), 0);
|
||||
}
|
||||
} else {
|
||||
auto invalid_val = 0;
|
||||
for (int i = 0; i < input_rows_count; i++) {
|
||||
col_to->insert_data(
|
||||
const_cast<const char*>(reinterpret_cast<char*>(&invalid_val)), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
block.get_by_position(result).column = std::move(col_to);
|
||||
@ -646,8 +746,8 @@ template <typename FunctionName, typename DateType, typename NativeType>
|
||||
struct CurrentDateImpl {
|
||||
using ReturnType = DateType;
|
||||
static constexpr auto name = FunctionName::name;
|
||||
static Status execute(FunctionContext* context, Block& block, size_t result,
|
||||
size_t input_rows_count) {
|
||||
static Status execute(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
|
||||
size_t result, size_t input_rows_count) {
|
||||
auto col_to = ColumnVector<NativeType>::create();
|
||||
if constexpr (std::is_same_v<DateType, DataTypeDateV2>) {
|
||||
DateV2Value<DateV2ValueType> dtv;
|
||||
@ -694,8 +794,8 @@ template <typename FunctionName>
|
||||
struct CurrentTimeImpl {
|
||||
using ReturnType = DataTypeFloat64;
|
||||
static constexpr auto name = FunctionName::name;
|
||||
static Status execute(FunctionContext* context, Block& block, size_t result,
|
||||
size_t input_rows_count) {
|
||||
static Status execute(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
|
||||
size_t result, size_t input_rows_count) {
|
||||
auto col_to = ColumnVector<Float64>::create();
|
||||
VecDateTimeValue dtv;
|
||||
if (dtv.from_unixtime(context->impl()->state()->timestamp_ms() / 1000,
|
||||
@ -719,8 +819,8 @@ struct CurrentTimeImpl {
|
||||
struct UtcTimestampImpl {
|
||||
using ReturnType = DataTypeDateTime;
|
||||
static constexpr auto name = "utc_timestamp";
|
||||
static Status execute(FunctionContext* context, Block& block, size_t result,
|
||||
size_t input_rows_count) {
|
||||
static Status execute(FunctionContext* context, Block& block, const ColumnNumbers& arguments,
|
||||
size_t result, size_t input_rows_count) {
|
||||
WhichDataType which(remove_nullable(block.get_by_position(result).type));
|
||||
if (which.is_date_time_v2()) {
|
||||
return executeImpl<DateV2Value<DateTimeV2ValueType>, UInt64>(context, block, result,
|
||||
|
||||
@ -2607,6 +2607,31 @@ bool DateV2Value<T>::from_unixtime(int64_t timestamp, const cctz::time_zone& ctz
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool DateV2Value<T>::from_unixtime(int64_t timestamp, int32_t nano_seconds,
|
||||
const std::string& timezone, const int scale) {
|
||||
cctz::time_zone ctz;
|
||||
if (!TimezoneUtils::find_cctz_time_zone(timezone, ctz)) {
|
||||
return false;
|
||||
}
|
||||
return from_unixtime(timestamp, nano_seconds, ctz, scale);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool DateV2Value<T>::from_unixtime(int64_t timestamp, int32_t nano_seconds,
|
||||
const cctz::time_zone& ctz, const int scale) {
|
||||
static const cctz::time_point<cctz::sys_seconds> epoch =
|
||||
std::chrono::time_point_cast<cctz::sys_seconds>(
|
||||
std::chrono::system_clock::from_time_t(0));
|
||||
cctz::time_point<cctz::sys_seconds> t = epoch + cctz::seconds(timestamp);
|
||||
|
||||
const auto tp = cctz::convert(t, ctz);
|
||||
|
||||
set_time(tp.year(), tp.month(), tp.day(), tp.hour(), tp.minute(), tp.second(),
|
||||
nano_seconds / std::pow(10, 9 - scale) * std::pow(10, 6 - scale));
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
const char* DateV2Value<T>::month_name() const {
|
||||
if (date_v2_value_.month_ < 1 || date_v2_value_.month_ > 12) {
|
||||
|
||||
@ -933,6 +933,9 @@ public:
|
||||
bool from_unixtime(int64_t, const std::string& timezone);
|
||||
bool from_unixtime(int64_t, const cctz::time_zone& ctz);
|
||||
|
||||
bool from_unixtime(int64_t, int32_t, const std::string& timezone, const int scale);
|
||||
bool from_unixtime(int64_t, int32_t, const cctz::time_zone& ctz, const int scale);
|
||||
|
||||
bool operator==(const DateV2Value<T>& other) const {
|
||||
// NOTE: This is not same with MySQL.
|
||||
// MySQL convert both to int with left value type and then compare
|
||||
|
||||
@ -81,6 +81,7 @@ import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collection;
|
||||
@ -550,6 +551,7 @@ public class Analyzer {
|
||||
Calendar currentDate = Calendar.getInstance();
|
||||
String nowStr = formatter.format(currentDate.getTime());
|
||||
queryGlobals.setNowString(nowStr);
|
||||
queryGlobals.setNanoSeconds(LocalDateTime.now().getNano());
|
||||
return queryGlobals;
|
||||
}
|
||||
|
||||
|
||||
@ -82,6 +82,10 @@ public class FunctionCallExpr extends Expr {
|
||||
.addAll(DECIMAL_SAME_TYPE_SET)
|
||||
.addAll(DECIMAL_WIDER_TYPE_SET)
|
||||
.addAll(STDDEV_FUNCTION_SET).build();
|
||||
|
||||
private static final ImmutableSet<String> TIME_FUNCTIONS_WITH_PRECISION =
|
||||
new ImmutableSortedSet.Builder(String.CASE_INSENSITIVE_ORDER)
|
||||
.add("now").add("current_timestamp").add("localtime").add("localtimestamp").build();
|
||||
private static final int STDDEV_DECIMAL_SCALE = 9;
|
||||
private static final String ELEMENT_EXTRACT_FN_NAME = "%element_extract%";
|
||||
|
||||
@ -1036,6 +1040,15 @@ public class FunctionCallExpr extends Expr {
|
||||
}
|
||||
}
|
||||
|
||||
if (TIME_FUNCTIONS_WITH_PRECISION.contains(fnName.getFunction().toLowerCase())
|
||||
&& fn != null && fn.getReturnType().isDatetimeV2()) {
|
||||
if (children.size() == 1 && children.get(0) instanceof IntLiteral) {
|
||||
fn.setReturnType(ScalarType.createDatetimeV2Type((int) ((IntLiteral) children.get(0)).getLongValue()));
|
||||
} else if (children.size() == 1) {
|
||||
fn.setReturnType(ScalarType.createDatetimeV2Type(6));
|
||||
}
|
||||
}
|
||||
|
||||
if (fnName.getFunction().equalsIgnoreCase("from_unixtime")
|
||||
|| fnName.getFunction().equalsIgnoreCase("date_format")) {
|
||||
// if has only one child, it has default time format: yyyy-MM-dd HH:mm:ss.SSSSSS
|
||||
|
||||
@ -61,6 +61,7 @@ import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@ -204,6 +205,7 @@ public class StreamLoadPlanner {
|
||||
queryGlobals.setTimestampMs(System.currentTimeMillis());
|
||||
queryGlobals.setTimeZone(taskInfo.getTimezone());
|
||||
queryGlobals.setLoadZeroTolerance(taskInfo.getMaxFilterRatio() <= 0.0);
|
||||
queryGlobals.setNanoSeconds(LocalDateTime.now().getNano());
|
||||
|
||||
params.setQueryGlobals(queryGlobals);
|
||||
|
||||
|
||||
@ -115,6 +115,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
@ -251,6 +252,7 @@ public class Coordinator {
|
||||
|
||||
this.queryGlobals.setNowString(DATE_FORMAT.format(new Date()));
|
||||
this.queryGlobals.setTimestampMs(System.currentTimeMillis());
|
||||
this.queryGlobals.setNanoSeconds(LocalDateTime.now().getNano());
|
||||
this.queryGlobals.setLoadZeroTolerance(false);
|
||||
if (context.getSessionVariable().getTimeZone().equals("CST")) {
|
||||
this.queryGlobals.setTimeZone(TimeUtils.DEFAULT_TIME_ZONE);
|
||||
|
||||
@ -55,6 +55,7 @@ import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
@ -353,6 +354,7 @@ public class FoldConstantsRule implements ExprRewriteRule {
|
||||
TQueryGlobals queryGlobals = new TQueryGlobals();
|
||||
queryGlobals.setNowString(DATE_FORMAT.format(new Date()));
|
||||
queryGlobals.setTimestampMs(System.currentTimeMillis());
|
||||
queryGlobals.setNanoSeconds(LocalDateTime.now().getNano());
|
||||
queryGlobals.setTimeZone(TimeUtils.DEFAULT_TIME_ZONE);
|
||||
if (context.getSessionVariable().getTimeZone().equals("CST")) {
|
||||
queryGlobals.setTimeZone(TimeUtils.DEFAULT_TIME_ZONE);
|
||||
|
||||
@ -428,6 +428,9 @@ visible_functions = [
|
||||
[['now', 'current_timestamp', 'localtime', 'localtimestamp'], 'DATETIME', [],
|
||||
'_ZN5doris18TimestampFunctions3nowEPN9doris_udf15FunctionContextE',
|
||||
'', '', 'vec', 'ALWAYS_NOT_NULLABLE'],
|
||||
[['now', 'current_timestamp', 'localtime', 'localtimestamp'], 'DATETIMEV2', ['INT'],
|
||||
'_ZN5doris18TimestampFunctions3nowEPN9doris_udf15FunctionContextE',
|
||||
'', '', 'vec', 'ALWAYS_NOT_NULLABLE'],
|
||||
[['curtime', 'current_time'], 'TIME', [],
|
||||
'_ZN5doris18TimestampFunctions7curtimeEPN9doris_udf15FunctionContextE',
|
||||
'', '', 'vec', 'ALWAYS_NOT_NULLABLE'],
|
||||
|
||||
@ -260,7 +260,9 @@ struct TQueryGlobals {
|
||||
3: optional string time_zone
|
||||
|
||||
// Set to true if in a load plan, the max_filter_ratio is 0.0
|
||||
4: optional bool load_zero_tolerance = false;
|
||||
4: optional bool load_zero_tolerance = false
|
||||
|
||||
5: optional i32 nano_seconds
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -383,3 +383,9 @@ true
|
||||
-- !sql --
|
||||
2018-04-02T15:03:28
|
||||
|
||||
-- !sql --
|
||||
19 19 21 22 23 24 25 26
|
||||
|
||||
-- !sql --
|
||||
19 19 21 22 23 24 25 26
|
||||
|
||||
|
||||
@ -303,4 +303,12 @@ suite("test_date_function") {
|
||||
qt_sql """ select STR_TO_DATE('Tue Jul 12 20:00:45 CST 2022', '%a %b %e %H:%i:%s %Y'); """
|
||||
qt_sql """ select STR_TO_DATE('Tue Jul 12 20:00:45 CST 2022', '%a %b %e %T CST %Y'); """
|
||||
qt_sql """ select STR_TO_DATE('2018-4-2 15:3:28','%Y-%m-%d %H:%i:%s'); """
|
||||
|
||||
qt_sql """ select length(cast(now() as string)), length(cast(now(0) as string)), length(cast(now(1) as string)),
|
||||
length(cast(now(2) as string)), length(cast(now(3) as string)), length(cast(now(4) as string)),
|
||||
length(cast(now(5) as string)), length(cast(now(6) as string)); """
|
||||
qt_sql """ select length(cast(current_timestamp() as string)), length(cast(current_timestamp(0) as string)),
|
||||
length(cast(current_timestamp(1) as string)), length(cast(current_timestamp(2) as string)),
|
||||
length(cast(current_timestamp(3) as string)), length(cast(current_timestamp(4) as string)),
|
||||
length(cast(current_timestamp(5) as string)), length(cast(current_timestamp(6) as string)); """
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user