/** * Copyright (c) 2021 OceanBase * OceanBase Database Proxy(ODP) is licensed under Mulan PubL v2. * You can use this software according to the terms and conditions of the Mulan PubL v2. * You may obtain a copy of Mulan PubL v2 at: * http://license.coscl.org.cn/MulanPubL-2.0 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. * See the Mulan PubL v2 for more details. */ #define USING_LOG_PREFIX COMMON #include "common/ob_obj_cast.h" #include #include "lib/charset/ob_dtoa.h" namespace oceanbase { namespace common { static const int64_t MAX_FLOAT_PRINT_SIZE = 64; static const int64_t MAX_DOUBLE_PRINT_SIZE = 64; static int identity(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { UNUSED(expect_type); UNUSED(params); UNUSED(cast_mode); if (&in != &out) { out = in; } return OB_SUCCESS; } static int not_support(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { UNUSED(params); LOG_WARN("not supported obj type convert", K(expect_type), K(in), K(out), K(cast_mode)); return OB_NOT_SUPPORTED; } static int unknown_other(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { return not_support(expect_type, params, in, out, cast_mode); } //////////////////////////////////////////////////////////////// // Utility func static int print_varchar(ObString &str, const char *format, ...) { int ret = OB_SUCCESS; if (OB_ISNULL(str.ptr()) || OB_UNLIKELY(str.size() <= 0)) { ret = OB_BUF_NOT_ENOUGH; LOG_WARN("output buffer for varchar not enough", K(ret), K(str.ptr()), K(str.size())); } else { va_list args; va_start(args, format); int32_t length = vsnprintf(str.ptr(), str.size(), format, args); va_end(args); if (OB_UNLIKELY(length < 0)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("failed to snprintf string", K(ret), K(length)); } else if (OB_UNLIKELY(length >= str.size())) { ret = OB_BUF_NOT_ENOUGH; LOG_WARN("output buffer for varchar not enough", K(str.size()), K(length)); } else { // need not care the result, we have judged the length above. str.set_length(length); } } return ret; } static int copy_string(const ObObjCastParams ¶ms, const ObObjType type, const char *str, int64_t len, ObObj &obj) { int ret = OB_SUCCESS; char *buf = NULL; if (OB_LIKELY(len > 0 && NULL != str)) { if (OB_LIKELY(NULL != params.zf_info_) && params.zf_info_->need_zerofill_) { int64_t str_len = std::max(len, static_cast(params.zf_info_->max_length_)); if (OB_UNLIKELY(NULL == (buf = static_cast(params.alloc(str_len))))) { ret = OB_ALLOCATE_MEMORY_FAILED; } else { int64_t zf = params.zf_info_->max_length_ - len; if (zf > 0) { MEMSET(buf, '0', zf); MEMCPY(buf + zf, str, len); len = str_len; // set string length } else { MEMCPY(buf, str, len); } } } else { if (OB_UNLIKELY(NULL == (buf = static_cast(params.alloc(len))))) { ret = OB_ALLOCATE_MEMORY_FAILED; } else { MEMCPY(buf, str, len); } } } obj.set_string(type, buf, static_cast(len)); return ret; } static int copy_string(const ObObjCastParams ¶ms, const ObObjType type, const ObString &str, ObObj &obj) { return copy_string(params, type, str.ptr(), str.length(), obj); } /* * check err when a string cast to int/uint/double/float according to endptr *@str input string *@endptr result pointer to end of converted string *@len length of str *@err * incorrect -> "a232"->int or "a2323.23"->double * truncated -> "23as" -> int or "as2332.a"->double * @note * This is called after one has called strntoull10rnd() or strntod function. */ static int check_convert_str_err(const char *str, const char *endptr, const int32_t len, const int err) { int ret = OB_SUCCESS; // 1. only one of str and endptr is null, it is invalid input. if ((OB_ISNULL(str) || OB_ISNULL(endptr)) && str != endptr) { ret = OB_ERR_UNEXPECTED; LOG_WARN("null pointer(s)", K(ret), K(str), K(endptr)); } else // 2. str == endptr include NULL == NULL. if (OB_UNLIKELY(str == endptr) || OB_UNLIKELY(EDOM == err)) { ret = OB_ERR_TRUNCATED_WRONG_VALUE_FOR_FIELD; //1366 } else { // 3. so here we are sure that both str and endptr are not NULL. endptr += ObCharset::scan_str(endptr, str + len, OB_SEQ_SPACES); endptr += ObCharset::scan_str(endptr, str + len, OB_SEQ_INTTAIL); if (endptr < str + len) { ret = OB_ERR_DATA_TRUNCATED; //1265 } } return ret; } //////////////////////////////////////////////////////////////// OB_INLINE int get_cast_ret(const ObCastMode cast_mode, int ret, int &warning) { if (OB_SUCCESS != ret && //OB_ERR_UNEXPECTED != ret && CM_IS_WARN_ON_FAIL(cast_mode)) { warning = ret; ret = OB_SUCCESS; } return ret; } #define CAST_FAIL(stmt) \ (OB_UNLIKELY((OB_SUCCESS != (ret = get_cast_ret(cast_mode, (stmt), params.warning_))))) #define SET_RES_OBJ(res, func_val, obj_type, comma, val, zero_val) \ do { \ if (OB_SUCC(ret)) { \ if (OB_SUCCESS == params.warning_ \ || OB_ERR_TRUNCATED_WRONG_VALUE == params.warning_ \ || OB_DATA_OUT_OF_RANGE == params.warning_ \ || OB_ERR_DATA_TRUNCATED == params.warning_ \ || OB_ERR_TRUNCATED_WRONG_VALUE_FOR_FIELD == params.warning_) { \ res.set_##func_val(obj_type comma val); \ } else if (CM_IS_ZERO_ON_WARN(cast_mode)) { \ res.set_##func_val(obj_type comma zero_val); \ } else { \ res.set_null(); \ } \ } else { \ res.set_##func_val(obj_type comma val); \ } \ } while (0) #define COMMA , #define SET_RES_INT(res) SET_RES_OBJ(res, int, expect_type, COMMA, value, 0) #define SET_RES_UINT(res) SET_RES_OBJ(res, uint, expect_type, COMMA, value, 0) #define SET_RES_FLOAT(res) SET_RES_OBJ(res, float, expect_type, COMMA, value, 0.0) #define SET_RES_DOUBLE(res) SET_RES_OBJ(res, double, expect_type, COMMA, value, 0.0) #define SET_RES_NUMBER(res) SET_RES_OBJ(res, number, expect_type, COMMA, value, (value.set_zero(), value)) #define SET_RES_DATETIME(res) SET_RES_OBJ(res, datetime, expect_type, COMMA, value, ObTimeConverter::ZERO_DATETIME) #define SET_RES_DATE(res) SET_RES_OBJ(res, date, , , value, ObTimeConverter::ZERO_DATE) #define SET_RES_TIME(res) SET_RES_OBJ(res, time, , , value, ObTimeConverter::ZERO_TIME) #define SET_RES_YEAR(res) SET_RES_OBJ(res, year, , , value, ObTimeConverter::ZERO_YEAR) #define SET_RES_ACCURACY(res_precision, res_scale, res_length) \ if (params.res_accuracy_ != NULL && OB_SUCCESS == ret) {\ params.res_accuracy_->set_scale(res_scale);\ params.res_accuracy_->set_precision(res_precision);\ params.res_accuracy_->set_length(res_length);\ } //////////////////////////////////////////////////////////////// // range check function templates. // check with given lower and upper limit. template OB_INLINE int numeric_range_check(const InType in_val, const OutType min_out_val, const OutType max_out_val, OutType &out_val) { int ret = OB_SUCCESS; if (in_val < static_cast(min_out_val)) { ret = OB_DATA_OUT_OF_RANGE; out_val = min_out_val; } else if (in_val > static_cast(max_out_val)) { ret = OB_DATA_OUT_OF_RANGE; out_val = max_out_val; } return ret; } // explicit for int_uint check, because we need use out_val to compare with max_out_val instead // of in_val, since we can't cast UINT64_MAX to int64. template <> OB_INLINE int numeric_range_check(const int64_t in_val, const uint64_t min_out_val, const uint64_t max_out_val, uint64_t &out_val) { int ret = OB_SUCCESS; if (in_val < 0) { ret = OB_DATA_OUT_OF_RANGE; out_val = 0; } else if (out_val > max_out_val) { ret = OB_DATA_OUT_OF_RANGE; out_val = max_out_val; } UNUSED(min_out_val); return ret; } // check if is negative only. template OB_INLINE int numeric_negative_check(OutType &out_val) { int ret = OB_SUCCESS; if (out_val < static_cast(0)) { ret = OB_DATA_OUT_OF_RANGE; out_val = static_cast(0); } return ret; } // explicit for number check. template <> OB_INLINE int numeric_negative_check(number::ObNumber &out_val) { int ret = OB_SUCCESS; if (out_val.is_negative()) { ret = OB_DATA_OUT_OF_RANGE; out_val.set_zero(); } return ret; } // check upper limit only. template OB_INLINE int numeric_upper_check(const InType in_val, const OutType max_out_val, OutType &out_val) { int ret = OB_SUCCESS; if (in_val > static_cast(max_out_val)) { ret = OB_DATA_OUT_OF_RANGE; out_val = max_out_val; } return ret; } template OB_INLINE int int_range_check(const ObObjType out_type, const InType in_val, int64_t &out_val) { return numeric_range_check(in_val, INT_MIN_VAL[out_type], INT_MAX_VAL[out_type], out_val); } template OB_INLINE int int_upper_check(const ObObjType out_type, InType in_val, int64_t &out_val) { return numeric_upper_check(in_val, INT_MAX_VAL[out_type], out_val); } OB_INLINE int uint_upper_check(const ObObjType out_type, uint64_t &out_val) { return numeric_upper_check(out_val, UINT_MAX_VAL[out_type], out_val); } template OB_INLINE int uint_range_check(const ObObjType out_type, const InType in_val, uint64_t &out_val) { return numeric_range_check(in_val, static_cast(0), UINT_MAX_VAL[out_type], out_val); } template OB_INLINE int real_range_check(const ObObjType out_type, const InType in_val, OutType &out_val) { return numeric_range_check(in_val, static_cast(REAL_MIN_VAL[out_type]), static_cast(REAL_MAX_VAL[out_type]), out_val); } template int real_range_check(const ObAccuracy &accuracy, Type &value) { int ret = OB_SUCCESS; const ObPrecision precision = accuracy.get_precision(); const ObScale scale = accuracy.get_scale(); if (OB_LIKELY(precision > 0) && OB_LIKELY(scale >= 0) && OB_LIKELY(precision >= scale)) { Type integer_part = static_cast(pow(10.0, static_cast(precision - scale))); Type decimal_part = static_cast(pow(10.0, static_cast(scale))); Type max_value = integer_part - 1 / decimal_part; Type min_value = -max_value; if (OB_FAIL(numeric_range_check(value, min_value, max_value, value))) { } else { value = static_cast(round(value * decimal_part) / decimal_part); } } return ret; } #define BOUND_INFO_START_POS 18 template ObPrecision get_precision_for_integer(T value) { static const uint64_t bound_info[] = { INT64_MAX + 1ULL, 999999999999999999ULL, 99999999999999999ULL, 9999999999999999ULL, 999999999999999ULL, 99999999999999ULL, 9999999999999ULL, 999999999999ULL, 99999999999ULL, 9999999999ULL, 999999999ULL, 99999999ULL, 9999999ULL, 999999ULL, 99999ULL, 9999ULL, 999ULL, 99ULL, 9ULL, 99ULL, 999ULL, 9999ULL, 99999ULL, 999999ULL, 9999999ULL, 99999999ULL, 999999999ULL, 9999999999ULL, 99999999999ULL, 999999999999ULL, 9999999999999ULL, 99999999999999ULL, 999999999999999ULL, 9999999999999999ULL, 99999999999999999ULL, 999999999999999999ULL, 9999999999999999999ULL, UINT64_MAX, }; int64_t flag = std::less()(value, 0) ? -1 : 1; uint64_t abs_value = value * flag; const uint64_t *iter = bound_info + BOUND_INFO_START_POS; while(abs_value > *iter) { iter += flag; } // *(iter - 1) < abs <= *iter return static_cast((iter - (bound_info + BOUND_INFO_START_POS)) * flag + 1); } //////////////////////////////////////////////////////////////// // Int -> XXX static const double ROUND_DOUBLE = 0.5; static int int_int(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; ObPrecision res_precision = -1; if (OB_UNLIKELY(ObIntTC != in.get_type_class() || ObIntTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else { int64_t value = in.get_int(); if (in.get_type() > expect_type && CAST_FAIL(int_range_check(expect_type, value, value))) { } else { out.set_int(expect_type, value); res_precision = get_precision_for_integer(value); } } SET_RES_ACCURACY(res_precision, DEFAULT_SCALE_FOR_INTEGER, DEFAULT_LENGTH_FOR_NUMERIC); return ret; } static int int_uint(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; ObPrecision res_precision = -1; if (OB_UNLIKELY(ObIntTC != in.get_type_class() || ObUIntTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else if (CM_SKIP_CAST_INT_UINT(cast_mode)) { out = in; res_precision = get_precision_for_integer(out.get_uint64()); } else { uint64_t value = static_cast(in.get_int()); if (CM_NEED_RANGE_CHECK(cast_mode) && CAST_FAIL(uint_range_check(expect_type, in.get_int(), value))) { } else { out.set_uint(expect_type, value); res_precision = get_precision_for_integer(out.get_uint64()); } } SET_RES_ACCURACY(res_precision, DEFAULT_SCALE_FOR_INTEGER, DEFAULT_LENGTH_FOR_NUMERIC); return ret; } static int int_float(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; if (OB_UNLIKELY(ObIntTC != in.get_type_class() || ObFloatTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else { float value = static_cast(in.get_int()); if (ObUFloatType == expect_type && CAST_FAIL(numeric_negative_check(value))) { } else { out.set_float(expect_type, value); } } SET_RES_ACCURACY(PRECISION_UNKNOWN_YET, SCALE_UNKNOWN_YET, LENGTH_UNKNOWN_YET); return ret; } static int int_double(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; if (OB_UNLIKELY(ObIntTC != in.get_type_class() || ObDoubleTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else { double value = static_cast(in.get_int()); if (ObUDoubleType == expect_type && CAST_FAIL(numeric_negative_check(value))) { } else { out.set_double(expect_type, value); } } SET_RES_ACCURACY(PRECISION_UNKNOWN_YET, SCALE_UNKNOWN_YET, LENGTH_UNKNOWN_YET); return ret; } static int int_number(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; ObPrecision res_precision = -1; if (OB_UNLIKELY(ObIntTC != in.get_type_class() || ObNumberTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else { int64_t value = in.get_int(); number::ObNumber nmb; if (ObUNumberType == expect_type && CAST_FAIL(numeric_negative_check(value))) { } else if (OB_FAIL(nmb.from(value, params))) { } else { out.set_number(expect_type, nmb); res_precision = get_precision_for_integer(in.get_int()); } } SET_RES_ACCURACY(res_precision, DEFAULT_SCALE_FOR_INTEGER, DEFAULT_LENGTH_FOR_NUMERIC); return ret; } static int int_datetime(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; if (OB_UNLIKELY(ObIntTC != 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)); } else { const ObTimeZoneInfo *tz_info = (ObTimestampType == expect_type) ? params.tz_info_ : NULL; int64_t value = 0; if (in.get_int() < 0) { CAST_FAIL(OB_INVALID_DATE_FORMAT); } else if (CAST_FAIL(ObTimeConverter::int_to_datetime(in.get_int(), 0, tz_info, value))) { } else { SET_RES_DATETIME(out); } } SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, MIN_SCALE_FOR_TEMPORAL, DEFAULT_LENGTH_FOR_TEMPORAL); return ret; } static int int_date(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; if (OB_UNLIKELY(ObIntTC != in.get_type_class() || ObDateTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else { int32_t value = 0; if (CAST_FAIL(ObTimeConverter::int_to_date(in.get_int(), value))) { } else { SET_RES_DATE(out); } } SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, DEFAULT_SCALE_FOR_DATE, DEFAULT_LENGTH_FOR_TEMPORAL); return ret; } static int int_time(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; if (OB_UNLIKELY(ObIntTC != in.get_type_class() || ObTimeTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else { int64_t value = 0; if (CAST_FAIL(ObTimeConverter::int_to_time(in.get_int(), value))) { } else { SET_RES_TIME(out); } } SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, MIN_SCALE_FOR_TEMPORAL, DEFAULT_LENGTH_FOR_TEMPORAL); return ret; } static int int_year(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; if (OB_UNLIKELY(ObIntTC != in.get_type_class() || ObYearTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else { uint8_t value = 0; if (CAST_FAIL(ObTimeConverter::int_to_year(in.get_int(), value))) { } else { SET_RES_YEAR(out); } } SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, DEFAULT_SCALE_FOR_YEAR, DEFAULT_LENGTH_FOR_TEMPORAL); return ret; } static int int_string(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; ObLength res_length = -1; if (OB_UNLIKELY(ObIntTC != in.get_type_class() || (ObStringTC != ob_obj_type_class(expect_type) && ObTextTC != ob_obj_type_class(expect_type)))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else { char buf[OB_CAST_TO_VARCHAR_MAX_LENGTH]; MEMSET(buf, 0, OB_CAST_TO_VARCHAR_MAX_LENGTH); ObString str(sizeof(buf), 0, buf); if (OB_FAIL(print_varchar(str, "%ld", in.get_int()))) { } else { ret = copy_string(params, expect_type, str, out); if (OB_SUCC(ret)) { res_length = static_cast(out.get_string_len()); } } } SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_STRING, DEFAULT_SCALE_FOR_STRING, res_length); UNUSED(cast_mode); return ret; } //////////////////////////////////////////////////////////////// // UInt -> XXX static int uint_int(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; ObPrecision res_precision = -1; if (OB_UNLIKELY(ObUIntTC != in.get_type_class() || ObIntTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else if (CM_IS_EXTERNAL_CALL(cast_mode) && CM_SKIP_CAST_INT_UINT(cast_mode)) { out = in; res_precision = get_precision_for_integer(out.get_int()); } else { int64_t value = static_cast(in.get_uint64()); if (CM_NEED_RANGE_CHECK(cast_mode) && CAST_FAIL(int_upper_check(expect_type, in.get_uint64(), value))) { } else { out.set_int(expect_type, value); res_precision = get_precision_for_integer(value); } } SET_RES_ACCURACY(res_precision, DEFAULT_SCALE_FOR_INTEGER, DEFAULT_LENGTH_FOR_NUMERIC); return ret; } static int uint_uint(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; ObPrecision res_precision = -1; if (OB_UNLIKELY(ObUIntTC != in.get_type_class() || ObUIntTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else { uint64_t value = in.get_uint64(); if (in.get_type() > expect_type && CAST_FAIL(uint_upper_check(expect_type, value))) { } else { out.set_uint(expect_type, value); res_precision = get_precision_for_integer(value); } } SET_RES_ACCURACY(res_precision, DEFAULT_SCALE_FOR_INTEGER, DEFAULT_LENGTH_FOR_NUMERIC); return ret; } static int uint_float(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; if (OB_UNLIKELY(ObUIntTC != in.get_type_class() || ObFloatTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else { out.set_float(expect_type, static_cast(in.get_uint64())); } UNUSED(cast_mode); SET_RES_ACCURACY(PRECISION_UNKNOWN_YET, SCALE_UNKNOWN_YET, LENGTH_UNKNOWN_YET); return ret; } static int uint_double(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; if (OB_UNLIKELY(ObUIntTC != in.get_type_class() || ObDoubleTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else { out.set_double(expect_type, static_cast(in.get_uint64())); } UNUSED(cast_mode); SET_RES_ACCURACY(PRECISION_UNKNOWN_YET, SCALE_UNKNOWN_YET, LENGTH_UNKNOWN_YET); return ret; } static int uint_number(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; number::ObNumber nmb; ObPrecision res_precision = -1; if (OB_UNLIKELY(ObUIntTC != in.get_type_class() || ObNumberTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else if (OB_FAIL(nmb.from(in.get_uint64(), params))) { } else { out.set_number(expect_type, nmb); res_precision = get_precision_for_integer(in.get_uint64()); } UNUSED(cast_mode); SET_RES_ACCURACY(res_precision, DEFAULT_SCALE_FOR_INTEGER, DEFAULT_LENGTH_FOR_NUMERIC); return ret; } static int uint_datetime(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; ObObj int64; if (OB_UNLIKELY(ObUIntTC != 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)); } else if (OB_FAIL(uint_int(ObIntType, params, in, int64, CM_UNSET_NO_CAST_INT_UINT(cast_mode)))) { } else if (OB_FAIL(int_datetime(expect_type, params, int64, out, cast_mode))) { } //has set the accuracy in prev int_datetime call return ret; } static int uint_date(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; ObObj int64; if (OB_UNLIKELY(ObUIntTC != in.get_type_class() || ObDateTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else if (OB_FAIL(uint_int(ObIntType, params, in, int64, CM_UNSET_NO_CAST_INT_UINT(cast_mode)))) { } else if (OB_FAIL(int_date(expect_type, params, int64, out, cast_mode))) { } SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, DEFAULT_SCALE_FOR_DATE, DEFAULT_LENGTH_FOR_TEMPORAL); return ret; } static int uint_time(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; ObObj int64; if (OB_UNLIKELY(ObUIntTC != in.get_type_class() || ObTimeTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else if (OB_FAIL(uint_int(ObIntType, params, in, int64, CM_UNSET_NO_CAST_INT_UINT(cast_mode)))) { } else if (OB_FAIL(int_time(expect_type, params, int64, out, cast_mode))) { } //accuracy has been set in prev int_time call return ret; } static int uint_year(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; ObObj int64; if (OB_UNLIKELY(ObUIntTC != in.get_type_class() || ObYearTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else if (OB_FAIL(uint_int(ObIntType, params, in, int64, CM_UNSET_NO_CAST_INT_UINT(cast_mode)))) { } else if (OB_FAIL(int_year(expect_type, params, int64, out, cast_mode))) { } SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, DEFAULT_SCALE_FOR_YEAR, DEFAULT_LENGTH_FOR_TEMPORAL); return ret; } static int uint_string(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; char buf[OB_CAST_TO_VARCHAR_MAX_LENGTH]; MEMSET(buf, 0, OB_CAST_TO_VARCHAR_MAX_LENGTH); ObLength res_length = -1; ObString str(sizeof(buf), 0, buf); if (OB_UNLIKELY(ObUIntTC != in.get_type_class() || (ObStringTC != ob_obj_type_class(expect_type) && ObTextTC != ob_obj_type_class(expect_type)))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else if (OB_FAIL(print_varchar(str, "%lu", in.get_uint64()))) { } else { ret = copy_string(params, expect_type, str, out); if (OB_SUCC(ret)) { res_length = static_cast(out.get_string_len()); } } UNUSED(cast_mode); SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_STRING, DEFAULT_SCALE_FOR_STRING, res_length); return ret; } //////////////////////////////////////////////////////////////// // Float -> XXX // directly stacit cast from float to int or uint: // case 1: float = -99999896450971467776.000000, int64 = -9223372036854775808, uint64 = 9223372036854775808. // case 2: float = 99999896450971467776.000000, int64 = -9223372036854775808, uint64 = 0. // case 3: float = -99999904.000000, int64 = -99999904, uint64 = 18446744073609551712. // case 4: float = 99999904.000000, int64 = 99999904, uint64 = 99999904. // we can see that if float value is out of range of int or uint value, the casted int or uint // value can't be used to compare with INT64_MAX and so on, see case 2. // so we should use float value to determine weither it is in range of int or uint. static int float_int(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; int64_t value = 0; ObPrecision res_precision = -1; if (OB_UNLIKELY(ObFloatTC != in.get_type_class() || ObIntTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else { if (in.get_float() < 0) { value = static_cast(in.get_float() - ROUND_DOUBLE); } else if (in.get_float() > 0) { value = static_cast(in.get_float() + ROUND_DOUBLE); } else { value = static_cast(in.get_float()); } if (CAST_FAIL(int_range_check(expect_type, in.get_float(), value))) { } else { out.set_int(expect_type, value); } if (OB_SUCC(ret)) { res_precision = get_precision_for_integer(value); } } SET_RES_ACCURACY(res_precision, DEFAULT_SCALE_FOR_INTEGER, DEFAULT_LENGTH_FOR_NUMERIC); return ret; } static int float_uint(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; uint64_t value = 0; ObPrecision res_precision = -1; if (OB_UNLIKELY(ObFloatTC != in.get_type_class() || ObUIntTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else { if (in.get_float() < 0) { value = static_cast(in.get_float() - ROUND_DOUBLE); } else if (in.get_float() > 0) { value = static_cast(in.get_float() + ROUND_DOUBLE); } else { value = static_cast(in.get_float()); } if (CM_NEED_RANGE_CHECK(cast_mode) && CAST_FAIL(uint_range_check(expect_type, in.get_float(), value))) { } else { out.set_uint(expect_type, value); } if (OB_SUCC(ret)) { res_precision = get_precision_for_integer(value); } } SET_RES_ACCURACY(res_precision, DEFAULT_SCALE_FOR_INTEGER, DEFAULT_LENGTH_FOR_NUMERIC); return ret; } static int float_float(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; float value = in.get_float(); if (OB_UNLIKELY(ObFloatTC != in.get_type_class() || ObFloatTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else if (ObUFloatType == expect_type && CAST_FAIL(numeric_negative_check(value))) { } else { out.set_float(expect_type, value); } SET_RES_ACCURACY(PRECISION_UNKNOWN_YET, SCALE_UNKNOWN_YET, LENGTH_UNKNOWN_YET); return ret; } static int float_double(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; double value = static_cast(in.get_float()); if (OB_UNLIKELY(ObFloatTC != in.get_type_class() || ObDoubleTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else if (ObUDoubleType == expect_type && CAST_FAIL(numeric_negative_check(value))) { } else { out.set_double(expect_type, value); } SET_RES_ACCURACY(PRECISION_UNKNOWN_YET, SCALE_UNKNOWN_YET, LENGTH_UNKNOWN_YET); return ret; } static int float_number(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; float value = in.get_float(); ObPrecision res_precision = -1; ObScale res_scale = -1; if (OB_UNLIKELY(ObFloatTC != in.get_type_class() || ObNumberTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else if (ObUNumberType == expect_type && CAST_FAIL(numeric_negative_check(value))) { } else { char buf[MAX_FLOAT_PRINT_SIZE]; MEMSET(buf, 0, MAX_FLOAT_PRINT_SIZE); snprintf(buf, MAX_FLOAT_PRINT_SIZE, "%f", value); number::ObNumber nmb; if (OB_FAIL(nmb.from(buf, params, &res_precision, &res_scale))) { } else { out.set_number(expect_type, nmb); } } SET_RES_ACCURACY(res_precision, res_scale, DEFAULT_LENGTH_FOR_NUMERIC); return ret; } static int double_datetime(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode); static int float_datetime(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; ObObj dbl; if (OB_UNLIKELY(ObFloatTC != 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)); } else if (OB_FAIL(float_double(ObDoubleType, params, in, dbl, cast_mode))) { } else if (OB_FAIL(double_datetime(expect_type, params, dbl, out, cast_mode))) { } //has set accuracy in prev double_datetime call return ret; } static int double_date(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode); static int float_date(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; ObObj dbl; if (OB_UNLIKELY(ObFloatTC != in.get_type_class() || ObDateTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else if (OB_FAIL(float_double(ObDoubleType, params, in, dbl, cast_mode))) { } else if (OB_FAIL(double_date(expect_type, params, dbl, out, cast_mode))) { } //has set accuracy in prev double_date call return ret; } static int double_time(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode); static int float_time(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; ObObj dbl; if (OB_UNLIKELY(ObFloatTC != in.get_type_class() || ObTimeTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else if (OB_FAIL(float_double(ObDoubleType, params, in, dbl, cast_mode))) { } else if (OB_FAIL(double_time(expect_type, params, dbl, out, cast_mode))) { } //has set accuracy in prev double_time call return ret; } static int float_string(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; char buf[OB_CAST_TO_VARCHAR_MAX_LENGTH]; MEMSET(buf, 0, OB_CAST_TO_VARCHAR_MAX_LENGTH); ObScale scale = in.get_scale(); int64_t length = 0; ObLength res_length = -1; if (OB_UNLIKELY(ObFloatTC != in.get_type_class() || (ObStringTC != ob_obj_type_class(expect_type) && ObTextTC != ob_obj_type_class(expect_type)))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else { if (0 <= scale) { length = ob_fcvt(in.get_float(), scale, sizeof(buf) - 1, buf, NULL); } else { length = ob_gcvt_opt(in.get_float(), OB_GCVT_ARG_FLOAT, (int)sizeof(buf) - 1, buf, NULL, lib::is_oracle_mode()); } ObString str(sizeof(buf), static_cast(length), buf); if (OB_FAIL(copy_string(params, expect_type, str, out))) { } else { res_length = static_cast(out.get_string_len()); } } UNUSED(cast_mode); SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_STRING, DEFAULT_SCALE_FOR_STRING, res_length); return ret; } //////////////////////////////////////////////////////////////// // Double -> XXX static int double_int(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; int64_t value = 0; ObPrecision res_precision = -1; if (OB_UNLIKELY(ObDoubleTC != in.get_type_class() || ObIntTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else { if (in.get_double() < 0) { value = static_cast(in.get_double() - ROUND_DOUBLE); } else if (in.get_double() > 0) { value = static_cast(in.get_double() + ROUND_DOUBLE); } else { value = static_cast(in.get_double()); } if (CAST_FAIL(int_range_check(expect_type, in.get_double(), value))) { } else { out.set_int(expect_type, value); } if (OB_SUCC(ret)) { res_precision = get_precision_for_integer(value); } } SET_RES_ACCURACY(res_precision, DEFAULT_SCALE_FOR_INTEGER, DEFAULT_LENGTH_FOR_NUMERIC); return ret; } static int double_uint(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; uint64_t value = 0; ObPrecision res_precision = -1; if (OB_UNLIKELY(ObDoubleTC != in.get_type_class() || ObUIntTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else { if (in.get_double() < 0) { value = static_cast(in.get_double() - ROUND_DOUBLE); } else if (in.get_double() > 0) { value = static_cast(in.get_double() + ROUND_DOUBLE); } else { value = static_cast(in.get_double()); } if (CM_NEED_RANGE_CHECK(cast_mode) && CAST_FAIL(uint_range_check(expect_type, in.get_double(), value))) { } else { out.set_uint(expect_type, value); } if (OB_SUCC(ret)) { res_precision = get_precision_for_integer(value); } } SET_RES_ACCURACY(res_precision, DEFAULT_SCALE_FOR_INTEGER, DEFAULT_LENGTH_FOR_NUMERIC); return ret; } static int double_float(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; float value = static_cast(in.get_double()); if (OB_UNLIKELY(ObDoubleTC != in.get_type_class() || ObFloatTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else if (CAST_FAIL(real_range_check(expect_type, in.get_double(), value))) { } else { out.set_float(expect_type, value); } SET_RES_ACCURACY(PRECISION_UNKNOWN_YET, SCALE_UNKNOWN_YET, LENGTH_UNKNOWN_YET); return ret; } static int double_double(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; double value = in.get_double(); if (OB_UNLIKELY(ObDoubleTC != in.get_type_class() || ObDoubleTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else if (ObUDoubleType == expect_type && CAST_FAIL(numeric_negative_check(value))) { } else { out.set_double(expect_type, value); } SET_RES_ACCURACY(PRECISION_UNKNOWN_YET, SCALE_UNKNOWN_YET, LENGTH_UNKNOWN_YET); return ret; } static int double_number(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; double value = in.get_double(); ObPrecision res_precision = -1; ObScale res_scale = -1; if (OB_UNLIKELY(ObDoubleTC != in.get_type_class() || ObNumberTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else if (ObUNumberType == expect_type && CAST_FAIL(numeric_negative_check(value))) { } else { char buf[MAX_DOUBLE_PRINT_SIZE]; MEMSET(buf, 0, MAX_DOUBLE_PRINT_SIZE); snprintf(buf, MAX_DOUBLE_PRINT_SIZE, "%lf", value); number::ObNumber nmb; if (OB_FAIL(nmb.from(buf, params, &res_precision, &res_scale))) { } else { out.set_number(expect_type, nmb); } } SET_RES_ACCURACY(res_precision, res_scale, DEFAULT_LENGTH_FOR_NUMERIC); return ret; } static int double_datetime(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { // double to datetime must cast to string first, then cast string to datetime. // because double 20151016153421.8 may actually 20151016153421.801 in memory, // so we will get '2015-10-16 15:34:21.801' instead of '2015-10-16 15:34:21.8'. // this problem can be resolved by cast double to string using ob_gcvt_opt(). int ret = OB_SUCCESS; ObScale res_scale = -1; if (OB_UNLIKELY(ObDoubleTC != 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)); } else { int64_t value = 0; const ObTimeZoneInfo *tz_info = (ObTimestampType == expect_type) ? params.tz_info_ : NULL; char buf[MAX_DOUBLE_PRINT_SIZE]; MEMSET(buf, 0, MAX_DOUBLE_PRINT_SIZE); int64_t length = ob_gcvt_opt(in.get_double(), OB_GCVT_ARG_DOUBLE, (int)sizeof(buf) - 1, buf, NULL, lib::is_oracle_mode()); ObString str(sizeof(buf), static_cast(length), buf); if (CAST_FAIL(ObTimeConverter::str_to_datetime(str, tz_info, value, &res_scale))) { } else { SET_RES_DATETIME(out); } } SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, res_scale, DEFAULT_LENGTH_FOR_TEMPORAL); return ret; } static int double_date(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { //TODO In datediff,mysql does truncate NOT round //So,we have to revise double 2 int which act as round (right now) to truncation int ret = OB_SUCCESS; ObObj int64; if (OB_UNLIKELY(ObDoubleTC != in.get_type_class() || ObDateTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else if (OB_FAIL(double_int(ObIntType, params, in, int64, cast_mode))) { } else if (OB_FAIL(int_date(expect_type, params, int64, out, cast_mode))) { } SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, DEFAULT_SCALE_FOR_DATE, DEFAULT_LENGTH_FOR_TEMPORAL); return ret; } static int double_time(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { // double to time must cast to string first, then cast string to time. // see comment in double_datetime. int ret = OB_SUCCESS; ObScale res_scale = -1; if (OB_UNLIKELY(ObDoubleTC != in.get_type_class() || ObTimeTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else { int64_t value = 0; char buf[MAX_DOUBLE_PRINT_SIZE]; MEMSET(buf, 0, MAX_DOUBLE_PRINT_SIZE); int64_t length = ob_gcvt_opt(in.get_double(), OB_GCVT_ARG_DOUBLE, (int)sizeof(buf) - 1, buf, NULL, lib::is_oracle_mode()); ObString str(sizeof(buf), static_cast(length), buf); if (CAST_FAIL(ObTimeConverter::str_to_time(str, value, &res_scale))) { } else { SET_RES_TIME(out); } } SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, res_scale, DEFAULT_LENGTH_FOR_TEMPORAL); return ret; } static int double_string(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; ObLength res_length = -1; if (OB_UNLIKELY(ObDoubleTC != in.get_type_class() || (ObStringTC != ob_obj_type_class(expect_type) && ObTextTC != ob_obj_type_class(expect_type)))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else { char buf[OB_CAST_TO_VARCHAR_MAX_LENGTH]; MEMSET(buf, 0, OB_CAST_TO_VARCHAR_MAX_LENGTH); ObScale scale = in.get_scale(); int64_t length = 0; if (0 <= scale) { length = ob_fcvt(in.get_double(), scale, sizeof(buf) - 1, buf, NULL); } else { length = ob_gcvt_opt(in.get_double(), OB_GCVT_ARG_DOUBLE, (int)sizeof(buf) - 1, buf, NULL, lib::is_oracle_mode()); } ObString str(sizeof(buf), static_cast(length), buf); if (OB_FAIL(copy_string(params, expect_type, str, out))) { } else { res_length = static_cast(out.get_string_len()); } } SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_STRING, DEFAULT_SCALE_FOR_STRING, res_length); UNUSED(cast_mode); return ret; } //////////////////////////////////////////////////////////////// // Number -> XXX static int string_int(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode); static int number_int(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; ObPrecision res_precision = -1; if (OB_UNLIKELY(ObNumberTC != in.get_type_class() || ObIntTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else { number::ObNumber nmb = in.get_number(); const char *value = nmb.format(); if (OB_ISNULL(value)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("null pointer", K(ret), K(value)); } else { ObObj from; from.set_varchar(value, static_cast(strlen(value))); ret = string_int(expect_type, params, from, out, cast_mode); } } if (OB_SUCC(ret)) { res_precision = get_precision_for_integer(out.get_int()); } SET_RES_ACCURACY(res_precision, DEFAULT_SCALE_FOR_INTEGER, DEFAULT_LENGTH_FOR_NUMERIC); return ret; } static int string_uint(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode); static int number_uint(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; ObPrecision res_precision = -1; if (OB_UNLIKELY(ObNumberTC != in.get_type_class() || ObUIntTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else { number::ObNumber nmb = in.get_number(); const char *value = nmb.format(); if (OB_ISNULL(value)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("null pointer", K(ret), K(value)); } else { ObObj from; from.set_varchar(value, static_cast(strlen(value))); ret = string_uint(expect_type, params, from, out, cast_mode); } } if (OB_SUCC(ret)) { res_precision = get_precision_for_integer(out.get_uint64()); } SET_RES_ACCURACY(res_precision, DEFAULT_SCALE_FOR_INTEGER, DEFAULT_LENGTH_FOR_NUMERIC); return ret; } static int string_float(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode); static int number_float(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; if (OB_UNLIKELY(ObNumberTC != in.get_type_class() || ObFloatTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else { const char *value = in.get_number().format(); if (OB_ISNULL(value)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("null pointer", K(ret), K(value)); } else { ObObj from; from.set_varchar(value, static_cast(strlen(value))); ret = string_float(expect_type, params, from, out, cast_mode); } } SET_RES_ACCURACY(PRECISION_UNKNOWN_YET, SCALE_UNKNOWN_YET, LENGTH_UNKNOWN_YET); return ret; } static int string_double(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode); static int number_double(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; if (OB_UNLIKELY(ObNumberTC != in.get_type_class() || ObDoubleTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else { const char *value = in.get_number().format(); if (OB_ISNULL(value)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("null pointer", K(ret), K(value)); } else { ObObj from; from.set_varchar(value, static_cast(strlen(value))); ret = string_double(expect_type, params, from, out, cast_mode); } } SET_RES_ACCURACY(PRECISION_UNKNOWN_YET, SCALE_UNKNOWN_YET, LENGTH_UNKNOWN_YET); return ret; } static int number_number(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; if (OB_UNLIKELY(ObNumberTC != in.get_type_class() || ObNumberTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else { number::ObNumber nmb = in.get_number(); number::ObNumber value; if (OB_FAIL(value.from(nmb, params))) { } else if (ObUNumberType == expect_type && CAST_FAIL(numeric_negative_check(value))) { } else { out.set_number(expect_type, value); } } //todo maybe we can do some dirty work to get better result. //for now, just set it to unknown.... SET_RES_ACCURACY(PRECISION_UNKNOWN_YET, SCALE_UNKNOWN_YET, LENGTH_UNKNOWN_YET); return ret; } static int string_datetime(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode); static int number_datetime(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; 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)); } else { const ObTimeZoneInfo *tz_info = (ObTimestampType == expect_type) ? params.tz_info_ : NULL; int64_t value = 0; int64_t int_part = 0; int64_t dec_part = 0; if (in.get_number().is_negative()) { CAST_FAIL(OB_INVALID_DATE_FORMAT); } else if ((ObTimestampType == expect_type && in.get_number().is_decimal())) { CAST_FAIL(OB_INVALID_DATE_FORMAT); } else if (!in.get_number().is_int_parts_valid_int64(int_part,dec_part)) { LOG_WARN("failed to convert number to int"); } else if (CAST_FAIL(ObTimeConverter::int_to_datetime(int_part, dec_part, tz_info, value))) { } else { SET_RES_DATETIME(out); } } SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, MIN_SCALE_FOR_TEMPORAL, DEFAULT_LENGTH_FOR_TEMPORAL); return ret; } static int string_date(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode); static int number_date(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; if (OB_UNLIKELY(ObNumberTC != in.get_type_class() || ObDateTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else { const char *value = in.get_number().format(); if (OB_ISNULL(value)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("null pointer", K(ret), K(value)); } else { ObObj from; from.set_varchar(value, static_cast(strlen(value))); ret = string_date(expect_type, params, from, out, cast_mode); } } SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, DEFAULT_SCALE_FOR_DATE, DEFAULT_LENGTH_FOR_TEMPORAL); return ret; } static int string_time(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode); static int number_time(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; if (OB_UNLIKELY(ObNumberTC != in.get_type_class() || ObTimeTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else { const char *value = in.get_number().format(); if (OB_ISNULL(value)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("null pointer", K(ret), K(value)); } else { ObObj from; from.set_varchar(value, static_cast(strlen(value))); ret = string_time(expect_type, params, from, out, cast_mode); } } //has set accuracy in prev string_time call return ret; } static int string_year(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode); static int number_year(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; if (OB_UNLIKELY(ObNumberTC != in.get_type_class() || ObYearTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else { const char *value = in.get_number().format(); if (OB_ISNULL(value)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("null pointer", K(ret), K(value)); } else { ObObj from; from.set_varchar(value, static_cast(strlen(value))); ret = string_year(expect_type, params, from, out, cast_mode); } } SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, DEFAULT_SCALE_FOR_YEAR, DEFAULT_LENGTH_FOR_TEMPORAL); return ret; } static int number_string(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; char buf[OB_CAST_TO_VARCHAR_MAX_LENGTH]; MEMSET(buf, 0, OB_CAST_TO_VARCHAR_MAX_LENGTH); int64_t len = 0; ObLength res_length = -1; if (OB_UNLIKELY(ObNumberTC != in.get_type_class() || (ObStringTC != ob_obj_type_class(expect_type) && ObTextTC != ob_obj_type_class(expect_type)))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else if (OB_SUCC(in.get_number().format(buf, sizeof(buf), len, in.get_scale()))) { ret = copy_string(params, expect_type, buf, len, out); if (OB_SUCC(ret)) { res_length = static_cast(out.get_string_len()); } } UNUSED(cast_mode); SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_STRING, DEFAULT_SCALE_FOR_STRING, res_length); return ret; } //////////////////////////////////////////////////////////// // Datetime -> XXX static int datetime_int(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; ObPrecision res_precision = -1; if (OB_UNLIKELY(ObDateTimeTC != in.get_type_class() || ObIntTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else { const ObTimeZoneInfo *tz_info = (ObTimestampType == in.get_type()) ? params.tz_info_ : NULL; int64_t value = 0; if (OB_FAIL(ObTimeConverter::datetime_to_int(in.get_datetime(), tz_info, value))) { } else if (expect_type < ObIntType && CAST_FAIL(int_range_check(expect_type, value, value))) { } else { out.set_int(expect_type, value); res_precision = get_precision_for_integer(value); } } SET_RES_ACCURACY(res_precision, DEFAULT_SCALE_FOR_INTEGER, DEFAULT_LENGTH_FOR_NUMERIC); return ret; } static int datetime_uint(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; ObPrecision res_precision = -1; if (OB_UNLIKELY(ObDateTimeTC != in.get_type_class() || ObUIntTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else { const ObTimeZoneInfo *tz_info = (ObTimestampType == in.get_type()) ? params.tz_info_ : NULL; int64_t int64 = 0; if (OB_FAIL(ObTimeConverter::datetime_to_int(in.get_datetime(), tz_info, int64))) { } else { uint64_t value = static_cast(int64); if (expect_type < ObUInt64Type && CAST_FAIL(uint_range_check(expect_type, int64, value))) { } else { out.set_uint(expect_type, value); res_precision = get_precision_for_integer(value); } } } SET_RES_ACCURACY(res_precision, DEFAULT_SCALE_FOR_INTEGER, DEFAULT_LENGTH_FOR_NUMERIC); return ret; } static int datetime_float(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; if (OB_UNLIKELY(ObDateTimeTC != in.get_type_class() || ObFloatTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else { const ObTimeZoneInfo *tz_info = (ObTimestampType == in.get_type()) ? params.tz_info_ : NULL; double value = 0.0; if (OB_FAIL(ObTimeConverter::datetime_to_double(in.get_datetime(), tz_info, value))) { } else { // if datetime_to_double return OB_SUCCESS, double value must be in (0, INT64_MAX), // so we can static_cast to float without range check. out.set_float(expect_type, static_cast(value)); } } SET_RES_ACCURACY(PRECISION_UNKNOWN_YET, SCALE_UNKNOWN_YET, LENGTH_UNKNOWN_YET); UNUSED(cast_mode); return ret; } static int datetime_double(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; if (OB_UNLIKELY(ObDateTimeTC != in.get_type_class() || ObDoubleTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else { const ObTimeZoneInfo *tz_info = (ObTimestampType == in.get_type()) ? params.tz_info_ : NULL; double value = 0.0; if (OB_FAIL(ObTimeConverter::datetime_to_double(in.get_datetime(), tz_info, value))) { } else { out.set_double(expect_type, value); } } SET_RES_ACCURACY(PRECISION_UNKNOWN_YET, SCALE_UNKNOWN_YET, LENGTH_UNKNOWN_YET); UNUSED(cast_mode); return ret; } static int datetime_number(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; ObPrecision res_precision = -1; ObScale res_scale = -1; if (OB_UNLIKELY(ObDateTimeTC != in.get_type_class() || ObNumberTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else { const ObTimeZoneInfo *tz_info = (ObTimestampType == in.get_type()) ? params.tz_info_ : NULL; char buf[OB_CAST_TO_VARCHAR_MAX_LENGTH]; MEMSET(buf, 0, OB_CAST_TO_VARCHAR_MAX_LENGTH); int64_t len = 0; number::ObNumber value; if (OB_FAIL(ObTimeConverter::datetime_to_str(in.get_datetime(), tz_info, in.get_scale(), buf, sizeof(buf), len, false))) { LOG_WARN("failed to convert datetime to string", K(ret)); } else if (CAST_FAIL(value.from(buf, len, params, &res_precision, &res_scale))) { LOG_WARN("failed to convert string to number", K(ret)); } else { out.set_number(expect_type, value); } } SET_RES_ACCURACY(res_precision, res_scale, DEFAULT_LENGTH_FOR_NUMERIC); return ret; } static int datetime_datetime(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; if (OB_UNLIKELY(ObDateTimeTC != 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)); } else { int64_t value = in.get_datetime(); if (ObDateTimeType == in.get_type() && ObTimestampType == expect_type) { ret = ObTimeConverter::datetime_to_timestamp(in.get_datetime(), params.tz_info_, value); } else if (ObTimestampType == in.get_type() && ObDateTimeType == expect_type) { ret = ObTimeConverter::timestamp_to_datetime(in.get_datetime(), params.tz_info_, value); } if (OB_FAIL(ret)) { } else { out.set_datetime(expect_type, value); } } SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, in.get_scale(), DEFAULT_LENGTH_FOR_TEMPORAL); UNUSED(cast_mode); return ret; } static int datetime_date(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; if (OB_UNLIKELY(ObDateTimeTC != in.get_type_class() || ObDateTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else { const ObTimeZoneInfo *tz_info = (ObTimestampType == in.get_type()) ? params.tz_info_ : NULL; int32_t value = 0; if (OB_FAIL(ObTimeConverter::datetime_to_date(in.get_datetime(), tz_info, value))) { } else { out.set_date(value); } } SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, DEFAULT_SCALE_FOR_DATE, DEFAULT_LENGTH_FOR_TEMPORAL); UNUSED(cast_mode); return ret; } static int datetime_time(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; if (OB_UNLIKELY(ObDateTimeTC != in.get_type_class() || ObTimeTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else { const ObTimeZoneInfo *tz_info = (ObTimestampType == in.get_type()) ? params.tz_info_ : NULL; int64_t value = 0; if (OB_FAIL(ObTimeConverter::datetime_to_time(in.get_datetime(), tz_info, value))) { } else { out.set_time(value); } } SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, in.get_scale(), DEFAULT_LENGTH_FOR_TEMPORAL); UNUSED(cast_mode); return ret; } static int datetime_year(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; if (OB_UNLIKELY(ObDateTimeTC != in.get_type_class() || ObYearTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else { const ObTimeZoneInfo *tz_info = (ObTimestampType == in.get_type()) ? params.tz_info_ : NULL; uint8_t value = 0; if (CAST_FAIL(ObTimeConverter::datetime_to_year(in.get_datetime(), tz_info, value))) { } else { SET_RES_YEAR(out); } } SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, DEFAULT_SCALE_FOR_YEAR, DEFAULT_LENGTH_FOR_TEMPORAL); UNUSED(cast_mode); return ret; } static int datetime_string(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; ObLength res_length = -1; if (OB_UNLIKELY(ObDateTimeTC != in.get_type_class() || (ObStringTC != ob_obj_type_class(expect_type) && ObTextTC != ob_obj_type_class(expect_type)))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else { const ObTimeZoneInfo *tz_info = (ObTimestampType == in.get_type()) ? params.tz_info_ : NULL; char buf[OB_CAST_TO_VARCHAR_MAX_LENGTH]; MEMSET(buf, 0, OB_CAST_TO_VARCHAR_MAX_LENGTH); int64_t len = 0; if (OB_FAIL(ObTimeConverter::datetime_to_str(in.get_datetime(), tz_info, in.get_scale(), buf, sizeof(buf), len))) { LOG_WARN("failed to convert datetime to string", K(ret)); } else { out.set_type(expect_type); ret = copy_string(params, expect_type, buf, len, out); if (OB_SUCC(ret)) { res_length = static_cast(out.get_string_len()); } } } SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_STRING, DEFAULT_SCALE_FOR_STRING, res_length); UNUSED(cast_mode); return ret; } //////////////////////////////////////////////////////////// // Date -> XXX static int date_int(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; int64_t value = 0; ObPrecision res_precision = -1; if (OB_UNLIKELY(ObDateTC != in.get_type_class() || ObIntTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else if (OB_FAIL(ObTimeConverter::date_to_int(in.get_date(), value))) { } else if (expect_type < ObInt32Type && CAST_FAIL(int_range_check(expect_type, value, value))) { } else { out.set_int(expect_type, value); res_precision = get_precision_for_integer(value); } SET_RES_ACCURACY(res_precision, DEFAULT_SCALE_FOR_INTEGER, DEFAULT_LENGTH_FOR_NUMERIC); return ret; } static int date_uint(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; ObPrecision res_precision = -1; int64_t int64 = 0; uint64_t value = 0; if (OB_UNLIKELY(ObDateTC != in.get_type_class() || ObUIntTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else if (OB_FAIL(ObTimeConverter::date_to_int(in.get_date(), int64))) { } else { value = static_cast(int64); if (expect_type < ObUInt32Type && CAST_FAIL(uint_range_check(expect_type, int64, value))) { } else { out.set_uint(expect_type, value); res_precision = get_precision_for_integer(value); } } SET_RES_ACCURACY(res_precision, DEFAULT_SCALE_FOR_INTEGER, DEFAULT_LENGTH_FOR_NUMERIC); return ret; } static int date_float(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; int64_t value = 0; if (OB_UNLIKELY(ObDateTC != in.get_type_class() || ObFloatTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else if (OB_FAIL(ObTimeConverter::date_to_int(in.get_date(), value))) { } else { out.set_float(expect_type, static_cast(value)); } SET_RES_ACCURACY(PRECISION_UNKNOWN_YET, SCALE_UNKNOWN_YET, LENGTH_UNKNOWN_YET); UNUSED(cast_mode); return ret; } static int date_double(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; int64_t value = 0; if (OB_UNLIKELY(ObDateTC != in.get_type_class() || ObDoubleTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else if (OB_FAIL(ObTimeConverter::date_to_int(in.get_date(), value))) { } else { out.set_double(expect_type, static_cast(value)); } SET_RES_ACCURACY(PRECISION_UNKNOWN_YET, SCALE_UNKNOWN_YET, LENGTH_UNKNOWN_YET); UNUSED(cast_mode); return ret; } static int date_number(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; ObObj obj_int; if (OB_UNLIKELY(ObDateTC != in.get_type_class() || ObNumberTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else if (OB_FAIL(date_int(ObIntType, params, in, obj_int, cast_mode))) { } else if (OB_FAIL(int_number(expect_type, params, obj_int, out, cast_mode))) { } //has set accuracy in prev int_number return ret; } static int date_datetime(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; if (OB_UNLIKELY(ObDateTC != 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)); } else { const ObTimeZoneInfo *tz_info = (ObTimestampType == expect_type) ? params.tz_info_ : NULL; int64_t value = 0; if (OB_FAIL(ObTimeConverter::date_to_datetime(in.get_date(), tz_info, value))) { } else { out.set_datetime(expect_type, value); } } SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, MIN_SCALE_FOR_TEMPORAL, DEFAULT_LENGTH_FOR_TEMPORAL); UNUSED(cast_mode); return ret; } static int date_time(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; if (OB_UNLIKELY(ObDateTC != in.get_type_class() || ObTimeTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else { out.set_time(ObTimeConverter::ZERO_TIME); } SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, MIN_SCALE_FOR_TEMPORAL, DEFAULT_LENGTH_FOR_TEMPORAL); UNUSED(cast_mode); return OB_SUCCESS; } static int date_year(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; uint8_t value = 0; if (OB_UNLIKELY(ObDateTC != in.get_type_class() || ObYearTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else if (CAST_FAIL(ObTimeConverter::date_to_year(in.get_date(), value))) { } else { SET_RES_YEAR(out); } SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, DEFAULT_SCALE_FOR_YEAR, DEFAULT_LENGTH_FOR_TEMPORAL); UNUSED(cast_mode); return ret; } static int date_string(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; char buf[OB_CAST_TO_VARCHAR_MAX_LENGTH]; MEMSET(buf, 0, OB_CAST_TO_VARCHAR_MAX_LENGTH); int64_t len = 0; ObLength res_length = -1; if (OB_UNLIKELY(ObDateTC != in.get_type_class() || (ObStringTC != ob_obj_type_class(expect_type) && ObTextTC != ob_obj_type_class(expect_type)))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else if (OB_FAIL(ObTimeConverter::date_to_str(in.get_date(), buf, sizeof(buf), len))) { } else { out.set_type(expect_type); ret = copy_string(params, expect_type, buf, len, out); if (OB_SUCC(ret)) { res_length = static_cast(out.get_string_len()); } } SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_STRING, DEFAULT_SCALE_FOR_STRING, res_length); UNUSED(cast_mode); return ret; } //////////////////////////////////////////////////////////// // Time -> XXX static int time_int(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; int64_t value = 0; ObPrecision res_precision = -1; if (OB_UNLIKELY(ObTimeTC != in.get_type_class() || ObIntTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else if (OB_FAIL(ObTimeConverter::time_to_int(in.get_time(), value))) { } else if (expect_type < ObInt32Type && CAST_FAIL(int_range_check(expect_type, value, value))) { } else { out.set_int(expect_type, value); res_precision = get_precision_for_integer(value); } SET_RES_ACCURACY(res_precision, DEFAULT_SCALE_FOR_INTEGER, DEFAULT_LENGTH_FOR_NUMERIC); return ret; } static int time_uint(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; int64_t int64 = 0; uint64_t value = 0; ObPrecision res_precision = -1; if (OB_UNLIKELY(ObTimeTC != in.get_type_class() || ObUIntTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else if (OB_FAIL(ObTimeConverter::time_to_int(in.get_time(), int64))) { } else { value = static_cast(int64); if (CM_NEED_RANGE_CHECK(cast_mode) && CAST_FAIL(uint_range_check(expect_type, int64, value))) { } else { out.set_uint(expect_type, value); res_precision = get_precision_for_integer(value); } } SET_RES_ACCURACY(res_precision, DEFAULT_SCALE_FOR_INTEGER, DEFAULT_LENGTH_FOR_NUMERIC); return ret; } static int time_float(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; double value = 0.0; if (OB_UNLIKELY(ObTimeTC != in.get_type_class() || ObFloatTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else if (OB_FAIL(ObTimeConverter::time_to_double(in.get_time(), value))) { } else if (ObUFloatType == expect_type && CAST_FAIL(numeric_negative_check(value))) { } else { // if time_to_double return OB_SUCCESS, double value must be in (INT64_MIN, INT64_MAX), // so we can static_cast to float without range check. out.set_float(expect_type, static_cast(value)); } SET_RES_ACCURACY(PRECISION_UNKNOWN_YET, SCALE_UNKNOWN_YET, LENGTH_UNKNOWN_YET); return ret; } static int time_double(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; double value = 0.0; if (OB_UNLIKELY(ObTimeTC != in.get_type_class() || ObDoubleTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else if (OB_FAIL(ObTimeConverter::time_to_double(in.get_time(), value))) { } else if (ObUDoubleType == expect_type && CAST_FAIL(numeric_negative_check(value))) { } else { out.set_double(expect_type, value); } SET_RES_ACCURACY(PRECISION_UNKNOWN_YET, SCALE_UNKNOWN_YET, LENGTH_UNKNOWN_YET); UNUSED(cast_mode); return ret; } static int time_number(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; char buf[OB_CAST_TO_VARCHAR_MAX_LENGTH]; MEMSET(buf, 0, OB_CAST_TO_VARCHAR_MAX_LENGTH); int64_t len = 0; number::ObNumber value; ObPrecision res_precision = -1; ObScale res_scale = -1; if (OB_UNLIKELY(ObTimeTC != in.get_type_class() || ObNumberTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else if (OB_FAIL(ObTimeConverter::time_to_str(in.get_time(), in.get_scale(), buf, sizeof(buf), len, false))) { } else if (CAST_FAIL(value.from(buf, len, params, &res_precision, &res_scale))) { } else { out.set_number(expect_type, value); } SET_RES_ACCURACY(res_precision, res_scale, DEFAULT_LENGTH_FOR_NUMERIC); return ret; } static int time_datetime(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; const ObTimeZoneInfo *tz_info = params.tz_info_; int64_t value = 0; if (OB_UNLIKELY(ObTimeTC != 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)); } else if (OB_FAIL(ObTimeConverter::time_to_datetime(in.get_time(), params.cur_time_, tz_info, value, expect_type))) { } else { out.set_datetime(expect_type, value); } SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, in.get_scale(), DEFAULT_LENGTH_FOR_TEMPORAL); UNUSED(cast_mode); return ret; } static int time_string(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; char buf[OB_CAST_TO_VARCHAR_MAX_LENGTH]; MEMSET(buf, 0, OB_CAST_TO_VARCHAR_MAX_LENGTH); int64_t len = 0; ObLength res_length = -1; if (OB_UNLIKELY(ObTimeTC != in.get_type_class() || (ObStringTC != ob_obj_type_class(expect_type) && ObTextTC != ob_obj_type_class(expect_type)))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else if (OB_FAIL(ObTimeConverter::time_to_str(in.get_time(), in.get_scale(), buf, sizeof(buf), len))) { } else { out.set_type(expect_type); ret = copy_string(params, expect_type, buf, len, out); if (OB_SUCC(ret)) { res_length = static_cast(out.get_string_len()); } } SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_STRING, DEFAULT_SCALE_FOR_STRING, res_length); UNUSED(cast_mode); return ret; } //////////////////////////////////////////////////////////// // Year -> XXX static int year_int(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; int64_t value = 0; ObPrecision res_precision = -1; if (OB_UNLIKELY(ObYearTC != in.get_type_class() || ObIntTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else if (OB_FAIL(ObTimeConverter::year_to_int(in.get_year(), value))) { } else if (expect_type < ObSmallIntType && CAST_FAIL(int_range_check(expect_type, value, value))) { } else { out.set_int(expect_type, value); res_precision = get_precision_for_integer(value); } SET_RES_ACCURACY(res_precision, DEFAULT_SCALE_FOR_INTEGER, DEFAULT_LENGTH_FOR_NUMERIC); return ret; } static int year_uint(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; int64_t int64 = 0; uint64_t value = 0; ObPrecision res_precision = -1; if (OB_UNLIKELY(ObYearTC != in.get_type_class() || ObUIntTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else if (OB_FAIL(ObTimeConverter::year_to_int(in.get_year(), int64))) { } else { value = static_cast(int64); if (expect_type < ObUSmallIntType && CAST_FAIL(uint_range_check(expect_type, int64, value))) { } else { out.set_uint(expect_type, value); res_precision = get_precision_for_integer(value); } } SET_RES_ACCURACY(res_precision, DEFAULT_SCALE_FOR_INTEGER, DEFAULT_LENGTH_FOR_NUMERIC); return ret; } static int year_float(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; int64_t value = 0; if (OB_UNLIKELY(ObYearTC != in.get_type_class() || ObFloatTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else if (OB_FAIL(ObTimeConverter::year_to_int(in.get_year(), value))) { } else { out.set_float(expect_type, static_cast(value)); } SET_RES_ACCURACY(PRECISION_UNKNOWN_YET, SCALE_UNKNOWN_YET, LENGTH_UNKNOWN_YET); UNUSED(cast_mode); return ret; } static int year_double(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; int64_t value = 0; if (OB_UNLIKELY(ObYearTC != in.get_type_class() || ObDoubleTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else if (OB_FAIL(ObTimeConverter::year_to_int(in.get_year(), value))) { } else { out.set_double(expect_type, static_cast(value)); } SET_RES_ACCURACY(PRECISION_UNKNOWN_YET, SCALE_UNKNOWN_YET, LENGTH_UNKNOWN_YET); UNUSED(cast_mode); return ret; } static int year_number(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; ObObj obj_int; if (OB_UNLIKELY(ObYearTC != in.get_type_class() || ObNumberTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else if (OB_FAIL(year_int(ObIntType, params, in, obj_int, cast_mode))) { } else if (OB_FAIL(int_number(expect_type, params, obj_int, out, cast_mode))) { } //has set accuracy in prev int_number return ret; } static int year_string(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; char buf[OB_CAST_TO_VARCHAR_MAX_LENGTH]; MEMSET(buf, 0, OB_CAST_TO_VARCHAR_MAX_LENGTH); int64_t len = 0; ObLength res_length = -1; if (OB_UNLIKELY(ObYearTC != in.get_type_class() || (ObStringTC != ob_obj_type_class(expect_type) && ObTextTC != ob_obj_type_class(expect_type)))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else if (OB_FAIL(ObTimeConverter::year_to_str(in.get_year(), buf, sizeof(buf), len))) { } else { out.set_type(expect_type); ret = copy_string(params, expect_type, buf, len, out); if (OB_SUCC(ret)) { res_length = static_cast(out.get_string_len()); } } SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_STRING, DEFAULT_SCALE_FOR_STRING, res_length); UNUSED(cast_mode); return ret; } //////////////////////////////////////////////////////////// // String -> XXX inline uint64_t hex_to_uint64(const ObString &str) { int32_t N = str.length(); const uint8_t *p = reinterpret_cast(str.ptr()); uint64_t value = 0; if (OB_LIKELY(NULL != p)) { for (int32_t i = 0; i < N; ++i, ++p) { value = value * 256 + *p; } } return value; } static int string_int(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; ObPrecision res_precision = -1; if (OB_UNLIKELY((ObStringTC != in.get_type_class() && ObTextTC != in.get_type_class()) || ObIntTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else { const ObString &str = in.get_string(); int64_t value = 0; if (ObHexStringType == in.get_type()) { value = static_cast(hex_to_uint64(str)); } else { int err = 0; char *endptr = NULL; value = static_cast(ObCharset::strntoullrnd(str.ptr(), str.length(), false, &endptr, &err)); if (ERANGE == err && (INT64_MIN == value || INT64_MAX == value)) { ret = OB_DATA_OUT_OF_RANGE; } else { ret = check_convert_str_err(str.ptr(), endptr, str.length(), err); } } if (CAST_FAIL(ret)) { } else if (expect_type < ObIntType && CAST_FAIL(int_range_check(expect_type, value, value))) { } else { SET_RES_INT(out); } } if (OB_SUCC(ret)) { res_precision = get_precision_for_integer(out.get_int()); } SET_RES_ACCURACY(res_precision, DEFAULT_SCALE_FOR_INTEGER, DEFAULT_LENGTH_FOR_NUMERIC); return ret; } static int string_uint(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; ObPrecision res_precision = -1; if (OB_UNLIKELY((ObStringTC != in.get_type_class() && ObTextTC != in.get_type_class()) || ObUIntTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else { const ObString &str = in.get_string(); uint64_t value = 0; if (ObHexStringType == in.get_type()) { value = hex_to_uint64(str); } else { int err = 0; char *endptr = NULL; value = ObCharset::strntoullrnd(str.ptr(), str.length(), true, &endptr, &err); if (ERANGE == err && (0 == value || UINT64_MAX == value)) { ret = OB_DATA_OUT_OF_RANGE; } else { ret = check_convert_str_err(str.ptr(), endptr, str.length(), err); } } if (CAST_FAIL(ret)) { } else if (expect_type < ObUInt64Type && CM_NEED_RANGE_CHECK(cast_mode) && CAST_FAIL(uint_upper_check(expect_type, value))) { } else { SET_RES_UINT(out); } } if (OB_SUCC(ret)) { res_precision = get_precision_for_integer(out.get_uint64()); } SET_RES_ACCURACY(res_precision, DEFAULT_SCALE_FOR_INTEGER, DEFAULT_LENGTH_FOR_NUMERIC); return ret; } static int string_float(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; ObObj dbl; if (OB_UNLIKELY((ObStringTC != in.get_type_class() && ObTextTC != in.get_type_class()) || ObFloatTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else if (OB_FAIL(string_double(ObDoubleType, params, in, dbl, cast_mode))) { } else if (OB_FAIL(double_float(expect_type, params, dbl, out, cast_mode))) { } //has set accuracy in prev double_float call return ret; } static int string_double(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; if (OB_UNLIKELY((ObStringTC != in.get_type_class() && ObTextTC != in.get_type_class()) || ObDoubleTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else { double value = 0.0; const ObString &str = in.get_string(); if (ObHexStringType == in.get_type()) { value = static_cast(hex_to_uint64(str)); } else { int err = 0; char *endptr = NULL; value = ObCharset::strntod(str.ptr(), str.length(), &endptr, &err); if (EOVERFLOW == err && (-DBL_MAX == value || DBL_MAX == value)) { ret = OB_DATA_OUT_OF_RANGE; } else { if (OB_SUCCESS != (ret = check_convert_str_err(str.ptr(), endptr, str.length(), err))) { ret = OB_ERR_DATA_TRUNCATED; } } } if (CAST_FAIL(ret)) { } else if (ObUDoubleType == expect_type && CAST_FAIL(numeric_negative_check(value))) { } else { SET_RES_DOUBLE(out); } } SET_RES_ACCURACY(PRECISION_UNKNOWN_YET, SCALE_UNKNOWN_YET, LENGTH_UNKNOWN_YET); return ret; } static int string_number(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; ObPrecision res_precision = -1; ObScale res_scale = -1; if (OB_UNLIKELY((ObStringTC != in.get_type_class() && ObTextTC != in.get_type_class()) || ObNumberTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else { const ObString &str = in.get_string(); number::ObNumber value; if (ObHexStringType == in.get_type()) { ret = value.from(hex_to_uint64(str), params); } else if (OB_UNLIKELY(0 == str.length())) { value.set_zero(); ret = OB_ERR_TRUNCATED_WRONG_VALUE_FOR_FIELD; } else { ret = value.from(str.ptr(), str.length(), params, &res_precision, &res_scale); } if (CAST_FAIL(ret)) { } else if (ObUNumberType == expect_type && CAST_FAIL(numeric_negative_check(value))) { } else { out.set_number(expect_type, value); } } SET_RES_ACCURACY(res_precision, res_scale, DEFAULT_LENGTH_FOR_NUMERIC); return ret; } static int string_datetime(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; ObScale res_scale = -1; if (OB_UNLIKELY((ObStringTC != in.get_type_class() && ObTextTC != 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)); } else { const ObTimeZoneInfo *tz_info = (ObTimestampType == expect_type) ? params.tz_info_ : NULL; int64_t value = 0; if (CAST_FAIL(ObTimeConverter::str_to_datetime(in.get_string(), tz_info, value, &res_scale))) { } else { SET_RES_DATETIME(out); } } SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, res_scale, DEFAULT_LENGTH_FOR_TEMPORAL); return ret; } static int string_date(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; int32_t value = 0; if (OB_UNLIKELY((ObStringTC != in.get_type_class() && ObTextTC != in.get_type_class()) || ObDateTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else if (CAST_FAIL(ObTimeConverter::str_to_date(in.get_string(), value))) { } else { SET_RES_DATE(out); } SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, DEFAULT_SCALE_FOR_DATE, DEFAULT_LENGTH_FOR_TEMPORAL); return ret; } static int string_time(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; int64_t value = 0; ObScale res_scale = -1; if (OB_UNLIKELY((ObStringTC != in.get_type_class() && ObTextTC != in.get_type_class()) || ObTimeTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else if (CAST_FAIL(ObTimeConverter::str_to_time(in.get_string(), value, &res_scale))) { } else { SET_RES_TIME(out); } SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, res_scale, DEFAULT_LENGTH_FOR_TEMPORAL); return ret; } static int string_year(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; ObObj int64; if (OB_UNLIKELY((ObStringTC != in.get_type_class() && ObTextTC != in.get_type_class()) || ObYearTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else if (OB_FAIL(string_int(ObIntType, params, in, int64, CM_SET_WARN_ON_FAIL(cast_mode)))) { } else if (CAST_FAIL(int_year(ObYearType, params, int64, out, cast_mode))) { } else if (CAST_FAIL(params.warning_)) { } SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, DEFAULT_SCALE_FOR_YEAR, DEFAULT_LENGTH_FOR_TEMPORAL); return ret; } static int string_string(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; ObLength res_length = -1; if (OB_UNLIKELY((ObStringTC != in.get_type_class() && ObTextTC != in.get_type_class()) || (ObStringTC != ob_obj_type_class(expect_type) && ObTextTC != ob_obj_type_class(expect_type)))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else { ObString str; in.get_string(str); ret = copy_string(params, expect_type, str, out); if (CS_TYPE_INVALID != in.get_collation_type()) { out.set_collation_type(in.get_collation_type()); } } if (OB_SUCC(ret)) { res_length = static_cast(out.get_string_len()); } SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_STRING, DEFAULT_SCALE_FOR_STRING, res_length); UNUSED(cast_mode); return ret; } ObObjCastFunc OB_OBJ_CAST[ObMaxTC][ObMaxTC] = { { /*null -> XXX*/ identity,/*null*/ identity,/*int*/ identity,/*uint*/ identity,/*float*/ identity,/*double*/ identity,/*number*/ identity,/*datetime*/ identity,/*date*/ identity,/*time*/ identity,/*year*/ identity,/*string*/ identity,/*extend*/ identity,/*unknown*/ identity,/*text*/ }, { /*int -> XXX*/ not_support,/*null*/ int_int,/*int*/ int_uint,/*uint*/ int_float,/*float*/ int_double,/*double*/ int_number,/*number*/ int_datetime,/*datetime*/ int_date,/*date*/ int_time,/*time*/ int_year,/*year*/ int_string,/*string*/ not_support,/*extend*/ not_support,/*unknown*/ int_string,/*text*/ }, { /*uint -> XXX*/ not_support,/*null*/ uint_int,/*int*/ uint_uint,/*uint*/ uint_float,/*float*/ uint_double,/*double*/ uint_number,/*number*/ uint_datetime,/*datetime*/ uint_date,/*date*/ uint_time,/*time*/ uint_year,/*year*/ uint_string,/*string*/ not_support,/*extend*/ not_support,/*unknown*/ uint_string,/*text*/ }, { /*float -> XXX*/ not_support,/*null*/ float_int,/*int*/ float_uint,/*uint*/ float_float,/*float*/ float_double,/*double*/ float_number,/*number*/ float_datetime,/*datetime*/ float_date,/*date*/ float_time,/*time*/ not_support,/*year*/ float_string,/*string*/ not_support,/*extend*/ not_support,/*unknown*/ float_string,/*text*/ }, { /*double -> XXX*/ not_support,/*null*/ double_int,/*int*/ double_uint,/*uint*/ double_float,/*float*/ double_double,/*double*/ double_number,/*number*/ double_datetime,/*datetime*/ double_date,/*date*/ double_time,/*time*/ not_support,/*year*/ double_string,/*string*/ not_support,/*extend*/ not_support,/*unknown*/ double_string,/*text*/ }, { /*number -> XXX*/ not_support,/*null*/ number_int,/*int*/ number_uint,/*uint*/ number_float,/*float*/ number_double,/*double*/ number_number,/*number*/ number_datetime,/*datetime*/ number_date,/*date*/ number_time,/*time*/ number_year,/*year*/ number_string,/*string*/ not_support,/*extend*/ not_support,/*unknown*/ number_string,/*text*/ }, { /*datetime -> XXX*/ not_support,/*null*/ datetime_int,/*int*/ datetime_uint,/*uint*/ datetime_float,/*float*/ datetime_double,/*double*/ datetime_number,/*number*/ datetime_datetime,/*datetime*/ datetime_date,/*date*/ datetime_time,/*time*/ datetime_year,/*year*/ datetime_string,/*string*/ not_support,/*extend*/ not_support,/*unknown*/ datetime_string,/*text*/ }, { /*date -> XXX*/ not_support,/*null*/ date_int,/*int*/ date_uint,/*uint*/ date_float,/*float*/ date_double,/*double*/ date_number,/*number*/ date_datetime,/*datetime*/ identity,/*date*/ date_time,/*time*/ date_year,/*year*/ date_string,/*string*/ not_support,/*extend*/ not_support,/*unknown*/ date_string,/*text*/ }, { /*time -> XXX*/ not_support,/*null*/ time_int,/*int*/ time_uint,/*uint*/ time_float,/*float*/ time_double,/*double*/ time_number,/*number*/ time_datetime,/*datetime*/ not_support,/*date*/ identity,/*time*/ not_support,/*year*/ time_string,/*string*/ not_support,/*extend*/ not_support,/*unknown*/ time_string,/*text*/ }, { /*year -> XXX*/ not_support,/*null*/ year_int,/*int*/ year_uint,/*uint*/ year_float,/*float*/ year_double,/*double*/ year_number,/*number*/ not_support,/*datetime*/ not_support,/*date*/ not_support,/*time*/ identity,/*year*/ year_string,/*string*/ not_support,/*extend*/ not_support,/*unknown*/ year_string,/*text*/ }, { /*string -> XXX*/ not_support,/*null*/ string_int,/*int*/ string_uint,/*uint*/ string_float,/*float*/ string_double,/*double*/ string_number,/*number*/ string_datetime,/*datetime*/ string_date,/*date*/ string_time,/*time*/ string_year,/*year*/ string_string,/*string*/ not_support,/*extend*/ not_support,/*unknown*/ string_string,/*text*/ }, { /*extend -> XXX*/ not_support,/*null*/ not_support,/*int*/ not_support,/*uint*/ not_support,/*float*/ not_support,/*double*/ not_support,/*number*/ not_support,/*datetime*/ not_support,/*date*/ not_support,/*time*/ not_support,/*year*/ not_support,/*string*/ identity,/*extend*/ not_support,/*unknown*/ not_support,/*text*/ }, { /*unknown -> XXX*/ unknown_other,/*null*/ unknown_other,/*int*/ unknown_other,/*uint*/ unknown_other,/*float*/ unknown_other,/*double*/ unknown_other,/*number*/ unknown_other,/*datetime*/ unknown_other,/*date*/ unknown_other,/*time*/ unknown_other,/*year*/ unknown_other,/*string*/ unknown_other,/*extend*/ identity,/*unknown*/ not_support,/*text*/ }, { /*text -> XXX*/ not_support,/*null*/ string_int,/*int*/ string_uint,/*uint*/ string_float,/*float*/ string_double,/*double*/ string_number,/*number*/ string_datetime,/*datetime*/ string_date,/*date*/ string_time,/*time*/ string_year,/*year*/ string_string,/*string*/ not_support,/*extend*/ not_support,/*unknown*/ string_string,/*text*/ }, }; //////////////////////////////////////////////////////////////// bool cast_supported(const ObObjTypeClass orig_tc, const ObObjTypeClass expect_tc) { bool bret = false; if (OB_UNLIKELY(ob_is_invalid_obj_tc(orig_tc) || ob_is_invalid_obj_tc(expect_tc))) { LOG_WARN("invalid cast type", K(orig_tc), K(expect_tc)); } else { bret = (OB_OBJ_CAST[orig_tc][expect_tc] != not_support); } return bret; } int float_range_check(ObObjCastParams ¶ms, const ObAccuracy &accuracy, const ObObj &obj, ObObj &buf_obj, const ObObj *&res_obj, const ObCastMode cast_mode) { int ret = OB_SUCCESS; float value = obj.get_float(); res_obj = &obj; if (CAST_FAIL(real_range_check(accuracy, value))) { } else if (obj.get_float() != value) { buf_obj.set_float(obj.get_type(), value); res_obj = &buf_obj; } return ret; } int double_check_precision(ObObjCastParams ¶ms, const ObAccuracy &accuracy, const ObObj &obj, ObObj &buf_obj, const ObObj *&res_obj, const ObCastMode cast_mode) { int ret = OB_SUCCESS; double value = obj.get_double(); res_obj = &obj; if (CAST_FAIL(real_range_check(accuracy, value))) { } else if (obj.get_double() != value) { buf_obj.set_double(obj.get_type(), value); res_obj = &buf_obj; } return ret; } int number_range_check(ObObjCastParams ¶ms, const ObAccuracy &accuracy, const ObObj &obj, ObObj &buf_obj, const ObObj *&res_obj, const ObCastMode cast_mode) { int ret = OB_SUCCESS; res_obj = NULL; static const int64_t BUFFER_SIZE = 2 * (number::ObNumber::MAX_SCALE + number::ObNumber::MAX_PRECISION); if (OB_ISNULL(params.allocator_v2_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("invalid allocator", K(ret), K(params.allocator_v2_), K(obj)); } else { int &cast_ret = CM_IS_ERROR_ON_FAIL(cast_mode) ? ret : params.warning_; ObPrecision precision = accuracy.get_precision(); ObScale scale = accuracy.get_scale(); ObIAllocator &allocator = *params.allocator_v2_; res_obj = &obj; if (OB_UNLIKELY(precision < scale)) { ret = OB_ERR_M_BIGGER_THAN_D; } else if (number::ObNumber::MAX_PRECISION >= precision && number::ObNumber::MAX_SCALE >= scale && precision >= 0 && scale >= 0) { // prepare string like "99.999". char buf[BUFFER_SIZE] = {0}; int pos = 0; buf[pos++] = '-'; if (precision == scale) { buf[pos++] = '0'; } MEMSET(buf + pos, '9', precision + 1); buf[pos + precision - scale] = '.'; // make min and max numbers. number::ObNumber min_num; number::ObNumber max_num; number::ObNumber in_val = obj.get_number(); number::ObNumber out_val; if (OB_FAIL(min_num.from(buf, allocator))) { } else if (OB_FAIL(max_num.from(buf + 1, allocator))) { } else if (in_val < min_num) { cast_ret = OB_DATA_OUT_OF_RANGE; buf_obj.set_number(obj.get_type(), min_num); } else if (in_val > max_num) { cast_ret = OB_DATA_OUT_OF_RANGE; buf_obj.set_number(obj.get_type(), max_num); } else if (OB_FAIL(out_val.from(in_val, allocator))) { } else if (OB_FAIL(out_val.round(scale))) { } else { buf_obj.set_number(obj.get_type(), out_val); } res_obj = &buf_obj; } else { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arguments", K(ret), K(precision), K(scale)); } } return ret; } int datetime_scale_check(ObObjCastParams ¶ms, const ObAccuracy &accuracy, const ObObj &obj, ObObj &buf_obj, const ObObj *&res_obj, const ObCastMode cast_mode) { int ret = OB_SUCCESS; res_obj = NULL; ObScale scale = accuracy.get_scale(); if (OB_UNLIKELY(scale > MAX_SCALE_FOR_TEMPORAL)) { ret = OB_ERR_TOO_BIG_PRECISION; } else if (OB_UNLIKELY(0 <= scale && scale < MAX_SCALE_FOR_TEMPORAL)) { int64_t value = obj.get_datetime(); ObTimeConverter::round_datetime(scale, value); buf_obj.set_datetime(obj.get_type(), value); res_obj = &buf_obj; } else { res_obj = &obj; } UNUSED(params); UNUSED(cast_mode); return ret; } int time_scale_check(ObObjCastParams ¶ms, const ObAccuracy &accuracy, const ObObj &obj, ObObj &buf_obj, const ObObj *&res_obj, const ObCastMode cast_mode) { int ret = OB_SUCCESS; res_obj = NULL; ObScale scale = accuracy.get_scale(); if (OB_LIKELY(0 <= scale && scale < MAX_SCALE_FOR_TEMPORAL)) { int64_t value = obj.get_time(); ObTimeConverter::round_datetime(scale, value); buf_obj.set_time(value); res_obj = &buf_obj; } else { res_obj = &obj; } UNUSED(params); UNUSED(cast_mode); return ret; } int string_length_check(ObObjCastParams ¶ms, const ObAccuracy &accuracy, const ObCollationType cs_type, const ObObj &obj, ObObj &buf_obj, const ObObj *&res_obj, const ObCastMode cast_mode) { int ret = OB_SUCCESS; int &cast_ret = CM_IS_ERROR_ON_FAIL(cast_mode) ? ret : params.warning_; const ObLength max_len_char = accuracy.get_length(); const char *str = obj.get_string_ptr(); const int32_t str_len_byte = obj.get_string_len(); const int32_t str_len_char = static_cast(ObCharset::strlen_char(cs_type, str, str_len_byte)); if (OB_UNLIKELY(max_len_char <= 0)) { buf_obj.set_string(obj.get_type(), NULL, 0); buf_obj.set_collation_level(obj.get_collation_level()); buf_obj.set_collation_type(obj.get_collation_type()); res_obj = &buf_obj; if (OB_UNLIKELY(0 == max_len_char && str_len_byte > 0)) { cast_ret = OB_ERR_DATA_TOO_LONG; OB_LOG(WARN, "char type length is too long", K(obj), K(max_len_char), K(str_len_char)); } } else { int32_t trunc_len_byte = -1; int32_t trunc_len_char = -1; if (obj.is_varbinary() || obj.is_binary()) { // str_len_char > max_len_char means an error or warning, no matter tail ' ' or '\0'. if (OB_UNLIKELY(str_len_char > max_len_char)) { cast_ret = OB_ERR_DATA_TOO_LONG; LOG_WARN("binary type length is too long", K(obj), K(max_len_char), K(str_len_char)); } } else { // trunc_len_char > max_len_char means an error or warning, without tail ' ', otherwise // str_len_char > max_len_char means only warning, even in strict mode. trunc_len_byte = static_cast(ObCharset::strlen_byte_no_sp(cs_type, str, str_len_byte)); trunc_len_char = static_cast(ObCharset::strlen_char(cs_type, str, trunc_len_byte)); if (OB_UNLIKELY(trunc_len_char > max_len_char)) { cast_ret = OB_ERR_DATA_TOO_LONG; LOG_WARN("char type length is too long", K(obj), K(max_len_char), K(trunc_len_char)); } else if (OB_UNLIKELY(str_len_char > max_len_char)) { params.warning_ = OB_ERR_DATA_TOO_LONG; LOG_WARN("char type length is too long", K(obj), K(max_len_char), K(str_len_char)); } } if (OB_SUCC(ret)) { if (OB_UNLIKELY(OB_ERR_DATA_TOO_LONG == params.warning_)) { // when warning, always trunc to max_len_char first. // besides, if char (not binary), trunc to trunc_len_char again, trim tail ' ' after first trunc. // the reason of two-trunc for char (not binary): // insert 'ab ! ' to char(3), we get an 'ab' in column, not 'ab ': // first trunc: 'ab ! ' to 'ab ', // second trunc: 'ab ' to 'ab'. trunc_len_byte = static_cast(ObCharset::charpos(cs_type, str, str_len_byte, max_len_char)); if (obj.is_char() && !obj.is_binary()) { trunc_len_byte = static_cast(ObCharset::strlen_byte_no_sp(cs_type, str, trunc_len_byte)); } if (OB_FAIL(copy_string(params, obj.get_type(), str, trunc_len_byte, buf_obj))) { } else { buf_obj.set_collation_level(obj.get_collation_level()); buf_obj.set_collation_type(obj.get_collation_type()); res_obj = &buf_obj; } } else { res_obj = &obj; } } } return ret; } int obj_collation_check(const bool is_strict_mode, const ObCollationType cs_type, ObObj &obj) { int ret = OB_SUCCESS; if (!ob_is_string_tc(obj.get_type()) || (cs_type == obj.get_collation_type())) { //nothing to do } else if (cs_type == CS_TYPE_BINARY) { obj.set_collation_type(cs_type); } else { ObString str; int64_t well_formed_len = 0; obj.get_string(str); if (OB_FAIL(ObCharset::well_formed_len(cs_type, str.ptr(), str.length(), well_formed_len))) { LOG_WARN("invalid string for charset", K(ret), K(cs_type), K(str), K(well_formed_len)); if (is_strict_mode) { ret = OB_ERR_INCORRECT_STRING_VALUE; LOG_USER_ERROR(ret, str.length(), str.ptr()); } else { ret = OB_SUCCESS; obj.set_collation_type(cs_type); str.assign_ptr(str.ptr(), static_cast(well_formed_len)); obj.set_string(obj.get_type(), str.ptr(), str.length()); LOG_WARN("invalid string for charset", K(ret), K(cs_type), K(str), K(well_formed_len), K(str.length())); } } else { obj.set_collation_type(cs_type); } } return ret; } int obj_accuracy_check(ObCastCtx &cast_ctx, const ObAccuracy &accuracy, const ObCollationType cs_type, const ObObj &obj, ObObj &buf_obj, const ObObj *&res_obj) { int ret = OB_SUCCESS; if (ObFloatTC == obj.get_type_class()) { ret = float_range_check(cast_ctx, accuracy, obj, buf_obj, res_obj, cast_ctx.cast_mode_); } else if (ObDoubleTC == obj.get_type_class()) { ret = double_check_precision(cast_ctx, accuracy, obj, buf_obj, res_obj, cast_ctx.cast_mode_); } else if (ObNumberTC == obj.get_type_class()) { ret = number_range_check(cast_ctx, accuracy, obj, buf_obj, res_obj, cast_ctx.cast_mode_); } else if (ObDateTimeTC == obj.get_type_class()) { ret = datetime_scale_check(cast_ctx, accuracy, obj, buf_obj, res_obj, cast_ctx.cast_mode_); } else if (ObTimeTC == obj.get_type_class()) { ret = time_scale_check(cast_ctx, accuracy, obj, buf_obj, res_obj, cast_ctx.cast_mode_); } else if (ObStringTC == obj.get_type_class()) { ret = string_length_check(cast_ctx, accuracy, cs_type, obj, buf_obj, res_obj, cast_ctx.cast_mode_); } else { //LOG_WARN("unexpected type class to check", K(obj)); } return ret; } int ob_obj_to_ob_time_with_date(const ObObj &obj, const ObTimeZoneInfo *tz_info, ObTime &ob_time) { int ret = OB_SUCCESS; switch (obj.get_type_class()) { case ObIntTC: // fallthrough. case ObUIntTC: { ret = ObTimeConverter::int_to_ob_time_with_date(obj.get_int(), ob_time); break; } case ObDateTimeTC: { ret = ObTimeConverter::datetime_to_ob_time(obj.get_datetime(), (ObTimestampType == obj.get_type()) ? tz_info : NULL, ob_time); break; } case ObDateTC: { ret = ObTimeConverter::date_to_ob_time(obj.get_date(), ob_time); break; } case ObTimeTC: { ret = ObTimeConverter::time_to_ob_time(obj.get_time(), ob_time); break; } case ObStringTC: { ret = ObTimeConverter::str_to_ob_time_with_date(obj.get_string(), ob_time); break; } default: { ret = OB_NOT_SUPPORTED; } } return ret; } int ob_obj_to_ob_time_without_date(const ObObj &obj, const ObTimeZoneInfo *tz_info, ObTime &ob_time) { int ret = OB_SUCCESS; switch (obj.get_type_class()) { case ObIntTC: // fallthrough. case ObUIntTC: { ret = ObTimeConverter::int_to_ob_time_without_date(obj.get_int(), ob_time); break; } case ObDateTimeTC: { ret = ObTimeConverter::datetime_to_ob_time(obj.get_datetime(), (ObTimestampType == obj.get_type()) ? tz_info : NULL, ob_time); break; } case ObDateTC: { ret = ObTimeConverter::date_to_ob_time(obj.get_date(), ob_time); break; } case ObTimeTC: { ret = ObTimeConverter::time_to_ob_time(obj.get_time(), ob_time); break; } case ObStringTC: { ret = ObTimeConverter::str_to_ob_time_without_date(obj.get_string(), ob_time); break; } default: { ret = OB_NOT_SUPPORTED; } } return ret; } int ObObjCasterV2::to_type(const ObObjType expect_type, ObCastCtx &cast_ctx, const ObObj &in_obj, ObObj &buf_obj, const ObObj *&res_obj) { int ret = OB_SUCCESS; res_obj = NULL; cast_ctx.warning_ = OB_SUCCESS; if (OB_UNLIKELY(expect_type == in_obj.get_type() || ObNullType == in_obj.get_type())) { res_obj = &in_obj; } else if (OB_FAIL(to_type(expect_type, CS_TYPE_INVALID, cast_ctx, in_obj, buf_obj))) { LOG_WARN("failed to cast obj", K(ret), K(in_obj), K(expect_type), K(cast_ctx.cast_mode_)); } else { res_obj = &buf_obj; } return ret; } int ObObjCasterV2::to_type(const ObObjType expect_type, ObCastCtx &cast_ctx, const ObObj &in_obj, ObObj &out_obj) { return to_type(expect_type, CS_TYPE_INVALID, cast_ctx, in_obj, out_obj); } int ObObjCasterV2::to_type(const ObObjType expect_type, const ObCollationType expect_cs_type, ObCastCtx &cast_ctx, const ObObj &in_obj, ObObj &out_obj) { int ret = OB_SUCCESS; const ObObjTypeClass in_tc = in_obj.get_type_class(); const ObObjTypeClass out_tc = ob_obj_type_class(expect_type); cast_ctx.warning_ = OB_SUCCESS; if (OB_UNLIKELY(ob_is_invalid_obj_tc(in_tc) || ob_is_invalid_obj_tc(out_tc))) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected type", K(ret), K(in_obj), K(expect_type)); } else if (OB_FAIL(OB_OBJ_CAST[in_tc][out_tc](expect_type, cast_ctx, in_obj, out_obj, cast_ctx.cast_mode_))) { LOG_WARN("failed to cast obj", K(ret), K(in_obj), K(expect_type), K(cast_ctx.cast_mode_)); } else { if (ObStringTC == out_tc) { if (CS_TYPE_INVALID != expect_cs_type) { // expect_cs_type has higher priority than collation of in_obj or connection. out_obj.set_collation_type(expect_cs_type); } else if (ObStringTC != in_tc) { // cast to varchar from other types, the result collation is collation_connection if (OB_UNLIKELY(CS_TYPE_INVALID == cast_ctx.connection_collation_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected collation type", K(ret), K(cast_ctx.connection_collation_)); } else if (out_obj.is_varchar_or_char()) { out_obj.set_collation_type(cast_ctx.connection_collation_); } } else { // collation of out_obj has been set in string_string(), nothing to do here. } } } return ret; } // given two objects with type A: a1 and a2, cast them to type B: b1 and b2, // if in any case: // a1 > a2 means b1 > b2, and // a1 < a2 means b1 < b2, and // a1 = a2 means b1 = b2, // then type A and B is cast monotonic. int ObObjCasterV2::is_cast_monotonic(ObObjType t1, ObObjType t2, bool &is_monotonic) { int ret = OB_SUCCESS; ObObjTypeClass tc1 = ob_obj_type_class(t1); ObObjTypeClass tc2 = ob_obj_type_class(t2); if (OB_UNLIKELY(ob_is_invalid_obj_tc(tc1) || ob_is_invalid_obj_tc(tc2))) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected type", K(ret), K(t1), K(t2), K(tc1), K(tc2)); } else { is_monotonic = CAST_MONOTONIC[tc1][tc2]; } return ret; } /* make sure that you have read the doc before you call these functions ! * * doc: http://www.atatech.org/articles/56575 */ int ObObjCasterV2::is_order_consistent(const ObObjMeta &from, const ObObjMeta &to, bool &result) { int ret = OB_SUCCESS; result = false; ObObjTypeClass tc1 = from.get_type_class(); ObObjTypeClass tc2 = to.get_type_class(); if (OB_UNLIKELY(ob_is_invalid_obj_tc(tc1) || ob_is_invalid_obj_tc(tc2))) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected obj type class", K(ret), K(from), K(to)); } else if (from.is_string_type() && to.is_string_type()) { ObCollationType res_cs_type = CS_TYPE_INVALID; ObCollationLevel res_cs_level = CS_LEVEL_INVALID; ObCollationType from_cs_type = from.get_collation_type(); ObCollationType to_cs_type = to.get_collation_type(); if (OB_FAIL(ObCharset::aggregate_collation(from.get_collation_level(), from_cs_type, to.get_collation_level(), to_cs_type, res_cs_level, res_cs_type))) { LOG_WARN("fail to aggregate collation", K(ret), K(from), K(to)); } else { int64_t idx_from = get_idx_of_collate(from_cs_type); int64_t idx_to = get_idx_of_collate(to_cs_type); int64_t idx_res = get_idx_of_collate(res_cs_type); if (OB_UNLIKELY(idx_from < 0 || idx_to < 0 || idx_res < 0 ||idx_from >= ObCharset::VALID_COLLATION_TYPES ||idx_to >= ObCharset::VALID_COLLATION_TYPES ||idx_res >= ObCharset::VALID_COLLATION_TYPES)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected collation type", K(ret), K(from), K(to)); } else { result = ORDER_CONSISTENT_WITH_BOTH_STRING[idx_from][idx_to][idx_res]; } } } else { result = ORDER_CONSISTENT[tc1][tc2]; } return ret; } /* make sure that you have read the doc before you call these functions ! * * doc: http://www.atatech.org/articles/56575 */ int ObObjCasterV2::is_injection(const ObObjMeta &from, const ObObjMeta &to, bool &result) { int ret = OB_SUCCESS; result = false; ObObjTypeClass tc1 = from.get_type_class(); ObObjTypeClass tc2 = to.get_type_class(); if (OB_UNLIKELY(ob_is_invalid_obj_tc(tc1) || ob_is_invalid_obj_tc(tc2))) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected obj type class", K(ret), K(from), K(to)); } else if (from.is_string_type() && to.is_string_type()) { ObCollationType res_cs_type = CS_TYPE_INVALID; ObCollationLevel res_cs_level = CS_LEVEL_INVALID; ObCollationType from_cs_type = from.get_collation_type(); ObCollationType to_cs_type = to.get_collation_type(); if (OB_FAIL(ObCharset::aggregate_collation(from.get_collation_level(), from_cs_type, to.get_collation_level(), to_cs_type, res_cs_level, res_cs_type))) { LOG_WARN("fail to aggregate collation", K(ret), K(from), K(to)); } else { int64_t idx_from = get_idx_of_collate(from_cs_type); int64_t idx_to = get_idx_of_collate(to_cs_type); int64_t idx_res = get_idx_of_collate(res_cs_type); if (OB_UNLIKELY(idx_from < 0 || idx_to < 0 || idx_res < 0 ||idx_from >= ObCharset::VALID_COLLATION_TYPES ||idx_to >= ObCharset::VALID_COLLATION_TYPES ||idx_res >= ObCharset::VALID_COLLATION_TYPES)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected collation type", K(ret), K(from), K(to)); } else { result = INJECTION_WITH_BOTH_STRING[idx_from][idx_to][idx_res]; } } } else { result = INJECTION[tc1][tc2]; } return ret; } const bool ObObjCasterV2::CAST_MONOTONIC[ObMaxTC][ObMaxTC] = { // null { false, // null false, // int false, // uint false, // float false, // double false, // number false, // datetime false, // date false, // time false, // year false, // string false, // extend false, // unknown false, // lob }, // int { false, // null true, // int true, // uint true, // float true, // double true, // number false, // datetime false, // date false, // time false, // year false, // string false, // extend false, // unknown false, // lob }, // uint { false, // null true, // int true, // uint true, // float true, // double true, // number false, // datetime false, // date false, // time false, // year false, // string false, // extend false, // unknown false, // lob }, // float { false, // null true, // int true, // uint true, // float true, // double true, // number false, // datetime false, // date false, // time false, // year false, // string false, // extend false, // unknown false, // lob }, // double { false, // null true, // int true, // uint true, // float true, // double true, // number false, // datetime false, // date false, // time false, // year false, // string false, // extend false, // unknown false, // lob }, // number { false, // null true, // int true, // uint true, // float true, // double true, // number false, // datetime false, // date false, // time false, // year false, // string false, // extend false, // unknown false, // lob }, // datetime { false, // null true, // int true, // uint true, // float true, // double true, // number true, // datetime true, // date false, // time true, // year true, // string false, // extend false, // unknown true, // lob }, // date { false, // null true, // int true, // uint true, // float true, // double true, // number true, // datetime true, // date false, // time true, // year true, // string false, // extend false, // unknown true, // lob }, // time { false, // null true, // int true, // uint true, // float true, // double true, // number true, // datetime false, // date true, // time false, // year false, // string false, // extend false, // unknown true, // lob }, // year { false, // null true, // int true, // uint true, // float true, // double true, // number true, // datetime true, // date false, // time true , // year true, // string false, // extend false, // unknown true, // lob }, // string { false, // null false, // int false, // uint false, // float false, // double false, // number false, // datetime false, // date false, // time false, // year true, // string false, // extend false, // unknown true, // lob }, // extend { false, // null false, // int false, // uint false, // float false, // double false, // number false, // datetime false, // date false, // time false, // year false, // string false, // extend false, // unknown false, // lob }, // unknown { false, // null false, // int false, // uint false, // float false, // double false, // number false, // datetime false, // date false, // time false, // year false, // string false, // extend false, // unknown false, // lob }, // lob { false, // null false, // int false, // uint false, // float false, // double false, // number false, // datetime false, // date false, // time false, // year true, // string false, // extend false, // unknown true, // lob }, }; const bool ObObjCasterV2::ORDER_CONSISTENT[ObMaxTC][ObMaxTC] = { // null { false, // null false, // int false, // uint false, // float false, // double false, // number false, // datetime false, // date false, // time false, // year false, // string false, // extend false, // unknown false, // lob }, // int { false, // null true, // int true, // uint true, // float true, // double true, // number false, // datetime false, // date false, // time true, // year false, // string false, // extend false, // unknown false, // lob }, // uint { false, // null true, // int true, // uint true, // float true, // double true, // number false, // datetime false, // date false, // time true, // year false, // string false, // extend false, // unknown false, // lob }, // float { false, // null false, // int false, // uint true, // float true, // double false, // number false, // datetime false, // date false, // time false, // year false, // string false, // extend false, // unknown false, // lob }, // double { false, // null false, // int false, // uint true, // float true, // double false, // number false, // datetime false, // date false, // time false, // year false, // string false, // extend false, // unknown false, // lob }, // number { false, // null true, // int true, // uint true, // float true, // double true, // number false, // datetime false, // date false, // time true, // year false, // string false, // extend false, // unknown false, // lob }, // datetime { false, // null false, // int false, // uint false, // float false, // double false, // number true, // datetime true, // date true, // time true, // year false, // string false, // extend false, // unknown false, // lob }, // date { false, // null false, // int false, // uint false, // float false, // double false, // number true, // datetime true, // date true, // time true, // year false, // string false, // extend false, // unknown false, // lob }, // time { false, // null false, // int false, // uint false, // float false, // double false, // number true, // datetime true, // date true, // time true, // year false, // string false, // extend false, // unknown false, // lob }, // year //0000-9999 { false, // null true, // int true, // uint true, // float true, // double true, // number false, // datetime false, // date false, // time true , // year false, // string false, // extend false, // unknown false, // lob }, // string { false, // null false, // int false, // uint false, // float false, // double false, // number false, // datetime false, // date false, // time false, // year false, // string false, // extend false, // unknown false, // lob }, // extend { false, // null false, // int false, // uint false, // float false, // double false, // number false, // datetime false, // date false, // time false, // year false, // string false, // extend false, // unknown false, // lob }, // unknown { false, // null false, // int false, // uint false, // float false, // double false, // number false, // datetime false, // date false, // time false, // year false, // string false, // extend false, // unknown false, // lob }, // lob { false, // null false, // int false, // uint false, // float false, // double false, // number false, // datetime false, // date false, // time false, // year false, // string false, // extend false, // unknown false, // lob }, }; const bool ObObjCasterV2::ORDER_CONSISTENT_WITH_BOTH_STRING[ObCharset::VALID_COLLATION_TYPES][ObCharset::VALID_COLLATION_TYPES][ObCharset::VALID_COLLATION_TYPES] = { //CS_TYPE_UTF8MB4_GENERAL_CI { //ci //utf8bin //bin {true, true, true},//CS_TYPE_UTF8MB4_GENERAL_CI {false, false , false},//CS_TYPE_UTF8MB4_BIN {false, false , false},//CS_TYPE_BINARY }, //CS_TYPE_UTF8MB4_BIN { //ci //utf8bin //bin {true, true , true},//CS_TYPE_UTF8MB4_GENERAL_CI {false, true , true},//CS_TYPE_UTF8MB4_BIN {false, true , true},//CS_TYPE_BINARY }, //CS_TYPE_BINARY { //ci //utf8bin //bin {true, true , true},//CS_TYPE_UTF8MB4_GENERAL_CI {false, true , true},//CS_TYPE_UTF8MB4_BIN {false, true , true},//CS_TYPE_BINARY } }; const bool ObObjCasterV2::INJECTION[ObMaxTC][ObMaxTC] = { // null { false, // null false, // int false, // uint false, // float false, // double false, // number false, // datetime false, // date false, // time false, // year false, // string false, // extend false, // unknown false, // lob }, // int { false, // null true, // int true, // uint true, // float true, // double true, // number true, // datetime true, // date true, // time true, // year false, // string false, // extend false, // unknown false, // lob }, // uint { false, // null true, // int true, // uint true, // float true, // double true, // number true, // datetime true, // date true, // time true, // year false, // string false, // extend false, // unknown false, // lob }, // float { false, // null false, // int false, // uint true, // float true, // double false, // number true, // datetime true, // date true, // time true, // year false, // string false, // extend false, // unknown false, // lob }, // double { false, // null false, // int false, // uint true, // float true, // double false, // number true, // datetime true, // date true, // time true, // year false, // string false, // extend false, // unknown false, // lob }, // number { false, // null true, // int true, // uint true, // float true, // double true, // number true, // datetime true, // date true, // time true, // year false, // string false, // extend false, // unknown false, // lob }, // datetime { false, // null false, // int false, // uint false, // float false, // double false, // number //2010-01-01 12:34:56.12345 = 20100101123456.1234520 and 2010-01-01 12:34:56.12345 = 20100101123456.1234530 true, // datetime true, // date true, // time true, // year false, // string false, // extend false, // unknown false, // lob }, // date { false, // null false, // int //think about 0000-00-00 false, // uint false, // float false, // double false, // number true, // datetime true, // date true, // time true, // year false, // string false, // extend false, // unknown false, // lob }, // time { false, // null false, // int false, // uint false, // float false, // double false, // number //think about time(5) = decimal(40,7) true, // datetime true, // date true, // time true, // year false, // string //00:12:34 = "00:12:34" and 00:12:34 = "00:12:34.000" false, // extend false, // unknown false, // lob }, // year //0000-9999 { false, // null true, // int true, // uint true, // float true, // double true, // number true, // datetime //1999 = 1999-00-00 00:00:00 true, // date //1999 = 1999-00-00 true, // time true , // year false, // string //1999 = "99" and 1999 = "1999" false, // extend false, // unknown false, // lob }, // string { false, // null true, // int true, // uint true, // float true, // double true, // number true, // datetime true, // date true, // time true, // year false, // string false, // extend false, // unknown false, // lob }, // extend { false, // null false, // int false, // uint false, // float false, // double false, // number false, // datetime false, // date false, // time false, // year false, // string false, // extend false, // unknown false, // lob }, // unknown { false, // null false, // int false, // uint false, // float false, // double false, // number false, // datetime false, // date false, // time false, // year false, // string false, // extend false, // unknown false, // lob }, // lob { false, // null true, // int true, // uint true, // float true, // double true, // number true, // datetime true, // date true, // time true, // year false, // string false, // extend false, // unknown false, // lob }, }; const bool ObObjCasterV2::INJECTION_WITH_BOTH_STRING[ObCharset::VALID_COLLATION_TYPES][ObCharset::VALID_COLLATION_TYPES][ObCharset::VALID_COLLATION_TYPES] = { //CS_TYPE_UTF8MB4_GENERAL_CI { //ci //utf8bin //bin {true, true, true},//CS_TYPE_UTF8MB4_GENERAL_CI {false, true , true},//CS_TYPE_UTF8MB4_BIN {false, true , true},//CS_TYPE_BINARY }, //CS_TYPE_UTF8MB4_BIN { //ci //utf8bin //bin {true, true , true},//CS_TYPE_UTF8MB4_GENERAL_CI {false, true , true},//CS_TYPE_UTF8MB4_BIN {false, true , true},//CS_TYPE_BINARY }, //CS_TYPE_BINARY { //ci //utf8bin //bin {true, true , true},//CS_TYPE_UTF8MB4_GENERAL_CI {false, true , true},//CS_TYPE_UTF8MB4_BIN {false, true , true},//CS_TYPE_BINARY } }; } // end namespace common } // end namespace oceanbase