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
129 changes: 121 additions & 8 deletions be/src/exprs/timestamp_functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -398,36 +398,36 @@ BigIntVal TimestampFunctions::timestamp_diff(FunctionContext* ctx, const DateTim
switch (unit) {
case YEAR: {
int year = (ts_value2.year() - ts_value1.year());
if (year >= 0) {
if (year > 0) {
year -= (ts_value2.to_int64() % 10000000000 - ts_value1.to_int64() % 10000000000) < 0;
} else {
} else if (year < 0) {
year += (ts_value2.to_int64() % 10000000000 - ts_value1.to_int64() % 10000000000) > 0;
}
return year;
}
case MONTH: {
int month = (ts_value2.year() - ts_value1.year()) * 12 + (ts_value2.month() - ts_value1.month());
if (month >= 0) {
if (month > 0) {
month -= (ts_value2.to_int64() % 100000000 - ts_value1.to_int64() % 100000000) < 0;
} else {
} else if (month < 0) {
month += (ts_value2.to_int64() % 100000000 - ts_value1.to_int64() % 100000000) > 0;
}
return month;
}
case WEEK: {
int day = ts_value2.daynr() - ts_value1.daynr();
if (day >= 0) {
if (day > 0) {
day -= ts_value2.time_part_diff(ts_value1) < 0;
} else {
} else if (day < 0) {
day += ts_value2.time_part_diff(ts_value1) > 0;
}
return day / 7;
}
case DAY: {
int day = ts_value2.daynr() - ts_value1.daynr();
if (day >= 0) {
if (day > 0) {
day -= ts_value2.time_part_diff(ts_value1) < 0;
} else {
} else if (day < 0) {
day += ts_value2.time_part_diff(ts_value1) > 0;
}
return day;
Expand Down Expand Up @@ -496,6 +496,119 @@ void TimestampFunctions::format_close(
}
}

DateTimeVal from_olap_datetime(uint64_t datetime) {
DateTimeValue ts_value;
if (!ts_value.from_olap_datetime(datetime)) {
return DateTimeVal::null();
}

DateTimeVal ts_val;
ts_value.to_datetime_val(&ts_val);
return ts_val;
}

#define _TR_4(TYPE, type, UNIT, unit) \
DateTimeVal TimestampFunctions::unit##_##type( \
FunctionContext* ctx, const DateTimeVal& ts_val, \
const IntVal& period, const DateTimeVal& origin) { \
return time_round<UNIT, TYPE>(ctx, ts_val, period, origin); \
} \
DateTimeVal TimestampFunctions::unit##_##type( \
FunctionContext* ctx, const DateTimeVal& ts_val, const DateTimeVal& origin) { \
return time_round<UNIT, TYPE>(ctx, ts_val, IntVal(1), origin); \
}

#define _TR_5(TYPE, type, UNIT, unit, ORIGIN) \
DateTimeVal TimestampFunctions::unit##_##type( \
FunctionContext* ctx, const DateTimeVal& ts_val) { \
return time_round<UNIT, TYPE>(ctx, ts_val, IntVal(1), ORIGIN); \
} \
DateTimeVal TimestampFunctions::unit##_##type( \
FunctionContext* ctx, const DateTimeVal& ts_val, const IntVal& period) { \
return time_round<UNIT, TYPE>(ctx, ts_val, period, ORIGIN); \
}

#define FLOOR 0
#define CEIL 1

static const DateTimeVal FIRST_DAY = from_olap_datetime(19700101000000);
static const DateTimeVal FIRST_SUNDAY = from_olap_datetime(19700104000000);

#define TIME_ROUND(UNIT, unit, ORIGIN) \
_TR_4(FLOOR, floor, UNIT, unit) _TR_4(CEIL, ceil, UNIT, unit) \
_TR_5(FLOOR, floor, UNIT, unit, ORIGIN) _TR_5(CEIL, ceil, UNIT, unit, ORIGIN)

TIME_ROUND(YEAR, year, FIRST_DAY)
TIME_ROUND(MONTH, month, FIRST_DAY)
TIME_ROUND(WEEK, week, FIRST_SUNDAY)
TIME_ROUND(DAY, day, FIRST_DAY)
TIME_ROUND(HOUR, hour, FIRST_DAY)
TIME_ROUND(MINUTE, minute, FIRST_DAY)
TIME_ROUND(SECOND, second, FIRST_DAY)

template <TimeUnit unit, bool type>
DateTimeVal TimestampFunctions::time_round(
FunctionContext* ctx, const DateTimeVal& ts_val,
const IntVal& period, const DateTimeVal& origin) {
if (ts_val.is_null || period.is_null || period.val < 1 || origin.is_null) {
return DateTimeVal::null();
}

DateTimeValue ts1 = DateTimeValue::from_datetime_val(origin);
DateTimeValue ts2 = DateTimeValue::from_datetime_val(ts_val);
int64_t diff;
switch (unit) {
case YEAR: {
int year = (ts2.year() - ts1.year());
diff = year - (ts2.to_int64() % 10000000000 < ts1.to_int64() % 10000000000);
break;
}
case MONTH: {
int month = (ts2.year() - ts1.year()) * 12 + (ts2.month() - ts1.month());
diff = month - (ts2.to_int64() % 100000000 < ts1.to_int64() % 100000000);
break;
}
case WEEK: {
int week = ts2.daynr() / 7 - ts1.daynr() / 7;
diff = week - (ts2.daynr() % 7 < ts1.daynr() % 7 + (ts2.time_part_diff(ts1) < 0));
break;
}
case DAY: {
int day = ts2.daynr() - ts1.daynr();
diff = day - (ts2.time_part_diff(ts1) < 0);
break;
}
case HOUR: {
int hour = (ts2.daynr() - ts1.daynr()) * 24 + (ts2.hour() - ts1.hour());
diff = hour - ((ts2.minute() * 60 + ts2.second()) < (ts1.minute() * 60 - ts1.second()));
break;
}
case MINUTE: {
int minute = (ts2.daynr() - ts1.daynr()) * 24 * 60 +
(ts2.hour() - ts1.hour()) * 60 + (ts2.minute() - ts1.minute());
diff = minute - (ts2.second() < ts1.second());
break;
}
case SECOND: {
diff = ts2.second_diff(ts1);
break;
}
default:
return DateTimeVal::null();
}
int64_t count = period.val;
int64_t step = diff - (diff % count + count) % count + (type == FLOOR ? 0 : count);
bool is_neg = step < 0;

TimeInterval interval(unit, is_neg ? -step : step, is_neg);
if (!ts1.date_add_interval(interval, unit)) {
return DateTimeVal::null();
}
DateTimeVal new_ts_val;
ts1.to_datetime_val(&new_ts_val);
return new_ts_val;
}

StringVal TimestampFunctions::date_format(
FunctionContext* ctx, const DateTimeVal& ts_val, const StringVal& format) {
if (ts_val.is_null || format.is_null) {
Expand Down
174 changes: 174 additions & 0 deletions be/src/exprs/timestamp_functions.h
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,180 @@ class TimestampFunctions {
static doris_udf::BigIntVal seconds_diff(
doris_udf::FunctionContext* ctx, const doris_udf::DateTimeVal& ts_val1, const doris_udf::DateTimeVal& ts_val2);

// Period functions.
template <TimeUnit unit, bool type>
static doris_udf::DateTimeVal time_round(
doris_udf::FunctionContext* ctx, const doris_udf::DateTimeVal& ts_val,
const doris_udf::IntVal& period, const doris_udf::DateTimeVal& origin);

static doris_udf::DateTimeVal year_floor(
doris_udf::FunctionContext* ctx, const doris_udf::DateTimeVal& ts_val);
static doris_udf::DateTimeVal year_floor(
doris_udf::FunctionContext* ctx, const doris_udf::DateTimeVal& ts_val,
const doris_udf::IntVal& period);
static doris_udf::DateTimeVal year_floor(
doris_udf::FunctionContext* ctx, const doris_udf::DateTimeVal& ts_val,
const doris_udf::DateTimeVal& origin);
static doris_udf::DateTimeVal year_floor(
doris_udf::FunctionContext* ctx, const doris_udf::DateTimeVal& ts_val,
const doris_udf::IntVal& period, const doris_udf::DateTimeVal& origin);

static doris_udf::DateTimeVal year_ceil(
doris_udf::FunctionContext* ctx, const doris_udf::DateTimeVal& ts_val);
static doris_udf::DateTimeVal year_ceil(
doris_udf::FunctionContext* ctx, const doris_udf::DateTimeVal& ts_val,
const doris_udf::IntVal& period);
static doris_udf::DateTimeVal year_ceil(
doris_udf::FunctionContext* ctx, const doris_udf::DateTimeVal& ts_val,
const doris_udf::DateTimeVal& origin);
static doris_udf::DateTimeVal year_ceil(
doris_udf::FunctionContext* ctx, const doris_udf::DateTimeVal& ts_val,
const doris_udf::IntVal& period, const doris_udf::DateTimeVal& origin);

static doris_udf::DateTimeVal month_floor(
doris_udf::FunctionContext* ctx, const doris_udf::DateTimeVal& ts_val);
static doris_udf::DateTimeVal month_floor(
doris_udf::FunctionContext* ctx, const doris_udf::DateTimeVal& ts_val,
const doris_udf::IntVal& period);
static doris_udf::DateTimeVal month_floor(
doris_udf::FunctionContext* ctx, const doris_udf::DateTimeVal& ts_val,
const doris_udf::DateTimeVal& origin);
static doris_udf::DateTimeVal month_floor(
doris_udf::FunctionContext* ctx, const doris_udf::DateTimeVal& ts_val,
const doris_udf::IntVal& period, const doris_udf::DateTimeVal& origin);

static doris_udf::DateTimeVal month_ceil(
doris_udf::FunctionContext* ctx, const doris_udf::DateTimeVal& ts_val);
static doris_udf::DateTimeVal month_ceil(
doris_udf::FunctionContext* ctx, const doris_udf::DateTimeVal& ts_val,
const doris_udf::IntVal& period);
static doris_udf::DateTimeVal month_ceil(
doris_udf::FunctionContext* ctx, const doris_udf::DateTimeVal& ts_val,
const doris_udf::DateTimeVal& origin);
static doris_udf::DateTimeVal month_ceil(
doris_udf::FunctionContext* ctx, const doris_udf::DateTimeVal& ts_val,
const doris_udf::IntVal& period, const doris_udf::DateTimeVal& origin);

static doris_udf::DateTimeVal week_floor(
doris_udf::FunctionContext* ctx, const doris_udf::DateTimeVal& ts_val);
static doris_udf::DateTimeVal week_floor(
doris_udf::FunctionContext* ctx, const doris_udf::DateTimeVal& ts_val,
const doris_udf::IntVal& period);
static doris_udf::DateTimeVal week_floor(
doris_udf::FunctionContext* ctx, const doris_udf::DateTimeVal& ts_val,
const doris_udf::DateTimeVal& origin);
static doris_udf::DateTimeVal week_floor(
doris_udf::FunctionContext* ctx, const doris_udf::DateTimeVal& ts_val,
const doris_udf::IntVal& period, const doris_udf::DateTimeVal& origin);

static doris_udf::DateTimeVal week_ceil(
doris_udf::FunctionContext* ctx, const doris_udf::DateTimeVal& ts_val);
static doris_udf::DateTimeVal week_ceil(
doris_udf::FunctionContext* ctx, const doris_udf::DateTimeVal& ts_val,
const doris_udf::IntVal& period);
static doris_udf::DateTimeVal week_ceil(
doris_udf::FunctionContext* ctx, const doris_udf::DateTimeVal& ts_val,
const doris_udf::DateTimeVal& origin);
static doris_udf::DateTimeVal week_ceil(
doris_udf::FunctionContext* ctx, const doris_udf::DateTimeVal& ts_val,
const doris_udf::IntVal& period, const doris_udf::DateTimeVal& origin);

static doris_udf::DateTimeVal day_floor(
doris_udf::FunctionContext* ctx, const doris_udf::DateTimeVal& ts_val);
static doris_udf::DateTimeVal day_floor(
doris_udf::FunctionContext* ctx, const doris_udf::DateTimeVal& ts_val,
const doris_udf::IntVal& period);
static doris_udf::DateTimeVal day_floor(
doris_udf::FunctionContext* ctx, const doris_udf::DateTimeVal& ts_val,
const doris_udf::DateTimeVal& origin);
static doris_udf::DateTimeVal day_floor(
doris_udf::FunctionContext* ctx, const doris_udf::DateTimeVal& ts_val,
const doris_udf::IntVal& period, const doris_udf::DateTimeVal& origin);

static doris_udf::DateTimeVal day_ceil(
doris_udf::FunctionContext* ctx, const doris_udf::DateTimeVal& ts_val);
static doris_udf::DateTimeVal day_ceil(
doris_udf::FunctionContext* ctx, const doris_udf::DateTimeVal& ts_val,
const doris_udf::IntVal& period);
static doris_udf::DateTimeVal day_ceil(
doris_udf::FunctionContext* ctx, const doris_udf::DateTimeVal& ts_val,
const doris_udf::DateTimeVal& origin);
static doris_udf::DateTimeVal day_ceil(
doris_udf::FunctionContext* ctx, const doris_udf::DateTimeVal& ts_val,
const doris_udf::IntVal& period, const doris_udf::DateTimeVal& origin);

static doris_udf::DateTimeVal hour_floor(
doris_udf::FunctionContext* ctx, const doris_udf::DateTimeVal& ts_val);
static doris_udf::DateTimeVal hour_floor(
doris_udf::FunctionContext* ctx, const doris_udf::DateTimeVal& ts_val,
const doris_udf::IntVal& period);
static doris_udf::DateTimeVal hour_floor(
doris_udf::FunctionContext* ctx, const doris_udf::DateTimeVal& ts_val,
const doris_udf::DateTimeVal& origin);
static doris_udf::DateTimeVal hour_floor(
doris_udf::FunctionContext* ctx, const doris_udf::DateTimeVal& ts_val,
const doris_udf::IntVal& period, const doris_udf::DateTimeVal& origin);

static doris_udf::DateTimeVal hour_ceil(
doris_udf::FunctionContext* ctx, const doris_udf::DateTimeVal& ts_val);
static doris_udf::DateTimeVal hour_ceil(
doris_udf::FunctionContext* ctx, const doris_udf::DateTimeVal& ts_val,
const doris_udf::IntVal& period);
static doris_udf::DateTimeVal hour_ceil(
doris_udf::FunctionContext* ctx, const doris_udf::DateTimeVal& ts_val,
const doris_udf::DateTimeVal& origin);
static doris_udf::DateTimeVal hour_ceil(
doris_udf::FunctionContext* ctx, const doris_udf::DateTimeVal& ts_val,
const doris_udf::IntVal& period, const doris_udf::DateTimeVal& origin);

static doris_udf::DateTimeVal minute_floor(
doris_udf::FunctionContext* ctx, const doris_udf::DateTimeVal& ts_val);
static doris_udf::DateTimeVal minute_floor(
doris_udf::FunctionContext* ctx, const doris_udf::DateTimeVal& ts_val,
const doris_udf::IntVal& period);
static doris_udf::DateTimeVal minute_floor(
doris_udf::FunctionContext* ctx, const doris_udf::DateTimeVal& ts_val,
const doris_udf::DateTimeVal& origin);
static doris_udf::DateTimeVal minute_floor(
doris_udf::FunctionContext* ctx, const doris_udf::DateTimeVal& ts_val,
const doris_udf::IntVal& period, const doris_udf::DateTimeVal& origin);

static doris_udf::DateTimeVal minute_ceil(
doris_udf::FunctionContext* ctx, const doris_udf::DateTimeVal& ts_val);
static doris_udf::DateTimeVal minute_ceil(
doris_udf::FunctionContext* ctx, const doris_udf::DateTimeVal& ts_val,
const doris_udf::IntVal& period);
static doris_udf::DateTimeVal minute_ceil(
doris_udf::FunctionContext* ctx, const doris_udf::DateTimeVal& ts_val,
const doris_udf::DateTimeVal& origin);
static doris_udf::DateTimeVal minute_ceil(
doris_udf::FunctionContext* ctx, const doris_udf::DateTimeVal& ts_val,
const doris_udf::IntVal& period, const doris_udf::DateTimeVal& origin);

static doris_udf::DateTimeVal second_floor(
doris_udf::FunctionContext* ctx, const doris_udf::DateTimeVal& ts_val);
static doris_udf::DateTimeVal second_floor(
doris_udf::FunctionContext* ctx, const doris_udf::DateTimeVal& ts_val,
const doris_udf::IntVal& period);
static doris_udf::DateTimeVal second_floor(
doris_udf::FunctionContext* ctx, const doris_udf::DateTimeVal& ts_val,
const doris_udf::DateTimeVal& origin);
static doris_udf::DateTimeVal second_floor(
doris_udf::FunctionContext* ctx, const doris_udf::DateTimeVal& ts_val,
const doris_udf::IntVal& period, const doris_udf::DateTimeVal& origin);

static doris_udf::DateTimeVal second_ceil(
doris_udf::FunctionContext* ctx, const doris_udf::DateTimeVal& ts_val);
static doris_udf::DateTimeVal second_ceil(
doris_udf::FunctionContext* ctx, const doris_udf::DateTimeVal& ts_val,
const doris_udf::IntVal& period);
static doris_udf::DateTimeVal second_ceil(
doris_udf::FunctionContext* ctx, const doris_udf::DateTimeVal& ts_val,
const doris_udf::DateTimeVal& origin);
static doris_udf::DateTimeVal second_ceil(
doris_udf::FunctionContext* ctx, const doris_udf::DateTimeVal& ts_val,
const doris_udf::IntVal& period, const doris_udf::DateTimeVal& origin);

// TimeZone correlation functions.
static doris_udf::DateTimeVal timestamp(
doris_udf::FunctionContext* ctx, const doris_udf::DateTimeVal& val);
Expand Down
16 changes: 8 additions & 8 deletions be/src/runtime/datetime_value.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,21 +57,21 @@ enum TimeUnit {
};

struct TimeInterval {
int32_t year;
int32_t month;
int32_t day;
int32_t hour;
int32_t minute;
int32_t second;
int32_t microsecond;
int64_t year;
int64_t month;
int64_t day;
int64_t hour;
int64_t minute;
int64_t second;
int64_t microsecond;
bool is_neg;

TimeInterval() :
year(0), month(0), day(0),
hour(0), minute(0), second(0), microsecond(0), is_neg(false) {
}

TimeInterval(TimeUnit unit, int count, bool is_neg_param) :
TimeInterval(TimeUnit unit, int64_t count, bool is_neg_param) :
year(0), month(0), day(0),
hour(0), minute(0), second(0), microsecond(0), is_neg(is_neg_param) {
switch (unit) {
Expand Down
Loading