support last_day in mysql mode
This commit is contained in:
parent
09edba0ff6
commit
74d0236609
14
deps/oblib/src/lib/ob_date_unit_type.cpp
vendored
14
deps/oblib/src/lib/ob_date_unit_type.cpp
vendored
@ -111,3 +111,17 @@ const char* ob_date_unit_type_num_str(enum ObDateUnitType type)
|
||||
static_assert(DATE_UNIT_MAX + 1 == ARRAYSIZEOF(date_unit_type_num), "size of array not match enum size");
|
||||
return date_unit_type_num[type];
|
||||
}
|
||||
|
||||
const char *ob_get_format_unit_type_str(enum ObGetFormatUnitType type)
|
||||
{
|
||||
static const char *get_format_unit_type_name[GET_FORMAT_MAX + 1] =
|
||||
{
|
||||
"date",
|
||||
"time",
|
||||
"datetime",
|
||||
"unknown",
|
||||
};
|
||||
static_assert(GET_FORMAT_MAX + 1 == ARRAYSIZEOF(get_format_unit_type_name),
|
||||
"size of array not match enum size");
|
||||
return get_format_unit_type_name[type];
|
||||
}
|
9
deps/oblib/src/lib/ob_date_unit_type.h
vendored
9
deps/oblib/src/lib/ob_date_unit_type.h
vendored
@ -45,9 +45,18 @@ enum ObDateUnitType {
|
||||
DATE_UNIT_MAX
|
||||
};
|
||||
|
||||
enum ObGetFormatUnitType
|
||||
{
|
||||
GET_FORMAT_DATE = 0,
|
||||
GET_FORMAT_TIME = 1,
|
||||
GET_FORMAT_DATETIME = 2,
|
||||
GET_FORMAT_MAX = 3,
|
||||
};
|
||||
|
||||
const char* ob_date_unit_type_str(enum ObDateUnitType type);
|
||||
const char* ob_date_unit_type_str_upper(enum ObDateUnitType type);
|
||||
const char* ob_date_unit_type_num_str(enum ObDateUnitType type);
|
||||
const char* ob_get_format_unit_type_str(enum ObGetFormatUnitType type);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
5
deps/oblib/src/lib/ob_define.h
vendored
5
deps/oblib/src/lib/ob_define.h
vendored
@ -2014,9 +2014,10 @@ inline int64_t ob_gettid()
|
||||
#define COMMA_REVERSE ",Reverse"
|
||||
#define BRACKET_REVERSE "(Reverse)"
|
||||
|
||||
#define ORALCE_LITERAL_PREFIX_DATE "DATE"
|
||||
#define ORALCE_LITERAL_PREFIX_TIMESTAMP "TIMESTAMP"
|
||||
#define LITERAL_PREFIX_DATE "DATE"
|
||||
#define LITERAL_PREFIX_TIMESTAMP "TIMESTAMP"
|
||||
#define ORACLE_LITERAL_PREFIX_INTERVAL "INTERVAL"
|
||||
#define MYSQL_LITERAL_PREFIX_TIME "TIME"
|
||||
inline bool is_x86()
|
||||
{
|
||||
#if defined(__x86_64__)
|
||||
|
7
deps/oblib/src/lib/ob_name_def.h
vendored
7
deps/oblib/src/lib/ob_name_def.h
vendored
@ -491,6 +491,7 @@
|
||||
#define N_TIME_STAMP_DIFF "timestampdiff"
|
||||
#define N_TIME_DIFF "timediff"
|
||||
#define N_PERIOD_DIFF "period_diff"
|
||||
#define N_PERIOD_ADD "period_add"
|
||||
#define N_SYS_SLEEP "sleep"
|
||||
#define N_UNIX_TIMESTAMP "unix_timestamp"
|
||||
#define N_FROM_UNIX_TIME "from_unixtime"
|
||||
@ -499,6 +500,9 @@
|
||||
#define N_STR_TO_DATE "str_to_date"
|
||||
#define N_TO_DATE "to_date"
|
||||
#define N_TO_CHAR "to_char"
|
||||
#define N_TIMESTAMP "timestamp"
|
||||
#define N_MAKEDATE "makedate"
|
||||
#define N_GET_FORMAT "get_format"
|
||||
#define N_FORMAT "format"
|
||||
#define N_TO_CLOB "to_clob"
|
||||
#define N_TO_BLOB "to_blob"
|
||||
@ -535,6 +539,8 @@
|
||||
#define N_CUR_DATE "cur_date"
|
||||
#define N_CURRENT_DATE "current_date"
|
||||
#define N_UTC_TIMESTAMP "utc_timestamp"
|
||||
#define N_UTC_TIME "utc_time"
|
||||
#define N_UTC_DATE "utc_date"
|
||||
#define N_SYSTIMESTAMP "systimestamp"
|
||||
#define N_MAKETIME "maketime"
|
||||
#define N_UPS_CUR_TIME "ups_cur_time"
|
||||
@ -634,6 +640,7 @@
|
||||
#define N_PAYLOAD "payload"
|
||||
#define N_CELLS "cells"
|
||||
#define N_OB_EXECUTION_ID "ob_execution_id"
|
||||
#define N_TIME_FORMAT "time_format"
|
||||
#define N_EXECUTION_TIME "execution_time"
|
||||
#define N_OB_JOB_ID "ob_job_id"
|
||||
#define N_OB_TASK_ID "ob_task_id"
|
||||
|
3
deps/oblib/src/lib/rc/context.cpp
vendored
3
deps/oblib/src/lib/rc/context.cpp
vendored
@ -21,8 +21,7 @@ namespace oceanbase {
|
||||
namespace lib {
|
||||
RLOCAL(bool, ContextTLOptGuard::enable_tl_opt);
|
||||
|
||||
int64_t __MemoryContext__::g_seq_id = 0;
|
||||
__MemoryContext__ &__MemoryContext__::root()
|
||||
__MemoryContext__& __MemoryContext__::root()
|
||||
{
|
||||
static __MemoryContext__ *root = nullptr;
|
||||
if (OB_UNLIKELY(nullptr == root)) {
|
||||
|
13
deps/oblib/src/lib/rc/context.h
vendored
13
deps/oblib/src/lib/rc/context.h
vendored
@ -308,7 +308,12 @@ class __MemoryContext__
|
||||
friend class MemoryContext;
|
||||
constexpr static uint64_t MAGIC_CODE = 0xfddf13244231dfdf;
|
||||
public:
|
||||
static int64_t g_seq_id;
|
||||
static int64_t gen_seq_id()
|
||||
{
|
||||
static __thread uint32_t local_id = 0;
|
||||
return common::get_itid() << 32 | local_id++;
|
||||
}
|
||||
|
||||
public:
|
||||
__MemoryContext__(const bool need_free, const DynamicInfo &di, __MemoryContext__ *parent,
|
||||
ContextParam ¶m, const int static_id)
|
||||
@ -519,9 +524,8 @@ public:
|
||||
free(ptr);
|
||||
}
|
||||
} else {
|
||||
const int64_t seq_id = ATOMIC_AAF(&__MemoryContext__::g_seq_id, 1);
|
||||
ref_context->magic_code_ = MAGIC_CODE;
|
||||
ref_context->seq_id_ = seq_id;
|
||||
ref_context->seq_id_ = gen_seq_id();
|
||||
context = ref_context;
|
||||
}
|
||||
return ret;
|
||||
@ -541,9 +545,8 @@ public:
|
||||
if (OB_FAIL(ret)) {
|
||||
ref_context.deinit();
|
||||
} else {
|
||||
const int64_t seq_id = ATOMIC_AAF(&__MemoryContext__::g_seq_id, 1);
|
||||
ref_context.magic_code_ = MAGIC_CODE;
|
||||
ref_context.seq_id_ = seq_id;
|
||||
ref_context.seq_id_ = gen_seq_id();
|
||||
context = &ref_context;
|
||||
}
|
||||
|
||||
|
170
deps/oblib/src/lib/timezone/ob_time_convert.cpp
vendored
170
deps/oblib/src/lib/timezone/ob_time_convert.cpp
vendored
@ -1941,7 +1941,7 @@ int ObTimeConverter::str_to_ob_time_with_date(const ObString& str, ObTime& ob_ti
|
||||
LOG_WARN("failed to get digits", K(ret), K(str));
|
||||
} else if (OB_FAIL(validate_datetime(ob_time, is_dayofmonth))) {
|
||||
// OK, it seems like a valid format, now we need check its value.
|
||||
LOG_WARN("datetime is invalid or out of range", K(ret), K(str), K(ob_time));
|
||||
LOG_WARN("datetime is invalid or out of range", K(ret), K(str), K(ob_time), K(lbt()));
|
||||
} else {
|
||||
ob_time.parts_[DT_DATE] = ob_time_to_date(ob_time);
|
||||
}
|
||||
@ -2106,6 +2106,17 @@ int ObTimeConverter::str_to_ob_time_without_date(const ObString& str, ObTime& ob
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define GET_YEAR_WEEK_WDAY(len, var, set_state, elem, max, min) \
|
||||
if (OB_SUCC(get_datetime_digits(str_pos, str_end, len, digits))) { \
|
||||
if (digits.value_ < min || digits.value_ > max) { \
|
||||
ret = OB_INVALID_DATE_VALUE; \
|
||||
} else { \
|
||||
var.elem##_set_state_ = ObYearWeekWdayElems::ElemSetState::set_state; \
|
||||
var.elem##_value_ = digits.value_; \
|
||||
} \
|
||||
}
|
||||
|
||||
|
||||
int ObTimeConverter::str_to_ob_time_format(const ObString& str, const ObString& fmt, ObTime& ob_time, int16_t* scale)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
@ -2129,6 +2140,8 @@ int ObTimeConverter::str_to_ob_time_format(const ObString& str, const ObString&
|
||||
ObString name;
|
||||
ObTimeDigits digits;
|
||||
ObTimeDelims delims;
|
||||
// https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_date-format
|
||||
ObYearWeekWdayElems week_day_elements;
|
||||
if (NULL != scale) {
|
||||
*scale = 0;
|
||||
}
|
||||
@ -2152,6 +2165,8 @@ int ObTimeConverter::str_to_ob_time_format(const ObString& str, const ObString&
|
||||
name.assign_ptr(const_cast<char*>(str_pos), static_cast<int32_t>(str_end - str_pos));
|
||||
if (OB_SUCC(get_str_array_idx(name, WDAY_ABBR_NAMES, DAYS_PER_WEEK, ob_time.parts_[DT_WDAY]))) {
|
||||
str_pos += WDAY_ABBR_NAMES[ob_time.parts_[DT_WDAY]].len_;
|
||||
week_day_elements.weekday_set_ = true;
|
||||
week_day_elements.weekday_value_ = ob_time.parts_[DT_WDAY] % DAYS_PER_WEEK;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -2270,19 +2285,62 @@ int ObTimeConverter::str_to_ob_time_format(const ObString& str, const ObString&
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'U':
|
||||
case 'u':
|
||||
case 'V':
|
||||
case 'v':
|
||||
case 'W':
|
||||
case 'w':
|
||||
case 'X':
|
||||
case 'U': {
|
||||
GET_YEAR_WEEK_WDAY(2, week_day_elements, UPPER_SET, week, 53, 0);
|
||||
week_day_elements.week_u_set_ = true;
|
||||
break;
|
||||
}
|
||||
case 'u': {
|
||||
GET_YEAR_WEEK_WDAY(2, week_day_elements, LOWER_SET, week, 53, 0);
|
||||
week_day_elements.week_u_set_ = true;
|
||||
break;
|
||||
}
|
||||
case 'V': {
|
||||
GET_YEAR_WEEK_WDAY(2, week_day_elements, UPPER_SET, week, 53, 1);
|
||||
week_day_elements.week_u_set_ = false;
|
||||
break;
|
||||
}
|
||||
case 'v': {
|
||||
GET_YEAR_WEEK_WDAY(2, week_day_elements, LOWER_SET, week, 53, 1);
|
||||
week_day_elements.week_u_set_ = false;
|
||||
break;
|
||||
}
|
||||
case 'W': {
|
||||
name.assign_ptr(const_cast<char *>(str_pos), static_cast<int32_t>(str_end - str_pos));
|
||||
if (OB_SUCC(get_str_array_idx(name, WDAY_NAMES, static_cast<int32_t>(DAYS_PER_WEEK),
|
||||
ob_time.parts_[DT_WDAY]))) {
|
||||
str_pos += WDAY_NAMES[ob_time.parts_[DT_WDAY]].len_;
|
||||
week_day_elements.weekday_set_ = true;
|
||||
week_day_elements.weekday_value_ = ob_time.parts_[DT_WDAY] % DAYS_PER_WEEK;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'w': {
|
||||
if (OB_SUCC(get_datetime_digits(str_pos, str_end, 1, digits))) {
|
||||
if (digits.value_ < 0 || digits.value_ > 6) {
|
||||
ret = OB_INVALID_DATE_VALUE;
|
||||
} else {
|
||||
week_day_elements.weekday_set_ = true;
|
||||
week_day_elements.weekday_value_ = digits.value_;
|
||||
ob_time.parts_[DT_WDAY] = 0 == digits.value_ ? DAYS_PER_WEEK : digits.value_;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'X': {
|
||||
GET_YEAR_WEEK_WDAY(4, week_day_elements, UPPER_SET, year, 9999, 0);
|
||||
break;
|
||||
}
|
||||
case 'x': {
|
||||
ret = OB_NOT_SUPPORTED; // not use in str_to_date()
|
||||
GET_YEAR_WEEK_WDAY(4, week_day_elements, LOWER_SET, year, 9999, 0);
|
||||
break;
|
||||
}
|
||||
case 'Y': {
|
||||
const char *ori_pos = str_pos;
|
||||
if (OB_SUCC(get_datetime_digits(str_pos, str_end, 4, digits))) {
|
||||
if (str_pos - ori_pos <= 2) {
|
||||
apply_date_year2_rule(digits);
|
||||
}
|
||||
ob_time.parts_[DT_YEAR] = digits.value_;
|
||||
}
|
||||
break;
|
||||
@ -2317,7 +2375,10 @@ int ObTimeConverter::str_to_ob_time_format(const ObString& str, const ObString&
|
||||
} else if (HOUR_PM == hour_flag && ob_time.parts_[DT_HOUR] > 0 && ob_time.parts_[DT_HOUR] < 12) {
|
||||
ob_time.parts_[DT_HOUR] += 12;
|
||||
}
|
||||
if (0 == ob_time.parts_[DT_MON] && 0 == ob_time.parts_[DT_MDAY] && 0 == ob_time.parts_[DT_YEAR]) {
|
||||
if (OB_FAIL(handle_year_week_wday(week_day_elements, ob_time))) {
|
||||
LOG_WARN("handle %u %x %v and %w value failed", K(ret));
|
||||
} else if (0 == ob_time.parts_[DT_MON] && 0 == ob_time.parts_[DT_MDAY]
|
||||
&& 0 == ob_time.parts_[DT_YEAR]) {
|
||||
if (OB_FAIL(validate_time(ob_time))) {
|
||||
LOG_WARN("time value is invalid or out of range", K(ret), K(str));
|
||||
}
|
||||
@ -2333,6 +2394,69 @@ int ObTimeConverter::str_to_ob_time_format(const ObString& str, const ObString&
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObTimeConverter::calc_date_with_year_week_wday(const ObYearWeekWdayElems &elements, ObTime &ot)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObTime tmp_ot;
|
||||
tmp_ot.parts_[DT_YEAR] = elements.is_year_set() ? elements.year_value_ : ot.parts_[DT_YEAR];
|
||||
tmp_ot.parts_[DT_MON] = 1;
|
||||
tmp_ot.parts_[DT_MDAY] = 1;
|
||||
tmp_ot.parts_[DT_DATE] = ob_time_to_date(tmp_ot);
|
||||
// now we get weekday of %X-01-01: tmp_ot.parts_[DT_WDAY]
|
||||
const bool is_sunday_start = elements.is_upper_week_set();
|
||||
int32_t week = elements.week_value_;
|
||||
int32_t weekday = is_sunday_start ? elements.weekday_value_
|
||||
: ((elements.weekday_value_ + DAYS_PER_WEEK - 1) % DAYS_PER_WEEK) + 1;
|
||||
// %X%V means week start with sunday and the first week in the year must contain sunday.
|
||||
const int32_t first_week_monday_offset_upper[DAYS_PER_WEEK] = {1, 7, 6, 5, 4, 3, 2};
|
||||
// %X%V means week start with monday and the first week in the year must contain at least 4 days.
|
||||
const int32_t first_week_monday_offset_lower[DAYS_PER_WEEK] = {1, 0, -1, -2, -3, 3, 2};
|
||||
int32_t offset = (elements.is_upper_week_set() ?
|
||||
first_week_monday_offset_upper[tmp_ot.parts_[DT_WDAY] % DAYS_PER_WEEK] :
|
||||
first_week_monday_offset_lower[tmp_ot.parts_[DT_WDAY] % DAYS_PER_WEEK])
|
||||
+ (week - 1) * DAYS_PER_WEEK + (weekday - 1);
|
||||
int32_t date_value = tmp_ot.parts_[DT_DATE] + offset;
|
||||
if (OB_FAIL(date_to_ob_time(date_value, ot))) {
|
||||
LOG_WARN("date to ob time failed", K(ret));
|
||||
}
|
||||
LOG_DEBUG("%x %v", K(ret), K(elements), K(tmp_ot), K(offset), K(date_value), K(ot));
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObTimeConverter::handle_year_week_wday(const ObYearWeekWdayElems &elements, ObTime &ot)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
//%X/%x must be used together with %V/%v
|
||||
if ((elements.is_year_set() || elements.is_week_v_set())
|
||||
&& !(elements.year_set_state_ == elements.week_set_state_ && elements.is_week_v_set())) {
|
||||
ret = OB_INVALID_DATE_VALUE;
|
||||
MEMSET(ot.parts_, 0, sizeof(*ot.parts_) * TOTAL_PART_CNT);
|
||||
ot.parts_[DT_DATE] = ZERO_DATE;
|
||||
LOG_WARN("%x and %v must be used together", K(ret), K(elements));
|
||||
} else if (elements.is_year_set()) {
|
||||
if (elements.year_value_ <= 0) {
|
||||
MEMSET(ot.parts_, 0, sizeof(*ot.parts_) * TOTAL_PART_CNT);
|
||||
ot.parts_[DT_DATE] = ZERO_DATE;
|
||||
} else if (elements.is_weekday_set()) {
|
||||
// calc date with elements %x, %v and %w/a
|
||||
if (OB_FAIL(calc_date_with_year_week_wday(elements, ot))) {
|
||||
LOG_WARN("calc date with year week and wday failed", K(ret));
|
||||
}
|
||||
}
|
||||
} else if (elements.is_week_u_set() && elements.is_weekday_set()) {
|
||||
if (0 == ot.parts_[DT_YEAR]) {
|
||||
MEMSET(ot.parts_, 0, sizeof(*ot.parts_) * TOTAL_PART_CNT);
|
||||
ot.parts_[DT_DATE] = ZERO_DATE;
|
||||
} else {
|
||||
// calc date with elements %y %u and %w/a
|
||||
if (OB_FAIL(calc_date_with_year_week_wday(elements, ot))) {
|
||||
LOG_WARN("calc date with year week and wday failed", K(ret));
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObTimeConverter::str_to_ob_interval(const ObString& str, ObDateUnitType unit_type, ObInterval& ob_interval)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
@ -2884,12 +3008,12 @@ int ObTimeConverter::data_fmt_nd(char* buffer, int64_t buf_len, int64_t& pos, co
|
||||
int ObTimeConverter::data_fmt_d(char* buffer, int64_t buf_len, int64_t& pos, int64_t target)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (OB_UNLIKELY(target < 0 || target >= 100)) {
|
||||
if (OB_UNLIKELY(target < 0)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LIB_TIME_LOG(ERROR, "invalid argument", K(ret), K(target));
|
||||
} else {
|
||||
// buffer_size_need will be 1 or 2
|
||||
int64_t buffer_size_need = 1 + (target >= 10);
|
||||
//buffer_size_need will be 1 or 2 or 3
|
||||
int64_t buffer_size_need = 1 + (target >= 10) + (target >= 100);
|
||||
if (OB_UNLIKELY(buffer_size_need > buf_len - pos)) {
|
||||
ret = OB_SIZE_OVERFLOW;
|
||||
LIB_TIME_LOG(WARN, "no enough space for buffer", K(ret), K(buffer_size_need), K(buf_len), K(pos));
|
||||
@ -4676,7 +4800,11 @@ int ObTimeConverter::ob_time_to_str_format(
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
ret = OB_NOT_SUPPORTED;
|
||||
if (pos >= buf_len) {
|
||||
ret = OB_SIZE_OVERFLOW;
|
||||
break;
|
||||
}
|
||||
buf[pos++] = *format_ptr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -5679,7 +5807,7 @@ int ObTimeConverter::otimestamp_add_nsecond(const ObOTimestampData ori_value, co
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObTimeConverter::calc_last_date_of_the_month(const int64_t ori_date_value, int64_t& result_date_value)
|
||||
int ObTimeConverter::calc_last_date_of_the_month(const int64_t ori_date_value, int64_t& result_date_value, const ObObjType dest_type)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObTime ob_time(DT_TYPE_DATETIME);
|
||||
@ -5698,9 +5826,17 @@ int ObTimeConverter::calc_last_date_of_the_month(const int64_t ori_date_value, i
|
||||
}
|
||||
|
||||
if (OB_SUCC(ret)) {
|
||||
if (OB_FAIL(ob_time_to_datetime(ob_time, cvrt_ctx, result_date_value))) {
|
||||
LOG_WARN("failed to calc result", K(ret));
|
||||
if (ObDateTimeType == dest_type) {
|
||||
if (OB_FAIL(ob_time_to_datetime(ob_time, cvrt_ctx, result_date_value))) {
|
||||
LOG_WARN("failed to calc result", K(ret));
|
||||
}
|
||||
} else if (ObDateType == dest_type) {
|
||||
result_date_value = static_cast<int64_t>(ob_time_to_date(ob_time));
|
||||
} else {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("unexpected dest type", K(ret), K(dest_type));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
LOG_DEBUG("debug calc_last_mday", K(ob_time), K(ori_date_value), K(result_date_value));
|
||||
|
43
deps/oblib/src/lib/timezone/ob_time_convert.h
vendored
43
deps/oblib/src/lib/timezone/ob_time_convert.h
vendored
@ -143,6 +143,7 @@ extern const int64_t USECS_PER_MIN;
|
||||
#define MIN_TO_USEC(min) ((min)*SECS_PER_MIN * USECS_PER_SEC)
|
||||
#define TIMESTAMP_MAX_VAL 253402272000
|
||||
#define DATETIME_MAX_VAL 253402300799999999
|
||||
#define DATE_MAX_VAL 2932896
|
||||
#define DATETIME_MIN_VAL -62167132800000000
|
||||
#define ORACLE_DATETIME_MIN_VAL -62135596800000000 // start from '0001-1-1 00:00:00'
|
||||
#define TIME_MAX_HOUR 838
|
||||
@ -293,6 +294,38 @@ public:
|
||||
static const ObString COMPAT_OLD_NLS_TIMESTAMP_FORMAT;
|
||||
static const ObString COMPAT_OLD_NLS_TIMESTAMP_TZ_FORMAT;
|
||||
|
||||
private:
|
||||
struct ObYearWeekWdayElems {
|
||||
enum ElemSetState
|
||||
{
|
||||
NOT_SET = 0,
|
||||
UPPER_SET = 1,
|
||||
LOWER_SET = 2
|
||||
};
|
||||
|
||||
ObYearWeekWdayElems() :
|
||||
year_set_state_(NOT_SET), year_value_(INT32_MAX),
|
||||
week_set_state_(NOT_SET), week_u_set_(true), week_value_(INT32_MAX),
|
||||
weekday_set_(false), weekday_value_(INT32_MAX)
|
||||
{}
|
||||
bool is_year_set() const { return NOT_SET != year_set_state_; }
|
||||
bool is_week_u_set() const { return NOT_SET != week_set_state_ && week_u_set_; }
|
||||
bool is_week_v_set() const { return NOT_SET != week_set_state_ && !week_u_set_; }
|
||||
bool is_upper_week_set() const {return UPPER_SET == week_set_state_; }
|
||||
bool is_weekday_set() const { return weekday_set_; }
|
||||
|
||||
VIRTUAL_TO_STRING_KV(K(year_set_state_), K(year_value_), K(week_set_state_), K(week_u_set_),
|
||||
K(week_value_), K(weekday_set_), K(weekday_value_));
|
||||
ElemSetState year_set_state_;
|
||||
int32_t year_value_;
|
||||
|
||||
ElemSetState week_set_state_;
|
||||
bool week_u_set_; // week is set -> true: %u is set. false: %v is set.
|
||||
int32_t week_value_;
|
||||
|
||||
bool weekday_set_;
|
||||
int32_t weekday_value_;
|
||||
};
|
||||
public:
|
||||
// int / double / string -> datetime(timestamp) / interval / date / time / year.
|
||||
static int int_to_datetime(int64_t int_part, int64_t dec_part, const ObTimeConvertCtx& cvrt_ctx, int64_t& value);
|
||||
@ -383,7 +416,7 @@ public:
|
||||
const ObTimeZoneInfo* tz_info, const int64_t nmonth, ObOTimestampData& result_value);
|
||||
static int otimestamp_add_nsecond(const ObOTimestampData ori_value, const int64_t nsecond,
|
||||
const int32_t fractional_second, ObOTimestampData& result_value);
|
||||
static int calc_last_date_of_the_month(const int64_t ori_date_value, int64_t& result_date_value);
|
||||
static int calc_last_date_of_the_month(const int64_t ori_date_value, int64_t& result_date_value, const ObObjType dest_type);
|
||||
static int calc_next_date_of_the_wday(
|
||||
const int64_t ori_date_value, const ObString& wday_name, int64_t& result_date_value);
|
||||
static int calc_days_and_months_between_dates(
|
||||
@ -401,6 +434,8 @@ public:
|
||||
const ObObjType target_type, ObTime& ob_time, ObScale& scale);
|
||||
static int str_to_ob_time_oracle_strict(const ObString& str, const ObTimeConvertCtx& cvrt_ctx,
|
||||
const bool is_timestamp_literal, ObTime& ob_time, ObScale& scale);
|
||||
static int calc_date_with_year_week_wday(const ObYearWeekWdayElems &elements, ObTime& ot);
|
||||
static int handle_year_week_wday(const ObYearWeekWdayElems& elements, ObTime& ot);
|
||||
static int str_to_ob_interval(const ObString& str, ObDateUnitType unit_type, ObInterval& ob_interval);
|
||||
static int usec_to_ob_time(int64_t usecs, ObTime& ob_time);
|
||||
static int datetime_to_ob_time(int64_t value, const ObTimeZoneInfo* tz_info, ObTime& ob_time);
|
||||
@ -459,6 +494,9 @@ public:
|
||||
static int decode_interval_ds(const char* data, const int64_t len, ObIntervalDSValue& value, ObScale& scale);
|
||||
static int encode_interval_ds(
|
||||
char* buf, const int64_t len, int64_t& pos, const ObIntervalDSValue& value, const ObScale scale);
|
||||
static int data_fmt_nd(char* buffer, int64_t buf_len, int64_t& pos, const int64_t n, int64_t target);
|
||||
static int data_fmt_d(char* buffer, int64_t buf_len, int64_t& pos, int64_t target);
|
||||
static int data_fmt_s(char* buffer, int64_t buf_len, int64_t& pos, const char* ptr);
|
||||
|
||||
public:
|
||||
// other functions.
|
||||
@ -543,9 +581,6 @@ private:
|
||||
int32_t& offset_min, int32_t& tz_id, int32_t& tran_type_id);
|
||||
static int get_str_array_idx(const ObString& str, const ObTimeConstStr* array, int32_t count, int32_t& idx);
|
||||
|
||||
static int data_fmt_nd(char* buffer, int64_t buf_len, int64_t& pos, const int64_t n, int64_t target);
|
||||
static int data_fmt_d(char* buffer, int64_t buf_len, int64_t& pos, int64_t target);
|
||||
static int data_fmt_s(char* buffer, int64_t buf_len, int64_t& pos, const char* ptr);
|
||||
static int get_day_and_month_from_year_day(const int32_t yday, const int32_t year, int32_t& month, int32_t& day);
|
||||
static int set_ob_time_year_may_conflict(
|
||||
ObTime& ob_time, int32_t& julian_year_value, int32_t check_year, int32_t set_year, bool overwrite);
|
||||
|
@ -11488,6 +11488,14 @@ static struct ObStrErrorInit {
|
||||
ORACLE_ERRNO[-OB_ERR_ILL_NAME_STRING] = 21560;
|
||||
ORACLE_STR_ERROR[-OB_ERR_ILL_NAME_STRING] = "ORA-21560: unexpected name string '%.*s'";
|
||||
ORACLE_STR_USER_ERROR[-OB_ERR_ILL_NAME_STRING] = "ORA-21560: unexpected name string '%.*s'";
|
||||
ERROR_NAME[-OB_ERR_INCORRECT_VALUE_FOR_FUNCTION] = "OB_ERR_INCORRECT_VALUE_FOR_FUNCTION";
|
||||
MYSQL_ERRNO[-OB_ERR_INCORRECT_VALUE_FOR_FUNCTION] = ER_WRONG_VALUE_FOR_TYPE;
|
||||
SQLSTATE[-OB_ERR_INCORRECT_VALUE_FOR_FUNCTION] = "HY000";
|
||||
STR_ERROR[-OB_ERR_INCORRECT_VALUE_FOR_FUNCTION] = "Incorrect value for function";
|
||||
STR_USER_ERROR[-OB_ERR_INCORRECT_VALUE_FOR_FUNCTION] = "Incorrect %.*s value: '%.*s' for function %.*s";
|
||||
ORACLE_ERRNO[-OB_ERR_INCORRECT_VALUE_FOR_FUNCTION] = 600;
|
||||
ORACLE_STR_ERROR[-OB_ERR_INCORRECT_VALUE_FOR_FUNCTION] = "ORA-00600: internal error code, arguments: -5936, Incorrect value for function";
|
||||
ORACLE_STR_USER_ERROR[-OB_ERR_INCORRECT_VALUE_FOR_FUNCTION] = "ORA-00600: internal error code, arguments: -5936, Incorrect %.*s value: '%.*s' for function %.*s";
|
||||
ERROR_NAME[-OB_TRANSACTION_SET_VIOLATION] = "OB_TRANSACTION_SET_VIOLATION";
|
||||
MYSQL_ERRNO[-OB_TRANSACTION_SET_VIOLATION] = -1;
|
||||
SQLSTATE[-OB_TRANSACTION_SET_VIOLATION] = "25000";
|
||||
|
@ -1311,6 +1311,7 @@ DEFINE_ERROR_EXT(OB_ERR_WINDOW_NAME_IS_NOT_DEFINE, -5929, -1, "HY000", "Window n
|
||||
DEFINE_ORACLE_ERROR(OB_ERR_OPEN_CURSORS_EXCEEDED, -5930, -1, "HY000", "maximum open cursors exceeded", 1000, "maximum open cursors exceeded");
|
||||
DEFINE_ORACLE_ERROR(OB_ERR_ARG_INVALID, -5931, -1, "HY000", "argument is null, invalid, or out of range", 21560, "argument %.*s is null, invalid, or out of range");
|
||||
DEFINE_ORACLE_ERROR(OB_ERR_ILL_NAME_STRING, -5932, -1, "HY000", "unexpected name string", 21560, "unexpected name string '%.*s'");
|
||||
DEFINE_ERROR_EXT(OB_ERR_INCORRECT_VALUE_FOR_FUNCTION, -5936, ER_WRONG_VALUE_FOR_TYPE, "HY000", "Incorrect value for function", "Incorrect %.*s value: '%.*s' for function %.*s");
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
//error code for transaction, mvcc and commitlog -6001 ---- -7000
|
||||
|
@ -1025,6 +1025,7 @@ constexpr int OB_ERR_WINDOW_NAME_IS_NOT_DEFINE = -5929;
|
||||
constexpr int OB_ERR_OPEN_CURSORS_EXCEEDED = -5930;
|
||||
constexpr int OB_ERR_ARG_INVALID = -5931;
|
||||
constexpr int OB_ERR_ILL_NAME_STRING = -5932;
|
||||
constexpr int OB_ERR_INCORRECT_VALUE_FOR_FUNCTION = -5936;
|
||||
constexpr int OB_TRANSACTION_SET_VIOLATION = -6001;
|
||||
constexpr int OB_TRANS_ROLLBACKED = -6002;
|
||||
constexpr int OB_ERR_EXCLUSIVE_LOCK_CONFLICT = -6003;
|
||||
@ -2585,6 +2586,7 @@ constexpr int OB_ERR_INVALID_DATE_MSG_FMT_V2 = -4219;
|
||||
#define OB_ERR_OPEN_CURSORS_EXCEEDED__USER_ERROR_MSG "maximum open cursors exceeded"
|
||||
#define OB_ERR_ARG_INVALID__USER_ERROR_MSG "argument is null, invalid, or out of range"
|
||||
#define OB_ERR_ILL_NAME_STRING__USER_ERROR_MSG "unexpected name string"
|
||||
#define OB_ERR_INCORRECT_VALUE_FOR_FUNCTION__USER_ERROR_MSG "Incorrect %.*s value: '%.*s' for function %.*s"
|
||||
#define OB_TRANSACTION_SET_VIOLATION__USER_ERROR_MSG "Transaction set changed during the execution"
|
||||
#define OB_TRANS_ROLLBACKED__USER_ERROR_MSG "transaction is rolled back"
|
||||
#define OB_ERR_EXCLUSIVE_LOCK_CONFLICT__USER_ERROR_MSG "Lock wait timeout exceeded; try restarting transaction"
|
||||
@ -4859,6 +4861,7 @@ constexpr int OB_ERR_INVALID_DATE_MSG_FMT_V2 = -4219;
|
||||
#define OB_ERR_OPEN_CURSORS_EXCEEDED__ORA_USER_ERROR_MSG "ORA-01000: maximum open cursors exceeded"
|
||||
#define OB_ERR_ARG_INVALID__ORA_USER_ERROR_MSG "ORA-21560: argument %.*s is null, invalid, or out of range"
|
||||
#define OB_ERR_ILL_NAME_STRING__ORA_USER_ERROR_MSG "ORA-21560: unexpected name string '%.*s'"
|
||||
#define OB_ERR_INCORRECT_VALUE_FOR_FUNCTION__ORA_USER_ERROR_MSG "ORA-00600: internal error code, arguments: -5936, Incorrect %.*s value: '%.*s' for function %.*s"
|
||||
#define OB_TRANSACTION_SET_VIOLATION__ORA_USER_ERROR_MSG \
|
||||
"ORA-00600: internal error code, arguments: -6001, Transaction set changed during the execution"
|
||||
#define OB_TRANS_ROLLBACKED__ORA_USER_ERROR_MSG "ORA-24761: transaction rolled back"
|
||||
|
@ -217,6 +217,8 @@ private:
|
||||
// In the type inference, the expression can set cast_mode to control the behavior of each parameter for type
|
||||
// conversion Just add your own special cast mode, some regular modes will be automatically added before putting in
|
||||
// the cast expr
|
||||
// Set cast_mode of type_ctx when calc_result_type works for static engine.
|
||||
// Usually need to override get_cast_mode() of ObExprOperator which works for non_static engine
|
||||
common::ObCastMode cast_mode_;
|
||||
sql::ObRawExpr* raw_expr_;
|
||||
};
|
||||
|
@ -2244,6 +2244,8 @@ static int number_datetime(
|
||||
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
const int64_t three_digit_min = 100;
|
||||
const int64_t eight_digit_max = 99999999;
|
||||
if (OB_UNLIKELY(ObNumberTC != in.get_type_class() || ObDateTimeTC != ob_obj_type_class(expect_type))) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
|
||||
@ -2255,13 +2257,20 @@ static int number_datetime(
|
||||
if (in.get_number().is_negative()) {
|
||||
ret = OB_INVALID_DATE_FORMAT;
|
||||
LOG_WARN("invalid date format", K(ret), K(in), K(cast_mode));
|
||||
} else if ((ObTimestampType == expect_type && in.get_number().is_decimal())) {
|
||||
} else if (!in.get_number().is_int_parts_valid_int64(int_part,dec_part)) {
|
||||
ret = OB_INVALID_DATE_FORMAT;
|
||||
LOG_WARN("invalid date format", K(ret), K(in), K(cast_mode));
|
||||
} else if (!in.get_number().is_int_parts_valid_int64(int_part, dec_part)) {
|
||||
ret = OB_INVALID_DATE_FORMAT;
|
||||
LOG_WARN("invalid date format", K(ret), K(in), K(cast_mode));
|
||||
} else {
|
||||
} else if (OB_UNLIKELY(dec_part != 0
|
||||
&& ((0 == int_part && ObTimestampType == expect_type)
|
||||
|| (int_part >= three_digit_min && int_part <= eight_digit_max)))) {
|
||||
if (CM_IS_COLUMN_CONVERT(cast_mode) && !CM_IS_WARN_ON_FAIL(cast_mode)) {
|
||||
ret = OB_INVALID_DATE_VALUE;
|
||||
LOG_WARN("invalid date value", K(ret));
|
||||
} else {
|
||||
dec_part = 0;
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
ret = ObTimeConverter::int_to_datetime(int_part, dec_part, cvrt_ctx, value);
|
||||
LOG_DEBUG("succ to number_datetime", K(ret), K(in), K(value), K(expect_type), K(int_part), K(dec_part));
|
||||
}
|
||||
@ -2325,9 +2334,9 @@ static int number_date(
|
||||
} else {
|
||||
ret = ObTimeConverter::int_to_date(int_part, value);
|
||||
if (OB_SUCC(ret) && OB_UNLIKELY(dec_part > 0)) {
|
||||
LOG_WARN("invalid date value with decimal part", K(ret));
|
||||
if (!CM_IS_WARN_ON_FAIL(cast_mode)) {
|
||||
if (CM_IS_COLUMN_CONVERT(cast_mode) && !CM_IS_WARN_ON_FAIL(cast_mode)) {
|
||||
ret = OB_INVALID_DATE_VALUE;
|
||||
LOG_WARN("invalid date value with decimal part", K(ret));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ namespace common {
|
||||
#define CM_SET_MIN_IF_OVERFLOW (1ULL << 9)
|
||||
// when casting string to integer, round if not set this flag, otherwise trunc.
|
||||
// but ceil will always round to +inf, and floor will always round to -inf.
|
||||
#define CM_STRING_INTEGER_TRUNC (1ULL << 9)
|
||||
#define CM_STRING_INTEGER_TRUNC (1ULL << 57)
|
||||
#define CM_COLUMN_CONVERT (1ULL << 58)
|
||||
#define CM_ENABLE_BLOB_CAST (1ULL << 59)
|
||||
#define CM_EXPLICIT_CAST (1ULL << 60)
|
||||
|
@ -386,6 +386,9 @@ ob_set_subtarget(ob_sql engine
|
||||
engine/expr/ob_expr_tanh.cpp
|
||||
engine/expr/ob_expr_time.cpp
|
||||
engine/expr/ob_expr_time_diff.cpp
|
||||
engine/expr/ob_expr_time_diff.h
|
||||
engine/expr/ob_expr_time_format.cpp
|
||||
engine/expr/ob_expr_time_format.h
|
||||
engine/expr/ob_expr_time_to_usec.cpp
|
||||
engine/expr/ob_expr_timestamp.cpp
|
||||
engine/expr/ob_expr_timestamp_add.cpp
|
||||
@ -439,6 +442,9 @@ ob_set_subtarget(ob_sql engine
|
||||
engine/expr/ob_expr_bool.cpp
|
||||
engine/expr/ob_expr_eval_functions.cpp
|
||||
engine/expr/ob_expr_maketime.cpp
|
||||
engine/expr/ob_expr_makedate.h
|
||||
engine/expr/ob_expr_makedate.cpp
|
||||
engine/join/ob_join_op.h
|
||||
engine/join/ob_join_op.cpp
|
||||
engine/join/ob_basic_nested_loop_join_op.cpp
|
||||
engine/join/ob_nested_loop_join_op.cpp
|
||||
|
@ -1348,8 +1348,9 @@ static int common_floating_string(
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int common_number_datetime(
|
||||
const number::ObNumber nmb, const ObObjType out_type, const ObTimeConvertCtx& cvrt_ctx, int64_t& out_val);
|
||||
static int common_number_datetime(const number::ObNumber nmb,
|
||||
const ObTimeConvertCtx &cvrt_ctx, int64_t &out_val,
|
||||
const ObCastMode cast_mode);
|
||||
|
||||
static OB_INLINE int common_double_datetime(
|
||||
const ObExpr& expr, const double val_double, ObEvalCtx& ctx, ObDatum& res_datum)
|
||||
@ -1379,7 +1380,7 @@ static OB_INLINE int common_double_datetime(
|
||||
ret = OB_INVALID_DATE_VALUE;
|
||||
}
|
||||
} else {
|
||||
ret = common_number_datetime(number, out_type, cvrt_ctx, out_val);
|
||||
ret = common_number_datetime(number, cvrt_ctx, out_val, expr.extra_);
|
||||
if (CAST_FAIL(ret)) {
|
||||
LOG_WARN("str_to_datetime failed", K(ret));
|
||||
} else {
|
||||
@ -1494,22 +1495,36 @@ static OB_INLINE int common_construct_otimestamp(
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int common_number_datetime(
|
||||
const number::ObNumber nmb, const ObObjType out_type, const ObTimeConvertCtx& cvrt_ctx, int64_t& out_val)
|
||||
static int common_number_datetime(const number::ObNumber nmb,
|
||||
const ObTimeConvertCtx &cvrt_ctx,
|
||||
int64_t &out_val,
|
||||
const ObCastMode cast_mode)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
int64_t int_part = 0;
|
||||
int64_t dec_part = 0;
|
||||
const int64_t three_digit_min = 100;
|
||||
const int64_t eight_digit_max = 99999999;
|
||||
if (nmb.is_negative()) {
|
||||
ret = OB_INVALID_DATE_VALUE;
|
||||
LOG_WARN("invalid datetime value", K(ret), K(nmb));
|
||||
} else if ((ObTimestampType == out_type && nmb.is_decimal())) {
|
||||
ret = OB_INVALID_DATE_VALUE;
|
||||
LOG_WARN("invalid date format", K(ret), K(nmb));
|
||||
} else if (!nmb.is_int_parts_valid_int64(int_part, dec_part)) {
|
||||
ret = OB_INVALID_DATE_VALUE;
|
||||
LOG_WARN("invalid date format", K(ret), K(nmb));
|
||||
} else {
|
||||
// Maybe we need a new framework to make precise control on whether we report an error,
|
||||
// instead of calling a function and check the return value and cast_mode,
|
||||
// then we can move this logic to ObTimeConverter::int_to_datetime.
|
||||
} else if (OB_UNLIKELY(dec_part != 0
|
||||
&& ((0 == int_part && cvrt_ctx.is_timestamp_)
|
||||
|| (int_part >= three_digit_min && int_part <= eight_digit_max)))) {
|
||||
if (CM_IS_COLUMN_CONVERT(cast_mode) && !CM_IS_WARN_ON_FAIL(cast_mode)) {
|
||||
ret = OB_INVALID_DATE_VALUE;
|
||||
LOG_WARN("invalid date value", K(ret), K(nmb));
|
||||
} else {
|
||||
dec_part = 0;
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
ret = ObTimeConverter::int_to_datetime(int_part, dec_part, cvrt_ctx, out_val);
|
||||
}
|
||||
return ret;
|
||||
@ -2229,7 +2244,7 @@ CAST_FUNC_NAME(number, datetime)
|
||||
ObObjType out_type = expr.datum_meta_.type_;
|
||||
ObTimeConvertCtx cvrt_ctx(session->get_timezone_info(), ObTimestampType == out_type);
|
||||
int64_t out_val = 0;
|
||||
ret = common_number_datetime(nmb, out_type, cvrt_ctx, out_val);
|
||||
ret = common_number_datetime(nmb, cvrt_ctx, out_val, expr.extra_);
|
||||
int warning = OB_SUCCESS;
|
||||
if (CAST_FAIL(ret)) {
|
||||
} else {
|
||||
@ -2258,18 +2273,16 @@ CAST_FUNC_NAME(number, date)
|
||||
} else {
|
||||
ret = ObTimeConverter::int_to_date(int_part, out_val);
|
||||
if (OB_SUCC(ret) && OB_UNLIKELY(dec_part > 0)) {
|
||||
LOG_WARN("invalid date value with decimal part", K(ret));
|
||||
if (!CM_IS_WARN_ON_FAIL(expr.extra_)) {
|
||||
if (CM_IS_COLUMN_CONVERT(expr.extra_) && !CM_IS_WARN_ON_FAIL(expr.extra_)) {
|
||||
ret = OB_INVALID_DATE_VALUE;
|
||||
LOG_WARN("invalid date value with decimal part", K(ret));
|
||||
}
|
||||
}
|
||||
LOG_DEBUG("stt, end common number date", K(int_part), K(dec_part), K(out_val), K(ret));
|
||||
}
|
||||
|
||||
if (CAST_FAIL(ret)) {
|
||||
} else {
|
||||
SET_RES_DATE(out_val);
|
||||
LOG_DEBUG("stt, number to date", K(nmb), K(out_val), K(ret), K(warning));
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
|
@ -83,7 +83,151 @@ int ObExprUtcTimestamp::cg_expr(ObExprCGCtx& op_cg_ctx, const ObRawExpr& raw_exp
|
||||
return OB_SUCCESS;
|
||||
}
|
||||
|
||||
ObExprCurTimestamp::ObExprCurTimestamp(ObIAllocator& alloc)
|
||||
ObExprUtcTime::ObExprUtcTime(ObIAllocator &alloc)
|
||||
: ObFuncExprOperator(alloc, T_FUN_SYS_UTC_TIME, N_UTC_TIME, 0, NOT_ROW_DIMENSION)
|
||||
{
|
||||
}
|
||||
ObExprUtcTime::~ObExprUtcTime()
|
||||
{
|
||||
}
|
||||
|
||||
int ObExprUtcTime::calc_result_type0(ObExprResType &type, ObExprTypeCtx &type_ctx) const
|
||||
{
|
||||
UNUSED(type_ctx);
|
||||
type.set_time();
|
||||
type.set_result_flag(NOT_NULL_FLAG);
|
||||
if (type.get_scale() < MIN_SCALE_FOR_TEMPORAL) {
|
||||
type.set_scale(MIN_SCALE_FOR_TEMPORAL);
|
||||
}
|
||||
return OB_SUCCESS;
|
||||
}
|
||||
|
||||
int ObExprUtcTime::calc_result0(ObObj &result, ObExprCtx &expr_ctx) const
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (OB_ISNULL(expr_ctx.phy_plan_ctx_)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("expr_ctx.phy_plan_ctx_ is null", K(ret));
|
||||
} else if (OB_UNLIKELY(!expr_ctx.phy_plan_ctx_->has_cur_time())) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("physical plan context don't have current time value");
|
||||
} else {
|
||||
int64_t ts_value = expr_ctx.phy_plan_ctx_->get_cur_time().get_timestamp();
|
||||
int64_t t_value = 0;
|
||||
if (OB_FAIL(ObTimeConverter::datetime_to_time(ts_value, NULL /* tz_info */, t_value))) {
|
||||
LOG_WARN("failed to convert datetime to time", K(ret));
|
||||
} else {
|
||||
ObTimeConverter::trunc_datetime(result_type_.get_scale(), t_value);
|
||||
result.set_time(t_value);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprUtcTime::cg_expr(ObExprCGCtx &op_cg_ctx, const ObRawExpr &raw_expr,
|
||||
ObExpr &rt_expr) const
|
||||
{
|
||||
UNUSED(raw_expr);
|
||||
UNUSED(op_cg_ctx);
|
||||
rt_expr.eval_func_ = ObExprUtcTime::eval_utc_time;
|
||||
return OB_SUCCESS;
|
||||
}
|
||||
|
||||
int ObExprUtcTime::eval_utc_time(const ObExpr &expr, ObEvalCtx &ctx,
|
||||
ObDatum &expr_datum)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (OB_ISNULL(ctx.exec_ctx_.get_physical_plan_ctx())) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("expr_ctx.phy_plan_ctx_ is null", K(ret));
|
||||
} else if (OB_UNLIKELY(!ctx.exec_ctx_.get_physical_plan_ctx()->has_cur_time())) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("physical plan context don't have current time value");
|
||||
} else {
|
||||
int64_t ts_value = ctx.exec_ctx_.get_physical_plan_ctx()->get_cur_time().get_timestamp();
|
||||
int64_t t_value = 0;
|
||||
if (OB_FAIL(ObTimeConverter::datetime_to_time(ts_value, NULL /* tz_info */, t_value))) {
|
||||
LOG_WARN("failed to convert datetime to time", K(ret));
|
||||
} else {
|
||||
ObTimeConverter::trunc_datetime(expr.datum_meta_.scale_, t_value);
|
||||
expr_datum.set_time(t_value);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
ObExprUtcDate::ObExprUtcDate(ObIAllocator &alloc)
|
||||
: ObFuncExprOperator(alloc, T_FUN_SYS_UTC_DATE, N_UTC_DATE, 0, NOT_ROW_DIMENSION)
|
||||
{
|
||||
}
|
||||
ObExprUtcDate::~ObExprUtcDate()
|
||||
{
|
||||
}
|
||||
|
||||
int ObExprUtcDate::calc_result_type0(ObExprResType &type, ObExprTypeCtx &type_ctx) const
|
||||
{
|
||||
UNUSED(type_ctx);
|
||||
type.set_date();
|
||||
type.set_result_flag(NOT_NULL_FLAG);
|
||||
type.set_scale(0);
|
||||
return OB_SUCCESS;
|
||||
}
|
||||
|
||||
int ObExprUtcDate::calc_result0(ObObj &result, ObExprCtx &expr_ctx) const
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (OB_ISNULL(expr_ctx.phy_plan_ctx_)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("expr_ctx.phy_plan_ctx_ is null", K(ret));
|
||||
} else if (OB_UNLIKELY(!expr_ctx.phy_plan_ctx_->has_cur_time())) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("physical plan context don't have current time value");
|
||||
} else {
|
||||
int64_t ts_value = 0;
|
||||
ts_value = expr_ctx.phy_plan_ctx_->get_cur_time().get_timestamp();
|
||||
int32_t d_value = 0;
|
||||
if (OB_FAIL(ObTimeConverter::datetime_to_date(ts_value, NULL /* tz_info */, d_value))) {
|
||||
LOG_WARN("failed to convert datetime to date", K(ret));
|
||||
} else {
|
||||
result.set_date(d_value);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprUtcDate::cg_expr(ObExprCGCtx &op_cg_ctx, const ObRawExpr &raw_expr,
|
||||
ObExpr &rt_expr) const
|
||||
{
|
||||
UNUSED(raw_expr);
|
||||
UNUSED(op_cg_ctx);
|
||||
rt_expr.eval_func_ = ObExprUtcDate::eval_utc_date;
|
||||
return OB_SUCCESS;
|
||||
}
|
||||
|
||||
int ObExprUtcDate::eval_utc_date(const ObExpr &expr, ObEvalCtx &ctx,
|
||||
ObDatum &expr_datum)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
UNUSED(expr);
|
||||
if (OB_ISNULL(ctx.exec_ctx_.get_physical_plan_ctx())) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("expr_ctx.phy_plan_ctx_ is null", K(ret));
|
||||
} else if (OB_UNLIKELY(!ctx.exec_ctx_.get_physical_plan_ctx()->has_cur_time())) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("physical plan context don't have current time value");
|
||||
} else {
|
||||
int64_t ts_value = ctx.exec_ctx_.get_physical_plan_ctx()->get_cur_time().get_timestamp();
|
||||
int32_t d_value = 0;
|
||||
if (OB_FAIL(ObTimeConverter::datetime_to_date(ts_value, NULL /* tz_info */, d_value))) {
|
||||
LOG_WARN("failed to convert datetime to date", K(ret));
|
||||
} else {
|
||||
expr_datum.set_date(d_value);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
ObExprCurTimestamp::ObExprCurTimestamp(ObIAllocator &alloc)
|
||||
: ObFuncExprOperator(alloc, T_FUN_SYS_CUR_TIMESTAMP, N_CUR_TIMESTAMP, 0, NOT_ROW_DIMENSION)
|
||||
{}
|
||||
ObExprCurTimestamp::~ObExprCurTimestamp()
|
||||
|
@ -31,6 +31,37 @@ private:
|
||||
DISALLOW_COPY_AND_ASSIGN(ObExprUtcTimestamp);
|
||||
};
|
||||
|
||||
class ObExprUtcTime : public ObFuncExprOperator {
|
||||
public:
|
||||
explicit ObExprUtcTime(common::ObIAllocator &alloc);
|
||||
virtual ~ObExprUtcTime();
|
||||
virtual int calc_result_type0(ObExprResType &type, common::ObExprTypeCtx &type_ctx) const;
|
||||
virtual int calc_result0(common::ObObj &result, common::ObExprCtx &expr_ctx) const;
|
||||
static int eval_utc_time(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &expr_datum);
|
||||
virtual int cg_expr(ObExprCGCtx &op_cg_ctx,
|
||||
const ObRawExpr &raw_expr,
|
||||
ObExpr &rt_expr) const override;
|
||||
|
||||
private:
|
||||
// disallow copy
|
||||
DISALLOW_COPY_AND_ASSIGN(ObExprUtcTime);
|
||||
};
|
||||
|
||||
class ObExprUtcDate : public ObFuncExprOperator {
|
||||
public:
|
||||
explicit ObExprUtcDate(common::ObIAllocator &alloc);
|
||||
virtual ~ObExprUtcDate();
|
||||
virtual int calc_result_type0(ObExprResType &type, common::ObExprTypeCtx &type_ctx) const;
|
||||
virtual int calc_result0(common::ObObj &result, common::ObExprCtx &expr_ctx) const;
|
||||
static int eval_utc_date(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &expr_datum);
|
||||
virtual int cg_expr(ObExprCGCtx &op_cg_ctx,
|
||||
const ObRawExpr &raw_expr,
|
||||
ObExpr &rt_expr) const override;
|
||||
private:
|
||||
// disallow copy
|
||||
DISALLOW_COPY_AND_ASSIGN(ObExprUtcDate);
|
||||
};
|
||||
|
||||
class ObExprCurTimestamp : public ObFuncExprOperator {
|
||||
public:
|
||||
explicit ObExprCurTimestamp(common::ObIAllocator& alloc);
|
||||
|
@ -593,7 +593,11 @@ int ObExprLastDay::calc_result_type1(ObExprResType& type, ObExprResType& type1,
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
UNUSED(type_ctx);
|
||||
type.set_datetime();
|
||||
if (is_oracle_mode()) {
|
||||
type.set_datetime();
|
||||
} else {
|
||||
type.set_date();
|
||||
}
|
||||
type.set_scale(OB_MAX_DATE_PRECISION);
|
||||
type1.set_calc_type(ObDateTimeType);
|
||||
type1.set_calc_scale(OB_MAX_DATETIME_PRECISION);
|
||||
@ -606,14 +610,20 @@ int ObExprLastDay::calc_result1(common::ObObj& result, const common::ObObj& obj,
|
||||
UNUSED(expr_ctx);
|
||||
int64_t ori_date_utc = 0;
|
||||
int64_t res_date_utc = 0;
|
||||
if (obj.is_null_oracle()) {
|
||||
const ObObjType res_type = is_oracle_mode() ? ObDateTimeType : ObDateType;
|
||||
if (obj.is_null()) {
|
||||
result.set_null();
|
||||
} else if (OB_FAIL(obj.get_datetime(ori_date_utc))) {
|
||||
LOG_WARN("fail to get datetime", K(ret));
|
||||
} else if (OB_FAIL(ObTimeConverter::calc_last_date_of_the_month(ori_date_utc, res_date_utc))) {
|
||||
LOG_WARN("fail to calc last mday", K(ret));
|
||||
} else if (OB_FAIL(ObTimeConverter::calc_last_date_of_the_month(ori_date_utc, res_date_utc,
|
||||
res_type))) {
|
||||
LOG_WARN("fail to calc last mday", K(ret), K(ori_date_utc), K(res_type));
|
||||
} else {
|
||||
result.set_datetime(res_date_utc);
|
||||
if (is_oracle_mode()) {
|
||||
result.set_datetime(res_date_utc);
|
||||
} else {
|
||||
result.set_date(static_cast<int32_t>(res_date_utc));
|
||||
}
|
||||
result.set_scale(OB_MAX_DATE_PRECISION);
|
||||
}
|
||||
return ret;
|
||||
@ -645,12 +655,18 @@ int ObExprLastDay::calc_last_day(const ObExpr& expr, ObEvalCtx& ctx, ObDatum& ex
|
||||
} else if (param1->is_null()) {
|
||||
expr_datum.set_null();
|
||||
} else {
|
||||
const ObObjType res_type = is_oracle_mode() ? ObDateTimeType : ObDateType;
|
||||
int64_t ori_date_utc = param1->get_datetime();
|
||||
int64_t res_date_utc = 0;
|
||||
if (OB_FAIL(ObTimeConverter::calc_last_date_of_the_month(ori_date_utc, res_date_utc))) {
|
||||
if (OB_FAIL(ObTimeConverter::calc_last_date_of_the_month(ori_date_utc, res_date_utc,
|
||||
res_type))) {
|
||||
LOG_WARN("fail to calc last mday", K(ret));
|
||||
} else {
|
||||
expr_datum.set_datetime(res_date_utc);
|
||||
if (is_oracle_mode()) {
|
||||
expr_datum.set_datetime(res_date_utc);
|
||||
} else {
|
||||
expr_datum.set_date(static_cast<int32_t>(res_date_utc));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,8 @@
|
||||
#include "sql/session/ob_sql_session_info.h"
|
||||
#include "sql/engine/expr/ob_datum_cast.h"
|
||||
#include "sql/engine/ob_exec_context.h"
|
||||
#include "lib/ob_date_unit_type.h"
|
||||
#include "sql/engine/expr/ob_expr_util.h"
|
||||
|
||||
namespace oceanbase {
|
||||
using namespace common;
|
||||
@ -185,5 +187,202 @@ int ObExprDateFormat::calc_date_format_invalid(const ObExpr& expr, ObEvalCtx& ct
|
||||
return ret;
|
||||
}
|
||||
|
||||
const char* ObExprGetFormat::FORMAT_STR[FORMAT_MAX] =
|
||||
{
|
||||
"EUR",
|
||||
"INTERNAL",
|
||||
"ISO",
|
||||
"JIS",
|
||||
"USA"
|
||||
};
|
||||
|
||||
const char* ObExprGetFormat::DATE_FORMAT[FORMAT_MAX + 1] =
|
||||
{
|
||||
"%d.%m.%Y",
|
||||
"%Y%m%d",
|
||||
"%Y-%m-%d",
|
||||
"%Y-%m-%d",
|
||||
"%m.%d.%Y",
|
||||
"invalid"
|
||||
};
|
||||
|
||||
const char* ObExprGetFormat::TIME_FORMAT[FORMAT_MAX + 1] =
|
||||
{
|
||||
"%H.%i.%s",
|
||||
"%H%i%s",
|
||||
"%H:%i:%s",
|
||||
"%H:%i:%s",
|
||||
"%h:%i:%s %p",
|
||||
"invalid"
|
||||
};
|
||||
|
||||
const char* ObExprGetFormat::DATETIME_FORMAT[FORMAT_MAX + 1] =
|
||||
{
|
||||
"%Y-%m-%d %H.%i.%s",
|
||||
"%Y%m%d%H%i%s",
|
||||
"%Y-%m-%d %H:%i:%s",
|
||||
"%Y-%m-%d %H:%i:%s",
|
||||
"%Y-%m-%d %H.%i.%s",
|
||||
"invalid"
|
||||
};
|
||||
|
||||
ObExprGetFormat::ObExprGetFormat(ObIAllocator &alloc)
|
||||
: ObStringExprOperator(alloc, T_FUN_SYS_GET_FORMAT, N_GET_FORMAT, 2)
|
||||
{
|
||||
}
|
||||
|
||||
ObExprGetFormat::~ObExprGetFormat()
|
||||
{
|
||||
}
|
||||
|
||||
inline int ObExprGetFormat::calc_result_type2(ObExprResType &type,
|
||||
ObExprResType &unit,
|
||||
ObExprResType &format,
|
||||
common::ObExprTypeCtx &type_ctx) const
|
||||
{
|
||||
UNUSED(type_ctx);
|
||||
UNUSED(unit);
|
||||
int ret = common::OB_SUCCESS;
|
||||
// common::ObCollationType collation_connection = common::CS_TYPE_INVALID;
|
||||
type.set_varchar();
|
||||
type.set_collation_type(type_ctx.get_coll_type());
|
||||
type.set_collation_level(common::CS_LEVEL_COERCIBLE);
|
||||
type.set_length(GET_FORMAT_MAX_LENGTH);
|
||||
format.set_calc_type(ObVarcharType);
|
||||
if (ObCharset::is_cs_nonascii(format.get_collation_type())) {
|
||||
format.set_calc_collation_type(CS_TYPE_UTF8MB4_GENERAL_CI);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprGetFormat::calc_result2(ObObj &result,
|
||||
const ObObj &unit,
|
||||
const ObObj &format,
|
||||
ObExprCtx &expr_ctx) const
|
||||
{
|
||||
UNUSED(expr_ctx);
|
||||
int ret = OB_SUCCESS;
|
||||
if (OB_UNLIKELY(ObIntType != unit.get_type()
|
||||
|| unit.get_int() < 0 || unit.get_int() >= GET_FORMAT_MAX)) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("unexpected unit date type", K(ret), K(unit));
|
||||
} else if (format.is_null()) {
|
||||
result.set_null();
|
||||
} else if (OB_UNLIKELY(ObVarcharType != format.get_type())) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("GET_FORMAT() expected a string as format argument");
|
||||
} else {
|
||||
Format fm = FORMAT_MAX;
|
||||
ObGetFormatUnitType type = static_cast<ObGetFormatUnitType>(unit.get_int());
|
||||
const ObString str = format.get_string();
|
||||
for (int64_t i = 0; i < FORMAT_MAX; i++) {
|
||||
if (0 == str.case_compare(FORMAT_STR[i])) {
|
||||
fm = static_cast<Format>(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (OB_UNLIKELY(FORMAT_MAX == fm)) {
|
||||
result.set_null();
|
||||
} else {
|
||||
const char *res_str = NULL;
|
||||
if (GET_FORMAT_DATE == type) {
|
||||
result.set_varchar(DATE_FORMAT[fm]);
|
||||
} else if (GET_FORMAT_TIME == type) {
|
||||
result.set_varchar(TIME_FORMAT[fm]);
|
||||
} else if (GET_FORMAT_DATETIME == type) {
|
||||
result.set_varchar(DATETIME_FORMAT[fm]);
|
||||
}
|
||||
if (OB_UNLIKELY(ObCharset::is_cs_nonascii(result_type_.get_collation_type()))
|
||||
&& OB_FAIL(convert_result_collation(result_type_, result, expr_ctx.calc_buf_))) {
|
||||
LOG_WARN("fail to convert result collation", K(ret));
|
||||
} else {
|
||||
result.set_collation(result_type_);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprGetFormat::cg_expr(ObExprCGCtx &op_cg_ctx,
|
||||
const ObRawExpr &raw_expr,
|
||||
ObExpr &rt_expr) const
|
||||
{
|
||||
UNUSED(op_cg_ctx);
|
||||
UNUSED(raw_expr);
|
||||
int ret = OB_SUCCESS;
|
||||
if (rt_expr.arg_cnt_ != 2) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("get_format expr should have two params", K(ret), K(rt_expr.arg_cnt_));
|
||||
} else if (OB_ISNULL(rt_expr.args_) || OB_ISNULL(rt_expr.args_[0])
|
||||
|| OB_ISNULL(rt_expr.args_[1])) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("children of get_format expr is null", K(ret), K(rt_expr.args_));
|
||||
} else if (ObIntType != rt_expr.args_[0]->datum_meta_.type_
|
||||
|| (ObVarcharType != rt_expr.args_[1]->datum_meta_.type_
|
||||
&& ObNullType != rt_expr.args_[1]->datum_meta_.type_)) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("invalid argument type", K(ret), K(rt_expr.args_[0]->datum_meta_),
|
||||
K(rt_expr.args_[1]->datum_meta_));
|
||||
} else {
|
||||
rt_expr.eval_func_ = ObExprGetFormat::calc_get_format;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprGetFormat::calc_get_format(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &expr_datum)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObDatum *unit = NULL;
|
||||
ObDatum *format = NULL;
|
||||
if (OB_FAIL(expr.eval_param_value(ctx, unit, format))) {
|
||||
LOG_WARN("calc param failed", K(ret));
|
||||
} else if (OB_UNLIKELY(unit->is_null() || unit->get_int() < 0
|
||||
|| unit->get_int() >= GET_FORMAT_MAX)) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("unexpected unit unit type", K(ret));
|
||||
} else if (format->is_null()) {
|
||||
expr_datum.set_null();
|
||||
} else {
|
||||
Format fm = FORMAT_MAX;
|
||||
ObGetFormatUnitType type = static_cast<ObGetFormatUnitType>(unit->get_int());
|
||||
const ObString str = format->get_string();
|
||||
for (int64_t i = 0; i < FORMAT_MAX; i++) {
|
||||
if (0 == str.case_compare(FORMAT_STR[i])) {
|
||||
fm = static_cast<Format>(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (OB_UNLIKELY(FORMAT_MAX == fm)) {
|
||||
expr_datum.set_null();
|
||||
} else {
|
||||
const char *res_str = NULL;
|
||||
const ObCollationType dest_cs_type = expr.datum_meta_.cs_type_;
|
||||
if (GET_FORMAT_DATE == type) {
|
||||
res_str = DATE_FORMAT[fm];
|
||||
} else if (GET_FORMAT_TIME == type) {
|
||||
res_str = TIME_FORMAT[fm];
|
||||
} else if (GET_FORMAT_DATETIME == type) {
|
||||
res_str = DATETIME_FORMAT[fm];
|
||||
}
|
||||
if (OB_LIKELY(!ObCharset::is_cs_nonascii(dest_cs_type))) {
|
||||
expr_datum.set_string(res_str);
|
||||
} else {
|
||||
ObExprStrResAlloc out_alloc(expr, ctx);
|
||||
ObString out;
|
||||
if (OB_FAIL(ObExprUtil::convert_string_collation(ObString::make_string(res_str),
|
||||
CS_TYPE_UTF8MB4_GENERAL_CI,
|
||||
out,
|
||||
expr.datum_meta_.cs_type_,
|
||||
out_alloc))) {
|
||||
LOG_WARN("convert string collation failed", K(ret));
|
||||
} else {
|
||||
expr_datum.set_string(out);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // namespace sql
|
||||
} // namespace oceanbase
|
||||
} // namespace oceanbase
|
@ -75,6 +75,46 @@ inline int ObExprDateFormat::calc_result_type2(
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
class ObExprGetFormat : public ObStringExprOperator
|
||||
{
|
||||
public:
|
||||
explicit ObExprGetFormat(common::ObIAllocator &alloc);
|
||||
virtual ~ObExprGetFormat();
|
||||
virtual int calc_result_type2(ObExprResType &type,
|
||||
ObExprResType &unit,
|
||||
ObExprResType &format,
|
||||
common::ObExprTypeCtx &type_ctx) const;
|
||||
virtual int calc_result2(common::ObObj &result,
|
||||
const common::ObObj &unit,
|
||||
const common::ObObj &format,
|
||||
common::ObExprCtx &expr_ctx) const;
|
||||
virtual int cg_expr(ObExprCGCtx &op_cg_ctx,
|
||||
const ObRawExpr &raw_expr,
|
||||
ObExpr &rt_expr) const override;
|
||||
static int calc_get_format(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &expr_datum);
|
||||
|
||||
private:
|
||||
enum Format
|
||||
{
|
||||
FORMAT_EUR = 0,
|
||||
FORMAT_INTERNAL = 1,
|
||||
FORMAT_ISO = 2,
|
||||
FORMAT_JIS = 3,
|
||||
FORMAT_USA = 4,
|
||||
FORMAT_MAX = 5,
|
||||
};
|
||||
// disallow copy
|
||||
static const int64_t GET_FORMAT_MAX_LENGTH = 17;
|
||||
static const char* FORMAT_STR[FORMAT_MAX];
|
||||
static const char* DATE_FORMAT[FORMAT_MAX + 1];
|
||||
static const char* TIME_FORMAT[FORMAT_MAX + 1];
|
||||
static const char* DATETIME_FORMAT[FORMAT_MAX + 1];
|
||||
DISALLOW_COPY_AND_ASSIGN(ObExprGetFormat);
|
||||
|
||||
};
|
||||
|
||||
} // namespace sql
|
||||
} // namespace oceanbase
|
||||
|
||||
|
@ -171,6 +171,8 @@
|
||||
#include "ob_expr_radians.h"
|
||||
#include "ob_expr_pi.h"
|
||||
#include "ob_expr_maketime.h"
|
||||
#include "ob_expr_makedate.h"
|
||||
#include "ob_expr_time_format.h"
|
||||
#include "ob_expr_to_blob.h"
|
||||
#include "ob_expr_to_outfile_row.h"
|
||||
#include "ob_expr_format.h"
|
||||
@ -651,7 +653,16 @@ static ObExpr::EvalFunc g_expr_eval_functions[] = {
|
||||
ObExprToMultiByte::calc_to_multi_byte, /* 397 */
|
||||
NULL, // ObExprDllUdf::eval_dll_udf, /* 398 */
|
||||
NULL, // ObExprRawtonhex::calc_rawtonhex_expr, /* 399 */
|
||||
ObExprPi::eval_pi /* 400 */
|
||||
ObExprPi::eval_pi, /* 400 */
|
||||
NULL, //eval_question_mark_func, /* 401 */
|
||||
ObExprUtcTime::eval_utc_time, /* 402 */
|
||||
ObExprUtcDate::eval_utc_date, /* 403 */
|
||||
ObExprGetFormat::calc_get_format, /* 404 */
|
||||
NULL, //ObExprCollectionConstruct::eval_collection_construct, /* 405 */
|
||||
NULL, //ObExprObjAccess::eval_obj_access, /* 406 */
|
||||
ObExprTimeFormat::calc_time_format, /* 407 */
|
||||
ObExprMakedate::calc_makedate, /* 408 */
|
||||
ObExprPeriodAdd::calc_periodadd, /* 409 */
|
||||
};
|
||||
|
||||
REG_SER_FUNC_ARRAY(OB_SFA_SQL_EXPR_EVAL, g_expr_eval_functions, ARRAYSIZEOF(g_expr_eval_functions));
|
||||
|
117
src/sql/engine/expr/ob_expr_makedate.cpp
Normal file
117
src/sql/engine/expr/ob_expr_makedate.cpp
Normal file
@ -0,0 +1,117 @@
|
||||
// Copyright 2021 Alibaba Inc. All Rights Reserved.
|
||||
// Author:
|
||||
// shanting <dachuan.sdc@antgroup.com>
|
||||
|
||||
#define USING_LOG_PREFIX SQL_ENG
|
||||
#include "lib/ob_name_def.h"
|
||||
#include "sql/engine/expr/ob_expr_makedate.h"
|
||||
#include "sql/engine/ob_exec_context.h"
|
||||
|
||||
namespace oceanbase
|
||||
{
|
||||
using namespace common;
|
||||
namespace sql
|
||||
{
|
||||
|
||||
ObExprMakedate::ObExprMakedate(ObIAllocator &alloc)
|
||||
: ObFuncExprOperator(alloc, T_FUN_SYS_MAKEDATE, N_MAKEDATE, 2, NOT_ROW_DIMENSION)
|
||||
{
|
||||
}
|
||||
|
||||
ObExprMakedate::~ObExprMakedate()
|
||||
{
|
||||
}
|
||||
|
||||
int ObExprMakedate::calc_result_type2(ObExprResType &type,
|
||||
ObExprResType &year,
|
||||
ObExprResType &day,
|
||||
common::ObExprTypeCtx &type_ctx) const
|
||||
{
|
||||
type_ctx.set_cast_mode(type_ctx.get_cast_mode() | CM_STRING_INTEGER_TRUNC);
|
||||
int ret = common::OB_SUCCESS;
|
||||
type.set_type(ObDateType);
|
||||
year.set_calc_type(ObIntType);
|
||||
day.set_calc_type(ObIntType);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int ObExprMakedate::calc_result2(ObObj &result,
|
||||
const ObObj &year,
|
||||
const ObObj &day,
|
||||
ObExprCtx &expr_ctx) const
|
||||
{
|
||||
UNUSED(expr_ctx);
|
||||
int ret = OB_SUCCESS;
|
||||
if (OB_UNLIKELY(year.is_null() || day.is_null())) {
|
||||
result.set_null();
|
||||
} else if (OB_FAIL(calc(result, year.get_int(), day.get_int()))) {
|
||||
LOG_WARN("calc make date failed", K(ret));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int ObExprMakedate::cg_expr(ObExprCGCtx &op_cg_ctx,
|
||||
const ObRawExpr &raw_expr,
|
||||
ObExpr &rt_expr) const
|
||||
{
|
||||
UNUSED(op_cg_ctx);
|
||||
UNUSED(raw_expr);
|
||||
int ret = OB_SUCCESS;
|
||||
if (rt_expr.arg_cnt_ != 2) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("makedate expr should have two params", K(ret), K(rt_expr.arg_cnt_));
|
||||
} else if (OB_ISNULL(rt_expr.args_) || OB_ISNULL(rt_expr.args_[0])
|
||||
|| OB_ISNULL(rt_expr.args_[1])) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("children of makedate expr is null", K(ret), K(rt_expr.args_));
|
||||
} else {
|
||||
rt_expr.eval_func_ = ObExprMakedate::calc_makedate;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprMakedate::calc_makedate(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &expr_datum)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObDatum *year = NULL;
|
||||
ObDatum *day = NULL;
|
||||
if (OB_FAIL(expr.eval_param_value(ctx, year, day))) {
|
||||
LOG_WARN("calc param failed", K(ret));
|
||||
} else if (year->is_null() || day->is_null()) {
|
||||
expr_datum.set_null();
|
||||
} else if (OB_FAIL(calc(expr_datum, year->get_int(), day->get_int()))) {
|
||||
LOG_WARN("calc make date failed", K(ret));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
int ObExprMakedate::calc(T &res, int64_t year, int64_t day)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (year < 0 || year > 9999 || day <= 0 || day > DATE_MAX_VAL) {
|
||||
res.set_null();
|
||||
} else {
|
||||
if (year < 70) {
|
||||
year += 2000;
|
||||
} else if (year < 100) {
|
||||
year += 1900;
|
||||
}
|
||||
ObTime ot;
|
||||
ot.parts_[DT_YEAR] = year;
|
||||
ot.parts_[DT_MON] = 1;
|
||||
ot.parts_[DT_MDAY] = 1;
|
||||
int32_t date_value = ObTimeConverter::ob_time_to_date(ot);
|
||||
if (date_value - 1 + day > DATE_MAX_VAL) {
|
||||
res.set_null();
|
||||
} else {
|
||||
res.set_date(date_value - 1 + day);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
42
src/sql/engine/expr/ob_expr_makedate.h
Normal file
42
src/sql/engine/expr/ob_expr_makedate.h
Normal file
@ -0,0 +1,42 @@
|
||||
// Copyright 2021 Alibaba Inc. All Rights Reserved.
|
||||
// Author:
|
||||
// shanting <dachuan.sdc@antgroup.com>
|
||||
|
||||
|
||||
#ifndef OB_SQL_ENGINE_EXPR_MAKEDATE_
|
||||
#define OB_SQL_ENGINE_EXPR_MAKEDATE_
|
||||
|
||||
#include "lib/allocator/ob_allocator.h"
|
||||
#include "sql/engine/expr/ob_expr_operator.h"
|
||||
|
||||
namespace oceanbase
|
||||
{
|
||||
namespace sql
|
||||
{
|
||||
class ObExprMakedate : public ObFuncExprOperator
|
||||
{
|
||||
public:
|
||||
explicit ObExprMakedate(common::ObIAllocator &alloc);
|
||||
virtual ~ObExprMakedate();
|
||||
virtual int calc_result_type2(ObExprResType &type,
|
||||
ObExprResType &year,
|
||||
ObExprResType &day,
|
||||
common::ObExprTypeCtx &type_ctx) const;
|
||||
virtual int calc_result2(common::ObObj &result,
|
||||
const common::ObObj &year,
|
||||
const common::ObObj &day,
|
||||
common::ObExprCtx &expr_ctx) const;
|
||||
virtual common::ObCastMode get_cast_mode() const { return CM_STRING_INTEGER_TRUNC;}
|
||||
static int calc_makedate(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &result);
|
||||
template <typename T>
|
||||
static int calc(T &res, int64_t year, int64_t day);
|
||||
virtual int cg_expr(ObExprCGCtx &expr_cg_ctx, const ObRawExpr &raw_expr,
|
||||
ObExpr &rt_expr) const override;
|
||||
private:
|
||||
// disallow copy
|
||||
DISALLOW_COPY_AND_ASSIGN(ObExprMakedate);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* OB_SQL_ENGINE_EXPR_MAKEDATE_ */
|
@ -3072,6 +3072,32 @@ int ObStringExprOperator::convert_result_collation(
|
||||
return ret;
|
||||
}
|
||||
|
||||
// for calc result type and length for function date_format and time_format.
|
||||
void ObStringExprOperator::calc_temporal_format_result_length(
|
||||
ObExprResType &type, const ObExprResType &format) const
|
||||
{
|
||||
const int64_t VARCHAR_RES_MAX_PARAM_LENGTH = 17;
|
||||
const int64_t TEXT_RES_MAX_PARAM_LENGTH = 728;
|
||||
const int64_t MAX_VARCHAR_BUFFER_SIZE = 256;
|
||||
if (ob_is_string_tc(format.get_type())) {
|
||||
// consistent with Mysql, result_length / format_length = 30
|
||||
const int64_t ratio = 30;
|
||||
if (format.get_length() <= VARCHAR_RES_MAX_PARAM_LENGTH) {
|
||||
type.set_varchar();
|
||||
type.set_length(format.get_length() * ratio);
|
||||
} else if (format.get_length() < TEXT_RES_MAX_PARAM_LENGTH) {
|
||||
type.set_type(ObTextType);
|
||||
} else {
|
||||
type.set_type(ObLongTextType);
|
||||
}
|
||||
} else if (ob_is_text_tc(format.get_type())) {
|
||||
type.set_type(ObTinyTextType == format.get_type() ? ObTextType : ObLongTextType);
|
||||
} else {
|
||||
type.set_varchar();
|
||||
type.set_length(MAX_VARCHAR_BUFFER_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
ObObjType ObStringExprOperator::get_result_type_mysql(int64_t char_length) const
|
||||
{
|
||||
/*
|
||||
|
@ -1458,7 +1458,7 @@ public:
|
||||
{}
|
||||
static int convert_result_collation(
|
||||
const ObExprResType& result_type, common::ObObj& result, common::ObIAllocator* allocator);
|
||||
|
||||
void calc_temporal_format_result_length(ObExprResType& type, const ObExprResType& format) const;
|
||||
protected:
|
||||
common::ObObjType get_result_type_mysql(int64_t char_length) const;
|
||||
static const int64_t MAX_CHAR_LENGTH_FOR_VARCAHR_RESULT = 512;
|
||||
|
@ -122,6 +122,7 @@
|
||||
#include "sql/engine/expr/ob_expr_period_diff.h"
|
||||
#include "sql/engine/expr/ob_expr_unix_timestamp.h"
|
||||
#include "sql/engine/expr/ob_expr_maketime.h"
|
||||
#include "sql/engine/expr/ob_expr_makedate.h"
|
||||
#include "sql/engine/expr/ob_expr_extract.h"
|
||||
#include "sql/engine/expr/ob_expr_to_days.h"
|
||||
#include "sql/engine/expr/ob_expr_day_of_func.h"
|
||||
@ -206,6 +207,7 @@
|
||||
#include "sql/engine/expr/ob_expr_sys_connect_by_path.h"
|
||||
#include "sql/engine/expr/ob_expr_sys_op_opnsize.h"
|
||||
#include "sql/engine/expr/ob_expr_shadow_uk_project.h"
|
||||
#include "sql/engine/expr/ob_expr_time_format.h"
|
||||
#include "sql/engine/expr/ob_expr_interval.h"
|
||||
#include "sql/engine/expr/ob_expr_week_of_func.h"
|
||||
#include "sql/engine/expr/ob_expr_userenv.h"
|
||||
@ -506,19 +508,24 @@ void ObExprOperatorFactory::register_expr_operators()
|
||||
REG_OP(ObExprTimeStampDiff);
|
||||
REG_OP(ObExprTimeDiff);
|
||||
REG_OP(ObExprPeriodDiff);
|
||||
REG_OP(ObExprPeriodAdd);
|
||||
REG_OP(ObExprUnixTimestamp);
|
||||
REG_OP(ObExprMakeTime);
|
||||
REG_OP(ObExprMakedate);
|
||||
REG_OP(ObExprExtract);
|
||||
REG_OP(ObExprToDays);
|
||||
REG_OP(ObExprPosition);
|
||||
REG_OP(ObExprFromDays);
|
||||
REG_OP(ObExprDateFormat);
|
||||
REG_OP(ObExprGetFormat);
|
||||
REG_OP(ObExprStrToDate);
|
||||
REG_OP(ObExprCurDate);
|
||||
REG_OP(ObExprCurTime);
|
||||
REG_OP(ObExprSysdate);
|
||||
REG_OP(ObExprCurTimestamp);
|
||||
REG_OP(ObExprUtcTimestamp);
|
||||
REG_OP(ObExprUtcTime);
|
||||
REG_OP(ObExprUtcDate);
|
||||
REG_OP(ObExprTimeToUsec);
|
||||
REG_OP(ObExprUsecToTime);
|
||||
REG_OP(ObExprMergingFrozenTime);
|
||||
@ -653,6 +660,9 @@ void ObExprOperatorFactory::register_expr_operators()
|
||||
REG_OP(ObExprFormat);
|
||||
REG_OP(ObExprLog);
|
||||
REG_OP(ObExprPi);
|
||||
REG_OP(ObExprLastDay);
|
||||
REG_OP(ObExprTimeFormat);
|
||||
REG_OP(ObExprTimestamp);
|
||||
// register oracle system function
|
||||
REG_OP_ORCL(ObExprSysConnectByPath);
|
||||
REG_OP_ORCL(ObExprTimestampNvl);
|
||||
|
@ -45,6 +45,28 @@ int ObExprPeriodDiff::calc_result2(ObObj& result, const ObObj& left, const ObObj
|
||||
return ret;
|
||||
}
|
||||
|
||||
int get_year_month(const uint64_t value, uint64_t &year, uint64_t &month)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
const uint64_t YEAR_BASE_YEAR = 1900;
|
||||
const uint64_t YEAR_VALUE_FACTOR = 100;
|
||||
const uint64_t YEAR_ADJUST_THRESHOLD = 70;
|
||||
const uint64_t YEAR_ADJUST_OFFSET = 2000;
|
||||
year = value / YEAR_VALUE_FACTOR;
|
||||
uint64_t tmp = year;
|
||||
/*
|
||||
*11(uint) will be treat as 11 + YEAR_ADJUST_OFFSET = 2011(year)
|
||||
*68(uint) will be treat as 68 + YEAR_BASE_YEAR = 1968(year)
|
||||
*1234(uint) will be treat as 1234(year)
|
||||
*/
|
||||
if (year < YEAR_ADJUST_THRESHOLD)
|
||||
year += YEAR_ADJUST_OFFSET;
|
||||
else if (tmp < YEAR_VALUE_FACTOR)
|
||||
year += YEAR_BASE_YEAR;
|
||||
month = value - tmp * YEAR_VALUE_FACTOR; // % operation ? too expensive !
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
int ObExprPeriodDiff::calc(T& result, const T& left, const T& right)
|
||||
{
|
||||
@ -67,28 +89,6 @@ int ObExprPeriodDiff::calc(T& result, const T& left, const T& right)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprPeriodDiff::get_year_month(const uint64_t value, uint64_t& year, uint64_t& month)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
const uint64_t YEAR_BASE_YEAR = 1900;
|
||||
const uint64_t YEAR_VALUE_FACTOR = 100;
|
||||
const uint64_t YEAR_ADJUST_THRESHOLD = 70;
|
||||
const uint64_t YEAR_ADJUST_OFFSET = 2000;
|
||||
year = value / YEAR_VALUE_FACTOR;
|
||||
uint64_t tmp = year;
|
||||
/*
|
||||
*11(uint) will be treat as 11 + YEAR_ADJUST_OFFSET = 2011(year)
|
||||
*68(uint) will be treat as 68 + YEAR_BASE_YEAR = 1968(year)
|
||||
*1234(uint) will be treat as 1234(year)
|
||||
*/
|
||||
if (year < YEAR_ADJUST_THRESHOLD)
|
||||
year += YEAR_ADJUST_OFFSET;
|
||||
else if (tmp < YEAR_VALUE_FACTOR)
|
||||
year += YEAR_BASE_YEAR;
|
||||
month = value - tmp * YEAR_VALUE_FACTOR; // % operation ? too expensive !
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprPeriodDiff::cg_expr(ObExprCGCtx& op_cg_ctx, const ObRawExpr& raw_expr, ObExpr& rt_expr) const
|
||||
{
|
||||
UNUSED(op_cg_ctx);
|
||||
@ -124,5 +124,119 @@ int ObExprPeriodDiff::calc_perioddiff(const ObExpr& expr, ObEvalCtx& ctx, ObDatu
|
||||
return ret;
|
||||
}
|
||||
|
||||
ObExprPeriodAdd::ObExprPeriodAdd(ObIAllocator &alloc)
|
||||
: ObFuncExprOperator(alloc, T_FUN_SYS_PERIOD_ADD, N_PERIOD_ADD, 2, NOT_ROW_DIMENSION)
|
||||
{
|
||||
}
|
||||
|
||||
ObExprPeriodAdd::~ObExprPeriodAdd()
|
||||
{
|
||||
}
|
||||
|
||||
int ObExprPeriodAdd::calc_result_type2(ObExprResType &type,
|
||||
ObExprResType &left,
|
||||
ObExprResType &right,
|
||||
common::ObExprTypeCtx &type_ctx) const
|
||||
{
|
||||
type.set_int();
|
||||
type.set_scale(common::ObAccuracy::DDL_DEFAULT_ACCURACY[common::ObIntType].scale_);
|
||||
type.set_precision(common::ObAccuracy::DDL_DEFAULT_ACCURACY[common::ObIntType].precision_);
|
||||
left.set_calc_type(common::ObIntType);
|
||||
right.set_calc_type(common::ObIntType);
|
||||
type_ctx.set_cast_mode(type_ctx.get_cast_mode() | CM_STRING_INTEGER_TRUNC);
|
||||
return common::OB_SUCCESS;
|
||||
}
|
||||
|
||||
int ObExprPeriodAdd::calc_result2(ObObj &result,
|
||||
const ObObj &left,
|
||||
const ObObj &right,
|
||||
ObExprCtx &expr_ctx) const
|
||||
{
|
||||
UNUSED(expr_ctx);
|
||||
int ret = OB_SUCCESS;
|
||||
if (OB_UNLIKELY(left.is_null() || right.is_null())) {
|
||||
result.set_null();
|
||||
} else {
|
||||
TYPE_CHECK(left, ObIntType);
|
||||
TYPE_CHECK(right, ObIntType);
|
||||
if (OB_SUCC(ret)) {
|
||||
ret = calc(result, left, right);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
int ObExprPeriodAdd::calc(
|
||||
T &result,
|
||||
const T &left,
|
||||
const T &right)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
int64_t lvalue = left.get_int();
|
||||
int64_t rvalue = right.get_int();
|
||||
uint64_t lyear = 0;
|
||||
uint64_t lmonth = 0;
|
||||
if (OB_UNLIKELY(lvalue <= 0)) {
|
||||
// not consistent with Mysql, by design.
|
||||
result.set_int(0);
|
||||
} else if (OB_FAIL(get_year_month(static_cast<uint64_t>(lvalue), lyear, lmonth))) {
|
||||
LOG_WARN("get_year_month failed", K(ret), K(lvalue), K(lyear), K(lmonth));
|
||||
} else {
|
||||
int64_t res_months = lyear * MONS_PER_YEAR + lmonth + rvalue;
|
||||
int64_t year = (res_months - 1) / MONS_PER_YEAR;
|
||||
int64_t month = ((res_months - 1) % MONS_PER_YEAR) + 1;
|
||||
if (OB_UNLIKELY(res_months <= 0 )) {
|
||||
result.set_int(0);
|
||||
} else {
|
||||
if (year < 70) {
|
||||
year += 2000;
|
||||
} else if (year < 100) {
|
||||
year += 1900;
|
||||
}
|
||||
result.set_int(year * 100 + month);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprPeriodAdd::cg_expr(ObExprCGCtx &op_cg_ctx,
|
||||
const ObRawExpr &raw_expr,
|
||||
ObExpr &rt_expr) const
|
||||
{
|
||||
UNUSED(op_cg_ctx);
|
||||
UNUSED(raw_expr);
|
||||
int ret = OB_SUCCESS;
|
||||
if (rt_expr.arg_cnt_ != 2) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("periodadd expr should have two params", K(ret), K(rt_expr.arg_cnt_));
|
||||
} else if (OB_ISNULL(rt_expr.args_) || OB_ISNULL(rt_expr.args_[0])
|
||||
|| OB_ISNULL(rt_expr.args_[1])) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("children of periodadd expr is null", K(ret), K(rt_expr.args_));
|
||||
} else {
|
||||
CK(ObIntType == rt_expr.args_[0]->datum_meta_.type_);
|
||||
CK(ObIntType == rt_expr.args_[1]->datum_meta_.type_);
|
||||
rt_expr.eval_func_ = ObExprPeriodAdd::calc_periodadd;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprPeriodAdd::calc_periodadd(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &expr_datum)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObDatum *param_datum1 = NULL;
|
||||
ObDatum *param_datum2 = NULL;
|
||||
if (OB_FAIL(expr.eval_param_value(ctx, param_datum1, param_datum2))) {
|
||||
LOG_WARN("eval param value failed", K(ret));
|
||||
} else if (OB_UNLIKELY(param_datum1->is_null() || param_datum2->is_null())) {
|
||||
expr_datum.set_null();
|
||||
} else {
|
||||
ObDatum *res_datum = static_cast<ObDatum *>(&expr_datum);
|
||||
ret = calc(*res_datum, *param_datum1, *param_datum2);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // namespace sql
|
||||
} // namespace oceanbase
|
||||
} // namespace oceanbase
|
@ -31,7 +31,6 @@ public:
|
||||
static int calc_perioddiff(const ObExpr& expr, ObEvalCtx& ctx, ObDatum& expr_datum);
|
||||
|
||||
private:
|
||||
static int get_year_month(const uint64_t value, uint64_t& year, uint64_t& month);
|
||||
// disallow copy
|
||||
DISALLOW_COPY_AND_ASSIGN(ObExprPeriodDiff);
|
||||
};
|
||||
@ -39,16 +38,41 @@ private:
|
||||
inline int ObExprPeriodDiff::calc_result_type2(
|
||||
ObExprResType& type, ObExprResType& left, ObExprResType& right, common::ObExprTypeCtx& type_ctx) const
|
||||
{
|
||||
UNUSED(type_ctx);
|
||||
UNUSED(left);
|
||||
UNUSED(right);
|
||||
type.set_int();
|
||||
type.set_scale(common::ObAccuracy::DDL_DEFAULT_ACCURACY[common::ObIntType].scale_);
|
||||
type.set_precision(common::ObAccuracy::DDL_DEFAULT_ACCURACY[common::ObIntType].precision_);
|
||||
left.set_calc_type(common::ObUInt64Type);
|
||||
right.set_calc_type(common::ObUInt64Type);
|
||||
type_ctx.set_cast_mode(type_ctx.get_cast_mode() | CM_STRING_INTEGER_TRUNC);
|
||||
return common::OB_SUCCESS;
|
||||
}
|
||||
|
||||
class ObExprPeriodAdd : public ObFuncExprOperator
|
||||
{
|
||||
public:
|
||||
explicit ObExprPeriodAdd(common::ObIAllocator &alloc);
|
||||
virtual ~ObExprPeriodAdd();
|
||||
virtual int calc_result_type2(ObExprResType &type,
|
||||
ObExprResType &left,
|
||||
ObExprResType &right,
|
||||
common::ObExprTypeCtx &type_ctx) const;
|
||||
template <typename T>
|
||||
static int calc(T &result, const T &left, const T &right);
|
||||
virtual int calc_result2(common::ObObj &result,
|
||||
const common::ObObj &left,
|
||||
const common::ObObj &right,
|
||||
common::ObExprCtx &expr_ctx) const;
|
||||
virtual common::ObCastMode get_cast_mode() const { return CM_STRING_INTEGER_TRUNC;}
|
||||
virtual int cg_expr(ObExprCGCtx &op_cg_ctx,
|
||||
const ObRawExpr &raw_expr,
|
||||
ObExpr &rt_expr) const override;
|
||||
static int calc_periodadd(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &expr_datum);
|
||||
|
||||
private:
|
||||
// disallow copy
|
||||
DISALLOW_COPY_AND_ASSIGN(ObExprPeriodAdd);
|
||||
};
|
||||
|
||||
} // namespace sql
|
||||
} // namespace oceanbase
|
||||
#endif //_OCEANBASE_SQL_OB_EXPR_PERIOD_DIFF_H_
|
||||
|
@ -132,6 +132,42 @@ int ObExprStrToDate::calc_result_type2(
|
||||
return ret;
|
||||
}
|
||||
|
||||
void print_user_warning(const int ret, ObString date_str)
|
||||
{
|
||||
if (OB_INVALID_DATE_FORMAT == ret) {
|
||||
ObString date_type_str("date");
|
||||
LOG_USER_WARN(OB_ERR_TRUNCATED_WRONG_VALUE, date_type_str.length(), date_type_str.ptr(),
|
||||
date_str.length(), date_str.ptr());
|
||||
} else if (OB_INVALID_DATE_VALUE == ret || OB_INVALID_ARGUMENT == ret) {
|
||||
ObString datetime_type_str("datetime");
|
||||
ObString func_str("str_to_date");
|
||||
LOG_USER_WARN(OB_ERR_INCORRECT_VALUE_FOR_FUNCTION,
|
||||
datetime_type_str.length(), datetime_type_str.ptr(),
|
||||
date_str.length(), date_str.ptr(),
|
||||
func_str.length(), func_str.ptr());
|
||||
}
|
||||
}
|
||||
|
||||
int set_error_code(const int ori_ret, ObString date_str)
|
||||
{
|
||||
int ret = ori_ret;
|
||||
if (OB_INVALID_DATE_FORMAT == ret) {
|
||||
ret = OB_ERR_TRUNCATED_WRONG_VALUE;
|
||||
ObString date_type_str("date");
|
||||
LOG_USER_ERROR(OB_ERR_TRUNCATED_WRONG_VALUE, date_type_str.length(), date_type_str.ptr(),
|
||||
date_str.length(), date_str.ptr());
|
||||
} else if (OB_INVALID_DATE_VALUE == ret || OB_INVALID_ARGUMENT == ret) {
|
||||
ret = OB_ERR_INCORRECT_VALUE_FOR_FUNCTION;
|
||||
ObString datetime_type_str("datetime");
|
||||
ObString func_str("str_to_date");
|
||||
LOG_USER_ERROR(OB_ERR_INCORRECT_VALUE_FOR_FUNCTION,
|
||||
datetime_type_str.length(), datetime_type_str.ptr(),
|
||||
date_str.length(), date_str.ptr(),
|
||||
func_str.length(), func_str.ptr());
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprStrToDate::calc_result2(ObObj& result, const ObObj& date, const ObObj& format, ObExprCtx& expr_ctx) const
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
@ -150,12 +186,16 @@ int ObExprStrToDate::calc_result2(ObObj& result, const ObObj& date, const ObObj&
|
||||
LOG_WARN("convert str to date failed", K(date), K(format), K(ret));
|
||||
if (CM_IS_WARN_ON_FAIL(expr_ctx.cast_mode_)) {
|
||||
if (OB_INVALID_DATE_FORMAT == ret) {
|
||||
print_user_warning(ret, date_str);
|
||||
ret = OB_SUCCESS;
|
||||
result.set_date(ObTimeConverter::ZERO_DATE);
|
||||
} else if (OB_INVALID_DATE_VALUE == ret) {
|
||||
} else if (OB_INVALID_DATE_VALUE == ret || OB_INVALID_ARGUMENT == ret) {
|
||||
print_user_warning(ret, date_str);
|
||||
ret = OB_SUCCESS;
|
||||
result.set_null();
|
||||
}
|
||||
} else {
|
||||
ret = set_error_code(ret, date_str);
|
||||
}
|
||||
} else {
|
||||
result.set_datetime(value);
|
||||
@ -217,10 +257,16 @@ static int calc(const ObExpr& expr, ObEvalCtx& ctx, bool& is_null, int64_t& res_
|
||||
// if res type is not datetime, will call ObTimeConverter::datetime_to_time()
|
||||
// or ObTimeConverter::datetime_to_date()
|
||||
res_int = ObTimeConverter::ZERO_DATETIME;
|
||||
} else if (OB_INVALID_DATE_VALUE == tmp_ret) {
|
||||
print_user_warning(OB_INVALID_DATE_FORMAT, date_str);
|
||||
} else if (OB_INVALID_DATE_VALUE == tmp_ret || OB_INVALID_ARGUMENT == tmp_ret) {
|
||||
ret = OB_SUCCESS;
|
||||
is_null = true;
|
||||
print_user_warning(tmp_ret, date_str);
|
||||
} else {
|
||||
ret = tmp_ret;
|
||||
}
|
||||
} else {
|
||||
ret = set_error_code(tmp_ret, date_str);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
292
src/sql/engine/expr/ob_expr_time_format.cpp
Normal file
292
src/sql/engine/expr/ob_expr_time_format.cpp
Normal file
@ -0,0 +1,292 @@
|
||||
// Copyright 2021 Alibaba Inc. All Rights Reserved.
|
||||
// Author:
|
||||
// shanting <dachuan.sdc@antgroup.com>
|
||||
|
||||
#define USING_LOG_PREFIX SQL_ENG
|
||||
#include "lib/ob_name_def.h"
|
||||
#include "sql/engine/expr/ob_expr_time_format.h"
|
||||
#include "sql/session/ob_sql_session_info.h"
|
||||
#include "sql/engine/expr/ob_datum_cast.h"
|
||||
#include "sql/engine/ob_exec_context.h"
|
||||
#include "sql/engine/expr/ob_expr_util.h"
|
||||
|
||||
namespace oceanbase
|
||||
{
|
||||
using namespace common;
|
||||
namespace sql
|
||||
{
|
||||
|
||||
ObExprTimeFormat::ObExprTimeFormat(ObIAllocator &alloc)
|
||||
: ObStringExprOperator(alloc, T_FUN_SYS_TIME_FORMAT, N_TIME_FORMAT, 2)
|
||||
{
|
||||
}
|
||||
|
||||
ObExprTimeFormat::~ObExprTimeFormat()
|
||||
{
|
||||
}
|
||||
|
||||
int ObExprTimeFormat::calc_result_type2(ObExprResType &type,
|
||||
ObExprResType &time,
|
||||
ObExprResType &format,
|
||||
common::ObExprTypeCtx &type_ctx) const
|
||||
{
|
||||
int ret = common::OB_SUCCESS;
|
||||
calc_temporal_format_result_length(type, format);
|
||||
type.set_collation_type(type_ctx.get_coll_type());
|
||||
type.set_collation_level(common::CS_LEVEL_COERCIBLE);
|
||||
|
||||
time.set_calc_type(ObTimeType);
|
||||
format.set_calc_type(ObVarcharType);
|
||||
format.set_calc_collation_type(type.get_collation_type());
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int ObExprTimeFormat::calc_result2(ObObj &result,
|
||||
const ObObj &time,
|
||||
const ObObj &format,
|
||||
ObExprCtx &expr_ctx) const
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
char *buf = NULL;
|
||||
int64_t buf_len = format.get_val_len() * OB_TEMPORAL_BUF_SIZE_RATIO;
|
||||
int64_t pos = 0;
|
||||
bool res_null = false;
|
||||
if (OB_UNLIKELY(time.is_null() || format.is_null())) {
|
||||
result.set_null();
|
||||
} else if (OB_UNLIKELY(ObVarcharType != format.get_type())) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("TIME_FORMAT() expected a string as format argument");
|
||||
} else if (OB_ISNULL(expr_ctx.calc_buf_)) {
|
||||
ret = OB_NOT_INIT;
|
||||
LOG_WARN("the pointer is null");
|
||||
} else if (OB_UNLIKELY(format.get_string().empty())) {
|
||||
result.set_null();
|
||||
} else if (OB_ISNULL(buf = static_cast<char *>(expr_ctx.calc_buf_->alloc(buf_len)))) {
|
||||
ret = OB_ALLOCATE_MEMORY_FAILED;
|
||||
LOG_ERROR("no more memory to alloc for buf");
|
||||
} else if (OB_FAIL(time_to_str_format(time.get_time(),
|
||||
format.get_string(),
|
||||
buf,
|
||||
buf_len,
|
||||
pos,
|
||||
res_null))) {
|
||||
LOG_WARN("failed to convert ob time to str with format");
|
||||
} else if (res_null) {
|
||||
result.set_null();
|
||||
} else {
|
||||
result.set_varchar(buf, static_cast<int32_t>(pos));
|
||||
result.set_collation(result_type_);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprTimeFormat::time_to_str_format(const int64_t &time_value, const ObString &format,
|
||||
char *buf, int64_t buf_len, int64_t &pos, bool &res_null)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObTime ob_time;
|
||||
if (ObTimeConverter::time_to_ob_time(time_value, ob_time)) {
|
||||
LOG_WARN("time to ob time failed", K(ret), K(time_value));
|
||||
} else if (OB_ISNULL(format.ptr()) || OB_ISNULL(buf)
|
||||
|| OB_UNLIKELY(format.length() <= 0 || buf_len <= 0)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("format or output string is invalid", K(ret), K(format), K(buf), K(buf_len));
|
||||
} else if (IS_NEG_TIME(ob_time.mode_) && OB_FAIL(databuff_printf(buf, buf_len, pos, "-"))) {
|
||||
LOG_WARN("print - failed", K(ret));
|
||||
} else {
|
||||
const char *format_ptr = format.ptr();
|
||||
const char *end_ptr = format.ptr() + format.length();
|
||||
const int32_t *parts = ob_time.parts_;
|
||||
//used for am/pm conversation in order to avoid if-else tests.
|
||||
int hour12 = ((parts[DT_HOUR] + 11) % 12) + 1;
|
||||
while (format_ptr < end_ptr && OB_SUCCESS == ret && !res_null) {
|
||||
if ('%' == *format_ptr) {
|
||||
format_ptr++;
|
||||
if (format_ptr >= end_ptr) {
|
||||
if (pos >= buf_len) {
|
||||
ret = OB_SIZE_OVERFLOW;
|
||||
break;
|
||||
}
|
||||
buf[pos++] = '%';
|
||||
break;
|
||||
}
|
||||
switch (*format_ptr) {
|
||||
case 'f': { //Microseconds (000000..999999), include '-' if value is negative.
|
||||
ret = ObTimeConverter::data_fmt_nd(buf, buf_len, pos, 6, parts[DT_USEC]);
|
||||
break;
|
||||
}
|
||||
case 'h': //Hour (01..12)
|
||||
case 'I': { //Hour (01..12)
|
||||
int hour = hour12;
|
||||
ret = ObTimeConverter::data_fmt_nd(buf, buf_len, pos, 2, hour);
|
||||
break;
|
||||
}
|
||||
case 'i': { //Minutes, numeric (00..59)
|
||||
ret = ObTimeConverter::data_fmt_nd(buf, buf_len, pos, 2, parts[DT_MIN]);
|
||||
break;
|
||||
}
|
||||
case 'H': { //Hour
|
||||
if (parts[DT_HOUR] < 100) {
|
||||
ret = ObTimeConverter::data_fmt_nd(buf, buf_len, pos, 2, parts[DT_HOUR]);
|
||||
} else {
|
||||
ret = ObTimeConverter::data_fmt_nd(buf, buf_len, pos, 3, parts[DT_HOUR]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'k': { //Hour
|
||||
ret = ObTimeConverter::data_fmt_d(buf, buf_len, pos, parts[DT_HOUR]);
|
||||
break;
|
||||
}
|
||||
case 'l': { //Hour (1..12)
|
||||
int hour = hour12;
|
||||
ret = ObTimeConverter::data_fmt_d(buf, buf_len, pos, hour);
|
||||
break;
|
||||
}
|
||||
case 'p': { //AM or PM
|
||||
const char *ptr = (parts[DT_HOUR] % 24) < 12 ? "AM" : "PM";
|
||||
ret = ObTimeConverter::data_fmt_s(buf, buf_len, pos, ptr);
|
||||
break;
|
||||
}
|
||||
case 'r': { //Time, 12-hour (hh:mm:ss followed by AM or PM)
|
||||
const char *ptr = (parts[DT_HOUR] % 24) < 12 ? "AM" : "PM";
|
||||
ret = databuff_printf(buf, buf_len, pos, "%02d:%02d:%02d %s", hour12, parts[DT_MIN], parts[DT_SEC], ptr);
|
||||
break;
|
||||
}
|
||||
case 'S': //Seconds (00..59)
|
||||
case 's': { //Seconds (00..59)
|
||||
ret = ObTimeConverter::data_fmt_nd(buf, buf_len, pos, 2, parts[DT_SEC]);
|
||||
break;
|
||||
}
|
||||
case 'T': { //Time (hh:mm:ss)
|
||||
if (parts[DT_HOUR] < 100) {
|
||||
ret = ObTimeConverter::data_fmt_nd(buf, buf_len, pos, 2, parts[DT_HOUR]);
|
||||
} else {
|
||||
ret = ObTimeConverter::data_fmt_nd(buf, buf_len, pos, 3, parts[DT_HOUR]);
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
ret = databuff_printf(buf, buf_len, pos, ":%02d:%02d", parts[DT_MIN], parts[DT_SEC]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'c': //Month, numeric (0..12)
|
||||
case 'e': { //Day of the month, numeric (0..31)
|
||||
ret = databuff_printf(buf, buf_len, pos, "0");
|
||||
break;
|
||||
}
|
||||
case 'd': //Day of the month, numeric (00..31)
|
||||
case 'm': //Month, numeric (00..12)
|
||||
case 'y': { //Year, numeric (two digits)
|
||||
ret = databuff_printf(buf, buf_len, pos, "00");
|
||||
break;
|
||||
}
|
||||
case 'Y': { //Year, numeric, four digits
|
||||
ret = databuff_printf(buf, buf_len, pos, "0000");
|
||||
break;
|
||||
}
|
||||
case 'a': //Abbreviated weekday name (Sun..Sat)
|
||||
case 'b': //Abbreviated month name (Jan..Dec)
|
||||
case 'D': //Day of the month with English suffix (0th, 1st, 2nd, 3rd...)
|
||||
case 'j': //Day of year (001..366)
|
||||
case 'M': //Month name (January..December)
|
||||
case 'U': //Week (00..53), where Sunday is the first day of the week
|
||||
case 'u': //Week (00..53), where Monday is the first day of the week
|
||||
case 'V': //Week (01..53), where Sunday is the first day of the week; used with %X
|
||||
case 'v': //Week (01..53), where Monday is the first day of the week; used with %x
|
||||
case 'W': //Weekday name (Sunday..Saturday)
|
||||
case 'w': //Day of the week (0=Sunday..6=Saturday)
|
||||
case 'X': //Year for the week where Sunday is the first day of the week
|
||||
case 'x': { //Year for the week, where Monday is the first day of the week
|
||||
res_null = true;
|
||||
break;
|
||||
}
|
||||
case '%': { //A literal "%" character
|
||||
if (pos >= buf_len) {
|
||||
ret = OB_SIZE_OVERFLOW;
|
||||
break;
|
||||
}
|
||||
buf[pos++] = '%';
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
if (pos >= buf_len) {
|
||||
ret = OB_SIZE_OVERFLOW;
|
||||
break;
|
||||
}
|
||||
buf[pos++] = *format_ptr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
format_ptr++;
|
||||
} else {
|
||||
LOG_WARN("print failed", K(ret), K(*format_ptr), K(time_value), K(ob_time));
|
||||
}
|
||||
} else if (pos >= buf_len) {
|
||||
ret = OB_SIZE_OVERFLOW;
|
||||
break;
|
||||
} else {
|
||||
buf[pos++] = *(format_ptr++);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprTimeFormat::cg_expr(ObExprCGCtx &op_cg_ctx,
|
||||
const ObRawExpr &raw_expr,
|
||||
ObExpr &rt_expr) const
|
||||
{
|
||||
UNUSED(op_cg_ctx);
|
||||
UNUSED(raw_expr);
|
||||
int ret = OB_SUCCESS;
|
||||
if (rt_expr.arg_cnt_ != 2) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("date_format expr should have two params", K(ret), K(rt_expr.arg_cnt_));
|
||||
} else if (OB_ISNULL(rt_expr.args_) || OB_ISNULL(rt_expr.args_[0])
|
||||
|| OB_ISNULL(rt_expr.args_[1])) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("children of date_format expr is null", K(ret), K(rt_expr.args_));
|
||||
} else {
|
||||
rt_expr.eval_func_ = ObExprTimeFormat::calc_time_format;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprTimeFormat::calc_time_format(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &expr_datum)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
char *buf = NULL;
|
||||
int64_t buf_len = 0;
|
||||
int64_t pos = 0;
|
||||
ObDatum *time = NULL;
|
||||
ObDatum *format = NULL;
|
||||
bool res_null = false;
|
||||
if (OB_FAIL(expr.eval_param_value(ctx, time, format))) {
|
||||
LOG_WARN("calc param failed", K(ret));
|
||||
} else if (time->is_null() || format->is_null()) {
|
||||
expr_datum.set_null();
|
||||
} else if (OB_UNLIKELY(format->get_string().empty())) {
|
||||
expr_datum.set_null();
|
||||
} else if (FALSE_IT(buf_len = format->get_string().length() * OB_TEMPORAL_BUF_SIZE_RATIO)) {
|
||||
} else if (OB_ISNULL(buf = expr.get_str_res_mem(ctx, buf_len))) {
|
||||
ret = OB_ALLOCATE_MEMORY_FAILED;
|
||||
LOG_ERROR("no more memory to alloc for buf", K(ret), K(buf_len));
|
||||
} else if (OB_FAIL(time_to_str_format(time->get_time(),
|
||||
format->get_string(),
|
||||
buf,
|
||||
buf_len,
|
||||
pos,
|
||||
res_null))) {
|
||||
LOG_WARN("failed to convert ob time to str with format");
|
||||
} else if (res_null) {
|
||||
expr_datum.set_null();
|
||||
} else {
|
||||
expr_datum.set_string(buf, static_cast<int32_t>(pos));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
45
src/sql/engine/expr/ob_expr_time_format.h
Normal file
45
src/sql/engine/expr/ob_expr_time_format.h
Normal file
@ -0,0 +1,45 @@
|
||||
// Copyright 2021 Alibaba Inc. All Rights Reserved.
|
||||
// Author:
|
||||
// shanting <dachuan.sdc@antgroup.com>
|
||||
|
||||
|
||||
#ifndef OCEANBASE_SQL_OB_EXPR_TIME_FORMAT_H_
|
||||
#define OCEANBASE_SQL_OB_EXPR_TIME_FORMAT_H_
|
||||
|
||||
#include "lib/timezone/ob_time_convert.h"
|
||||
#include "sql/engine/expr/ob_expr_operator.h"
|
||||
|
||||
namespace oceanbase
|
||||
{
|
||||
namespace sql
|
||||
{
|
||||
class ObExprTimeFormat : public ObStringExprOperator
|
||||
{
|
||||
public:
|
||||
explicit ObExprTimeFormat(common::ObIAllocator &alloc);
|
||||
virtual ~ObExprTimeFormat();
|
||||
virtual int calc_result_type2(ObExprResType &type,
|
||||
ObExprResType &date,
|
||||
ObExprResType &format,
|
||||
common::ObExprTypeCtx &type_ctx) const;
|
||||
virtual int calc_result2(common::ObObj &result,
|
||||
const common::ObObj &date,
|
||||
const common::ObObj &format,
|
||||
common::ObExprCtx &expr_ctx) const;
|
||||
virtual int cg_expr(ObExprCGCtx &op_cg_ctx,
|
||||
const ObRawExpr &raw_expr,
|
||||
ObExpr &rt_expr) const override;
|
||||
static int time_to_str_format(const int64_t &time_value, const common::ObString &format,
|
||||
char *buf, int64_t buf_len, int64_t &pos, bool &res_null);
|
||||
static int calc_time_format(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &expr_datum);
|
||||
private:
|
||||
// disallow copy
|
||||
DISALLOW_COPY_AND_ASSIGN(ObExprTimeFormat);
|
||||
|
||||
static const int64_t OB_TEMPORAL_BUF_SIZE_RATIO = 30;
|
||||
};
|
||||
|
||||
} //sql
|
||||
} //oceanbase
|
||||
|
||||
#endif //OCEANBASE_SQL_OB_EXPR_TIME_FORMAT_H_
|
@ -275,5 +275,47 @@ int ObExprToTimestampTZ::set_my_result_from_ob_time(ObExprCtx& expr_ctx, ObTime&
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
ObExprTimestamp::ObExprTimestamp(ObIAllocator &alloc)
|
||||
: ObFuncExprOperator(alloc, T_FUN_SYS_TIMESTAMP, N_TIMESTAMP, 1, NOT_ROW_DIMENSION)
|
||||
{
|
||||
}
|
||||
|
||||
ObExprTimestamp::~ObExprTimestamp()
|
||||
{
|
||||
}
|
||||
|
||||
int ObExprTimestamp::calc_result_type1(ObExprResType &type,
|
||||
ObExprResType &type1,
|
||||
ObExprTypeCtx &type_ctx) const
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
//param will be casted to ObDatetimeType before calculation
|
||||
type1.set_calc_type(ObDateTimeType);
|
||||
type.set_type(ObDateTimeType);
|
||||
//deduce scale now.
|
||||
int16_t scale1 = MIN(type1.get_scale(), MAX_SCALE_FOR_TEMPORAL);
|
||||
int16_t scale = (SCALE_UNKNOWN_YET == scale1) ? MAX_SCALE_FOR_TEMPORAL : scale1;
|
||||
type.set_scale(scale);
|
||||
type_ctx.set_cast_mode(type_ctx.get_cast_mode() | CM_NULL_ON_WARN);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObExprTimestamp::calc_result1(ObObj &result,
|
||||
const ObObj &obj,
|
||||
ObExprCtx &expr_ctx) const
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (OB_UNLIKELY(obj.is_null())) {
|
||||
result.set_null();
|
||||
} else {
|
||||
TYPE_CHECK(obj, ObDateTimeType);
|
||||
result = obj;
|
||||
}
|
||||
UNUSED(expr_ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
} // namespace sql
|
||||
} // namespace oceanbase
|
||||
|
@ -84,6 +84,23 @@ private:
|
||||
DISALLOW_COPY_AND_ASSIGN(ObExprToTimestampTZ);
|
||||
};
|
||||
|
||||
class ObExprTimestamp : public ObFuncExprOperator
|
||||
{
|
||||
public:
|
||||
explicit ObExprTimestamp(common::ObIAllocator &alloc);
|
||||
virtual ~ObExprTimestamp();
|
||||
virtual int calc_result_type1(ObExprResType &type,
|
||||
ObExprResType &type1,
|
||||
common::ObExprTypeCtx &type_ctx) const;
|
||||
virtual int calc_result1(common::ObObj &result,
|
||||
const common::ObObj &time,
|
||||
common::ObExprCtx &expr_ctx) const;
|
||||
virtual common::ObCastMode get_cast_mode() const { return CM_NULL_ON_WARN;}
|
||||
private :
|
||||
//disallow copy
|
||||
DISALLOW_COPY_AND_ASSIGN(ObExprTimestamp);
|
||||
};
|
||||
|
||||
} // namespace sql
|
||||
} // namespace oceanbase
|
||||
|
||||
|
@ -561,6 +561,22 @@ typedef enum ObItemType {
|
||||
T_FUN_SYS_NLS_UPPER = 1577,
|
||||
T_FUN_KEEP_WM_CONCAT = 1578,
|
||||
T_FUN_WM_CONCAT = 1579,
|
||||
T_FUN_TOP_FRE_HIST = 1580,
|
||||
T_FUN_UNISTR = 1581,
|
||||
T_FUN_PLSQL_VARIABLE = 1582,
|
||||
T_FUN_ASCIISTR = 1583,
|
||||
T_FUN_PL_AGG_UDF = 1584,
|
||||
T_FUN_SYS_AT_TIME_ZONE = 1585,
|
||||
T_FUN_SYS_AT_LOCAL = 1586,
|
||||
T_FUN_HYBRID_HIST = 1587,
|
||||
T_FUN_SYS_RAWTONHEX = 1588,
|
||||
T_FUN_SYS_TIMESTAMP = 1589,
|
||||
T_FUN_SYS_GET_FORMAT = 1590,
|
||||
T_FUN_SYS_MAKEDATE = 1591,
|
||||
T_FUN_SYS_PERIOD_ADD = 1592,
|
||||
T_FUN_SYS_UTC_TIME = 1593,
|
||||
T_FUN_SYS_UTC_DATE = 1594,
|
||||
T_FUN_SYS_TIME_FORMAT = 1595,
|
||||
///< @note add new oracle only function type before this line
|
||||
|
||||
T_FUN_SYS_END = 2000,
|
||||
|
@ -308,7 +308,7 @@ END_P SET_VAR DELIMITER
|
||||
%type <node> create_tenant_stmt opt_tenant_option_list alter_tenant_stmt drop_tenant_stmt
|
||||
%type <node> create_restore_point_stmt drop_restore_point_stmt
|
||||
%type <node> create_resource_stmt drop_resource_stmt alter_resource_stmt
|
||||
%type <node> cur_timestamp_func cur_time_func cur_date_func now_synonyms_func utc_timestamp_func sys_interval_func sysdate_func
|
||||
%type <node> cur_timestamp_func cur_time_func cur_date_func now_synonyms_func utc_timestamp_func utc_time_func utc_date_func sys_interval_func sysdate_func
|
||||
%type <node> opt_create_resource_pool_option_list create_resource_pool_option alter_resource_pool_option_list alter_resource_pool_option
|
||||
%type <node> opt_shrink_unit_option unit_id_list
|
||||
%type <node> opt_resource_unit_option_list resource_unit_option
|
||||
@ -424,7 +424,7 @@ END_P SET_VAR DELIMITER
|
||||
%type <node> create_savepoint_stmt rollback_savepoint_stmt release_savepoint_stmt
|
||||
%type <node> opt_qb_name
|
||||
%type <node> opt_force_purge
|
||||
%type <node> opt_sql_throttle_for_priority opt_sql_throttle_using_cond sql_throttle_one_or_more_metrics sql_throttle_metric
|
||||
%type <node> opt_sql_throttle_for_priority opt_sql_throttle_using_cond sql_throttle_one_or_more_metrics sql_throttle_metric get_format_unit
|
||||
%start sql_stmt
|
||||
%%
|
||||
////////////////////////////////////////////////////////////////
|
||||
@ -2126,6 +2126,14 @@ MOD '(' expr ',' expr ')'
|
||||
{
|
||||
$$ = $1;
|
||||
}
|
||||
| utc_time_func
|
||||
{
|
||||
$$ = $1;
|
||||
}
|
||||
| utc_date_func
|
||||
{
|
||||
$$ = $1;
|
||||
}
|
||||
| CAST '(' expr AS cast_data_type ')'
|
||||
{
|
||||
//cast_data_type is a T_CAST_ARGUMENT rather than a T_INT to avoid being parameterized automatically
|
||||
@ -2202,6 +2210,13 @@ MOD '(' expr ',' expr ')'
|
||||
make_name_node($$, result->malloc_pool_, "time");
|
||||
malloc_non_terminal_node($$, result->malloc_pool_, T_FUN_SYS, 2, $$, params);
|
||||
}
|
||||
| TIMESTAMP '(' expr ')'
|
||||
{
|
||||
ParseNode *params = NULL;
|
||||
malloc_non_terminal_node(params, result->malloc_pool_, T_EXPR_LIST, 1, $3);
|
||||
make_name_node($$, result->malloc_pool_, "timestamp");
|
||||
malloc_non_terminal_node($$, result->malloc_pool_, T_FUN_SYS, 2, $$, params);
|
||||
}
|
||||
| MONTH '(' expr ')'
|
||||
{
|
||||
ParseNode *params = NULL;
|
||||
@ -2237,6 +2252,13 @@ MOD '(' expr ',' expr ')'
|
||||
make_name_node($$, result->malloc_pool_, "second");
|
||||
malloc_non_terminal_node($$, result->malloc_pool_, T_FUN_SYS, 2, $$, params);
|
||||
}
|
||||
| GET_FORMAT '(' get_format_unit ',' expr ')'
|
||||
{
|
||||
ParseNode *params = NULL;
|
||||
malloc_non_terminal_node(params, result->malloc_pool_, T_EXPR_LIST, 2, $3, $5);
|
||||
make_name_node($$, result->malloc_pool_, "get_format");
|
||||
malloc_non_terminal_node($$, result->malloc_pool_, T_FUN_SYS, 2, $$, params);
|
||||
}
|
||||
| MINUTE '(' expr ')'
|
||||
{
|
||||
ParseNode *params = NULL;
|
||||
@ -2482,7 +2504,11 @@ INTERVAL '(' expr ',' expr ')'
|
||||
;
|
||||
|
||||
utc_timestamp_func:
|
||||
UTC_TIMESTAMP '(' ')'
|
||||
UTC_TIMESTAMP
|
||||
{
|
||||
malloc_non_terminal_node($$, result->malloc_pool_, T_FUN_SYS_UTC_TIMESTAMP, 1, NULL);
|
||||
}
|
||||
| UTC_TIMESTAMP '(' ')'
|
||||
{
|
||||
malloc_non_terminal_node($$, result->malloc_pool_, T_FUN_SYS_UTC_TIMESTAMP, 1, NULL);
|
||||
}
|
||||
@ -2492,6 +2518,33 @@ UTC_TIMESTAMP '(' ')'
|
||||
}
|
||||
;
|
||||
|
||||
utc_time_func:
|
||||
UTC_TIME
|
||||
{
|
||||
malloc_non_terminal_node($$, result->malloc_pool_, T_FUN_SYS_UTC_TIME, 1, NULL);
|
||||
}
|
||||
| UTC_TIME '(' ')'
|
||||
{
|
||||
malloc_non_terminal_node($$, result->malloc_pool_, T_FUN_SYS_UTC_TIME, 1, NULL);
|
||||
}
|
||||
| UTC_TIME '(' INTNUM ')'
|
||||
{
|
||||
malloc_non_terminal_node($$, result->malloc_pool_, T_FUN_SYS_UTC_TIME, 1, $3);
|
||||
}
|
||||
;
|
||||
|
||||
utc_date_func:
|
||||
UTC_DATE
|
||||
{
|
||||
malloc_non_terminal_node($$, result->malloc_pool_, T_FUN_SYS_UTC_DATE, 1, NULL);
|
||||
}
|
||||
| UTC_DATE '(' ')'
|
||||
{
|
||||
malloc_non_terminal_node($$, result->malloc_pool_, T_FUN_SYS_UTC_DATE, 1, NULL);
|
||||
}
|
||||
;
|
||||
|
||||
|
||||
sysdate_func:
|
||||
SYSDATE '(' ')'
|
||||
{
|
||||
@ -4236,6 +4289,24 @@ DATETIME { $$[0] = T_DATETIME; $$[1] = 0; }
|
||||
| TIME { $$[0] = T_TIME; $$[1] = 0; }
|
||||
;
|
||||
|
||||
get_format_unit:
|
||||
DATETIME
|
||||
{
|
||||
malloc_terminal_node($$, result->malloc_pool_, T_INT);
|
||||
$$->value_ = GET_FORMAT_DATETIME;
|
||||
}
|
||||
| DATE
|
||||
{
|
||||
malloc_terminal_node($$, result->malloc_pool_, T_INT);
|
||||
$$->value_ = GET_FORMAT_DATE;
|
||||
}
|
||||
| TIME
|
||||
{
|
||||
malloc_terminal_node($$, result->malloc_pool_, T_INT);
|
||||
$$->value_ = GET_FORMAT_TIME;
|
||||
}
|
||||
;
|
||||
|
||||
data_type:
|
||||
int_type_i opt_int_length_i opt_unsigned_i opt_zerofill_i
|
||||
{
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -502,6 +502,22 @@ const char* get_type_name(int type)
|
||||
case T_FUN_SYS_NLS_UPPER : return "T_FUN_SYS_NLS_UPPER";
|
||||
case T_FUN_KEEP_WM_CONCAT : return "T_FUN_KEEP_WM_CONCAT";
|
||||
case T_FUN_WM_CONCAT : return "T_FUN_WM_CONCAT";
|
||||
case T_FUN_TOP_FRE_HIST : return "T_FUN_TOP_FRE_HIST";
|
||||
case T_FUN_UNISTR : return "T_FUN_UNISTR";
|
||||
case T_FUN_PLSQL_VARIABLE : return "T_FUN_PLSQL_VARIABLE";
|
||||
case T_FUN_ASCIISTR : return "T_FUN_ASCIISTR";
|
||||
case T_FUN_PL_AGG_UDF : return "T_FUN_PL_AGG_UDF";
|
||||
case T_FUN_SYS_AT_TIME_ZONE : return "T_FUN_SYS_AT_TIME_ZONE";
|
||||
case T_FUN_SYS_AT_LOCAL : return "T_FUN_SYS_AT_LOCAL";
|
||||
case T_FUN_HYBRID_HIST : return "T_FUN_HYBRID_HIST";
|
||||
case T_FUN_SYS_RAWTONHEX : return "T_FUN_SYS_RAWTONHEX";
|
||||
case T_FUN_SYS_TIMESTAMP : return "T_FUN_SYS_TIMESTAMP";
|
||||
case T_FUN_SYS_GET_FORMAT : return "T_FUN_SYS_GET_FORMAT";
|
||||
case T_FUN_SYS_MAKEDATE : return "T_FUN_SYS_MAKEDATE";
|
||||
case T_FUN_SYS_PERIOD_ADD : return "T_FUN_SYS_PERIOD_ADD";
|
||||
case T_FUN_SYS_UTC_TIME : return "T_FUN_SYS_UTC_TIME";
|
||||
case T_FUN_SYS_UTC_DATE : return "T_FUN_SYS_UTC_DATE";
|
||||
case T_FUN_SYS_TIME_FORMAT : return "T_FUN_SYS_TIME_FORMAT";
|
||||
case T_FUN_SYS_END : return "T_FUN_SYS_END";
|
||||
case T_MAX_OP : return "T_MAX_OP";
|
||||
case T_FUN_MATCH_AGAINST : return "T_FUN_MATCH_AGAINST";
|
||||
|
@ -257,6 +257,8 @@ bool ObSqlParameterization::is_tree_not_param(const ParseNode* tree)
|
||||
ret_bool = true;
|
||||
} else if (T_FUN_SYS_UTC_TIMESTAMP == tree->type_) {
|
||||
ret_bool = true;
|
||||
} else if (T_FUN_SYS_UTC_TIME == tree->type_) {
|
||||
ret_bool = true;
|
||||
} else if (T_FUN_SYS_SYSDATE == tree->type_) {
|
||||
ret_bool = true;
|
||||
} else if (T_FUN_SYS_SYSTIMESTAMP == tree->type_) {
|
||||
|
@ -418,7 +418,7 @@ int ObRawExprDeduceType::calc_result_type(
|
||||
|
||||
if (OB_SUCC(ret)) {
|
||||
ObItemType item_type = expr.get_expr_type();
|
||||
if (T_FUN_SYS_UTC_TIMESTAMP == item_type || T_FUN_SYS_CUR_TIMESTAMP == item_type ||
|
||||
if (T_FUN_SYS_UTC_TIME == item_type || T_FUN_SYS_UTC_TIMESTAMP == item_type || T_FUN_SYS_CUR_TIMESTAMP == item_type ||
|
||||
T_FUN_SYS_LOCALTIMESTAMP == item_type || T_FUN_SYS_CUR_TIME == item_type || T_FUN_SYS_SYSDATE == item_type ||
|
||||
T_FUN_SYS_SYSTIMESTAMP == item_type) {
|
||||
/*
|
||||
|
@ -569,6 +569,7 @@ int ObRawExprInfoExtractor::visit(ObSysFunRawExpr& expr)
|
||||
if (OB_SUCC(ret)) {
|
||||
if (T_FUN_SYS_CUR_TIMESTAMP == expr.get_expr_type() || T_FUN_SYS_CUR_TIME == expr.get_expr_type() ||
|
||||
T_FUN_SYS_CUR_DATE == expr.get_expr_type() || T_FUN_SYS_UTC_TIMESTAMP == expr.get_expr_type() ||
|
||||
T_FUN_SYS_UTC_TIME == expr.get_expr_type() || T_FUN_SYS_UTC_DATE == expr.get_expr_type() ||
|
||||
T_FUN_SYS_LOCALTIMESTAMP == expr.get_expr_type() ||
|
||||
(T_FUN_SYS_SYSDATE == expr.get_expr_type() && lib::is_oracle_mode()) ||
|
||||
T_FUN_SYS_SYSTIMESTAMP == expr.get_expr_type() ||
|
||||
|
@ -189,9 +189,9 @@ int ObRawExprPrinter::print(ObConstRawExpr* expr)
|
||||
} else if (OB_FAIL(expr->get_value().print_sql_literal(buf_, buf_len_, *pos_, print_params_))) {
|
||||
LOG_WARN("fail to print sql literal", K(ret));
|
||||
}
|
||||
} else if (expr->get_literal_prefix() == ORALCE_LITERAL_PREFIX_DATE) {
|
||||
} else if (expr->get_literal_prefix() == LITERAL_PREFIX_DATE && expr->get_value().is_datetime()) {
|
||||
int32_t tmp_date = 0;
|
||||
if (OB_FAIL(databuff_printf(buf_, buf_len_, *pos_, "%s '", ORALCE_LITERAL_PREFIX_DATE))) {
|
||||
if (OB_FAIL(databuff_printf(buf_, buf_len_, *pos_, "%s '", LITERAL_PREFIX_DATE))) {
|
||||
LOG_WARN("fail to print literal prefix", K(ret));
|
||||
} else if (OB_FAIL(ObTimeConverter::datetime_to_date(expr->get_value().get_datetime(), NULL, tmp_date))) {
|
||||
LOG_WARN("fail to datetime_to_date", "datetime", expr->get_value().get_datetime(), K(ret));
|
||||
@ -931,7 +931,8 @@ int ObRawExprPrinter::print(ObSysFunRawExpr* expr)
|
||||
} else {
|
||||
ObString func_name = expr->get_func_name();
|
||||
switch (expr->get_expr_type()) {
|
||||
case T_FUN_SYS_UTC_TIMESTAMP: {
|
||||
case T_FUN_SYS_UTC_TIMESTAMP:
|
||||
case T_FUN_SYS_UTC_TIME: {
|
||||
const int16_t scale = static_cast<int16_t>(expr->get_result_type().get_scale());
|
||||
if (scale > 0) {
|
||||
DATA_PRINTF("%.*s(%d)", LEN_AND_PTR(func_name), scale);
|
||||
@ -1327,6 +1328,24 @@ int ObRawExprPrinter::print(ObSysFunRawExpr* expr)
|
||||
}
|
||||
break;
|
||||
}
|
||||
case T_FUN_SYS_GET_FORMAT: {
|
||||
if (2 != expr->get_param_count()) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("param count should be equal 2", K(ret), K(expr->get_param_count()));
|
||||
} else {
|
||||
DATA_PRINTF("get_format(");
|
||||
// temporal_unit
|
||||
if (OB_SUCC(ret)) {
|
||||
if (OB_FAIL(print_get_format_unit(expr->get_param_expr(0)))) {
|
||||
LOG_WARN("fail to print date unit", K(ret));
|
||||
}
|
||||
}
|
||||
DATA_PRINTF(", ");
|
||||
PRINT_EXPR(expr->get_param_expr(1));
|
||||
DATA_PRINTF(")");
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
// substr
|
||||
// date, month
|
||||
@ -2079,6 +2098,33 @@ int ObRawExprPrinter::print_date_unit(ObRawExpr* expr)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObRawExprPrinter::print_get_format_unit(ObRawExpr *expr)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
|
||||
if (OB_ISNULL(buf_) || OB_ISNULL(pos_) || OB_ISNULL(expr)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("stmt_ is NULL of buf_ is NULL or pos_ is NULL or expr is NULL", K(ret));
|
||||
} else {
|
||||
if (ObRawExpr::EXPR_CONST != expr->get_expr_class()) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("expr class should be EXPR_CONST", K(ret), K(expr->get_expr_class()));
|
||||
} else {
|
||||
int64_t get_format_type = GET_FORMAT_MAX;
|
||||
ObConstRawExpr *con_expr = static_cast<ObConstRawExpr*>(expr);
|
||||
if (OB_ISNULL(con_expr)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("con_expr should not be NULL", K(ret));
|
||||
} else {
|
||||
con_expr->get_value().get_int(get_format_type);
|
||||
DATA_PRINTF("%s", ob_get_format_unit_type_str(static_cast<ObGetFormatUnitType>(get_format_type)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// 1. ob not support cast(expr as char charset xxx)
|
||||
int ObRawExprPrinter::print_cast_type(ObRawExpr* expr)
|
||||
{
|
||||
|
@ -97,6 +97,7 @@ private:
|
||||
int print(ObPseudoColumnRawExpr* expr);
|
||||
|
||||
int print_date_unit(ObRawExpr* expr);
|
||||
int print_get_format_unit(ObRawExpr* expr);
|
||||
int print_cast_type(ObRawExpr* expr);
|
||||
|
||||
int print_partition_exprs(ObWinFunRawExpr* expr);
|
||||
|
@ -620,7 +620,7 @@ int ObRawExprResolverImpl::do_recursive_resolve(const ParseNode* node, ObRawExpr
|
||||
}
|
||||
|
||||
case T_FUN_SYS_UTC_TIMESTAMP: {
|
||||
ObString err_info("now");
|
||||
ObString err_info("utc_timestamp");
|
||||
if (OB_FAIL(process_timestamp_node(node, err_info, expr))) {
|
||||
LOG_WARN("fail to process timestamp node", K(ret), K(node));
|
||||
} else {
|
||||
@ -628,6 +628,15 @@ int ObRawExprResolverImpl::do_recursive_resolve(const ParseNode* node, ObRawExpr
|
||||
}
|
||||
break;
|
||||
}
|
||||
case T_FUN_SYS_UTC_TIME: {
|
||||
ObString err_info("utc_time");
|
||||
if (OB_FAIL(process_timestamp_node(node, err_info, expr))) {
|
||||
LOG_WARN("fail to process timestamp node", K(ret), K(node));
|
||||
} else {
|
||||
static_cast<ObSysFunRawExpr*>(expr)->set_func_name(ObString::make_string(N_UTC_TIME));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case T_FUN_SYS_CUR_TIMESTAMP: {
|
||||
if (share::is_oracle_mode()) {
|
||||
if (OB_FAIL(process_oracle_timestamp_node(node,
|
||||
@ -704,6 +713,16 @@ int ObRawExprResolverImpl::do_recursive_resolve(const ParseNode* node, ObRawExpr
|
||||
}
|
||||
break;
|
||||
}
|
||||
case T_FUN_SYS_UTC_DATE: {
|
||||
ObSysFunRawExpr* f_expr = NULL;
|
||||
if (OB_FAIL(ctx_.expr_factory_.create_raw_expr(T_FUN_SYS_UTC_DATE, f_expr))) {
|
||||
LOG_WARN("fail to create raw expr", K(ret));
|
||||
} else {
|
||||
f_expr->set_func_name(ObString::make_string(N_UTC_DATE));
|
||||
expr = f_expr;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case T_COLLATION: {
|
||||
// used in internal function `set_collation' to implement COLLATE clause
|
||||
if (OB_FAIL(process_collation_node(node, expr))) {
|
||||
|
@ -808,6 +808,7 @@ int ObResolverUtils::resolve_const(const ParseNode* node, const stmt::StmtType s
|
||||
val.set_date(time_val);
|
||||
val.set_scale(0);
|
||||
val.set_param_meta(val.get_meta());
|
||||
literal_prefix = ObString::make_string(LITERAL_PREFIX_DATE);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -821,6 +822,7 @@ int ObResolverUtils::resolve_const(const ParseNode* node, const stmt::StmtType s
|
||||
val.set_time(time_val);
|
||||
val.set_scale(scale);
|
||||
val.set_param_meta(val.get_meta());
|
||||
literal_prefix = ObString::make_string(MYSQL_LITERAL_PREFIX_TIME);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -833,8 +835,8 @@ int ObResolverUtils::resolve_const(const ParseNode* node, const stmt::StmtType s
|
||||
} else {
|
||||
val.set_datetime(time_val);
|
||||
val.set_scale(OB_MAX_DATE_PRECISION);
|
||||
literal_prefix = ObString::make_string(ORALCE_LITERAL_PREFIX_DATE);
|
||||
val.set_param_meta(val.get_meta());
|
||||
literal_prefix = ObString::make_string(LITERAL_PREFIX_DATE);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -849,6 +851,7 @@ int ObResolverUtils::resolve_const(const ParseNode* node, const stmt::StmtType s
|
||||
val.set_datetime(time_val);
|
||||
val.set_scale(scale);
|
||||
val.set_param_meta(val.get_meta());
|
||||
literal_prefix = ObString::make_string(LITERAL_PREFIX_TIMESTAMP);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -864,7 +867,7 @@ int ObResolverUtils::resolve_const(const ParseNode* node, const stmt::StmtType s
|
||||
/* use max scale bug:#18093350 */
|
||||
val.set_otimestamp_value(value_type, tz_value);
|
||||
val.set_scale(OB_MAX_TIMESTAMP_TZ_PRECISION);
|
||||
literal_prefix = ObString::make_string(ORALCE_LITERAL_PREFIX_TIMESTAMP);
|
||||
literal_prefix = ObString::make_string(LITERAL_PREFIX_TIMESTAMP);
|
||||
val.set_param_meta(val.get_meta());
|
||||
}
|
||||
break;
|
||||
|
Loading…
x
Reference in New Issue
Block a user