support last_day in mysql mode

This commit is contained in:
jg0 2021-07-27 21:39:15 +08:00 committed by wangzelin.wzl
parent 09edba0ff6
commit 74d0236609
45 changed files with 26893 additions and 25079 deletions

View File

@ -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];
}

View File

@ -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
}

View File

@ -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__)

View File

@ -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"

View File

@ -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)) {

View File

@ -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 &param, 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;
}

View File

@ -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));

View File

@ -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);

View File

@ -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";

View File

@ -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

View File

@ -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"

View File

@ -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_;
};

View File

@ -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));
}
}
}

View File

@ -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)

View File

@ -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

View File

@ -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;

View File

@ -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()

View File

@ -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);

View File

@ -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));
}
}
}

View File

@ -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

View File

@ -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

View File

@ -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));

View 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;
}
}
}

View 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_ */

View File

@ -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
{
/*

View File

@ -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;

View File

@ -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);

View File

@ -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

View File

@ -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_

View File

@ -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);
}
}
}

View 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;
}
}
}

View 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_

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -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

View File

@ -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";

View File

@ -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_) {

View File

@ -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) {
/*

View File

@ -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() ||

View File

@ -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)
{

View File

@ -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);

View File

@ -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))) {

View File

@ -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;