/** * Copyright (c) 2021 OceanBase * OceanBase CE 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 "share/object/ob_obj_cast.h" #include #include #include "lib/charset/ob_dtoa.h" #include "lib/string/ob_sql_string.h" #include "rpc/obmysql/ob_mysql_util.h" #include "share/ob_worker.h" #include "share/object/ob_obj_cast_util.h" // from sql_parser_base.h #define DEFAULT_STR_LENGTH -1 namespace oceanbase { using namespace lib; using namespace share; namespace common { using namespace number; static const int64_t MAX_DOUBLE_STRICT_PRINT_SIZE = 512; static int cast_identity( const ObObjType expect_type, ObObjCastParams& params, 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 cast_not_support( const ObObjType expect_type, ObObjCastParams& params, 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 cast_not_expected( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { UNUSED(params); LOG_WARN("not expected obj type convert", K(expect_type), K(in), K(out), K(cast_mode)); return OB_ERR_UNEXPECTED; } static int cast_inconsistent_types( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { UNUSED(params); UNUSED(out); UNUSED(cast_mode); LOG_WARN("inconsistent datatypes", "expected", expect_type, "got", in.get_type()); return OB_ERR_INVALID_TYPE_FOR_OP; } static int cast_not_support_enum_set( const ObExpectType& expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out) { UNUSED(params); LOG_WARN("not supported obj type convert", K(expect_type), K(in), K(out)); return OB_NOT_SUPPORTED; } static int cast_identity_enum_set(const ObExpectType& expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out) { UNUSED(expect_type); UNUSED(params); if (&in != &out) { out = in; } return OB_SUCCESS; } static int cast_not_expected_enum_set( const ObExpectType& expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out) { UNUSED(params); LOG_WARN("not expected obj type convert", K(expect_type), K(in), K(out)); return OB_ERR_UNEXPECTED; } static int unknown_other( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { return cast_not_support(expect_type, params, in, out, cast_mode); } //////////////////////////////////////////////////////////////// // Utility func // %align_offset is used in mysql mode to align blob to other charset. static int copy_string(const ObObjCastParams& params, const ObObjType type, const char* str, int64_t len, ObObj& obj, int64_t align_offset = 0) { 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 { len += align_offset; if (OB_UNLIKELY(NULL == (buf = static_cast(params.alloc(len))))) { ret = OB_ALLOCATE_MEMORY_FAILED; } else { MEMSET(buf, 0, align_offset); MEMCPY(buf + align_offset, str, len - align_offset); } } } if (OB_SUCC(ret)) { if (ob_is_text_tc(type)) { obj.set_lob_value(type, buf, static_cast(len)); } else if (ob_is_raw(type)) { obj.set_raw(buf, static_cast(len)); } else { obj.set_string(type, buf, static_cast(len)); } } return ret; } static int copy_string( const ObObjCastParams& params, const ObObjType type, const ObString& str, ObObj& obj, int64_t align_offset = 0) { return copy_string(params, type, str.ptr(), str.length(), obj, align_offset); } /* * 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. */ 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), KP(str), KP(endptr)); } else if (is_oracle_mode() && 0 != err) { ret = OB_ERR_CAST_VARCHAR_TO_NUMBER; } 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 LOG_DEBUG("check_convert_str_err", K(len), K(str - endptr)); } } return ret; } static int convert_string_collation(const ObString& in, const ObCollationType in_collation, ObString& out, const ObCollationType out_collation, ObObjCastParams& params) { int ret = OB_SUCCESS; if (!ObCharset::is_valid_collation(in_collation) || !ObCharset::is_valid_collation(out_collation) || ObCharset::charset_type_by_coll(in_collation) == CHARSET_BINARY || ObCharset::charset_type_by_coll(out_collation) == CHARSET_BINARY || (ObCharset::charset_type_by_coll(in_collation) == ObCharset::charset_type_by_coll(out_collation))) { out = in; } else if (in.empty()) { out.reset(); } else { char* buf = NULL; const int32_t CharConvertFactorNum = 4; int32_t buf_len = in.length() * CharConvertFactorNum; uint32_t result_len = 0; if (OB_ISNULL(buf = static_cast(params.alloc(buf_len)))) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("alloc memory failed", K(ret)); } else if (OB_FAIL(ObCharset::charset_convert( in_collation, in.ptr(), in.length(), out_collation, buf, buf_len, result_len))) { LOG_WARN("charset convert failed", K(ret)); } else { out.assign_ptr(buf, result_len); } } LOG_DEBUG("convert_string_collation", K(in.length()), K(in_collation), K(out.length()), K(out_collation)); return ret; } //////////////////////////////////////////////////////////////// OB_INLINE int get_cast_ret(const ObCastMode cast_mode, int ret, int& warning) { // compatibility for old ob if (OB_UNLIKELY(OB_ERR_UNEXPECTED_TZ_TRANSITION == ret) || OB_UNLIKELY(OB_ERR_UNKNOWN_TIME_ZONE == ret)) { ret = OB_INVALID_DATE_VALUE; } else 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 CAST_RET(stmt) (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_DOUBLE_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_BIT(res) SET_RES_OBJ(res, bit, , , value, 0) #define SET_RES_ENUM(res) SET_RES_OBJ(res, enum, , , value, 0) #define SET_RES_SET(res) SET_RES_OBJ(res, set, , , value, 0) #define SET_RES_OTIMESTAMP(res) SET_RES_OBJ(res, otimestamp_value, expect_type, COMMA, value, ObOTimestampData()) #define SET_RES_INTERVAL_YM(res) SET_RES_OBJ(res, interval_ym, , , value, ObIntervalYMValue()) #define SET_RES_INTERVAL_DS(res) SET_RES_OBJ(res, interval_ds, , , value, ObIntervalDSValue()) #define SET_RES_UROWID(res) SET_RES_OBJ(res, urowid, , , value, ObURowIDData()); #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); \ } #define SET_RES_ACCURACY_STRING(type, res_precision, res_length) \ if (params.res_accuracy_ != NULL && OB_SUCCESS == ret) { \ params.res_accuracy_->set_precision(res_precision); \ params.res_accuracy_->set_length(res_length); \ if (ob_is_text_tc(type)) { \ params.res_accuracy_->set_scale(DEFAULT_SCALE_FOR_TEXT); \ } else { \ params.res_accuracy_->set_scale(DEFAULT_SCALE_FOR_STRING); \ } \ } //////////////////////////////////////////////////////////////// // range check function templates. //////////////////////////////////////////////////////////////////////////////////////////////////// ObNumber ObNumberConstValue::MYSQL_MIN[ObNumber::MAX_PRECISION + 1][ObNumber::MAX_SCALE + 1] = {}; ObNumber ObNumberConstValue::MYSQL_MAX[ObNumber::MAX_PRECISION + 1][ObNumber::MAX_SCALE + 1] = {}; ObNumber ObNumberConstValue::MYSQL_CHECK_MIN[ObNumber::MAX_PRECISION + 1][ObNumber::MAX_SCALE + 1] = {}; ObNumber ObNumberConstValue::MYSQL_CHECK_MAX[ObNumber::MAX_PRECISION + 1][ObNumber::MAX_SCALE + 1] = {}; ObNumber ObNumberConstValue::ORACLE_CHECK_MIN[OB_MAX_NUMBER_PRECISION + 1] [ObNumberConstValue::MAX_ORACLE_SCALE_SIZE + 1] = {}; ObNumber ObNumberConstValue::ORACLE_CHECK_MAX[OB_MAX_NUMBER_PRECISION + 1] [ObNumberConstValue::MAX_ORACLE_SCALE_SIZE + 1] = {}; int ObNumberConstValue::init(ObIAllocator& allocator, const lib::ObMemAttr& attr) { int ret = OB_SUCCESS; int64_t total_alloc_size = 0; const int64_t BUFFER_SIZE = 2 * (ObNumber::MAX_SCALE + ObNumber::MAX_PRECISION); char buf[BUFFER_SIZE]; buf[BUFFER_SIZE - 1] = '\0'; // prepare string like "99.999". int pos = 0; buf[pos++] = '-'; { CompatModeGuard tmp_mode(ObWorker::CompatMode::MYSQL); for (int16_t precision = OB_MIN_DECIMAL_PRECISION; OB_SUCC(ret) && precision <= ObNumber::MAX_PRECISION; ++precision) { for (int16_t scale = 0; OB_SUCC(ret) && precision >= scale && scale <= ObNumber::MAX_SCALE; ++scale) { pos = 1; MEMSET(buf + pos, 0, BUFFER_SIZE - pos); if (precision == scale) { buf[pos++] = '0'; } MEMSET(buf + pos, '9', precision + 1); buf[pos + precision + 1] = '5'; buf[pos + precision - scale] = '.'; // make min and max numbers. ObNumber& min_check_num = MYSQL_CHECK_MIN[precision][scale]; ObNumber& max_check_num = MYSQL_CHECK_MAX[precision][scale]; ObString tmp_string(pos + precision + 1 + 1, buf); if (OB_FAIL(min_check_num.from(tmp_string.ptr(), tmp_string.length(), allocator, attr))) { LOG_ERROR("fail to call from", K(precision), K(scale), K(tmp_string), K(pos), K(ret)); } else if (OB_FAIL(max_check_num.from(tmp_string.ptr() + 1, tmp_string.length() - 1, allocator, attr))) { LOG_ERROR("fail to call from", K(precision), K(scale), K(tmp_string), K(pos), K(ret)); } else { total_alloc_size += sizeof(uint32_t) * (min_check_num.get_length() + max_check_num.get_length()); LOG_DEBUG("succ to build mysql min max check number", K(precision), K(scale), K(tmp_string), K(total_alloc_size), K(min_check_num), K(max_check_num)); } if (OB_SUCC(ret)) { buf[pos + precision + 1] = '0'; // make min and max numbers. ObNumber& min_num = MYSQL_MIN[precision][scale]; ObNumber& max_num = MYSQL_MAX[precision][scale]; if (OB_FAIL(min_num.from(tmp_string.ptr(), tmp_string.length(), allocator, attr))) { LOG_ERROR("fail to call from", K(precision), K(scale), K(tmp_string), K(pos), K(ret)); } else if (OB_FAIL(max_num.from(tmp_string.ptr() + 1, tmp_string.length() - 1, allocator, attr))) { LOG_ERROR("fail to call from", K(precision), K(scale), K(tmp_string), K(pos), K(ret)); } else { total_alloc_size += sizeof(uint32_t) * (min_num.get_length() + max_num.get_length()); LOG_DEBUG("succ to build mysql min max number", K(precision), K(scale), K(tmp_string), K(total_alloc_size), K(min_num), K(max_num)); } } } } } { CompatModeGuard tmp_mode(ObWorker::CompatMode::ORACLE); for (int16_t precision = OB_MIN_NUMBER_PRECISION; OB_SUCC(ret) && precision <= OB_MAX_NUMBER_PRECISION; ++precision) { for (int16_t scale = ObNumber::MIN_SCALE; OB_SUCC(ret) && scale <= ObNumber::MAX_SCALE; ++scale) { pos = 1; MEMSET(buf + pos, 0, BUFFER_SIZE - pos); ObNumber& min_check_num = ORACLE_CHECK_MIN[precision][scale + MAX_ORACLE_SCALE_DELTA]; ObNumber& max_check_num = ORACLE_CHECK_MAX[precision][scale + MAX_ORACLE_SCALE_DELTA]; ObString tmp_string; if (precision >= scale && scale >= 0) { /* number(3, 1) => legal range(-99.95, 99.95) */ if (precision == scale) { buf[pos++] = '0'; } MEMSET(buf + pos, '9', precision + 1); buf[pos + precision - scale] = '.'; buf[pos + precision + 1] = '5'; tmp_string.assign_ptr(buf, pos + precision + 1 + 1); } else if (scale < 0) { /* number(2, -3) => legal range: (-99500, 99500) */ MEMSET(buf + pos, '9', precision); buf[pos + precision] = '5'; MEMSET(buf + pos + precision + 1, '0', 0 - scale - 1); tmp_string.assign_ptr(buf, pos + precision - scale); } else { // number(2, 3) => legal range:(-0.0995, 0.0995) buf[pos++] = '0'; buf[pos++] = '.'; MEMSET(buf + pos, '0', scale - precision); MEMSET(buf + pos + scale - precision, '9', precision); buf[pos + scale] = '5'; tmp_string.assign_ptr(buf, pos + scale + 1); } // make min and max numbers. if (OB_FAIL(min_check_num.from(tmp_string.ptr(), tmp_string.length(), allocator, attr))) { LOG_ERROR("fail to call from", K(precision), K(scale), K(tmp_string), K(ret)); } else if (OB_FAIL(max_check_num.from(tmp_string.ptr() + 1, tmp_string.length() - 1, allocator, attr))) { LOG_ERROR("fail to call from", K(precision), K(scale), K(tmp_string), K(ret)); } else { total_alloc_size += sizeof(uint32_t) * (min_check_num.get_length() + max_check_num.get_length()); LOG_DEBUG("succ to build min max number", K(precision), K(scale), K(tmp_string), K(total_alloc_size), K(min_check_num), K(max_check_num)); } } } } return ret; } // Type is float/double template int real_range_check_only(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))) {} } 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 ObHexUtils::unhex(const ObString& text, ObCastCtx& cast_ctx, ObObj& result) { int ret = OB_SUCCESS; ObString str_result; char* buf = NULL; const bool need_fill_zero = (1 == text.length() % 2); const int32_t tmp_length = text.length() / 2 + need_fill_zero; int32_t alloc_length = (0 == tmp_length ? 1 : tmp_length); if (OB_ISNULL(cast_ctx.allocator_v2_)) { ret = OB_INVALID_ARGUMENT; LOG_WARN("allocator in cast ctx is NULL", K(ret), K(text)); } else if (OB_ISNULL(buf = static_cast(cast_ctx.allocator_v2_->alloc(alloc_length)))) { result.set_null(); ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("alloc memory failed", K(alloc_length), K(ret)); } else { int32_t i = 0; char c1 = 0; char c2 = 0; if (text.length() > 0) { if (need_fill_zero) { c1 = '0'; c2 = text[0]; i = 0; } else { c1 = text[0]; c2 = text[1]; i = 1; } } while (OB_SUCC(ret) && i < text.length()) { if (isxdigit(c1) && isxdigit(c2)) { buf[i / 2] = (char)((get_xdigit(c1) << 4) | get_xdigit(c2)); c1 = text[++i]; c2 = text[++i]; } else { ret = OB_ERR_INVALID_HEX_NUMBER; LOG_WARN("invalid hex number", K(ret), K(c1), K(c2), K(text)); } } if (OB_SUCC(ret)) { str_result.assign_ptr(buf, tmp_length); result.set_varchar(str_result); } } return ret; } int ObHexUtils::hex(const ObString& text, ObCastCtx& cast_ctx, ObObj& result) { int ret = OB_SUCCESS; ObString str_result; char* buf = NULL; const int32_t alloc_length = text.empty() ? 1 : text.length() * 2; if (OB_ISNULL(cast_ctx.allocator_v2_)) { ret = OB_INVALID_ARGUMENT; LOG_WARN("allocator in cast ctx is NULL", K(ret), K(text)); } else if (OB_ISNULL(buf = static_cast(cast_ctx.allocator_v2_->alloc(alloc_length)))) { result.set_null(); ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("alloc memory failed", K(ret), K(alloc_length)); } else { static const char* HEXCHARS = "0123456789ABCDEF"; int32_t pos = 0; for (int32_t i = 0; i < text.length(); ++i) { buf[pos++] = HEXCHARS[text[i] >> 4 & 0xF]; buf[pos++] = HEXCHARS[text[i] & 0xF]; } str_result.assign_ptr(buf, pos); result.set_varchar(str_result); LOG_DEBUG("succ to hex", K(text), "length", text.length(), K(str_result)); } return ret; } int ObHexUtils::hex_for_mysql(const uint64_t uint_val, common::ObCastCtx& cast_ctx, common::ObObj& result) { int ret = OB_SUCCESS; char* buf = NULL; const int32_t MAX_INT64_LEN = 20; if (OB_ISNULL(cast_ctx.allocator_v2_)) { ret = OB_INVALID_ARGUMENT; LOG_WARN("allocator in cast ctx is NULL", K(ret), K(uint_val)); } else if (OB_ISNULL(buf = static_cast(cast_ctx.allocator_v2_->alloc(MAX_INT64_LEN)))) { result.set_null(); ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("alloc memory failed", K(ret)); } else { int pos = snprintf(buf, MAX_INT64_LEN, "%lX", uint_val); if (OB_UNLIKELY(pos <= 0) || OB_UNLIKELY(pos >= MAX_INT64_LEN)) { ret = OB_SIZE_OVERFLOW; LOG_ERROR("size is overflow", K(ret), K(uint_val)); } else { ObString str_result(pos, buf); result.set_varchar(str_result); } } return ret; } // https://docs.oracle.com/en/database/oracle/oracle-database/12.2/sqlrf/RAWTOHEX.html // As a SQL built-in function, RAWTOHEX accepts an argument of any scalar data type other than LONG, // LONG RAW, CLOB, NCLOB, BLOB, or BFILE. If the argument is of a data type other than RAW, // then this function converts the argument value, which is represented using some number of data bytes, // into a RAW value with the same number of data bytes. The data itself is not modified in any way, // but the data type is recast to a RAW data type. int ObHexUtils::rawtohex(const ObObj& text, ObCastCtx& cast_ctx, ObObj& result) { int ret = OB_SUCCESS; if (text.is_null()) { result.set_null(); } else { ObString str; ObObj num_obj; char* splice_num_str = NULL; // for splice Desc and degits_ of number. ObOTimestampData time_value; switch (text.get_type()) { // TODO::this should same as oracle, and support dump func case ObTinyIntType: case ObSmallIntType: case ObInt32Type: case ObIntType: { int64_t int_value = text.get_int(); number::ObNumber nmb; if (OB_FAIL(nmb.from(int_value, cast_ctx))) { LOG_WARN("fail to int_number", K(ret), K(int_value), "type", text.get_type()); } else { num_obj.set_number(ObNumberType, nmb); int32_t alloc_len = static_cast(sizeof(num_obj.get_number_desc()) + num_obj.get_number_byte_length()); if (OB_ISNULL(cast_ctx.allocator_v2_)) { ret = OB_INVALID_ARGUMENT; LOG_WARN("allocator in cast ctx is NULL", K(ret)); } else if (OB_ISNULL(splice_num_str = static_cast(cast_ctx.allocator_v2_->alloc(alloc_len)))) { result.set_null(); ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("alloc memory failed", K(ret), K(alloc_len)); } else { MEMCPY(splice_num_str, &(num_obj.get_number_desc()), sizeof(num_obj.get_number_desc())); MEMCPY(splice_num_str + sizeof(num_obj.get_number_desc()), num_obj.get_data_ptr(), num_obj.get_number_byte_length()); str.assign_ptr(static_cast(splice_num_str), alloc_len); } LOG_DEBUG("succ to int_number", K(ret), K(int_value), "type", num_obj.get_type(), K(nmb), K(str)); } break; } case ObNumberFloatType: case ObNumberType: { int32_t alloc_len = static_cast(sizeof(text.get_number_desc()) + text.get_number_byte_length()); if (OB_ISNULL(cast_ctx.allocator_v2_)) { ret = OB_INVALID_ARGUMENT; LOG_WARN("allocator in cast ctx is NULL", K(ret)); } else if (OB_ISNULL(splice_num_str = static_cast(cast_ctx.allocator_v2_->alloc(alloc_len)))) { result.set_null(); ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("alloc memory failed", K(ret), K(alloc_len)); } else { MEMCPY(splice_num_str, &(text.get_number_desc()), sizeof(text.get_number_desc())); MEMCPY(splice_num_str + sizeof(text.get_number_desc()), text.get_data_ptr(), text.get_number_byte_length()); str.assign_ptr(static_cast(splice_num_str), alloc_len); } break; } case ObDateTimeType: { str.assign_ptr(static_cast(text.get_data_ptr()), static_cast(sizeof(int64_t))); break; } case ObNVarchar2Type: case ObNCharType: case ObVarcharType: case ObCharType: case ObLongTextType: case ObRawType: { // https://www.techonthenet.com/oracle/functions/rawtohex.php // NOTE:: when convert string to raw, Oracle use utl_raw.cast_to_raw(), while PL/SQL use hextoraw() // here we use utl_raw.cast_to_raw(), as we can not distinguish in which SQL str = text.get_varbinary(); break; } case ObTimestampTZType: case ObTimestampLTZType: case ObTimestampNanoType: { time_value = text.get_otimestamp_value(); str.assign_ptr(reinterpret_cast(&time_value), static_cast(text.get_otimestamp_store_size())); break; } case ObLobType: { const ObLobLocator* lob_locator = text.get_lob_locator(); if (OB_ISNULL(lob_locator)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("lob_locator is null", K(ret)); } else if (OB_FAIL(lob_locator->get_payload(str))) { LOG_WARN("get payload from lob_locator failed", K(ret), K(*lob_locator)); } break; } default: { ret = OB_ERR_INVALID_HEX_NUMBER; LOG_WARN("invalid hex number", K(ret), K(text), "type", text.get_type()); } } if (OB_SUCC(ret)) { if (OB_FAIL(hex(str, cast_ctx, result))) { LOG_WARN("fail to convert to hex", K(ret), K(str)); } else { result.set_default_collation_type(); } } } LOG_DEBUG("succ to rawtohex", "type", text.get_type(), K(text), K(result), K(lbt())); return ret; } int ObHexUtils::hextoraw(const ObObj& text, ObCastCtx& cast_ctx, ObObj& result) { int ret = OB_SUCCESS; if (text.is_null()) { result.set_null(); } else if (text.is_numeric_type()) { number::ObNumber nmb_val; if (OB_FAIL(get_uint(text, cast_ctx, nmb_val))) { LOG_WARN("fail to get uint64", K(ret), K(text)); } else if (OB_FAIL(uint_to_raw(nmb_val, cast_ctx, result))) { LOG_WARN("fail to convert to hex", K(ret), K(nmb_val)); } } else if (text.is_raw()) { // fast path if (OB_FAIL(copy_raw(text, cast_ctx, result))) { LOG_WARN("fail to convert to hex", K(ret), K(text)); } } else if (text.is_character_type() || text.is_varbinary_or_binary()) { ObString utf8_string; if (OB_FAIL(convert_string_collation( text.get_string(), text.get_collation_type(), utf8_string, ObCharset::get_system_collation(), cast_ctx))) { LOG_WARN("convert_string_collation", K(ret)); } else if (OB_FAIL(unhex(utf8_string, cast_ctx, result))) { LOG_WARN("fail to convert to hex", K(ret), K(text)); } else { result.set_raw(result.get_raw()); } } else { ret = OB_ERR_INVALID_HEX_NUMBER; LOG_WARN("invalid hex number", K(ret), K(text)); } LOG_DEBUG("succ to hextoraw", "type", text.get_type(), K(text), K(result.get_raw()), K(result), K(lbt())); return ret; } int ObHexUtils::get_uint(const ObObj& obj, ObCastCtx& cast_ctx, number::ObNumber& out) { int ret = OB_SUCCESS; if (OB_UNLIKELY(!ob_is_accurate_numeric_type(obj.get_type()))) { ret = OB_ERR_INVALID_HEX_NUMBER; LOG_WARN("invalid hex number", K(ret), K(obj)); } else if (obj.is_number() || obj.is_unumber()) { const number::ObNumber& value = obj.get_number(); if (OB_FAIL(out.from(value, cast_ctx))) { LOG_WARN("deep copy failed", K(ret), K(obj)); } else if (OB_UNLIKELY(!out.is_integer()) || OB_UNLIKELY(out.is_negative())) { ret = OB_ERR_INVALID_HEX_NUMBER; LOG_WARN("invalid hex number", K(ret), K(out)); } else if (OB_FAIL(out.round(0))) { LOG_WARN("round failed", K(ret), K(out)); } } else { if (OB_UNLIKELY(obj.get_int() < 0)) { ret = OB_ERR_INVALID_HEX_NUMBER; LOG_WARN("invalid hex number", K(ret), K(obj)); } else if (OB_FAIL(out.from(obj.get_int(), cast_ctx))) { LOG_WARN("deep copy failed", K(ret), K(obj)); } } return ret; } int ObHexUtils::uint_to_raw(const number::ObNumber& uint_num, ObCastCtx& cast_ctx, ObObj& result) { int ret = OB_SUCCESS; const int64_t oracle_max_avail_len = 40; char uint_buf[number::ObNumber::MAX_TOTAL_SCALE] = {0}; int64_t uint_pos = 0; ObString uint_str; if (OB_FAIL(uint_num.format(uint_buf, number::ObNumber::MAX_TOTAL_SCALE, uint_pos, 0))) { LOG_WARN("fail to format ", K(ret), K(uint_num)); } else if (uint_pos > oracle_max_avail_len) { ret = OB_ERR_INVALID_HEX_NUMBER; LOG_WARN("invalid hex number", K(ret), K(uint_pos), K(oracle_max_avail_len), K(uint_num)); } else { uint_str.assign_ptr(uint_buf, static_cast(uint_pos)); if (OB_FAIL(unhex(uint_str, cast_ctx, result))) { LOG_WARN("fail to str_to_raw", K(ret), K(result)); } else { result.set_raw(result.get_raw()); } } return ret; } int ObHexUtils::copy_raw(const common::ObObj& obj, common::ObCastCtx& cast_ctx, common::ObObj& result) { int ret = OB_SUCCESS; char* buf = NULL; const ObString& value = obj.get_raw(); const int32_t alloc_length = value.empty() ? 1 : value.length(); if (OB_ISNULL(cast_ctx.allocator_v2_)) { ret = OB_INVALID_ARGUMENT; LOG_WARN("allocator in cast ctx is NULL", K(ret)); } else if (OB_ISNULL(buf = static_cast(cast_ctx.allocator_v2_->alloc(alloc_length)))) { result.set_null(); ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("alloc memory failed", K(ret), K(alloc_length)); } else { MEMCPY(buf, value.ptr(), value.length()); result.set_raw(buf, value.length()); } return ret; } static int check_convert_string(const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out) { int ret = OB_SUCCESS; // UNUSED(expect_type); // UNUSED(params); // if (lib::is_oracle_mode()) { // //varchar2 --> raw // if (in.is_varchar_or_char() && ob_is_varbinary_type(expect_type, params.expect_obj_collation_)) { // if (OB_FAIL(ObHexUtils::hextoraw(in, params, out))) { // LOG_WARN("fail to hextoraw", K(ret), K(in)); // } // //raw --> varchar2 // } else if (in.is_varbinary() && ob_is_varchar_char_type(expect_type, params.expect_obj_collation_)) { // if (OB_FAIL(ObHexUtils::rawtohex(in, params, out))) { // LOG_WARN("fail to rawtohex", K(ret), K(in)); // } // } else { // //TODO::for lob, for long raw , // out = in; // LOG_DEBUG("do nothing"); // } // LOG_DEBUG("finish check_convert_string", K(ret), "in_type", in.get_type(), "in_cs_type", // in.get_collation_type(), K(in), K(expect_type), "expect_cs_type", params.dest_collation_, K(out)); if (lib::is_oracle_mode() && ob_is_blob(expect_type, params.expect_obj_collation_) && !in.is_blob() && !in.is_raw()) { if (in.is_varchar_or_char()) { if (OB_FAIL(ObHexUtils::hextoraw(in, params, out))) { LOG_WARN("fail to hextoraw for blob", K(ret), K(in)); } } else { ret = OB_NOT_SUPPORTED; LOG_ERROR("invalid use of blob type", K(ret), K(in), K(expect_type)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "Cast to blob type"); } } else { out = in; } return ret; } static int check_convert_string( const ObObjType expect_type, ObObjCastParams& params, const ObString& in_string, ObObj& out) { ObObj tmp_obj; tmp_obj.set_varchar(in_string); return check_convert_string(expect_type, params, tmp_obj, out); } static int check_convert_string( const ObObjType expect_type, ObObjCastParams& params, const char* in_str, const int64_t len, ObObj& out) { ObObj tmp_obj; tmp_obj.set_varchar(in_str, static_cast(len)); return check_convert_string(expect_type, params, tmp_obj, out); } //////////////////////////////////////////////////////////////// // Int -> XXX static const double ROUND_DOUBLE = 0.5; static int int_int( const ObObjType expect_type, ObObjCastParams& params, 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& params, 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& params, 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 { double value = static_cast(in.get_int()); if (ObUFloatType == expect_type && CAST_FAIL(numeric_negative_check(value))) { } else { out.set_float(expect_type, static_cast(value)); } } SET_RES_ACCURACY(PRECISION_UNKNOWN_YET, SCALE_UNKNOWN_YET, LENGTH_UNKNOWN_YET); return ret; } static int int_double( const ObObjType expect_type, ObObjCastParams& params, 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& params, 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& params, 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 { ObTimeConvertCtx cvrt_ctx(params.dtc_params_.tz_info_, ObTimestampType == expect_type); int64_t value = 0; if (in.get_int() < 0) { ret = OB_INVALID_DATE_FORMAT; } else { ret = ObTimeConverter::int_to_datetime(in.get_int(), 0, cvrt_ctx, value); } if (CAST_FAIL(ret)) { } 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_datetime_interval( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; if (OB_UNLIKELY(ObIntTC != in.get_type_class()) || OB_UNLIKELY(ObDateTimeTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else { // oracle treate int as day int64_t value = in.get_int() * USECS_PER_DAY; SET_RES_DATETIME(out); LOG_DEBUG("succ to int_datetime_interval", K(ret), K(in), K(value), K(expect_type)); } 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& params, 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& params, 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& params, 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& params, 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 { ObObj tmp_out; ObFastFormatInt ffi(in.get_int()); ObString tmp_str; if (OB_FAIL(convert_string_collation(ObString(ffi.length(), ffi.ptr()), ObCharset::get_system_collation(), tmp_str, params.dest_collation_, params))) { LOG_WARN("fail to convert string collation", K(ret)); } else if (OB_FAIL(check_convert_string(expect_type, params, tmp_str.ptr(), tmp_str.length(), tmp_out))) { LOG_WARN("fail to check_convert_string", K(ret), K(in), K(expect_type)); } else if (OB_FAIL(copy_string(params, expect_type, tmp_out.get_string(), out))) { } else { res_length = static_cast(out.get_string_len()); } } SET_RES_ACCURACY_STRING(expect_type, DEFAULT_PRECISION_FOR_STRING, res_length); UNUSED(cast_mode); return ret; } static int int_bit( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { UNUSED(cast_mode); int ret = OB_SUCCESS; uint64_t value = static_cast(in.get_int()); int32_t bit_len = 0; if (OB_UNLIKELY(ObIntTC != in.get_type_class() || ObBitTC != 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(get_bit_len(value, bit_len))) { LOG_WARN("fail to get bit len", K(ret), K(value), K(bit_len)); } else { SET_RES_BIT(out); SET_RES_ACCURACY(static_cast(bit_len), DEFAULT_SCALE_FOR_BIT, DEFAULT_LENGTH_FOR_NUMERIC); } return ret; } static int uint_enum(const ObExpectType& expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out); static int int_enum(const ObExpectType& expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out) { int ret = OB_SUCCESS; if (OB_UNLIKELY(ObEnumType != expect_type.get_type()) || OB_UNLIKELY(ObIntTC != in.get_type_class())) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", K(expect_type), K(in), K(ret)); } else { uint64_t value = static_cast(in.get_int()); ObObj uint_val; uint_val.set_uint64(value); if (OB_FAIL(uint_enum(expect_type, params, uint_val, out))) { LOG_WARN("fail to cast uint to enum", K(expect_type), K(in), K(uint_val), K(out), K(ret)); } } return ret; } static int uint_set(const ObExpectType& expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out); static int int_set(const ObExpectType& expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out) { int ret = OB_SUCCESS; if (OB_UNLIKELY(ObSetType != expect_type.get_type()) || OB_UNLIKELY(ObIntTC != in.get_type_class())) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", K(expect_type), K(in), K(ret)); } else { uint64_t value = static_cast(in.get_int()); ObObj uint_val; uint_val.set_uint64(value); if (OB_FAIL(uint_set(expect_type, params, uint_val, out))) { LOG_WARN("fail to cast uint to enum", K(expect_type), K(in), K(uint_val), K(out), K(ret)); } } return ret; } static int string_lob(const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode, const ObLobLocator* lob_locator); static int string_lob( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { return string_lob(expect_type, params, in, out, cast_mode, NULL); } #define CAST_TO_LOB_METHOD(TYPE, TYPE_CLASS) \ static int TYPE##_lob( \ const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) \ { \ int ret = OB_SUCCESS; \ ObObj tmp_val; \ if (OB_UNLIKELY(TYPE_CLASS != in.get_type_class() || ObLobTC != 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(TYPE##_string(ObLongTextType, params, in, tmp_val, cast_mode))) { \ LOG_WARN("fail to cast" #TYPE "to string", K(ret), K(expect_type), K(in), K(tmp_val)); \ } else if (OB_FAIL(string_lob(expect_type, params, tmp_val, out, cast_mode))) { \ LOG_WARN("fail to cast string to lob", K(ret), K(expect_type), K(in), K(tmp_val)); \ } \ return ret; \ } CAST_TO_LOB_METHOD(int, ObIntTC); //////////////////////////////////////////////////////////////// // UInt -> XXX static int uint_int( const ObObjType expect_type, ObObjCastParams& params, 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& params, 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& params, 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 { // for compatibility with mysql, we cast uint to double first, then to float. double value = static_cast(in.get_uint64()); out.set_float(expect_type, static_cast(value)); } 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& params, 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& params, 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& params, 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& params, 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& params, 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& params, 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& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; ObLength res_length = -1; 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 { ObObj tmp_out; ObFastFormatInt ffi(in.get_uint64()); ObString tmp_str; if (OB_FAIL(convert_string_collation(ObString(ffi.length(), ffi.ptr()), ObCharset::get_system_collation(), tmp_str, params.dest_collation_, params))) { LOG_WARN("fail to convert string collation", K(ret)); } else if (OB_FAIL(check_convert_string(expect_type, params, tmp_str.ptr(), tmp_str.length(), tmp_out))) { LOG_WARN("fail to check_convert_string", K(ret), K(in), K(expect_type)); } else if (OB_FAIL(copy_string(params, expect_type, tmp_out.get_string(), out))) { } else { res_length = static_cast(out.get_string_len()); } } UNUSED(cast_mode); SET_RES_ACCURACY_STRING(expect_type, DEFAULT_PRECISION_FOR_STRING, res_length); return ret; } static int uint_bit( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { UNUSED(cast_mode); int ret = OB_SUCCESS; uint64_t value = in.get_uint64(); int32_t bit_len = 0; if (OB_UNLIKELY(ObUIntTC != in.get_type_class() || ObBitTC != 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(get_bit_len(value, bit_len))) { LOG_WARN("fail to get bit len", K(ret), K(value), K(bit_len)); } else { SET_RES_BIT(out); SET_RES_ACCURACY(static_cast(bit_len), DEFAULT_SCALE_FOR_BIT, DEFAULT_LENGTH_FOR_NUMERIC); } return ret; } static int uint_enum(const ObExpectType& expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out) { int ret = OB_SUCCESS; ObCastMode cast_mode = params.cast_mode_; const ObIArray* type_infos = NULL; if (OB_UNLIKELY(ObEnumType != expect_type.get_type()) || OB_UNLIKELY(ObUIntTC != in.get_type_class()) || OB_ISNULL(type_infos = expect_type.get_type_infos())) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", K(expect_type), K(in), K(ret)); } else { uint64_t value = in.get_uint64(); if (OB_UNLIKELY(0 == value || value > type_infos->count())) { value = 0; ret = OB_ERR_DATA_TRUNCATED; LOG_WARN("input value out of range", K(in), K(expect_type), K(ret)); } if (OB_FAIL(ret) && CM_IS_WARN_ON_FAIL(cast_mode)) { params.warning_ = OB_ERR_DATA_TRUNCATED; ret = OB_SUCCESS; } LOG_DEBUG("finish uint_enum", K(ret), K(expect_type), K(in), K(out), KPC(type_infos), K(lbt())); SET_RES_ENUM(out); } return ret; } static int uint_set(const ObExpectType& expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out) { int ret = OB_SUCCESS; ObCastMode cast_mode = params.cast_mode_; const ObIArray* type_infos = NULL; int64_t val_cnt = 0; if (OB_UNLIKELY(ObSetType != expect_type.get_type()) || OB_UNLIKELY(ObUIntTC != in.get_type_class()) || OB_ISNULL(type_infos = expect_type.get_type_infos())) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", K(expect_type), K(in), K(ret)); } else { uint64_t value = in.get_uint64(); val_cnt = type_infos->count(); if (OB_UNLIKELY(val_cnt <= 0)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpect val_cnt", K(in), K(out), K(expect_type), K(ret)); } else if (val_cnt >= 64) { // do nothing } else if (val_cnt < 64 && value > ((1ULL << val_cnt) - 1)) { value = value & ((1ULL << val_cnt) - 1); ret = OB_ERR_DATA_TRUNCATED; LOG_WARN("input value out of range", K(in), K(val_cnt), K(ret)); } if (OB_FAIL(ret) && CM_IS_WARN_ON_FAIL(cast_mode)) { params.warning_ = OB_ERR_DATA_TRUNCATED; ret = OB_SUCCESS; } LOG_DEBUG("finish uint_set", K(ret), K(expect_type), K(in), K(out), KPC(type_infos), K(lbt())); SET_RES_SET(out); } return ret; } CAST_TO_LOB_METHOD(uint, ObUIntTC); //////////////////////////////////////////////////////////////// // 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. int common_double_int(const double in, int64_t& out, const int64_t trunc_min_value, const int64_t trunc_max_value) { int ret = OB_SUCCESS; out = 0; if (in <= static_cast(LLONG_MIN)) { out = trunc_min_value; if (in < static_cast(LLONG_MIN)) { ret = OB_DATA_OUT_OF_RANGE; } } else if (in >= static_cast(LLONG_MAX)) { out = trunc_max_value; if (in > static_cast(LLONG_MAX)) { ret = OB_DATA_OUT_OF_RANGE; } } else { out = static_cast(rint(in)); } return ret; } static int float_int( const ObObjType expect_type, ObObjCastParams& params, 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 (CAST_FAIL(common_double_int( in.get_float(), value, LLONG_MIN, CM_IS_COLUMN_CONVERT(cast_mode) ? LLONG_MAX : LLONG_MIN))) { LOG_WARN("cast float to int failed", K(ret), K(in), K(value)); } else if (CAST_FAIL(int_range_check(expect_type, value, 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& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; uint64_t value = 0; ObPrecision res_precision = -1; double in_value = static_cast(in.get_float()); bool is_column_convert = CM_IS_COLUMN_CONVERT(cast_mode); 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_value <= static_cast(LLONG_MIN) || in_value >= static_cast(ULLONG_MAX)) { value = static_cast(LLONG_MIN); ret = OB_DATA_OUT_OF_RANGE; } else { if (is_column_convert) { value = static_cast(rint(in_value)); } else { value = static_cast(static_cast(rint(in_value))); } if (in_value < 0 && value != 0) { ret = OB_DATA_OUT_OF_RANGE; } } if (CAST_FAIL(ret)) { LOG_WARN("cast float to uint failed", K(ret), K(in), K(value)); } } if (OB_FAIL(ret)) { } else if (CM_NEED_RANGE_CHECK(cast_mode) && CAST_FAIL(uint_range_check(expect_type, value, 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& params, 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& params, 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& params, 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_DOUBLE_STRICT_PRINT_SIZE]; MEMSET(buf, 0, MAX_DOUBLE_STRICT_PRINT_SIZE); int64_t length = 0; if (lib::is_oracle_mode()) { length = ob_gcvt_opt(in.get_float(), OB_GCVT_ARG_FLOAT, sizeof(buf) - 1, buf, NULL, TRUE); } else { length = ob_gcvt(in.get_float(), OB_GCVT_ARG_DOUBLE, sizeof(buf) - 1, buf, NULL); } ObString str(sizeof(buf), static_cast(length), buf); number::ObNumber nmb; if (OB_FAIL(nmb.from_sci_opt(str.ptr(), str.length(), params, &res_precision, &res_scale))) { LOG_WARN("fail to from str to number", K(ret), K(str)); } else { out.set_number(expect_type, nmb); } LOG_DEBUG("finish float to number", K(ret), K(str), K(length), K(in), K(expect_type), K(nmb), K(out), K(lbt())); } SET_RES_ACCURACY(res_precision, res_scale, DEFAULT_LENGTH_FOR_NUMERIC); return ret; } static int double_datetime( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode); static int float_datetime( const ObObjType expect_type, ObObjCastParams& params, 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_datetime_interval( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode); static int float_datetime_interval( const ObObjType expect_type, ObObjCastParams& params, 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_interval(expect_type, params, dbl, out, cast_mode))) { } return ret; } static int double_date( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode); static int float_date( const ObObjType expect_type, ObObjCastParams& params, 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& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode); static int float_time( const ObObjType expect_type, ObObjCastParams& params, 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& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; char buf[OB_CAST_TO_VARCHAR_MAX_LENGTH] = {0}; 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, sizeof(buf) - 1, buf, NULL, lib::is_oracle_mode()); } ObString str(sizeof(buf), static_cast(length), buf); LOG_DEBUG("finish float_string", K(ret), K(in), K(expect_type), K(str)); ObObj tmp_out; ObString tmp_str; if (OB_FAIL(convert_string_collation( str, ObCharset::get_system_collation(), tmp_str, params.dest_collation_, params))) { LOG_WARN("fail to convert string collation", K(ret)); } else if (OB_FAIL(check_convert_string(expect_type, params, tmp_str.ptr(), tmp_str.length(), tmp_out))) { LOG_WARN("fail to check_convert_string", K(ret), K(in), K(expect_type)); } else if (OB_FAIL(copy_string(params, expect_type, tmp_out.get_string(), out))) { } else { res_length = static_cast(out.get_string_len()); } } UNUSED(cast_mode); SET_RES_ACCURACY_STRING(expect_type, DEFAULT_PRECISION_FOR_STRING, res_length); return ret; } static int float_bit( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { UNUSED(cast_mode); int ret = OB_SUCCESS; uint64_t value = static_cast(in.get_float()); int32_t bit_len = 0; if (OB_UNLIKELY(ObFloatTC != in.get_type_class() || ObBitTC != 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(get_bit_len(value, bit_len))) { LOG_WARN("fail to get bit len", K(ret), K(value), K(bit_len)); } else { SET_RES_BIT(out); SET_RES_ACCURACY(static_cast(bit_len), DEFAULT_SCALE_FOR_BIT, DEFAULT_LENGTH_FOR_NUMERIC); } return ret; } static int float_enum(const ObExpectType& expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out) { int ret = OB_SUCCESS; if (OB_UNLIKELY(ObEnumType != expect_type.get_type()) || OB_UNLIKELY(ObFloatTC != in.get_type_class())) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", K(expect_type), K(in), K(ret)); } else { int64_t value = static_cast(in.get_float()); ObObj int_val(value); if (OB_FAIL(int_enum(expect_type, params, int_val, out))) { LOG_WARN("fail to cast int to enum", K(expect_type), K(in), K(int_val), K(out), K(ret)); } } return ret; } static int float_set(const ObExpectType& expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out) { int ret = OB_SUCCESS; if (OB_UNLIKELY(ObSetType != expect_type.get_type()) || OB_UNLIKELY(ObFloatTC != in.get_type_class())) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", K(expect_type), K(in), K(ret)); } else { int64_t value = static_cast(in.get_float()); ObObj int_val(value); if (OB_FAIL(int_set(expect_type, params, int_val, out))) { LOG_WARN("fail to cast int to enum", K(expect_type), K(in), K(int_val), K(out), K(ret)); } } return ret; } CAST_TO_LOB_METHOD(float, ObFloatTC); //////////////////////////////////////////////////////////////// // Double -> XXX static int double_int( const ObObjType expect_type, ObObjCastParams& params, 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 (CAST_FAIL(common_double_int(in.get_double(), value, LLONG_MIN, LLONG_MAX))) { LOG_WARN("common double to in failed", K(ret), K(in), K(cast_mode)); } else if (CAST_FAIL(int_range_check(expect_type, value, value))) { LOG_WARN("int range check failed", K(ret), K(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& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; uint64_t value = 0; ObPrecision res_precision = -1; double in_value = in.get_double(); bool is_column_convert = CM_IS_COLUMN_CONVERT(cast_mode); 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_value <= static_cast(LLONG_MIN)) { value = static_cast(LLONG_MIN); ret = OB_DATA_OUT_OF_RANGE; } else if (in_value >= static_cast(ULLONG_MAX)) { value = static_cast(LLONG_MAX); ret = OB_DATA_OUT_OF_RANGE; } else { if (is_column_convert) { value = static_cast(rint(in_value)); } else if (in_value >= static_cast(LLONG_MAX)) { value = static_cast(LLONG_MAX); } else { value = static_cast(static_cast(rint(in_value))); } if (in_value < 0 && value != 0) { ret = OB_DATA_OUT_OF_RANGE; } } if (CAST_FAIL(ret)) { LOG_WARN("cast float to uint failed", K(ret), K(in), K(value)); } } if (OB_FAIL(ret)) { } else if (CM_NEED_RANGE_CHECK(cast_mode) && CAST_FAIL(uint_range_check(expect_type, value, 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& params, 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); LOG_DEBUG("succ to double_float", K(ret), K(in), K(value), K(out)); } SET_RES_ACCURACY(PRECISION_UNKNOWN_YET, SCALE_UNKNOWN_YET, LENGTH_UNKNOWN_YET); return ret; } static int double_double( const ObObjType expect_type, ObObjCastParams& params, 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& params, 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_STRICT_PRINT_SIZE]; MEMSET(buf, 0, MAX_DOUBLE_STRICT_PRINT_SIZE); int64_t length = ob_gcvt_opt(in.get_double(), OB_GCVT_ARG_DOUBLE, sizeof(buf) - 1, buf, NULL, lib::is_oracle_mode()); ObString str(sizeof(buf), static_cast(length), buf); number::ObNumber nmb; if (OB_FAIL(nmb.from_sci_opt(str.ptr(), str.length(), params, &res_precision, &res_scale))) { } else { out.set_number(expect_type, nmb); } LOG_DEBUG("finish double to number", K(ret), K(str), K(length), K(in), K(expect_type), K(nmb), K(out), K(lbt())); } SET_RES_ACCURACY(res_precision, res_scale, DEFAULT_LENGTH_FOR_NUMERIC); return ret; } static int number_datetime( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode); static int double_datetime( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { // double to datetime must cast to number 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 number. int ret = OB_SUCCESS; ObScale res_scale = -1; int64_t value = 0; ObTimeConvertCtx cvrt_ctx(params.dtc_params_.tz_info_, ObTimestampType == expect_type); ObObj tmp_num_obj; 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 if (OB_FAIL(double_number(ObNumberType, params, in, tmp_num_obj, cast_mode))) { LOG_WARN("cast double to number failed", K(ret), K(cast_mode)); if (CM_IS_WARN_ON_FAIL(cast_mode)) { ret = OB_SUCCESS; if (CM_IS_ZERO_ON_WARN(cast_mode)) { out.set_datetime(expect_type, ObTimeConverter::ZERO_DATETIME); } else { out.set_null(); } } else { ret = OB_INVALID_DATE_VALUE; } } else if (CAST_FAIL(number_datetime(expect_type, params, tmp_num_obj, out, cast_mode))) { LOG_WARN("number to datetime failed", K(ret)); } return ret; } static int double_datetime_interval( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; ObScale res_scale = -1; if (OB_UNLIKELY(ObDoubleTC != in.get_type_class()) || OB_UNLIKELY(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 int64_t value = static_cast(in.get_double() * static_cast(USECS_PER_DAY)); LOG_DEBUG("succ to double_datetime_interval", K(ret), K(in), K(value), K(expect_type)); 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& params, 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& params, 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(in.get_double(), OB_GCVT_ARG_DOUBLE, sizeof(buf) - 1, buf, NULL); 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_year(const ObObjType expect_type, ObObjCastParams ¶ms, const ObObj &in, ObObj &out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; if (OB_UNLIKELY(ObDoubleTC != 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; double in_val = in.get_double(); in_val = in_val < 0 ? INT_MIN : in_val + 0.5; uint64_t intvalue = static_cast(in_val); if (CAST_FAIL(ObTimeConverter::int_to_year(intvalue, 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 double_string( const ObObjType expect_type, ObObjCastParams& params, 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] = {0}; 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, sizeof(buf) - 1, buf, NULL, lib::is_oracle_mode()); } ObString str(sizeof(buf), static_cast(length), buf); LOG_DEBUG("finish double_string", K(ret), K(in), K(expect_type), K(str)); ObObj tmp_out; ObString tmp_str; if (OB_FAIL(convert_string_collation( str, ObCharset::get_system_collation(), tmp_str, params.dest_collation_, params))) { LOG_WARN("fail to convert string collation", K(ret)); } else if (OB_FAIL(check_convert_string(expect_type, params, tmp_str, tmp_out))) { LOG_WARN("fail to check_convert_string", K(ret), K(in), K(expect_type)); } else if (OB_FAIL(copy_string(params, expect_type, tmp_out.get_string(), out))) { } else { res_length = static_cast(out.get_string_len()); } } SET_RES_ACCURACY_STRING(expect_type, DEFAULT_PRECISION_FOR_STRING, res_length); UNUSED(cast_mode); return ret; } static int double_bit( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { UNUSED(cast_mode); int ret = OB_SUCCESS; uint64_t value = static_cast(in.get_double()); int32_t bit_len = 0; if (OB_UNLIKELY(ObDoubleTC != in.get_type_class() || ObBitTC != 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(get_bit_len(value, bit_len))) { LOG_WARN("fail to get bit len", K(ret), K(value), K(bit_len)); } else { SET_RES_BIT(out); SET_RES_ACCURACY(static_cast(bit_len), DEFAULT_SCALE_FOR_BIT, DEFAULT_LENGTH_FOR_NUMERIC); } return ret; } static int double_enum(const ObExpectType& expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out) { int ret = OB_SUCCESS; if (OB_UNLIKELY(ObEnumType != expect_type.get_type()) || OB_UNLIKELY(ObDoubleTC != in.get_type_class())) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", K(expect_type), K(in), K(ret)); } else { int64_t value = static_cast(in.get_double()); ObObj int_val(value); if (OB_FAIL(int_enum(expect_type, params, int_val, out))) { LOG_WARN("fail to cast int to enum", K(expect_type), K(in), K(int_val), K(out), K(ret)); } } return ret; } static int double_set(const ObExpectType& expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out) { int ret = OB_SUCCESS; if (OB_UNLIKELY(ObSetType != expect_type.get_type()) || OB_UNLIKELY(ObDoubleTC != in.get_type_class())) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", K(expect_type), K(in), K(ret)); } else { int64_t value = static_cast(in.get_double()); ObObj int_val(value); if (OB_FAIL(int_set(expect_type, params, int_val, out))) { LOG_WARN("fail to cast int to enum", K(expect_type), K(in), K(int_val), K(out), K(ret)); } } return ret; } CAST_TO_LOB_METHOD(double, ObDoubleTC); //////////////////////////////////////////////////////////////// // Number -> XXX static int string_int( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode); static int number_int( const ObObjType expect_type, ObObjCastParams& params, 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 { const 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, CM_UNSET_STRING_INTEGER_TRUNC(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& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode); static int number_uint( const ObObjType expect_type, ObObjCastParams& params, 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 { const 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, CM_UNSET_STRING_INTEGER_TRUNC(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& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode); static int number_float( const ObObjType expect_type, ObObjCastParams& params, 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& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode); static int number_double( const ObObjType expect_type, ObObjCastParams& params, 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& params, 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 { const 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, NUMBER_SCALE_UNKNOWN_YET, LENGTH_UNKNOWN_YET); return ret; } static int string_datetime( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode); static int number_datetime( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; const int64_t three_digit_min = 100; const int64_t eight_digit_max = 99999999; if (OB_UNLIKELY(ObNumberTC != in.get_type_class() || ObDateTimeTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else { ObTimeConvertCtx cvrt_ctx(params.dtc_params_.tz_info_, ObTimestampType == expect_type); int64_t value = 0; int64_t int_part = 0; int64_t dec_part = 0; if (in.get_number().is_negative()) { ret = OB_INVALID_DATE_FORMAT; LOG_WARN("invalid date format", K(ret), K(in), K(cast_mode)); } else if (!in.get_number().is_int_parts_valid_int64(int_part,dec_part)) { ret = OB_INVALID_DATE_FORMAT; LOG_WARN("invalid date format", K(ret), K(in), K(cast_mode)); } else if (OB_UNLIKELY(dec_part != 0 && ((0 == int_part && ObTimestampType == expect_type) || (int_part >= three_digit_min && int_part <= eight_digit_max)))) { if (CM_IS_COLUMN_CONVERT(cast_mode) && !CM_IS_WARN_ON_FAIL(cast_mode)) { ret = OB_INVALID_DATE_VALUE; LOG_WARN("invalid date value", K(ret)); } else { dec_part = 0; } } if (OB_SUCC(ret)) { ret = ObTimeConverter::int_to_datetime(int_part, dec_part, cvrt_ctx, value); LOG_DEBUG("succ to number_datetime", K(ret), K(in), K(value), K(expect_type), K(int_part), K(dec_part)); } if (CAST_FAIL(ret)) { } else { SET_RES_DATETIME(out); } } SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, MIN_SCALE_FOR_TEMPORAL, DEFAULT_LENGTH_FOR_TEMPORAL); return ret; } static int number_datetime_interval( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; if (OB_UNLIKELY(ObNumberTC != in.get_type_class()) || OB_UNLIKELY(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 int_part = 0; int64_t dec_part = 0; if (!in.get_number().is_int_parts_valid_int64(int_part, dec_part)) { ret = OB_INVALID_DATE_FORMAT; LOG_WARN("invalid date format", K(ret), K(in), K(cast_mode)); } else { const int64_t value = static_cast(int_part * USECS_PER_DAY) + (in.is_negative_number() ? -1 : 1) * static_cast(static_cast(dec_part) / NSECS_PER_SEC * static_cast(USECS_PER_DAY)); LOG_DEBUG("succ to number_datetime_interval", K(ret), K(in), K(value), K(expect_type), K(int_part), K(dec_part)); 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& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode); static int number_date( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; ObObj int64; int32_t value = 0; 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 { int64_t int_part = 0; int64_t dec_part = 0; const number::ObNumber nmb = in.get_number(); if (nmb.is_negative()) { ret = OB_INVALID_DATE_VALUE; LOG_WARN("invalid date value", K(ret), K(nmb)); } else if (!nmb.is_int_parts_valid_int64(int_part, dec_part)) { ret = OB_INVALID_DATE_VALUE; LOG_WARN("invalid date format", K(ret), K(nmb)); } else { ret = ObTimeConverter::int_to_date(int_part, value); if (OB_SUCC(ret) && OB_UNLIKELY(dec_part > 0)) { if (CM_IS_COLUMN_CONVERT(cast_mode) && !CM_IS_WARN_ON_FAIL(cast_mode)) { ret = OB_INVALID_DATE_VALUE; LOG_WARN("invalid date value with decimal part", K(ret)); } } } if (CAST_FAIL(ret)) { } else { SET_RES_DATE(out); } } return ret; } static int string_time( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode); static int number_time( const ObObjType expect_type, ObObjCastParams& params, 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& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode); static int number_year( const ObObjType expect_type, ObObjCastParams& params, 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 if (in.get_number().is_negative()) { uint8_t value = 0; if (CAST_FAIL(ObTimeConverter::int_to_year(INT_MIN, 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& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; char buf[OB_CAST_TO_VARCHAR_MAX_LENGTH] = {0}; 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 (is_oracle_mode() && ob_is_blob(expect_type, params.dest_collation_)) { ret = OB_ERR_INVALID_TYPE_FOR_OP; LOG_WARN("cast number to blob not allowed", K(ret)); } else { if (lib::is_oracle_mode() && params.format_number_with_limit_) { if (OB_FAIL(in.get_number().format_with_oracle_limit(buf, sizeof(buf), len, in.get_scale()))) { LOG_WARN("fail to format", K(ret), K(in.get_number())); } } else { if (OB_FAIL(in.get_number().format(buf, sizeof(buf), len, in.get_scale()))) { LOG_WARN("fail to format", K(ret), K(in.get_number())); } } if (OB_SUCC(ret)) { ObString tmp_str; ObObj tmp_out; if (OB_FAIL(convert_string_collation( ObString(len, buf), ObCharset::get_system_collation(), tmp_str, params.dest_collation_, params))) { LOG_WARN("fail to convert string collation", K(ret)); } else if (OB_FAIL(check_convert_string(expect_type, params, tmp_str, tmp_out))) { LOG_WARN("fail to check_convert_string", K(ret), K(in), K(expect_type)); } else if (OB_FAIL(copy_string(params, expect_type, tmp_out.get_string(), out))) { } else { res_length = static_cast(out.get_string_len()); } } } UNUSED(cast_mode); SET_RES_ACCURACY_STRING(expect_type, DEFAULT_PRECISION_FOR_STRING, res_length); return ret; } static int number_bit( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; ObObj tmp_val; if (OB_UNLIKELY(ObNumberTC != in.get_type_class() || ObBitTC != 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(number_uint(ObUInt64Type, params, in, tmp_val, cast_mode))) { LOG_WARN("fail to cast number to uint", K(ret), K(expect_type), K(in), K(tmp_val)); } else if (OB_FAIL(uint_bit(expect_type, params, tmp_val, out, cast_mode))) { LOG_WARN("fail to cast uint to bit", K(ret), K(expect_type), K(out), K(tmp_val)); } return ret; } static int number_enum(const ObExpectType& expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out) { int ret = OB_SUCCESS; ObObj double_val; ObCastMode cast_mode = params.cast_mode_; if (OB_UNLIKELY(ObEnumType != expect_type.get_type()) || OB_UNLIKELY(ObNumberTC != in.get_type_class())) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", K(expect_type), K(in), K(ret)); } else if (OB_FAIL(number_double(ObDoubleType, params, in, double_val, cast_mode))) { LOG_WARN("fail to cast number to double", K(in), K(double_val), K(ret)); } else if (OB_FAIL(double_enum(expect_type, params, double_val, out))) { LOG_WARN("fail to cast double to enum", K(expect_type), K(out), K(double_val), K(ret)); } return ret; } static int number_set(const ObExpectType& expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out) { int ret = OB_SUCCESS; ObObj double_val; ObCastMode cast_mode = params.cast_mode_; if (OB_UNLIKELY(ObSetType != expect_type.get_type()) || OB_UNLIKELY(ObNumberTC != in.get_type_class())) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", K(expect_type), K(in), K(ret)); } else if (OB_FAIL(number_double(ObDoubleType, params, in, double_val, cast_mode))) { LOG_WARN("fail to cast number to double", K(in), K(double_val), K(ret)); } else if (OB_FAIL(double_set(expect_type, params, double_val, out))) { LOG_WARN("fail to cast double to enum", K(expect_type), K(out), K(double_val), K(ret)); } return ret; } CAST_TO_LOB_METHOD(number, ObNumberTC); //////////////////////////////////////////////////////////// // Datetime -> XXX static int datetime_int( const ObObjType expect_type, ObObjCastParams& params, 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.dtc_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& params, 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.dtc_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& params, 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.dtc_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& params, 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.dtc_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& params, 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.dtc_params_.tz_info_ : NULL; ObString nls_format; char buf[OB_CAST_TO_VARCHAR_MAX_LENGTH] = {0}; int64_t len = 0; number::ObNumber value; if (OB_FAIL(ObTimeConverter::datetime_to_str( in.get_datetime(), tz_info, nls_format, 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& params, 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.dtc_params_.tz_info_, value); ret = OB_ERR_UNEXPECTED_TZ_TRANSITION == ret ? OB_INVALID_DATE_VALUE : ret; } else if (ObTimestampType == in.get_type() && ObDateTimeType == expect_type) { ret = ObTimeConverter::timestamp_to_datetime(in.get_datetime(), params.dtc_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& params, 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.dtc_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& params, 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.dtc_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& params, 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.dtc_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& params, 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.dtc_params_.tz_info_ : NULL; ObString nls_format; if (lib::is_oracle_mode() && !params.dtc_params_.force_use_standard_format_) { nls_format = params.dtc_params_.get_nls_format(ObDateTimeType); } char buf[OB_CAST_TO_VARCHAR_MAX_LENGTH] = {0}; int64_t len = 0; if (OB_FAIL(ObTimeConverter::datetime_to_str( in.get_datetime(), tz_info, nls_format, in.get_scale(), buf, sizeof(buf), len))) { LOG_WARN("failed to convert datetime to string", K(ret)); } else { out.set_type(expect_type); ObString tmp_str; ObObj tmp_out; if (OB_FAIL(convert_string_collation( ObString(len, buf), ObCharset::get_system_collation(), tmp_str, params.dest_collation_, params))) { LOG_WARN("fail to convert string collation", K(ret)); } else if (OB_FAIL(check_convert_string(expect_type, params, tmp_str, tmp_out))) { LOG_WARN("fail to check_convert_string", K(ret), K(in), K(expect_type)); } else if (OB_FAIL(copy_string(params, expect_type, tmp_out.get_string(), out))) { } else { res_length = static_cast(out.get_string_len()); } } } SET_RES_ACCURACY_STRING(expect_type, DEFAULT_PRECISION_FOR_STRING, res_length); UNUSED(cast_mode); return ret; } static int string_bit( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode); static int datetime_bit( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; ObObj tmp_val; if (OB_UNLIKELY(ObDateTimeTC != in.get_type_class() || ObBitTC != 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(datetime_string(ObVarcharType, params, in, tmp_val, cast_mode))) { LOG_WARN("fail to cast datetime to string", K(ret), K(expect_type), K(in), K(tmp_val)); } else if (OB_FAIL(string_bit(expect_type, params, tmp_val, out, cast_mode))) { LOG_WARN("fail to cast string to bit", K(ret), K(expect_type), K(in), K(tmp_val)); } return ret; } static int string_enum(const ObExpectType& expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out); static int datetime_enum(const ObExpectType& expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out) { int ret = OB_SUCCESS; ObObj str_val; ObCastMode cast_mode = params.cast_mode_; if (OB_UNLIKELY(ObEnumType != expect_type.get_type()) || OB_UNLIKELY(ObDateTimeTC != in.get_type_class())) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", K(expect_type), K(in), K(ret)); } else if (OB_FAIL(datetime_string(ObVarcharType, params, in, str_val, cast_mode))) { LOG_WARN("fail to cast number to double", K(in), K(str_val), K(ret)); } else if (OB_FAIL(string_enum(expect_type, params, str_val, out))) { LOG_WARN("fail to cast double to enum", K(expect_type), K(out), K(str_val), K(ret)); } return ret; } static int string_set(const ObExpectType& expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out); static int datetime_set(const ObExpectType& expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out) { int ret = OB_SUCCESS; ObObj str_val; ObCastMode cast_mode = params.cast_mode_; if (OB_UNLIKELY(ObSetType != expect_type.get_type()) || OB_UNLIKELY(ObDateTimeTC != in.get_type_class())) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", K(expect_type), K(in), K(ret)); } else if (OB_FAIL(datetime_string(ObVarcharType, params, in, str_val, cast_mode))) { LOG_WARN("fail to cast number to double", K(in), K(str_val), K(ret)); } else if (OB_FAIL(string_set(expect_type, params, str_val, out))) { LOG_WARN("fail to cast double to enum", K(expect_type), K(out), K(str_val), K(ret)); } return ret; } static int datetime_otimestamp( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; if (OB_UNLIKELY(ObDateTimeTC != in.get_type_class()) || OB_UNLIKELY(ObOTimestampTC != 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 dt_value = 0; if (ObTimestampType == in.get_type()) { int64_t utc_value = in.get_timestamp(); if (OB_FAIL(ObTimeConverter::timestamp_to_datetime(utc_value, params.dtc_params_.tz_info_, dt_value))) { LOG_WARN("failed to convert timestamp to datetime", K(ret)); } } else { dt_value = in.get_datetime(); } if (OB_SUCC(ret)) { int64_t odate_value = 0; ObOTimestampData value; ObTimeConverter::datetime_to_odate(dt_value, odate_value); if (OB_FAIL(ObTimeConverter::odate_to_otimestamp(odate_value, params.dtc_params_.tz_info_, expect_type, value))) { LOG_WARN("fail to timestamp_to_timestamp_tz", K(ret), K(in), K(expect_type)); } else { SET_RES_OTIMESTAMP(out); } } } SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, in.get_scale(), DEFAULT_LENGTH_FOR_TEMPORAL); UNUSED(cast_mode); return ret; } CAST_TO_LOB_METHOD(datetime, ObDateTimeTC); //////////////////////////////////////////////////////////// // Date -> XXX static int date_int( const ObObjType expect_type, ObObjCastParams& params, 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& params, 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& params, 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& params, 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& params, 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& params, 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 { ObTimeConvertCtx cvrt_ctx(params.dtc_params_.tz_info_, ObTimestampType == expect_type); int64_t value = 0; if (OB_FAIL(ObTimeConverter::date_to_datetime(in.get_date(), cvrt_ctx, 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& params, 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& params, 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& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; char buf[OB_CAST_TO_VARCHAR_MAX_LENGTH] = {0}; 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_STRING(expect_type, DEFAULT_PRECISION_FOR_STRING, res_length); UNUSED(cast_mode); return ret; } static int date_bit( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; ObObj tmp_val; if (OB_UNLIKELY(ObDateTC != in.get_type_class() || ObBitTC != 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_string(ObVarcharType, params, in, tmp_val, cast_mode))) { LOG_WARN("fail to cast datetime to string", K(ret), K(expect_type), K(in), K(tmp_val)); } else if (OB_FAIL(string_bit(expect_type, params, tmp_val, out, cast_mode))) { LOG_WARN("fail to cast string to bit", K(ret), K(expect_type), K(in), K(tmp_val)); } return ret; } static int date_enum(const ObExpectType& expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out) { int ret = OB_SUCCESS; ObObj str_val; ObCastMode cast_mode = params.cast_mode_; if (OB_UNLIKELY(ObEnumType != expect_type.get_type()) || OB_UNLIKELY(ObDateTC != in.get_type_class())) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", K(expect_type), K(in), K(ret)); } else if (OB_FAIL(date_string(ObVarcharType, params, in, str_val, cast_mode))) { LOG_WARN("fail to cast number to double", K(in), K(str_val), K(ret)); } else if (OB_FAIL(string_enum(expect_type, params, str_val, out))) { LOG_WARN("fail to cast double to enum", K(expect_type), K(out), K(str_val), K(ret)); } return ret; } static int date_set(const ObExpectType& expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out) { int ret = OB_SUCCESS; ObObj str_val; ObCastMode cast_mode = params.cast_mode_; if (OB_UNLIKELY(ObSetType != expect_type.get_type()) || OB_UNLIKELY(ObDateTC != in.get_type_class())) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", K(expect_type), K(in), K(ret)); } else if (OB_FAIL(date_string(ObVarcharType, params, in, str_val, cast_mode))) { LOG_WARN("fail to cast number to double", K(in), K(str_val), K(ret)); } else if (OB_FAIL(string_set(expect_type, params, str_val, out))) { LOG_WARN("fail to cast double to enum", K(expect_type), K(out), K(str_val), K(ret)); } return ret; } CAST_TO_LOB_METHOD(date, ObDateTC); //////////////////////////////////////////////////////////// // Time -> XXX static int time_int( const ObObjType expect_type, ObObjCastParams& params, 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& params, 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& params, 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& params, 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& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; char buf[OB_CAST_TO_VARCHAR_MAX_LENGTH] = {0}; 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& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; const ObTimeZoneInfo* tz_info = params.dtc_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_date( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; const ObTimeZoneInfo* tz_info = params.dtc_params_.tz_info_; int32_t value = 0; if (OB_UNLIKELY(ObTimeTC != 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(ObTimeConverter::datetime_to_date(params.cur_time_, tz_info, value))) { LOG_WARN("datetime_to_date failed", K(ret), K(params.cur_time_)); } 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 time_string( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; char buf[OB_CAST_TO_VARCHAR_MAX_LENGTH] = {0}; 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_STRING(expect_type, DEFAULT_PRECISION_FOR_STRING, res_length); UNUSED(cast_mode); return ret; } static int time_bit( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; ObObj tmp_val; if (OB_UNLIKELY(ObTimeTC != in.get_type_class() || ObBitTC != 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(time_string(ObVarcharType, params, in, tmp_val, cast_mode))) { LOG_WARN("fail to cast datetime to string", K(ret), K(expect_type), K(in), K(tmp_val)); } else if (OB_FAIL(string_bit(expect_type, params, tmp_val, out, cast_mode))) { LOG_WARN("fail to cast string to bit", K(ret), K(expect_type), K(in), K(tmp_val)); } return ret; } static int time_enum(const ObExpectType& expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out) { int ret = OB_SUCCESS; ObObj str_val; ObCastMode cast_mode = params.cast_mode_; if (OB_UNLIKELY(ObEnumType != expect_type.get_type()) || OB_UNLIKELY(ObTimeTC != in.get_type_class())) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", K(expect_type), K(in), K(ret)); } else if (OB_FAIL(time_string(ObVarcharType, params, in, str_val, cast_mode))) { LOG_WARN("fail to cast number to double", K(in), K(str_val), K(ret)); } else if (OB_FAIL(string_enum(expect_type, params, str_val, out))) { LOG_WARN("fail to cast double to enum", K(expect_type), K(out), K(str_val), K(ret)); } return ret; } static int time_set(const ObExpectType& expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out) { int ret = OB_SUCCESS; ObObj str_val; ObCastMode cast_mode = params.cast_mode_; if (OB_UNLIKELY(ObSetType != expect_type.get_type()) || OB_UNLIKELY(ObTimeTC != in.get_type_class())) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", K(expect_type), K(in), K(ret)); } else if (OB_FAIL(time_string(ObVarcharType, params, in, str_val, cast_mode))) { LOG_WARN("fail to cast number to double", K(in), K(str_val), K(ret)); } else if (OB_FAIL(string_set(expect_type, params, str_val, out))) { LOG_WARN("fail to cast double to enum", K(expect_type), K(out), K(str_val), K(ret)); } return ret; } CAST_TO_LOB_METHOD(time, ObTimeTC); //////////////////////////////////////////////////////////// // Year -> XXX static int year_int( const ObObjType expect_type, ObObjCastParams& params, 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& params, 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& params, 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& params, 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& params, 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_date( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; int64_t in_value = 0; if (OB_UNLIKELY(ObYearTC != 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(ObTimeConverter::year_to_int(in.get_year(), in_value))) { } else { int32_t value = 0; if (CAST_FAIL(ObTimeConverter::int_to_date(in_value, 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 year_string( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; char buf[OB_CAST_TO_VARCHAR_MAX_LENGTH] = {0}; 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_STRING(expect_type, DEFAULT_PRECISION_FOR_STRING, res_length); UNUSED(cast_mode); return ret; } static int year_bit( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; ObObj tmp_val; if (OB_UNLIKELY(ObYearTC != in.get_type_class() || ObBitTC != 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, tmp_val, cast_mode))) { LOG_WARN("fail to cast datetime to int", K(ret), K(expect_type), K(in), K(tmp_val)); } else if (OB_FAIL(int_bit(expect_type, params, tmp_val, out, cast_mode))) { LOG_WARN("fail to cast int to bit", K(ret), K(expect_type), K(in), K(tmp_val)); } return ret; } static int year_enum(const ObExpectType& expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out) { int ret = OB_SUCCESS; ObObj uint_val; ObCastMode cast_mode = params.cast_mode_; if (OB_UNLIKELY(ObEnumType != expect_type.get_type()) || OB_UNLIKELY(ObYearTC != in.get_type_class())) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", K(expect_type), K(in), K(ret)); } else if (OB_FAIL(year_uint(ObUInt64Type, params, in, uint_val, cast_mode))) { LOG_WARN("fail to cast number to double", K(in), K(uint_val), K(ret)); } else if (OB_FAIL(uint_enum(expect_type, params, uint_val, out))) { LOG_WARN("fail to cast double to enum", K(expect_type), K(out), K(uint_val), K(ret)); } return ret; } static int year_set(const ObExpectType& expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out) { int ret = OB_SUCCESS; ObObj uint_val; ObCastMode cast_mode = params.cast_mode_; if (OB_UNLIKELY(ObSetType != expect_type.get_type()) || OB_UNLIKELY(ObYearTC != in.get_type_class())) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", K(expect_type), K(in), K(ret)); } else if (OB_FAIL(year_uint(ObUInt64Type, params, in, uint_val, cast_mode))) { LOG_WARN("fail to cast number to double", K(in), K(uint_val), K(ret)); } else if (OB_FAIL(uint_set(expect_type, params, uint_val, out))) { LOG_WARN("fail to cast double to enum", K(expect_type), K(out), K(uint_val), K(ret)); } return ret; } CAST_TO_LOB_METHOD(year, ObYearTC); //////////////////////////////////////////////////////////// // String -> XXX int common_string_unsigned_integer(const ObCastMode& cast_mode, const ObObjType& in_type, const ObString& in_str, const bool is_str_integer_cast, uint64_t& out_val) { int ret = OB_SUCCESS; if (ObHexStringType == in_type) { out_val = hex_to_uint64(in_str); } else { int err = 0; char* endptr = NULL; if (is_str_integer_cast && CM_IS_STRING_INTEGER_TRUNC(cast_mode)) { out_val = ObCharset::strntoull(in_str.ptr(), in_str.length(), 10, &endptr, &err); if (ERANGE == err && (INT64_MIN == out_val || INT64_MAX == out_val)) { ret = OB_DATA_OUT_OF_RANGE; } else if (endptr == in_str.ptr() || endptr != in_str.ptr() + in_str.length()) { ret = OB_ERR_TRUNCATED_WRONG_VALUE; if (CM_IS_WARN_ON_FAIL(cast_mode)) { ObString tmp_msg("INTEGER"); LOG_USER_WARN(OB_ERR_TRUNCATED_WRONG_VALUE, tmp_msg.length(), tmp_msg.ptr(), in_str.length(), in_str.ptr()); } } } else { out_val = ObCharset::strntoullrnd(in_str.ptr(), in_str.length(), true, &endptr, &err); if (ERANGE == err && (0 == out_val || UINT64_MAX == out_val)) { ret = OB_DATA_OUT_OF_RANGE; } else { ret = check_convert_str_err(in_str.ptr(), endptr, in_str.length(), err); } } } return ret; } int common_string_integer(const ObCastMode& cast_mode, const ObObjType& in_type, const ObString& in_str, const bool is_str_integer_cast, int64_t& out_val) { int ret = OB_SUCCESS; if (ObHexStringType == in_type) { out_val = static_cast(hex_to_uint64(in_str)); } else { int err = 0; char* endptr = NULL; if (is_str_integer_cast && CM_IS_STRING_INTEGER_TRUNC(cast_mode)) { out_val = ObCharset::strntoll(in_str.ptr(), in_str.length(), 10, &endptr, &err); if (ERANGE == err && (INT64_MIN == out_val || INT64_MAX == out_val)) { ret = OB_DATA_OUT_OF_RANGE; } else if (endptr == in_str.ptr() || endptr != in_str.ptr() + in_str.length()) { ret = OB_ERR_TRUNCATED_WRONG_VALUE; if (CM_IS_WARN_ON_FAIL(cast_mode)) { ObString tmp_msg("INTEGER"); LOG_USER_WARN(OB_ERR_TRUNCATED_WRONG_VALUE, tmp_msg.length(), tmp_msg.ptr(), in_str.length(), in_str.ptr()); } } } else { out_val = static_cast(ObCharset::strntoullrnd(in_str.ptr(), in_str.length(), false, &endptr, &err)); if (ERANGE == err && (INT64_MIN == out_val || INT64_MAX == out_val)) { ret = OB_DATA_OUT_OF_RANGE; } else { ret = check_convert_str_err(in_str.ptr(), endptr, in_str.length(), err); } } } return ret; } static int string_int( const ObObjType expect_type, ObObjCastParams& params, 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 if (lib::is_oracle_mode() && in.is_blob()) { ret = OB_NOT_SUPPORTED; LOG_ERROR("invalid use of blob type", K(ret), K(in), K(expect_type)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "Cast to blob type"); } else { const ObString& str = in.get_string(); int64_t value = 0; const bool is_str_int_cast = true; if (CAST_FAIL(common_string_integer(cast_mode, in.get_type(), str, is_str_int_cast, value))) { } 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& params, 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 if (lib::is_oracle_mode() && in.is_blob()) { ret = OB_NOT_SUPPORTED; LOG_ERROR("invalid use of blob type", K(ret), K(in), K(expect_type)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "Cast to blob type"); } else { const ObString& str = in.get_string(); uint64_t value = 0; const bool is_str_int_cast = true; if (CAST_FAIL(common_string_unsigned_integer(cast_mode, in.get_type(), str, is_str_int_cast, value))) { } 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& params, 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 (lib::is_oracle_mode() && in.is_blob()) { ret = OB_NOT_SUPPORTED; LOG_ERROR("invalid use of blob type", K(ret), K(in), K(expect_type)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "Cast to blob 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& params, 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 if (lib::is_oracle_mode() && in.is_blob()) { ret = OB_NOT_SUPPORTED; LOG_ERROR("invalid use of blob type", K(ret), K(in), K(expect_type)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "Cast to blob type"); } else { double value = 0.0; if (ObHexStringType == in.get_type()) { value = static_cast(hex_to_uint64(in.get_string())); } else { int err = 0; char* endptr = NULL; ObString str_utf8; if (OB_FAIL(convert_string_collation( in.get_string(), in.get_collation_type(), str_utf8, ObCharset::get_system_collation(), params))) { LOG_WARN("convert_string_collation", K(ret), K(str_utf8), K(in.get_string())); } else { value = ObCharset::strntod(str_utf8.ptr(), str_utf8.length(), &endptr, &err); if (EOVERFLOW == err && (-DBL_MAX == value || DBL_MAX == value)) { ret = OB_DATA_OUT_OF_RANGE; } else { ObString trimed_str = str_utf8.trim(); if (lib::is_mysql_mode() && 0 == trimed_str.length()) { if (!CM_IS_COLUMN_CONVERT(cast_mode)) { // skip } else { ret = OB_ERR_DOUBLE_TRUNCATED; LOG_WARN("convert string to double failed", K(ret), K(str_utf8)); } } else if (OB_SUCCESS != (ret = check_convert_str_err(str_utf8.ptr(), endptr, str_utf8.length(), err))) { LOG_WARN("failed to check_convert_str_err", K(ret), K(str_utf8), K(value), K(err)); ret = OB_ERR_DOUBLE_TRUNCATED; if (CM_IS_WARN_ON_FAIL(cast_mode)) { LOG_USER_WARN(OB_ERR_DOUBLE_TRUNCATED, str_utf8.length(), str_utf8.ptr()); } } } } } 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& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; ObPrecision res_precision = PRECISION_UNKNOWN_YET; ObScale res_scale = NUMBER_SCALE_UNKNOWN_YET; ObString utf8_string; if (OB_ISNULL(params.allocator_v2_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("invalid allocator", K(ret)); } else 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 if (lib::is_oracle_mode() && in.is_blob()) { ret = OB_NOT_SUPPORTED; LOG_ERROR("invalid use of blob type", K(ret), K(in), K(expect_type)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "Cast to blob type"); } else { number::ObNumber value; if (ObHexStringType == in.get_type()) { ret = value.from(hex_to_uint64(in.get_string()), params); } else if (OB_UNLIKELY(0 == in.get_string().length())) { value.set_zero(); ret = OB_ERR_TRUNCATED_WRONG_VALUE_FOR_FIELD; } else if (OB_FAIL(convert_string_collation( in.get_string(), in.get_collation_type(), utf8_string, ObCharset::get_system_collation(), params))) { LOG_WARN("convert_string_collation", K(ret)); } else { const ObString& str = utf8_string; ret = value.from_sci_opt(str.ptr(), str.length(), params, &res_precision, &res_scale); // select cast('1e500' as decimal); -> max_val // select cast('-1e500' as decimal); -> min_val if (ret == OB_NUMERIC_OVERFLOW) { int64_t i = 0; while (i < str.length() && isspace(str[i])) { ++i; } bool is_neg = (str[i] == '-'); int tmp_ret = OB_SUCCESS; const ObAccuracy& def_acc = ObAccuracy::DDL_DEFAULT_ACCURACY2[0][expect_type]; const ObPrecision prec = def_acc.get_precision(); const ObScale scale = def_acc.get_scale(); const ObNumber* bound_num = NULL; if (is_neg) { bound_num = &(ObNumberConstValue::MYSQL_MIN[prec][scale]); } else { bound_num = &(ObNumberConstValue::MYSQL_MAX[prec][scale]); } if (OB_ISNULL(bound_num)) { tmp_ret = OB_ERR_UNEXPECTED; LOG_WARN("bound_num is NULL", K(tmp_ret), K(ret), K(is_neg)); } else if (OB_SUCCESS != (tmp_ret = value.from(*bound_num, *params.allocator_v2_))) { LOG_WARN("copy min number failed", K(ret), K(tmp_ret), KPC(bound_num)); } } } 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& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; ObScale res_scale = -1; ObString utf8_string; 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 if (lib::is_oracle_mode() && in.is_blob()) { ret = OB_NOT_SUPPORTED; LOG_ERROR("invalid use of blob type", K(ret), K(in), K(expect_type)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "Cast to blob type"); } else if (OB_FAIL(convert_string_collation( in.get_string(), in.get_collation_type(), utf8_string, ObCharset::get_system_collation(), params))) { LOG_WARN("convert_string_collation", K(ret)); } else { int64_t value = 0; ObTimeConvertCtx cvrt_ctx(params.dtc_params_.tz_info_, ObTimestampType == expect_type); if (lib::is_oracle_mode()) { cvrt_ctx.oracle_nls_format_ = params.dtc_params_.get_nls_format(ObDateTimeType); CAST_RET(ObTimeConverter::str_to_date_oracle(utf8_string, cvrt_ctx, value)); } else { CAST_RET(ObTimeConverter::str_to_datetime(utf8_string, cvrt_ctx, value, &res_scale)); } if (OB_SUCC(ret)) { 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& params, 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 (lib::is_oracle_mode() && in.is_blob()) { ret = OB_NOT_SUPPORTED; LOG_ERROR("invalid use of blob type", K(ret), K(in), K(expect_type)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "Cast to blob 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& params, 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 (lib::is_oracle_mode() && in.is_blob()) { ret = OB_NOT_SUPPORTED; LOG_ERROR("invalid use of blob type", K(ret), K(in), K(expect_type)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "Cast to blob 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& params, 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 (lib::is_oracle_mode() && in.is_blob()) { ret = OB_NOT_SUPPORTED; LOG_ERROR("invalid use of blob type", K(ret), K(in), K(expect_type)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "Cast to blob type"); } else if (OB_FAIL(string_int( ObIntType, params, in, int64, CM_UNSET_STRING_INTEGER_TRUNC(CM_SET_WARN_ON_FAIL(cast_mode))))) { } else if (0 == int64.get_int()) { const uint8_t base_year = 100; uint8_t value = 4 == in.get_string().length() ? ObTimeConverter::ZERO_YEAR : base_year; SET_RES_YEAR(out); } 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& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; ObLength res_length = -1; ObObj tmp_out; if (OB_UNLIKELY( (ObStringTC != in.get_type_class() && ObTextTC != in.get_type_class()) || OB_UNLIKELY(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 (lib::is_oracle_mode() && !(in.is_blob() && ob_is_blob(expect_type, params.expect_obj_collation_)) && (in.is_blob())) { ret = OB_NOT_SUPPORTED; LOG_WARN("invalid cast of blob type", K(ret), K(in), K(out.get_meta()), K(expect_type), K(cast_mode)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "cast to blob type"); } else if (ObTextTC == in.get_type_class() && in.is_lob_outrow()) { ret = OB_NOT_SUPPORTED; LOG_WARN("invalid cast of out row lob obj", K(ret), K(in), K(out.get_meta()), K(expect_type), K(cast_mode)); } else if (lib::is_oracle_mode() && in.is_clob() && (0 == in.get_string().length()) && !ob_is_clob(expect_type, params.expect_obj_collation_)) { out.set_null(); } else { ObString str; in.get_string(str); if (0 != str.length() && CS_TYPE_BINARY != in.get_collation_type() && CS_TYPE_BINARY != params.dest_collation_ && (ObCharset::charset_type_by_coll(in.get_collation_type()) != ObCharset::charset_type_by_coll(params.dest_collation_))) { char* buf = NULL; // gbk and utf16 is fixed 2 btyes, utf8mb4 is 1 to 4 bytes, // so the factor should be 2. const int32_t CharConvertFactorNum = 2; int32_t buf_len = str.length() * CharConvertFactorNum; uint32_t result_len = 0; if (OB_UNLIKELY(NULL == (buf = static_cast(params.alloc(buf_len))))) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("alloc memory failed", K(ret)); } else if (OB_FAIL(ObCharset::charset_convert(in.get_collation_type(), str.ptr(), str.length(), params.dest_collation_, buf, buf_len, result_len))) { LOG_WARN("charset convert failed", K(ret), K(in.get_collation_type()), K(params.dest_collation_), K(params.is_ignore_)); if (params.is_ignore_) { ObString question_mark = ObCharsetUtils::get_const_str(params.dest_collation_, '?'); int32_t str_offset = 0; int64_t buf_offset = 0; while (str_offset < str.length() && buf_offset + question_mark.length() <= buf_len) { int64_t offset = ObCharset::charpos(in.get_collation_type(), str.ptr() + str_offset, str.length() - str_offset, 1); ret = ObCharset::charset_convert(in.get_collation_type(), str.ptr() + str_offset, offset, params.dest_collation_, buf + buf_offset, buf_len - buf_offset, result_len); str_offset += offset; if (OB_SUCCESS == ret) { buf_offset += result_len; } else { MEMCPY(buf + buf_offset, question_mark.ptr(), question_mark.length()); buf_offset += question_mark.length(); } } if (str_offset < str.length()) { ret = OB_SIZE_OVERFLOW; LOG_WARN("size overflow", K(ret), K(str), KPHEX(str.ptr(), str.length())); } else { result_len = buf_offset; ret = OB_SUCCESS; LOG_WARN("charset convert failed", K(ret), K(in.get_collation_type()), K(params.dest_collation_)); } } } LOG_DEBUG("convert result", K(str), "result", ObHexEscapeSqlStr(ObString(result_len, buf))); if (OB_SUCC(ret)) { if (ObTextTC == ob_obj_type_class(expect_type)) { out.set_lob_value(expect_type, buf, static_cast(result_len)); } else { out.set_string(expect_type, buf, static_cast(result_len)); } if (CS_TYPE_INVALID != in.get_collation_type()) { out.set_collation_type(params.dest_collation_); } } } else { // When convert blob to other charset, need to align to mbminlen of destination charset // by add '\0' prefix in mysql mode. (see mysql String::copy) int64_t align_offset = 0; const ObCharsetInfo* cs = NULL; if (CS_TYPE_BINARY == in.get_collation_type() && is_mysql_mode() && NULL != (cs = ObCharset::get_charset(params.dest_collation_))) { if (cs->mbminlen > 0 && in.get_string_len() % cs->mbminlen != 0) { align_offset = cs->mbminlen - in.get_string_len() % cs->mbminlen; } } if (OB_FAIL(check_convert_string(expect_type, params, in, tmp_out))) { LOG_WARN("failed to check_and_convert_string", K(ret), K(in), K(expect_type)); } else if (OB_FAIL(copy_string(params, expect_type, tmp_out.get_string(), out, align_offset))) { } else { if (CS_TYPE_INVALID != tmp_out.get_collation_type()) { out.set_collation_type(tmp_out.get_collation_type()); } if (ObTextTC == ob_obj_type_class(expect_type)) { out.set_lob_inrow(); } } } } if (OB_SUCC(ret)) { res_length = static_cast(out.get_string_len()); } SET_RES_ACCURACY_STRING(expect_type, DEFAULT_PRECISION_FOR_STRING, res_length); UNUSED(cast_mode); return ret; } static int string_bit( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; uint64_t value = 0; if (OB_UNLIKELY((ObStringTC != in.get_type_class() && ObTextTC != in.get_type_class()) || ObBitTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else if (lib::is_oracle_mode() && in.is_blob()) { ret = OB_NOT_SUPPORTED; LOG_ERROR("invalid use of blob type", K(ret), K(in), K(expect_type)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "Cast to blob type"); } else { int32_t bit_len = 0; const ObString& str = in.get_string(); if (OB_FAIL(get_bit_len(str, bit_len))) { LOG_WARN("fail to get bit length", K(ret), K(str)); } else if (OB_UNLIKELY(bit_len <= 0)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("bit length is less than or equal to zero", K(ret), K(str), K(bit_len)); } else { if (ObHexStringType == in.get_type() && str.empty()) { value = 0; ret = OB_ERR_TRUNCATED_WRONG_VALUE_FOR_FIELD; LOG_WARN("hex string is empty, can't cast to bit", K(ret), K(in)); } else if (OB_UNLIKELY(bit_len > OB_MAX_BIT_LENGTH)) { value = UINT64_MAX; ret = OB_ERR_DATA_TOO_LONG; LOG_WARN("bit type length is too long", K(ret), K(str), K(OB_MAX_BIT_LENGTH), K(bit_len)); } else { value = hex_to_uint64(str); } if (OB_FAIL(ret) && CM_IS_WARN_ON_FAIL(cast_mode)) { params.warning_ = OB_DATA_OUT_OF_RANGE; ret = OB_SUCCESS; } if (OB_SUCC(ret)) { SET_RES_BIT(out); SET_RES_ACCURACY(static_cast(bit_len), DEFAULT_SCALE_FOR_BIT, DEFAULT_LENGTH_FOR_NUMERIC); } } } return ret; } static int string_enum(const ObExpectType& expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out) { int ret = OB_SUCCESS; ObCastMode cast_mode = params.cast_mode_; const ObIArray* type_infos = NULL; const ObCollationType in_cs_type = ObCharset::is_valid_collation(in.get_collation_type()) ? in.get_collation_type() : ObCharset::get_system_collation(); ObCollationType cs_type = expect_type.get_collation_type(); int32_t pos = 0; uint64_t value = 0; int32_t no_sp_len = 0; ObString no_sp_val; ObString in_str; if (OB_UNLIKELY(ObEnumType != expect_type.get_type()) || OB_UNLIKELY(ObStringTC != in.get_type_class() && ObTextTC != in.get_type_class()) || OB_ISNULL(type_infos = expect_type.get_type_infos())) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", K(expect_type), K(in), K(ret)); } else if (lib::is_oracle_mode() && in.is_blob()) { ret = OB_NOT_SUPPORTED; LOG_ERROR("invalid use of blob type", K(ret), K(in), K(expect_type)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "Cast to blob type"); } else if (OB_FAIL(ObCharset::charset_convert(*params.allocator_v2_, in.get_string(), in_cs_type, cs_type, in_str))) { LOG_WARN("convert charset failed", K(ret), K(in), K(cs_type)); } else { no_sp_len = static_cast(ObCharset::strlen_byte_no_sp(cs_type, in_str.ptr(), in_str.length())); no_sp_val.assign_ptr(in_str.ptr(), static_cast(no_sp_len)); if (OB_FAIL(find_type(*type_infos, cs_type, no_sp_val, pos))) { LOG_WARN("fail to find type", KPC(type_infos), K(cs_type), K(no_sp_val), K(in_str), K(pos), K(ret)); } else if (OB_UNLIKELY(pos < 0)) { if (!in_str.is_numeric()) { ret = OB_ERR_DATA_TRUNCATED; } else { int err = 0; int64_t val_cnt = type_infos->count(); value = ObCharset::strntoull(in_str.ptr(), in_str.length(), 10, &err); if (err != 0 || value > val_cnt) { value = 0; ret = OB_ERR_DATA_TRUNCATED; LOG_WARN("input value out of range", K(in), K(val_cnt), K(ret), K(err)); } } if (OB_FAIL(ret) && CM_IS_WARN_ON_FAIL(cast_mode)) { params.warning_ = OB_ERR_DATA_TRUNCATED; ret = OB_SUCCESS; } } else { value = pos + 1; // enum start from 1 } LOG_DEBUG("finish string_enum", K(ret), K(expect_type), K(in), K(out), KPC(type_infos), K(lbt())); SET_RES_ENUM(out); } return ret; } static int string_set(const ObExpectType& expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out) { int ret = OB_SUCCESS; ObCastMode cast_mode = params.cast_mode_; const ObIArray* type_infos = NULL; const ObCollationType in_cs_type = ObCharset::is_valid_collation(in.get_collation_type()) ? in.get_collation_type() : ObCharset::get_system_collation(); ObCollationType cs_type = expect_type.get_collation_type(); const ObString& sep = ObCharsetUtils::get_const_str(cs_type, ','); int32_t pos = 0; uint64_t value = 0; ObString in_str; ObString val_str; bool is_last_value = false; if (OB_UNLIKELY(ObSetType != expect_type.get_type()) || OB_UNLIKELY(ObStringTC != in.get_type_class() && ObTextTC != in.get_type_class()) || OB_ISNULL(type_infos = expect_type.get_type_infos()) || !ObCharset::is_valid_collation(cs_type)) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", K(expect_type), K(in), K(cs_type), K(ret)); } else if (lib::is_oracle_mode() && in.is_blob()) { ret = OB_NOT_SUPPORTED; LOG_ERROR("invalid use of blob type", K(ret), K(in), K(expect_type)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "Cast to blob type"); } else if (in.get_string().empty()) { value = 0; } else if (OB_FAIL(ObCharset::charset_convert(*params.allocator_v2_, in.get_string(), in_cs_type, cs_type, in_str))) { } else { const char* remain = in_str.ptr(); int64_t remain_len = ObCharset::strlen_byte_no_sp(cs_type, in_str.ptr(), in_str.length()); do { pos = 0; const char* sep_loc = NULL; if (NULL == (sep_loc = static_cast(memmem(remain, remain_len, sep.ptr(), sep.length())))) { is_last_value = true; val_str.assign_ptr(remain, remain_len); if (OB_FAIL(find_type(*type_infos, cs_type, val_str, pos))) { LOG_WARN("fail to find type", KPC(type_infos), K(cs_type), K(val_str), K(in_str), K(pos), K(ret)); } } else { val_str.assign_ptr(remain, sep_loc - remain); remain_len = remain_len - (sep_loc - remain + sep.length()); remain = sep_loc + sep.length(); if (OB_FAIL(find_type(*type_infos, cs_type, val_str, pos))) { LOG_WARN("fail to find type", KPC(type_infos), K(cs_type), K(val_str), K(in_str), K(pos), K(ret)); } } if (OB_FAIL(ret)) { } else if (pos < 0) { // not found if (CM_IS_WARN_ON_FAIL(cast_mode)) { params.warning_ = OB_ERR_DATA_TRUNCATED; LOG_INFO( "input value out of range, and set out value zero", K(pos), K(in), K(val_str), K(in_str), K(expect_type)); } else { ret = OB_ERR_DATA_TRUNCATED; LOG_WARN("data truncate", K(pos), K(in), K(val_str), K(in_str), K(expect_type), K(ret)); } } else { pos %= 64; // value_count can more than 64 if has duplicated values in mysql. value |= (1ULL << pos); } } while (OB_SUCC(ret) && !is_last_value); // Bug30666903: check implicit cast logic to handle number cases if (in_str.is_numeric() && (OB_ERR_DATA_TRUNCATED == ret || (params.warning_ == OB_ERR_DATA_TRUNCATED && CM_IS_WARN_ON_FAIL(cast_mode)))) { int err = 0; value = ObCharset::strntoull(in_str.ptr(), in_str.length(), 10, &err); if (err == 0) { ret = OB_SUCCESS; uint32_t val_cnt = type_infos->count(); if (OB_UNLIKELY(val_cnt <= 0)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpect val_cnt", K(in), K(out), K(expect_type), K(ret)); } else if (val_cnt >= 64) { // do nothing } else if (val_cnt < 64 && value > ((1ULL << val_cnt) - 1)) { value = 0; ret = OB_ERR_DATA_TRUNCATED; LOG_WARN("input value out of range", K(in), K(val_cnt), K(ret)); } if (OB_FAIL(ret) && CM_IS_WARN_ON_FAIL(cast_mode)) { params.warning_ = OB_ERR_DATA_TRUNCATED; ret = OB_SUCCESS; } } else { value = 0; } } } LOG_DEBUG("finish string_set", K(ret), K(expect_type), K(in), K(out), KPC(type_infos), K(lbt())); SET_RES_SET(out); return ret; } static int string_otimestamp( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { UNUSED(cast_mode); int ret = OB_SUCCESS; ObScale res_scale = -1; ObString utf8_string; if (OB_UNLIKELY(ObStringTC != in.get_type_class() && ObTextTC != in.get_type_class()) || OB_UNLIKELY(ObOTimestampTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else if (lib::is_oracle_mode() && in.is_blob()) { ret = OB_NOT_SUPPORTED; LOG_ERROR("invalid use of blob type", K(ret), K(in), K(expect_type)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "Cast to blob type"); } else if (OB_FAIL(convert_string_collation( in.get_string(), in.get_collation_type(), utf8_string, ObCharset::get_system_collation(), params))) { LOG_WARN("convert_string_collation", K(ret)); } else { ObOTimestampData value; ObTimeConvertCtx cvrt_ctx(params.dtc_params_.tz_info_, true); cvrt_ctx.oracle_nls_format_ = params.dtc_params_.get_nls_format(expect_type); if (CAST_FAIL(ObTimeConverter::str_to_otimestamp(utf8_string, cvrt_ctx, expect_type, value, res_scale))) { } else { SET_RES_OTIMESTAMP(out); } } SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, res_scale, DEFAULT_LENGTH_FOR_TEMPORAL); return ret; } static int string_raw( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { UNUSED(cast_mode); int ret = OB_SUCCESS; ObLength res_length = -1; if (OB_UNLIKELY(ObStringTC != in.get_type_class()) || OB_UNLIKELY(ObRawTC != 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(ObHexUtils::hextoraw(in, params, out))) { LOG_WARN("fail to hextoraw", K(ret), K(in), K(expect_type)); } else { res_length = static_cast(out.get_string_len()); } SET_RES_ACCURACY_STRING(expect_type, DEFAULT_PRECISION_FOR_STRING, res_length); return ret; } static int string_interval( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { UNUSED(cast_mode); int ret = OB_SUCCESS; ObScale res_scale = -1; ObLength res_length = -1; ObPrecision res_precision = -1; ObString utf8_string; if (OB_UNLIKELY(!in.is_string_type()) || OB_UNLIKELY(ObIntervalTC != 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(convert_string_collation( in.get_string(), in.get_collation_type(), utf8_string, ObCharset::get_system_collation(), params))) { LOG_WARN("convert_string_collation", K(ret)); } else if (ObIntervalYMType == expect_type) { ObIntervalYMValue value; // don't know the scale, use the max scale and return the real scale res_scale = ObAccuracy::MAX_ACCURACY2[ORACLE_MODE][ObIntervalYMType].get_scale(); if (CAST_FAIL(ObTimeConverter::str_to_interval_ym(utf8_string, value, res_scale))) { } else { SET_RES_INTERVAL_YM(out); out.set_scale(res_scale); } } else { ObIntervalDSValue value; // don't know the scale, use the max scale and return the real scale res_scale = ObAccuracy::MAX_ACCURACY2[ORACLE_MODE][ObIntervalDSType].get_scale(); if (CAST_FAIL(ObTimeConverter::str_to_interval_ds(utf8_string, value, res_scale))) { } else { SET_RES_INTERVAL_DS(out); out.set_scale(res_scale); } } SET_RES_ACCURACY(res_precision, res_scale, res_length); return ret; } static int string_rowid( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; if (OB_UNLIKELY(ob_obj_type_class(expect_type) != ObRowIDTC) || OB_UNLIKELY(in.get_type_class() != ObStringTC)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected arguments", K(expect_type), K(in)); } else if (ObURowIDType != expect_type) { ret = OB_NOT_SUPPORTED; LOG_WARN("only support urowid for now", K(ret), K(expect_type)); } else { ObURowIDData value; if (OB_FAIL(ObURowIDData::decode2urowid(in.get_string_ptr(), in.get_string_len(), *params.allocator_v2_, value))) { LOG_WARN("failed to decode to urowid", K(ret)); } else { SET_RES_UROWID(out); } } return ret; } static int string_lob(const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode, const ObLobLocator* lob_locator) { int ret = OB_SUCCESS; ObObj tmp_out; if (!share::is_oracle_mode()) { ret = OB_ERR_UNEXPECTED; LOG_WARN("Unexpected tenant mode", K(ret)); } else if (OB_UNLIKELY((ObStringTC != in.get_type_class() && ObTextTC != in.get_type_class()) || OB_UNLIKELY(!ob_is_lob_locator(expect_type)))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else if (OB_FAIL(string_string(ObLongTextType, params, in, tmp_out, cast_mode))) { LOG_WARN("fail to cast string to longtext", K(ret), K(in)); } else if (tmp_out.is_null()) { out.set_null(); } else { ObString str; char* buf = nullptr; ObLobLocator* result = nullptr; if (OB_FAIL(tmp_out.get_string(str))) { STORAGE_LOG(WARN, "Failed to get string from obj", K(ret), K(tmp_out)); } const int64_t buf_len = sizeof(ObLobLocator) + (NULL == lob_locator ? 0 : lob_locator->payload_offset_) + str.length(); if (OB_FAIL(ret)) { } else if (OB_ISNULL(buf = static_cast(params.alloc(buf_len)))) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("Failed to allocate memory for lob locator", K(ret), K(str)); } else if (FALSE_IT(result = reinterpret_cast(buf))) { } else if (NULL == lob_locator) { if (OB_FAIL(result->init(str))) { STORAGE_LOG(WARN, "Failed to init lob locator", K(ret), K(str), KPC(result)); } } else if (NULL != lob_locator) { ObString rowid; if (lob_locator->is_inline_mode()) { // inline mode if (OB_FAIL(lob_locator->get_rowid(rowid))) { LOG_WARN("get rowid failed", K(ret)); } else if (OB_FAIL(result->init(lob_locator->table_id_, lob_locator->column_id_, lob_locator->snapshot_version_, lob_locator->flags_, rowid, str))) { STORAGE_LOG(WARN, "Failed to init lob locator", K(ret), K(str), KPC(result)); } } else { // compat mode if (OB_FAIL(result->init(str))) { STORAGE_LOG(WARN, "Failed to init lob locator", K(ret), K(str), KPC(result)); } } } if (OB_SUCC(ret)) { out = tmp_out; out.set_lob_locator(*result); } } return ret; } //////////////////////////////////////////////////////////// // bit -> XXX static int bit_int( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; ObPrecision res_precision = -1; int64_t value = 0; if (OB_UNLIKELY(ObBitTC != in.get_type_class() || ObIntTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_WARN("invalid argument", K(in), K(expect_type), K(ret)); } else { value = static_cast(in.get_bit()); if (expect_type < ObIntType && CM_NEED_RANGE_CHECK(cast_mode) && CAST_FAIL(int_range_check(expect_type, value, value))) { } else { SET_RES_INT(out); 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 bit_uint( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; ObPrecision res_precision = -1; uint64_t value = 0; if (OB_UNLIKELY(ObBitTC != in.get_type_class() || ObUIntTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_WARN("invalid argument", K(in), K(expect_type), K(ret)); } else { value = static_cast(in.get_bit()); if (expect_type < ObUInt64Type && CM_NEED_RANGE_CHECK(cast_mode) && CAST_FAIL(uint_upper_check(expect_type, value))) { } else { SET_RES_UINT(out); 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 bit_double( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode); static int bit_float( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; ObObj dbl; if (OB_UNLIKELY((ObBitTC != 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(bit_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 bit_double( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { UNUSED(cast_mode); int ret = OB_SUCCESS; double value = 0.0; if (OB_UNLIKELY((ObBitTC != 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 { value = static_cast(in.get_bit()); SET_RES_DOUBLE(out); SET_RES_ACCURACY(PRECISION_UNKNOWN_YET, SCALE_UNKNOWN_YET, LENGTH_UNKNOWN_YET); } return ret; } static int bit_number( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { UNUSED(cast_mode); int ret = OB_SUCCESS; number::ObNumber nmb; ObPrecision res_precision = -1; if (OB_UNLIKELY(ObBitTC != 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_bit(), params))) { LOG_WARN("fail to make number", K(ret), K(in)); } else { out.set_number(expect_type, nmb); res_precision = get_precision_for_integer(in.get_bit()); SET_RES_ACCURACY(res_precision, DEFAULT_SCALE_FOR_INTEGER, DEFAULT_LENGTH_FOR_NUMERIC); } return ret; } static int bit_datetime( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; uint64_t bit_value = in.get_bit(); int64_t value = 0; ObScale res_scale = -1; if (OB_UNLIKELY((ObBitTC != 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 (CM_IS_COLUMN_CONVERT(cast_mode)) { // if cast mode is column convert, using bit as int64 to do cast. ObTimeConvertCtx cvrt_ctx(params.dtc_params_.tz_info_, ObTimestampType == expect_type); if (CAST_FAIL(ObTimeConverter::int_to_datetime(bit_value, 0, cvrt_ctx, value))) { LOG_WARN("int_to_datetime failed", K(ret), K(bit_value)); } } else { // using bit as char array to do cast. ObScale scale = in.get_scale(); const int32_t BUF_LEN = (OB_MAX_BIT_LENGTH + 7) / 8; int64_t pos = 0; char buf[BUF_LEN]; MEMSET(buf, 0, BUF_LEN); if (OB_FAIL(bit_to_char_array(bit_value, scale, buf, BUF_LEN, pos))) { LOG_WARN("fail to store val", KP(buf), K(BUF_LEN), K(bit_value), K(pos)); } else { ObString str(pos, buf); ObTimeConvertCtx cvrt_ctx(params.dtc_params_.tz_info_, ObTimestampType == expect_type); if (CAST_FAIL(ObTimeConverter::str_to_datetime(str, cvrt_ctx, value, &res_scale))) { LOG_WARN("int_to_datetime failed", K(ret), K(bit_value), K(str)); } } } if (OB_SUCC(ret)) { SET_RES_DATETIME(out); SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, res_scale, DEFAULT_LENGTH_FOR_TEMPORAL); } return ret; } static int bit_date( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; uint64_t bit_value = in.get_bit(); int32_t value = 0; ObScale res_scale = -1; if (OB_UNLIKELY((ObBitTC != 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 (CM_IS_COLUMN_CONVERT(cast_mode)) { // if cast mode is column convert, using bit as int64 to do cast. if (CAST_FAIL(ObTimeConverter::int_to_date(bit_value, value))) { LOG_WARN("int_to_date failed", K(ret), K(bit_value)); } } else { // using bit as char array to do cast. ObScale scale = in.get_scale(); const int32_t BUF_LEN = (OB_MAX_BIT_LENGTH + 7) / 8; int64_t pos = 0; char buf[BUF_LEN]; MEMSET(buf, 0, BUF_LEN); if (OB_FAIL(bit_to_char_array(bit_value, scale, buf, BUF_LEN, pos))) { LOG_WARN("fail to store val", KP(buf), K(BUF_LEN), K(bit_value), K(pos)); } else { ObString str(pos, buf); if (CAST_FAIL(ObTimeConverter::str_to_date(str, value))) { LOG_WARN("str_to_date failed", K(ret), K(bit_value), K(str)); } } } if (OB_SUCC(ret)) { SET_RES_DATE(out); SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, res_scale, DEFAULT_LENGTH_FOR_TEMPORAL); } return ret; } static int bit_time( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; uint64_t bit_value = in.get_bit(); int64_t value = 0; ObScale res_scale = -1; if (OB_UNLIKELY((ObBitTC != 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 (CM_IS_COLUMN_CONVERT(cast_mode)) { // if cast mode is column convert, using bit as int64 to do cast. if (CAST_FAIL(ObTimeConverter::int_to_time(bit_value, value))) { LOG_WARN("int_to_time failed", K(ret), K(bit_value)); } } else { // using bit as char array to do cast. ObScale scale = in.get_scale(); const int32_t BUF_LEN = (OB_MAX_BIT_LENGTH + 7) / 8; int64_t pos = 0; char buf[BUF_LEN]; MEMSET(buf, 0, BUF_LEN); if (OB_FAIL(bit_to_char_array(bit_value, scale, buf, BUF_LEN, pos))) { LOG_WARN("fail to store val", KP(buf), K(BUF_LEN), K(bit_value), K(pos)); } else { ObString str(pos, buf); if (CAST_FAIL(ObTimeConverter::str_to_time(str, value, &res_scale))) { LOG_WARN("str_to_date failed", K(ret), K(bit_value), K(str)); } } } if (OB_SUCC(ret)) { SET_RES_TIME(out); SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, res_scale, DEFAULT_LENGTH_FOR_TEMPORAL); } return ret; } static int bit_year( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; uint64_t bit_value = in.get_bit(); uint8_t value = 0; ObScale res_scale = -1; if (OB_UNLIKELY((ObBitTC != 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::int_to_year(bit_value, value))) { LOG_WARN("int_to_year faile", K(ret), K(bit_value)); } else { SET_RES_YEAR(out); SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, res_scale, DEFAULT_LENGTH_FOR_TEMPORAL); } return ret; } static int bit_string( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; uint64_t value = in.get_bit(); ObLength res_length = -1; char *res_buf; int32_t bytes_length = 0; if (OB_UNLIKELY((ObBitTC != 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 (CM_IS_COLUMN_CONVERT(cast_mode)) { // if cast mode is column convert, using bit as int64 to do cast. ObFastFormatInt ffi(value); ObString tmp_str; if (OB_FAIL(convert_string_collation(ObString(ffi.length(), ffi.ptr()), ObCharset::get_system_collation(), tmp_str, params.dest_collation_, params))) { LOG_WARN("fail to convert string collation", K(ret)); } else { res_buf = tmp_str.ptr(); bytes_length = tmp_str.length(); } } else { // using bit as char array to do cast. ObScale scale = in.get_scale(); const int32_t BUF_LEN = (OB_MAX_BIT_LENGTH + 7) / 8; int64_t pos = 0; char tmp_buf[BUF_LEN]; MEMSET(tmp_buf, 0, BUF_LEN); if (OB_FAIL(bit_to_char_array(value, scale, tmp_buf, BUF_LEN, pos))) { LOG_WARN("fail to store val", KP(tmp_buf), K(BUF_LEN), K(value), K(pos)); } else { res_buf = tmp_buf; bytes_length = pos; } } if (OB_SUCC(ret)) { if (OB_FAIL(copy_string(params, expect_type, res_buf, bytes_length, out))) { LOG_WARN("fail to copy string", KP(res_buf), K(bytes_length), K(value), K(out), K(expect_type)); } else { res_length = static_cast(out.get_string_len()); SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_STRING, DEFAULT_SCALE_FOR_STRING, res_length); } } return ret; } static int bit_bit( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { UNUSED(cast_mode); int ret = OB_SUCCESS; uint64_t value = in.get_bit(); int32_t bit_len = 0; if (OB_UNLIKELY(ObBitTC != in.get_type_class() || ObBitTC != 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(get_bit_len(value, bit_len))) { LOG_WARN("fail to get bit len", K(ret), K(value), K(bit_len)); } else { SET_RES_BIT(out); SET_RES_ACCURACY(static_cast(bit_len), DEFAULT_SCALE_FOR_BIT, DEFAULT_LENGTH_FOR_NUMERIC); } return ret; } static int bit_enum(const ObExpectType& expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out) { int ret = OB_SUCCESS; if (OB_UNLIKELY(ObEnumType != expect_type.get_type()) || OB_UNLIKELY(ObBitTC != in.get_type_class())) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", K(expect_type), K(in), K(ret)); } else { uint64_t value = in.get_bit(); ObObj uint_val; uint_val.set_uint64(value); if (OB_FAIL(uint_enum(expect_type, params, uint_val, out))) { LOG_WARN("fail to cast int to enum", K(expect_type), K(in), K(uint_val), K(out), K(ret)); } } return ret; } static int bit_set(const ObExpectType& expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out) { int ret = OB_SUCCESS; if (OB_UNLIKELY(ObSetType != expect_type.get_type()) || OB_UNLIKELY(ObBitTC != in.get_type_class())) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid argument", K(expect_type), K(in), K(ret)); } else { uint64_t value = in.get_bit(); ObObj uint_val; uint_val.set_uint64(value); if (OB_FAIL(uint_set(expect_type, params, uint_val, out))) { LOG_WARN("fail to cast int to enum", K(expect_type), K(in), K(uint_val), K(out), K(ret)); } } return ret; } CAST_TO_LOB_METHOD(bit, ObBitTC); ObCastEnumOrSetFunc OB_CAST_ENUM_OR_SET[ObMaxTC][2] = { { /*null -> enum_or_set*/ cast_identity_enum_set, /*enum*/ cast_identity_enum_set, /*set*/ }, { /*int -> enum_or_set*/ int_enum, /*enum*/ int_set, /*set*/ }, { /*uint -> enum_or_set*/ uint_enum, /*enum*/ uint_set, /*set*/ }, { /*float -> enum_or_set*/ float_enum, /*enum*/ float_set, /*set*/ }, { /*double -> enum_or_set*/ double_enum, /*enum*/ double_set, /*set*/ }, { /*number -> enum_or_set*/ number_enum, /*enum*/ number_set, /*set*/ }, { /*datetime -> enum_or_set*/ datetime_enum, /*enum*/ datetime_set, /*set*/ }, { /*date -> enum_or_set*/ date_enum, /*enum*/ date_set, /*set*/ }, { /*time -> enum_or_set*/ time_enum, /*enum*/ time_set, /*set*/ }, { /*year -> enum_or_set*/ year_enum, /*enum*/ year_set, /*set*/ }, { /*string -> enum_or_set*/ string_enum, /*enum*/ string_set, /*set*/ }, { /*extend -> enum_or_set*/ cast_not_support_enum_set, /*enum*/ cast_not_support_enum_set, /*set*/ }, { /*unknow -> enum_or_set*/ cast_not_support_enum_set, /*enum*/ cast_not_support_enum_set, /*set*/ }, { /*text -> enum_or_set*/ string_enum, /*enum*/ string_set, /*set*/ }, { /*bit -> enum_or_set*/ bit_enum, /*enum*/ bit_set, /*set*/ }, { /*enumset tc -> enum_or_set*/ cast_not_expected_enum_set, /*enum*/ cast_not_expected_enum_set, /*set*/ }, { /*enumset_inner tc -> enum_or_set*/ cast_not_expected_enum_set, /*enum*/ cast_not_expected_enum_set, /*set*/ }, { /*text -> enum_or_set*/ cast_not_support_enum_set, /*enum*/ cast_not_support_enum_set, /*set*/ }, }; //////////////////////////////////////////////////////////// // enum -> XXX static int enumset_int( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { // we regard enum as uint64 when int_value is needed int ret = OB_SUCCESS; if (OB_UNLIKELY(ObEnumSetTC != 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 { ObObj uint64_in; uint64_in.set_uint64(in.get_uint64()); ret = uint_int(expect_type, params, uint64_in, out, cast_mode); } return ret; } static int enumset_uint( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; ObPrecision res_precision = -1; if (OB_UNLIKELY(ObEnumSetTC != 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 (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 enumset_float( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; if (OB_UNLIKELY(ObEnumSetTC != 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 enumset_double( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; if (OB_UNLIKELY(ObEnumSetTC != 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 enumset_number( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; number::ObNumber nmb; ObPrecision res_precision = -1; if (OB_UNLIKELY(ObEnumSetTC != 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))) { LOG_ERROR("failed to from number", K(ret), K(in), K(expect_type)); } 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 enumset_year( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; ObObj int64; if (OB_UNLIKELY(ObEnumSetTC != 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(enumset_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 enumset_bit( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { UNUSED(cast_mode); int ret = OB_SUCCESS; uint64_t value = in.get_uint64(); int32_t bit_len = 0; if (OB_UNLIKELY(ObEnumSetTC != in.get_type_class() || ObBitTC != 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(get_bit_len(value, bit_len))) { LOG_WARN("fail to get bit len", K(ret), K(value), K(bit_len)); } else { SET_RES_BIT(out); SET_RES_ACCURACY(static_cast(bit_len), DEFAULT_SCALE_FOR_BIT, DEFAULT_LENGTH_FOR_NUMERIC); } return ret; } static int get_uint64_from_enumset_inner(const ObObj& in, ObObj& out) { int ret = OB_SUCCESS; ObEnumSetInnerValue inner_value; if (OB_UNLIKELY(ObEnumSetInnerTC != in.get_type_class())) { LOG_ERROR("invalid input type", K(ret), K(in)); } else if (OB_FAIL(in.get_enumset_inner_value(inner_value))) { LOG_WARN("failed to get_enumset_inner_value", K(in), K(ret)); } else { out.set_uint64(inner_value.numberic_value_); } return ret; } static int get_string_from_enumset_inner(const ObObj& in, ObObj& out) { int ret = OB_SUCCESS; ObEnumSetInnerValue inner_value; if (OB_UNLIKELY(ObEnumSetInnerTC != in.get_type_class())) { LOG_ERROR("invalid input type", K(ret), K(in)); } else if (OB_FAIL(in.get_enumset_inner_value(inner_value))) { LOG_WARN("failed to get_enumset_inner_value", K(in), K(ret)); } else { out.set_varchar(inner_value.string_value_); out.set_collation_type(in.get_collation_type()); out.set_collation_level(in.get_collation_level()); } return ret; } /* used for case when or in , comment temporary */ // static int enumset_inner_int(const ObObjType expect_type, ObObjCastParams ¶ms, // const ObObj &in, ObObj &out, const ObCastMode cast_mode) //{ // //we regard enum as uint16 when int_value is needed // int ret = OB_SUCCESS; // ObObj uint64; // if (OB_UNLIKELY(ObEnumSetInnerTC != 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(get_uint64_from_enumset_inner(in, uint64))) { // LOG_WARN("failed to get_uint64_from_enumset_inner", K(in), K(ret)); // } else if (OB_FAIL(uint_int(expect_type, params, uint64, out, cast_mode))) { // LOG_WARN("failed to cast uint to int", K(in), K(uint64), K(ret)); // } else {/*do nothing*/} // return ret; //} // // static int enumset_inner_uint(const ObObjType expect_type, ObObjCastParams ¶ms, // const ObObj &in, ObObj &out, const ObCastMode cast_mode) //{ // //we regard enum as uint16 when int_value is needed // int ret = OB_SUCCESS; // ObObj uint64; // if (OB_UNLIKELY(ObEnumSetInnerTC != 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(get_uint64_from_enumset_inner(in, uint64))) { // LOG_WARN("failed to get_uint64_from_enumset_inner", K(in), K(ret)); // } else if (OB_FAIL(uint_uint(expect_type, params, uint64, out, cast_mode))) { // LOG_WARN("failed to cast uint to uint", K(in), K(uint64), K(ret)); // } else {/*do nothing*/} // return ret; //} // // static int enumset_inner_float(const ObObjType expect_type, ObObjCastParams ¶ms, // const ObObj &in, ObObj &out, const ObCastMode cast_mode) //{ // //we regard enum as uint16 when int_value is needed // int ret = OB_SUCCESS; // ObObj uint64; // if (OB_UNLIKELY(ObEnumSetInnerTC != 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(get_uint64_from_enumset_inner(in, uint64))) { // LOG_WARN("failed to get_uint64_from_enumset_inner", K(in), K(ret)); // } else if (OB_FAIL(uint_float(expect_type, params, uint64, out, cast_mode))) { // LOG_WARN("failed to cast uint to float", K(in), K(uint64), K(ret)); // } else {/*do nothing*/} // return ret; //} // // static int enumset_inner_double(const ObObjType expect_type, ObObjCastParams ¶ms, // const ObObj &in, ObObj &out, const ObCastMode cast_mode) //{ // //we regard enum as uint16 when int_value is needed // int ret = OB_SUCCESS; // ObObj uint64; // if (OB_UNLIKELY(ObEnumSetInnerTC != 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(get_uint64_from_enumset_inner(in, uint64))) { // LOG_WARN("failed to get_uint64_from_enumset_inner", K(in), K(ret)); // } else if (OB_FAIL(uint_double(expect_type, params, uint64, out, cast_mode))) { // LOG_WARN("failed to cast uint to double", K(in), K(uint64), K(ret)); // } else {/*do nothing*/} // return ret; //} // // static int enumset_inner_number(const ObObjType expect_type, ObObjCastParams ¶ms, // const ObObj &in, ObObj &out, const ObCastMode cast_mode) //{ // //we regard enum as uint16 when int_value is needed // int ret = OB_SUCCESS; // ObObj uint64; // if (OB_UNLIKELY(ObEnumSetInnerTC != in.get_type_class() // || ObNumberTC != ob_obj_type_class(expect_type))) { // ret = OB_ERR_UNEXPECTED; // LOG_ERROR("invalid input type", K(in), K(expect_type), K(ret)); // } else if (OB_FAIL(get_uint64_from_enumset_inner(in, uint64))) { // LOG_WARN("failed to get_uint64_from_enumset_inner", K(in), K(ret)); // } else if (OB_FAIL(uint_number(expect_type, params, uint64, out, cast_mode))) { // LOG_WARN("failed to cast uint to number", K(in), K(uint64), K(ret)); // } else {/*do nothing*/} // return ret; //} static int enumset_inner_int( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { // we regard enum as uint16 when int_value is needed int ret = OB_SUCCESS; ObObj uint64; if (OB_UNLIKELY(ObEnumSetInnerTC != 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(get_uint64_from_enumset_inner(in, uint64))) { LOG_WARN("failed to get_uint64_from_enumset_inner", K(in), K(ret)); } else if (OB_FAIL(uint_int(expect_type, params, uint64, out, cast_mode))) { LOG_WARN("failed to cast uint to int", K(in), K(uint64), K(ret)); } else { /*do nothing*/ } return ret; } static int enumset_inner_uint( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { // we regard enum as uint16 when int_value is needed int ret = OB_SUCCESS; ObObj uint64; if (OB_UNLIKELY(ObEnumSetInnerTC != 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(get_uint64_from_enumset_inner(in, uint64))) { LOG_WARN("failed to get_uint64_from_enumset_inner", K(in), K(ret)); } else if (OB_FAIL(uint_uint(expect_type, params, uint64, out, cast_mode))) { LOG_WARN("failed to cast uint to uint", K(in), K(uint64), K(ret)); } else { /*do nothing*/ } return ret; } static int enumset_inner_float( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { // we regard enum as uint16 when int_value is needed int ret = OB_SUCCESS; ObObj uint64; if (OB_UNLIKELY(ObEnumSetInnerTC != 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(get_uint64_from_enumset_inner(in, uint64))) { LOG_WARN("failed to get_uint64_from_enumset_inner", K(in), K(ret)); } else if (OB_FAIL(uint_float(expect_type, params, uint64, out, cast_mode))) { LOG_WARN("failed to cast uint to float", K(in), K(uint64), K(ret)); } else { /*do nothing*/ } return ret; } static int enumset_inner_double( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { // we regard enum as uint16 when int_value is needed int ret = OB_SUCCESS; ObObj uint64; if (OB_UNLIKELY(ObEnumSetInnerTC != 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(get_uint64_from_enumset_inner(in, uint64))) { LOG_WARN("failed to get_uint64_from_enumset_inner", K(in), K(ret)); } else if (OB_FAIL(uint_double(expect_type, params, uint64, out, cast_mode))) { LOG_WARN("failed to cast uint to double", K(in), K(uint64), K(ret)); } else { /*do nothing*/ } return ret; } static int enumset_inner_number( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { // we regard enum as uint16 when int_value is needed int ret = OB_SUCCESS; ObObj uint64; if (OB_UNLIKELY(ObEnumSetInnerTC != in.get_type_class() || ObNumberTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(in), K(expect_type), K(ret)); } else if (OB_FAIL(get_uint64_from_enumset_inner(in, uint64))) { LOG_WARN("failed to get_uint64_from_enumset_inner", K(in), K(ret)); } else if (OB_FAIL(uint_number(expect_type, params, uint64, out, cast_mode))) { LOG_WARN("failed to cast uint to number", K(in), K(uint64), K(ret)); } else { /*do nothing*/ } return ret; } static int enumset_inner_year( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { // we regard enum as uint64 when int_value is needed int ret = OB_SUCCESS; ObObj uint64; if (OB_UNLIKELY(ObEnumSetInnerTC != 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(get_uint64_from_enumset_inner(in, uint64))) { LOG_WARN("failed to get_uint64_from_enumset_inner", K(in), K(ret)); } else if (OB_FAIL(uint_year(expect_type, params, uint64, out, cast_mode))) { LOG_WARN("failed to cast uint to year", K(in), K(uint64), K(ret)); } else { /*do nothing*/ } return ret; } static int enumset_inner_bit( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { // we regard enum as uint16 when int_value is needed int ret = OB_SUCCESS; ObObj uint64; if (OB_UNLIKELY(ObEnumSetInnerTC != in.get_type_class() || ObBitTC != 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(get_uint64_from_enumset_inner(in, uint64))) { LOG_WARN("failed to get_uint64_from_enumset_inner", K(in), K(ret)); } else if (OB_FAIL(uint_bit(expect_type, params, uint64, out, cast_mode))) { LOG_WARN("failed to cast uint to year", K(in), K(uint64), K(ret)); } else { /*do nothing*/ } return ret; } static int enumset_inner_datetime( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { // we regard enum as uint16 when int_value is needed int ret = OB_SUCCESS; ObObj str_value; if (OB_UNLIKELY(ObEnumSetInnerTC != 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(get_string_from_enumset_inner(in, str_value))) { LOG_WARN("failed to get_string_from_enumset_inner", K(in), K(ret)); } else if (OB_FAIL(string_datetime(expect_type, params, str_value, out, cast_mode))) { LOG_WARN("failed to cast string to datetime", K(in), K(str_value), K(ret)); } else { /*do nothing*/ } return ret; } static int enumset_inner_date( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { // we regard enum as uint16 when int_value is needed int ret = OB_SUCCESS; ObObj str_value; if (OB_UNLIKELY(ObEnumSetInnerTC != 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(get_string_from_enumset_inner(in, str_value))) { LOG_WARN("failed to get_string_from_enumset_inner", K(in), K(ret)); } else if (OB_FAIL(string_date(expect_type, params, str_value, out, cast_mode))) { LOG_WARN("failed to cast string to date", K(in), K(str_value), K(ret)); } else { /*do nothing*/ } return ret; } static int enumset_inner_time( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { // we regard enum as uint16 when int_value is needed int ret = OB_SUCCESS; ObObj str_value; if (OB_UNLIKELY(ObEnumSetInnerTC != 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(get_string_from_enumset_inner(in, str_value))) { LOG_WARN("failed to get_string_from_enumset_inner", K(in), K(ret)); } else if (OB_FAIL(string_time(expect_type, params, str_value, out, cast_mode))) { LOG_WARN("failed to cast string to time", K(in), K(str_value), K(ret)); } else { /*do nothing*/ } return ret; } static int enumset_inner_string( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { // we regard enum as uint16 when int_value is needed int ret = OB_SUCCESS; ObObj str_value; if (OB_UNLIKELY(ObEnumSetInnerTC != in.get_type_class() || ObStringTC != 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(get_string_from_enumset_inner(in, str_value))) { LOG_WARN("failed to get_string_from_enumset_inner", K(in), K(ret)); } else if (OB_FAIL(string_string(expect_type, params, str_value, out, cast_mode))) { LOG_WARN("failed to cast string to string", K(in), K(str_value), K(ret)); } else { /*do nothing*/ } return ret; } //////////////////////////////////////////////////////////// // OTimestamp -> XXX static int otimestamp_datetime( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; int64_t usec = 0; if (OB_UNLIKELY(ObOTimestampTC != in.get_type_class()) || OB_UNLIKELY(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::otimestamp_to_odate( in.get_type(), in.get_otimestamp_value(), params.dtc_params_.tz_info_, usec))) { LOG_WARN("fail to timestamp_tz_to_timestamp", K(ret), K(in), K(expect_type)); } else { ObTimeConverter::trunc_datetime(OB_MAX_DATE_PRECISION, usec); out.set_datetime(expect_type, usec); out.set_scale(OB_MAX_DATE_PRECISION); } SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, in.get_scale(), DEFAULT_LENGTH_FOR_TEMPORAL); UNUSED(cast_mode); return ret; } static int otimestamp_string( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; ObLength res_length = -1; if (OB_UNLIKELY(ObOTimestampTC != in.get_type_class()) || OB_UNLIKELY(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] = {0}; int64_t len = 0; if (OB_FAIL(ObTimeConverter::otimestamp_to_str(in.get_otimestamp_value(), params.dtc_params_, in.get_scale(), in.get_type(), buf, OB_CAST_TO_VARCHAR_MAX_LENGTH, len))) { LOG_WARN("failed to convert otimestamp to string", K(ret)); } else { ObString tmp_str; ObObj tmp_out; if (OB_FAIL(convert_string_collation( ObString(len, buf), ObCharset::get_system_collation(), tmp_str, params.dest_collation_, params))) { LOG_WARN("fail to convert string collation", K(ret)); } else if (OB_FAIL(check_convert_string(expect_type, params, tmp_str, tmp_out))) { LOG_WARN("fail to check_convert_string", K(ret), K(in), K(expect_type)); } else if (OB_FAIL(copy_string(params, expect_type, tmp_out.get_string(), out))) { LOG_WARN("failed to copy_string", K(ret), K(expect_type), K(len)); } else { out.set_type(expect_type); res_length = static_cast(out.get_string_len()); } } } SET_RES_ACCURACY_STRING(expect_type, DEFAULT_PRECISION_FOR_STRING, res_length); UNUSED(cast_mode); return ret; } static int otimestamp_otimestamp( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; ObOTimestampData value; if (OB_UNLIKELY(ObOTimestampTC != in.get_type_class()) || OB_UNLIKELY(ObOTimestampTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else if (ObTimestampNanoType == in.get_type()) { if (OB_FAIL(ObTimeConverter::odate_to_otimestamp( in.get_otimestamp_value().time_us_, params.dtc_params_.tz_info_, expect_type, value))) { LOG_WARN("fail to odate_to_otimestamp", K(ret), K(expect_type)); } else { value.time_ctx_.tail_nsec_ = in.get_otimestamp_value().time_ctx_.tail_nsec_; } } else if (ObTimestampNanoType == expect_type) { if (OB_FAIL(ObTimeConverter::otimestamp_to_odate( in.get_type(), in.get_otimestamp_value(), params.dtc_params_.tz_info_, *(int64_t*)&value.time_us_))) { LOG_WARN("fail to otimestamp_to_odate", K(ret), K(expect_type)); } else { value.time_ctx_.tail_nsec_ = in.get_otimestamp_value().time_ctx_.tail_nsec_; } } else { if (OB_FAIL(ObTimeConverter::otimestamp_to_otimestamp( in.get_type(), in.get_otimestamp_value(), params.dtc_params_.tz_info_, expect_type, value))) { LOG_WARN("fail to otimestamp_to_otimestamp", K(ret), K(expect_type)); } } if (OB_SUCC(ret)) { SET_RES_OTIMESTAMP(out); } SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, in.get_scale(), DEFAULT_LENGTH_FOR_TEMPORAL); UNUSED(cast_mode); return ret; } //////////////////////////////////////////////////////////// // Interval -> XXX static int interval_string( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; char buf[OB_CAST_TO_VARCHAR_MAX_LENGTH] = {0}; int64_t len = 0; ObLength res_length = -1; bool is_explicit_cast = CM_IS_EXPLICIT_CAST(cast_mode); if (OB_UNLIKELY(!ob_is_string_type(expect_type) || ObIntervalTC != in.get_type_class())) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else { ret = in.is_interval_ym() ? ObTimeConverter::interval_ym_to_str( in.get_interval_ym(), in.get_scale(), buf, OB_CAST_TO_VARCHAR_MAX_LENGTH, len, is_explicit_cast) : ObTimeConverter::interval_ds_to_str( in.get_interval_ds(), in.get_scale(), buf, OB_CAST_TO_VARCHAR_MAX_LENGTH, len, is_explicit_cast); if (OB_FAIL(ret)) { LOG_WARN("failed to convert interval to str"); } else { ObString tmp_str; ObObj tmp_out; if (OB_FAIL(convert_string_collation( ObString(len, buf), ObCharset::get_system_collation(), tmp_str, params.dest_collation_, params))) { LOG_WARN("fail to convert string collation", K(ret)); } else if (OB_FAIL(check_convert_string(expect_type, params, tmp_str, tmp_out))) { LOG_WARN("fail to check_convert_string", K(ret), K(in), K(expect_type)); } else if (OB_FAIL(copy_string(params, expect_type, tmp_out.get_string(), out))) { LOG_WARN("failed to copy_string", K(ret), K(expect_type), K(len)); } else { out.set_type(expect_type); res_length = static_cast(out.get_string_len()); } } } SET_RES_ACCURACY_STRING(expect_type, DEFAULT_PRECISION_FOR_STRING, res_length); UNUSED(cast_mode); return ret; } static int interval_interval( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; if (OB_UNLIKELY(ObIntervalTC != ob_obj_type_class(expect_type) || ObIntervalTC != in.get_type_class())) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else if (OB_UNLIKELY(expect_type != in.get_type())) { ret = cast_inconsistent_types(expect_type, params, in, out, cast_mode); } else { if (&in != &out) { out = in; } } return ret; } //////////////////////////////////////////////////////////// // Raw -> XXX // lob is excluded. static int raw_string( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { UNUSED(cast_mode); int ret = OB_SUCCESS; ObLength res_length = -1; ObString tmp_str; ObObj tmp_obj; if (OB_UNLIKELY((ObRawTC != in.get_type_class()) || OB_UNLIKELY(ObStringTC != 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(ObHexUtils::rawtohex(in, params, tmp_obj))) { LOG_WARN("fail to rawtohex", K(ret), K(in), K(expect_type)); } else { if (!ObCharset::is_cs_nonascii(params.dest_collation_)) { out.set_string(expect_type, tmp_obj.get_string_ptr(), tmp_obj.get_string_len()); out.set_collation_type(params.dest_collation_); res_length = static_cast(out.get_string_len()); } else { if (OB_FAIL(convert_string_collation( tmp_obj.get_string(), ObCharset::get_system_collation(), tmp_str, params.dest_collation_, params))) { LOG_WARN("failed to convert string collation", K(ret)); } else { out.set_string(expect_type, tmp_str.ptr(), tmp_str.length()); out.set_collation_type(params.dest_collation_); res_length = static_cast(out.get_string_len()); } } } SET_RES_ACCURACY_STRING(expect_type, DEFAULT_PRECISION_FOR_STRING, res_length); return ret; } static int raw_longtext( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { UNUSED(cast_mode); int ret = OB_SUCCESS; ObLength res_length = -1; ObString tmp_str; ObObj tmp_obj; if (OB_UNLIKELY((ObRawTC != in.get_type_class()) || OB_UNLIKELY(!ob_is_text_tc(expect_type)))) { ret = OB_ERR_UNEXPECTED; LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); } else if (ob_is_clob(expect_type, params.expect_obj_collation_)) { // raw to clob if (OB_FAIL(ObHexUtils::rawtohex(in, params, tmp_obj))) { LOG_WARN("fail to rawtohex", K(ret), K(in), K(expect_type)); } else { if (!ObCharset::is_cs_nonascii(params.expect_obj_collation_)) { out.set_varchar_value(tmp_obj.get_string_ptr(), tmp_obj.get_string_len()); out.set_collation_type(params.expect_obj_collation_); } else { if (OB_FAIL(convert_string_collation(tmp_obj.get_string(), ObCharset::get_system_collation(), tmp_str, params.expect_obj_collation_, params))) { LOG_WARN("failed to convert string collation", K(ret)); } else { out.set_varchar_value(tmp_str.ptr(), tmp_str.length()); out.set_collation_type(params.expect_obj_collation_); } } } } else if (ob_is_blob(expect_type, params.expect_obj_collation_)) { // raw to blob if (OB_FAIL(copy_string(params, expect_type, in.get_string(), out))) { LOG_WARN("failed to copy string", K(ret), K(in), K(expect_type)); } } if (OB_SUCC(ret)) { out.set_type(expect_type); out.set_lob_inrow(); out.set_collation_type(params.expect_obj_collation_); out.set_collation_level(CS_LEVEL_IMPLICIT); res_length = static_cast(out.get_string_len()); } SET_RES_ACCURACY_STRING(expect_type, DEFAULT_PRECISION_FOR_STRING, res_length); return ret; } static int raw_lob( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; ObObj tmp_val; if (OB_UNLIKELY((ObRawTC != in.get_type_class()) || OB_UNLIKELY(ObLobTC != 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(raw_longtext(ObLongTextType, params, in, tmp_val, cast_mode))) { LOG_WARN("fail to cast raw to longtext", K(ret), K(expect_type), K(in), K(tmp_val)); } else if (OB_FAIL(string_lob(expect_type, params, tmp_val, out, cast_mode))) { LOG_WARN("fail to cast string to lob", K(ret), K(expect_type), K(in), K(tmp_val)); } return ret; } static int raw_raw( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { UNUSED(cast_mode); int ret = OB_SUCCESS; ObLength res_length = -1; ObObj tmp_out; if (OB_UNLIKELY((ObRawTC != in.get_type_class()) || OB_UNLIKELY(ObRawTC != 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(check_convert_string(expect_type, params, in, tmp_out))) { LOG_WARN("failed to check_and_convert_string", K(ret), K(in), K(expect_type)); } else if (OB_FAIL(copy_string(params, expect_type, tmp_out.get_string(), out))) { LOG_WARN("failed to copy string", K(ret), K(in), K(expect_type)); } else { out.set_type(expect_type); res_length = static_cast(out.get_string_len()); } SET_RES_ACCURACY_STRING(expect_type, DEFAULT_PRECISION_FOR_STRING, res_length); return ret; } //////////////////////////////////////////////////////////// // rowid -> XXX static int rowid_string( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { UNUSED(cast_mode); int ret = OB_SUCCESS; ObLength res_length = -1; if (OB_UNLIKELY(ObRowIDTC != in.get_type_class()) || OB_UNLIKELY(ObStringTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_WARN("invalid input type", K(ret), K(in), K(expect_type)); } else if (!in.is_urowid()) { ret = OB_NOT_SUPPORTED; LOG_WARN("not support rowid for now", K(ret)); } else { int64_t pos = 0; char* base64_buf = NULL; int64_t base64_buf_len = in.get_urowid().needed_base64_buffer_size(); if (OB_ISNULL(base64_buf = (char*)(params.alloc(base64_buf_len)))) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("failed to allocate memory", K(ret)); } else if (OB_FAIL(in.get_urowid().get_base64_str(base64_buf, base64_buf_len, pos))) { LOG_WARN("failed to get base64 string", K(ret)); } else { ObString tmp_str; ObObj tmp_out; if (OB_FAIL(convert_string_collation(ObString(base64_buf_len, base64_buf), ObCharset::get_system_collation(), tmp_str, params.dest_collation_, params))) { LOG_WARN("failed to convert string collation", K(ret)); } else if (OB_FAIL(check_convert_string(expect_type, params, tmp_str, tmp_out))) { LOG_WARN("failed to check convert string", K(ret)); } else if (OB_FAIL(copy_string(params, expect_type, tmp_out.get_string(), out))) { LOG_WARN("failed to copy_string", K(ret), K(expect_type)); } else { out.set_type(expect_type); res_length = static_cast(out.get_string_len()); } } } SET_RES_ACCURACY_STRING(expect_type, DEFAULT_PRECISION_FOR_STRING, res_length); return ret; } static int rowid_rowid( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; if (OB_UNLIKELY(ObRowIDTC != in.get_type_class()) || OB_UNLIKELY(ObRowIDTC != ob_obj_type_class(expect_type))) { ret = OB_ERR_UNEXPECTED; LOG_WARN("invalid input type", K(ret), K(in), K(expect_type)); } else if (OB_UNLIKELY(ObURowIDType != expect_type || ObURowIDType != in.get_type())) { ret = OB_NOT_SUPPORTED; LOG_WARN("only support urowid type for now", K(ret)); } else { UNUSED(params); UNUSED(cast_mode); if (&in != &out) { out = in; } } return ret; } //////////////////////////////////////////////////////////// // Lob -> XXX #define CAST_LOB_TO_OTHER_TYPE(TYPE, TYPE_CLASS) \ static int lob_##TYPE( \ const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) \ { \ int ret = OB_SUCCESS; \ if (OB_UNLIKELY(ObLobTC != in.get_type_class() || TYPE_CLASS != ob_obj_type_class(expect_type))) { \ ret = OB_ERR_UNEXPECTED; \ LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); \ } else if (lib::is_oracle_mode() && in.is_blob_locator()) { \ ret = OB_NOT_SUPPORTED; \ LOG_ERROR("invalid use of blob type", K(ret), K(in), K(expect_type)); \ LOG_USER_ERROR(OB_NOT_SUPPORTED, "Blob cast to other type"); \ } else { \ ObString str; \ if (OB_FAIL(in.get_string(str))) { \ STORAGE_LOG(WARN, "Failed to get payload from lob locator", K(ret), K(in)); \ } else { \ ObObj tmp_obj; \ tmp_obj.set_varchar(str); \ tmp_obj.set_collation_type(in.get_collation_type()); \ if (OB_FAIL(string_##TYPE(expect_type, params, tmp_obj, out, cast_mode))) { \ LOG_WARN("string to " #TYPE "failed", K(ret), K(tmp_obj)); \ } \ } \ } \ return ret; \ } CAST_LOB_TO_OTHER_TYPE(int, ObIntTC); CAST_LOB_TO_OTHER_TYPE(uint, ObUIntTC); CAST_LOB_TO_OTHER_TYPE(double, ObDoubleTC); CAST_LOB_TO_OTHER_TYPE(float, ObFloatTC); CAST_LOB_TO_OTHER_TYPE(number, ObNumberTC); CAST_LOB_TO_OTHER_TYPE(datetime, ObDateTimeTC); CAST_LOB_TO_OTHER_TYPE(date, ObDateTC); CAST_LOB_TO_OTHER_TYPE(time, ObTimeTC); CAST_LOB_TO_OTHER_TYPE(year, ObYearTC); CAST_LOB_TO_OTHER_TYPE(bit, ObBitTC); CAST_LOB_TO_OTHER_TYPE(otimestamp, ObOTimestampTC); CAST_LOB_TO_OTHER_TYPE(interval, ObIntervalTC); CAST_LOB_TO_OTHER_TYPE(rowid, ObRowIDTC); static int lob_string( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; ObObj tmp_out; ObString in_str; if (OB_UNLIKELY(ObLobTC != in.get_type_class() || OB_UNLIKELY(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(in.get_string(in_str))) { LOG_WARN("get string failed", K(ret)); } else { ObObj tmp_in = in; tmp_in.set_string(ObLongTextType, in_str); if (OB_FAIL(string_string(expect_type, params, tmp_in, out, cast_mode))) { LOG_WARN("cast string to string failed", K(ret)); } } return ret; } static int lob_lob( const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) { int ret = OB_SUCCESS; if (OB_UNLIKELY(ObLobTC != in.get_type_class() || ObLobTC != 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_collation_type() == params.expect_obj_collation_) { out = in; } else if (lib::is_oracle_mode() && in.is_blob_locator()) { ret = OB_NOT_SUPPORTED; LOG_ERROR("invalid use of blob type", K(ret), K(in), K(expect_type)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "Blob cast to other type"); } else if (lib::is_oracle_mode() && in.is_clob_locator() && CS_TYPE_BINARY == params.expect_obj_collation_) { ret = OB_NOT_SUPPORTED; LOG_WARN("Can't convert collation type of clob to binary", K(ret), K(in), K(expect_type), K(params.expect_obj_collation_)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "Convert collation type of clob to binary"); } else { ObString str; if (OB_FAIL(in.get_string(str))) { STORAGE_LOG(WARN, "Failed to get payload from lob locator", K(ret), K(in)); } else { ObObj tmp_obj; tmp_obj.set_varchar(str); tmp_obj.set_collation_type(in.get_collation_type()); if (OB_FAIL(string_lob(expect_type, params, tmp_obj, out, cast_mode, in.get_lob_locator()))) { LOG_WARN("string to rowid failed", K(ret), K(tmp_obj)); } } } return ret; } ObObjCastFunc OB_OBJ_CAST[ObMaxTC][ObMaxTC] = { { /*null -> XXX*/ cast_identity, /*null*/ cast_identity, /*int*/ cast_identity, /*uint*/ cast_identity, /*float*/ cast_identity, /*double*/ cast_identity, /*number*/ cast_identity, /*datetime*/ cast_identity, /*date*/ cast_identity, /*time*/ cast_identity, /*year*/ cast_identity, /*string*/ cast_identity, /*extend*/ cast_identity, /*unknown*/ cast_identity, /*text*/ cast_identity, /*bit*/ cast_identity, /*enumset*/ cast_identity, /*enumsetInner*/ cast_identity, /*otimestamp*/ cast_inconsistent_types, /*raw*/ cast_not_expected, /*interval*/ cast_not_expected, /*rowid*/ cast_identity, /*lob*/ }, { /*int -> XXX*/ cast_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*/ cast_not_support, /*extend*/ cast_not_support, /*unknown*/ int_string, /*text*/ int_bit, /*bit*/ cast_not_expected, /*enumset*/ cast_not_expected, /*enumset_inner*/ cast_not_support, /*otimestamp*/ cast_inconsistent_types, /*raw*/ cast_not_expected, /*interval*/ cast_not_expected, /*rowid*/ int_lob, /*lob*/ }, { /*uint -> XXX*/ cast_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*/ cast_not_support, /*extend*/ cast_not_support, /*unknown*/ uint_string, /*text*/ uint_bit, /*bit*/ cast_not_expected, /*enumset*/ cast_not_expected, /*enumset_inner*/ cast_not_support, /*otimestamp*/ cast_inconsistent_types, /*raw*/ cast_not_expected, /*interval*/ cast_not_expected, /*rowid*/ uint_lob, /*lob*/ }, { /*float -> XXX*/ cast_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*/ cast_not_support, /*year*/ float_string, /*string*/ cast_not_support, /*extend*/ cast_not_support, /*unknown*/ float_string, /*text*/ float_bit, /*bit*/ cast_not_expected, /*enumset*/ cast_not_expected, /*enumset_inner*/ cast_not_support, /*otimestamp*/ cast_inconsistent_types, /*raw*/ cast_not_expected, /*interval*/ cast_not_expected, /*rowid*/ float_lob, /*lob*/ }, { /*double -> XXX*/ cast_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*/ double_year, /*year*/ double_string, /*string*/ cast_not_support, /*extend*/ cast_not_support, /*unknown*/ double_string, /*text*/ double_bit, /*bit*/ cast_not_expected, /*enumset*/ cast_not_expected, /*enumset_inner*/ cast_not_support, /*otimestamp*/ cast_inconsistent_types, /*raw*/ cast_not_expected, /*interval*/ cast_not_expected, /*rowid*/ double_lob, /*lob*/ }, { /*number -> XXX*/ cast_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*/ cast_not_support, /*extend*/ cast_not_support, /*unknown*/ number_string, /*text*/ number_bit, /*bit*/ cast_not_expected, /*enumset*/ cast_not_expected, /*enumset_inner*/ cast_not_support, /*otimestamp*/ cast_inconsistent_types, /*raw*/ cast_not_expected, /*interval*/ cast_not_expected, /*rowid*/ number_lob, /*lob*/ }, { /*datetime -> XXX*/ cast_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*/ cast_not_support, /*extend*/ cast_not_support, /*unknown*/ datetime_string, /*text*/ datetime_bit, /*bit*/ cast_not_expected, /*enumset*/ cast_not_expected, /*enumset_inner*/ datetime_otimestamp, /*otimestamp*/ cast_inconsistent_types, /*raw*/ cast_not_expected, /*interval*/ cast_not_expected, /*rowid*/ datetime_lob, /*lob*/ }, { /*date -> XXX*/ cast_not_support, /*null*/ date_int, /*int*/ date_uint, /*uint*/ date_float, /*float*/ date_double, /*double*/ date_number, /*number*/ date_datetime, /*datetime*/ cast_identity, /*date*/ date_time, /*time*/ date_year, /*year*/ date_string, /*string*/ cast_not_support, /*extend*/ cast_not_support, /*unknown*/ date_string, /*text*/ date_bit, /*bit*/ cast_not_expected, /*enumset*/ cast_not_expected, /*enumset_inner*/ cast_not_support, /*otimestamp*/ cast_inconsistent_types, /*raw*/ cast_not_expected, /*interval*/ cast_not_expected, /*rowid*/ date_lob, /*lob*/ }, { /*time -> XXX*/ cast_not_support, /*null*/ time_int, /*int*/ time_uint, /*uint*/ time_float, /*float*/ time_double, /*double*/ time_number, /*number*/ time_datetime, /*datetime*/ time_date, /*date*/ cast_identity, /*time*/ cast_not_support, /*year*/ time_string, /*string*/ cast_not_support, /*extend*/ cast_not_support, /*unknown*/ time_string, /*text*/ time_bit, /*bit*/ cast_not_expected, /*enumset*/ cast_not_expected, /*enumset_inner*/ cast_not_support, /*otimestamp*/ cast_inconsistent_types, /*raw*/ cast_not_expected, /*interval*/ cast_not_expected, /*rowid*/ time_lob, /*lob*/ }, { /*year -> XXX*/ cast_not_support, /*null*/ year_int, /*int*/ year_uint, /*uint*/ year_float, /*float*/ year_double, /*double*/ year_number, /*number*/ cast_not_support, /*datetime*/ year_date, /*date*/ cast_not_support, /*time*/ cast_identity, /*year*/ year_string, /*string*/ cast_not_support, /*extend*/ cast_not_support, /*unknown*/ year_string, /*text*/ year_bit, /*bit*/ cast_not_expected, /*enumset*/ cast_not_expected, /*enumset_inner*/ cast_not_support, /*otimestamp*/ cast_inconsistent_types, /*raw*/ cast_not_expected, /*interval*/ cast_not_expected, /*rowid*/ year_lob, /*lob*/ }, { /*string -> XXX*/ cast_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*/ cast_not_support, /*extend*/ cast_not_support, /*unknown*/ string_string, /*text*/ string_bit, /*bit*/ cast_not_expected, /*enumset*/ cast_not_expected, /*enumset_inner*/ string_otimestamp, /*otimestamp*/ cast_inconsistent_types, /*raw*/ cast_not_expected, /*interval*/ cast_not_expected, /*rowid*/ string_lob, /*lob*/ }, { /*extend -> XXX*/ cast_not_support, /*null*/ cast_not_support, /*int*/ cast_not_support, /*uint*/ cast_not_support, /*float*/ cast_not_support, /*double*/ cast_not_support, /*number*/ cast_not_support, /*datetime*/ cast_not_support, /*date*/ cast_not_support, /*time*/ cast_not_support, /*year*/ cast_not_support, /*string*/ cast_identity, /*extend*/ cast_not_support, /*unknown*/ cast_not_support, /*text*/ cast_not_support, /*bit*/ cast_not_support, /*enumset*/ cast_not_support, /*enumset_inner*/ cast_not_support, /*otimestamp*/ cast_inconsistent_types, /*raw*/ cast_not_expected, /*interval*/ cast_not_expected, /*rowid*/ cast_not_support, /*lob*/ }, { /*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*/ cast_identity, /*unknown*/ cast_not_support, /*text*/ unknown_other, /*bit*/ unknown_other, /*enumset*/ unknown_other, /*enumsetInner*/ unknown_other, /*otimestamp*/ cast_inconsistent_types, /*raw*/ cast_not_expected, /*interval*/ cast_not_expected, /*rowid*/ cast_not_support, /*lob*/ }, { /*text -> XXX*/ cast_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*/ cast_not_support, /*extend*/ cast_not_support, /*unknown*/ string_string, /*text*/ string_bit, /*bit*/ cast_not_expected, /*enumset*/ cast_not_expected, /*enumset_inner*/ string_otimestamp, /*otimestamp*/ cast_inconsistent_types, /*raw*/ cast_not_expected, /*interval*/ cast_not_expected, /*rowid*/ string_lob, /*lob*/ }, { /*bit -> XXX*/ cast_not_support, /*null*/ bit_int, /*int*/ bit_uint, /*uint*/ bit_float, /*float*/ bit_double, /*double*/ bit_number, /*number*/ bit_datetime, /*datetime*/ bit_date, /*date*/ bit_time, /*time*/ bit_year, /*year*/ bit_string, /*string*/ cast_not_support, /*extend*/ cast_not_support, /*unknown*/ bit_string, /*text*/ bit_bit, /*bit*/ cast_not_expected, /*enumset*/ cast_not_expected, /*enumset_inner*/ cast_not_support, /*otimestamp*/ cast_inconsistent_types, /*raw*/ cast_not_expected, /*interval*/ cast_not_expected, /*rowid*/ bit_lob, /*lob*/ }, { /*enum -> XXX*/ cast_not_support, /*null*/ enumset_int, /*int*/ enumset_uint, /*uint*/ enumset_float, /*float*/ enumset_double, /*double*/ enumset_number, /*number*/ cast_not_expected, /*datetime*/ cast_not_expected, /*date*/ cast_not_expected, /*time*/ enumset_year, /*year*/ cast_not_expected, /*string*/ cast_not_support, /*extend*/ cast_not_support, /*unknown*/ cast_not_expected, /*text*/ enumset_bit, /*bit*/ cast_not_expected, /*enumset*/ cast_not_expected, /*enumset_inner*/ cast_not_support, /*otimestamp*/ cast_inconsistent_types, /*raw*/ cast_not_expected, /*interval*/ cast_not_expected, /*rowid*/ cast_not_expected, /*lob*/ }, { /*enumset_inner -> XXX*/ cast_not_support, /*null*/ enumset_inner_int, /*int*/ enumset_inner_uint, /*uint*/ enumset_inner_float, /*float*/ enumset_inner_double, /*double*/ enumset_inner_number, /*number*/ enumset_inner_datetime, /*datetime*/ enumset_inner_date, /*date*/ enumset_inner_time, /*time*/ enumset_inner_year, /*year*/ enumset_inner_string, /*string*/ cast_not_support, /*extend*/ cast_not_support, /*unknown*/ cast_not_support, /*text*/ enumset_inner_bit, /*bit*/ cast_not_expected, /*enumset*/ cast_not_expected, /*enumset_inner*/ cast_not_expected, /*otimestamp*/ cast_inconsistent_types, /*raw*/ cast_not_expected, /*interval*/ cast_not_expected, /*rowid*/ cast_not_support, /*lob*/ }, { /*otimestamp -> XXX*/ cast_not_expected, /*null*/ cast_not_expected, /*int*/ cast_not_expected, /*uint*/ cast_not_expected, /*float*/ cast_not_expected, /*double*/ cast_not_expected, /*number*/ cast_not_expected, /*datetime*/ cast_not_expected, /*date*/ cast_not_expected, /*time*/ cast_not_expected, /*year*/ cast_not_expected, /*string*/ cast_not_expected, /*extend*/ cast_not_expected, /*unknown*/ cast_not_expected, /*text*/ cast_not_expected, /*bit*/ cast_not_expected, /*enumset*/ cast_not_expected, /*enumset_inner*/ otimestamp_otimestamp, /*otimestamp*/ cast_inconsistent_types, /*raw*/ cast_not_expected, /*interval*/ cast_not_expected, /*rowid*/ cast_not_expected, /*lob*/ }, { /*raw -> XXX*/ cast_not_expected, /*null*/ cast_not_expected, /*int*/ cast_not_expected, /*uint*/ cast_not_expected, /*float*/ cast_not_expected, /*double*/ cast_not_expected, /*number*/ cast_not_expected, /*datetime*/ cast_not_expected, /*date*/ cast_not_expected, /*time*/ cast_not_expected, /*year*/ cast_not_expected, /*string*/ cast_not_expected, /*extend*/ cast_not_expected, /*unknown*/ cast_not_expected, /*text*/ cast_not_expected, /*bit*/ cast_not_expected, /*enumset*/ cast_not_expected, /*enumset_inner*/ cast_not_expected, /*otimestamp*/ cast_not_expected, /*raw*/ cast_not_expected, /*interval*/ cast_not_expected, /*rowid*/ cast_not_expected, /*lob*/ }, { /*interval -> XXX*/ cast_not_expected, /*null*/ cast_not_expected, /*int*/ cast_not_expected, /*uint*/ cast_not_expected, /*float*/ cast_not_expected, /*double*/ cast_not_expected, /*number*/ cast_not_expected, /*datetime*/ cast_not_expected, /*date*/ cast_not_expected, /*time*/ cast_not_expected, /*year*/ cast_not_expected, /*string*/ cast_not_expected, /*extend*/ cast_not_expected, /*unknown*/ cast_not_expected, /*text*/ cast_not_expected, /*bit*/ cast_not_expected, /*enumset*/ cast_not_expected, /*enumset_inner*/ cast_not_expected, /*otimestamp*/ cast_not_expected, /*raw*/ cast_not_expected, /*interval*/ cast_not_expected, /*rowid*/ cast_not_expected, /*lob*/ }, { /*rowid -> XXX*/ cast_not_expected, /*null*/ cast_not_expected, /*int*/ cast_not_expected, /*uint*/ cast_not_expected, /*float*/ cast_not_expected, /*double*/ cast_not_expected, /*number*/ cast_not_expected, /*datetime*/ cast_not_expected, /*date*/ cast_not_expected, /*time*/ cast_not_expected, /*year*/ cast_not_expected, /*string*/ cast_not_expected, /*extend*/ cast_not_expected, /*unknown*/ cast_not_expected, /*text*/ cast_not_expected, /*bit*/ cast_not_expected, /*enumset*/ cast_not_expected, /*enumset_inner*/ cast_not_expected, /*otimestamp*/ cast_not_expected, /*raw*/ cast_not_expected, /*interval*/ cast_not_expected, /*rowid*/ cast_not_expected, /*lob*/ }, { /*lob -> XXX*/ cast_not_support, /*null*/ lob_int, /*int*/ lob_uint, /*uint*/ lob_float, /*float*/ lob_double, /*double*/ lob_number, /*number*/ lob_datetime, /*datetime*/ lob_date, /*date*/ lob_time, /*time*/ lob_year, /*year*/ lob_string, /*string*/ cast_not_support, /*extend*/ cast_not_support, /*unknown*/ lob_string, /*text*/ lob_bit, /*bit*/ cast_not_expected, /*enumset*/ cast_not_expected, /*enumset_inner*/ lob_otimestamp, /*otimestamp*/ cast_inconsistent_types, /*raw*/ cast_not_expected, /*interval*/ cast_not_expected, /*rowid*/ lob_lob, /*lob*/ }, }; ObObjCastFunc OBJ_CAST_ORACLE_EXPLICIT[ObMaxTC][ObMaxTC] = { { /*null -> XXX*/ cast_identity, /*null*/ cast_identity, /*int*/ cast_identity, /*uint*/ cast_identity, /*float*/ cast_identity, /*double*/ cast_identity, /*number*/ cast_identity, /*datetime*/ cast_identity, /*date*/ cast_identity, /*time*/ cast_identity, /*year*/ cast_identity, /*string*/ cast_identity, /*extend*/ cast_identity, /*unknown*/ cast_identity, /*text*/ cast_identity, /*bit*/ cast_identity, /*enumset*/ cast_identity, /*enumsetInner*/ cast_identity, /*otimestamp*/ cast_identity, /*raw*/ cast_identity, /*interval*/ cast_identity, /*rowid*/ cast_identity, /*lob*/ }, { /*int -> XXX*/ cast_not_support, /*null*/ int_int, /*int*/ int_uint, /*uint*/ int_float, /*float*/ int_double, /*double*/ int_number, /*number*/ cast_not_support, /*datetime*/ cast_not_support, /*date*/ cast_not_support, /*time*/ cast_not_support, /*year*/ int_string, /*string*/ cast_not_support, /*extend*/ cast_not_support, /*unknown*/ int_string, /*text*/ int_bit, /*bit*/ cast_not_expected, /*enumset*/ cast_not_expected, /*enumset_inner*/ cast_not_support, /*otimestamp*/ cast_not_support, /*raw*/ cast_not_support, /*interval*/ cast_not_support, /*rowid*/ cast_inconsistent_types, /*lob*/ }, { /*uint -> XXX*/ cast_not_support, /*null*/ uint_int, /*int*/ uint_uint, /*uint*/ uint_float, /*float*/ uint_double, /*double*/ uint_number, /*number*/ cast_not_support, /*datetime*/ cast_not_support, /*date*/ cast_not_support, /*time*/ cast_not_support, /*year*/ uint_string, /*string*/ cast_not_support, /*extend*/ cast_not_support, /*unknown*/ uint_string, /*text*/ uint_bit, /*bit*/ cast_not_expected, /*enumset*/ cast_not_expected, /*enumset_inner*/ cast_not_support, /*otimestamp*/ cast_not_support, /*raw*/ cast_not_support, /*interval*/ cast_not_support, /*rowid*/ cast_inconsistent_types, /*lob*/ }, { /*float -> XXX*/ cast_not_support, /*null*/ float_int, /*int*/ float_uint, /*uint*/ float_float, /*float*/ float_double, /*double*/ float_number, /*number*/ cast_not_support, /*datetime*/ cast_not_support, /*date*/ cast_not_support, /*time*/ cast_not_support, /*year*/ float_string, /*string*/ cast_not_support, /*extend*/ cast_not_support, /*unknown*/ float_string, /*text*/ float_bit, /*bit*/ cast_not_expected, /*enumset*/ cast_not_expected, /*enumset_inner*/ cast_not_support, /*otimestamp*/ cast_not_support, /*raw*/ cast_not_support, /*interval*/ cast_not_support, /*rowid*/ cast_inconsistent_types, /*lob*/ }, { /*double -> XXX*/ cast_not_support, /*null*/ double_int, /*int*/ double_uint, /*uint*/ double_float, /*float*/ double_double, /*double*/ double_number, /*number*/ cast_not_support, /*datetime*/ cast_not_expected, /*date*/ cast_not_support, /*time*/ cast_not_support, /*year*/ double_string, /*string*/ cast_not_support, /*extend*/ cast_not_support, /*unknown*/ double_string, /*text*/ double_bit, /*bit*/ cast_not_expected, /*enumset*/ cast_not_expected, /*enumset_inner*/ cast_not_support, /*otimestamp*/ cast_not_support, /*raw*/ cast_not_support, /*interval*/ cast_not_support, /*rowid*/ cast_inconsistent_types, /*lob*/ }, { /*number -> XXX*/ cast_not_support, /*null*/ number_int, /*int*/ number_uint, /*uint*/ number_float, /*float*/ number_double, /*double*/ number_number, /*number*/ cast_not_support, /*datetime*/ cast_not_support, /*date*/ cast_not_support, /*time*/ cast_not_support, /*year*/ number_string, /*string*/ cast_not_support, /*extend*/ cast_not_support, /*unknown*/ number_string, /*text*/ number_bit, /*bit*/ cast_not_expected, /*enumset*/ cast_not_expected, /*enumset_inner*/ cast_not_support, /*otimestamp*/ cast_not_support, /*raw*/ cast_not_support, /*interval*/ cast_not_support, /*rowid*/ cast_inconsistent_types, /*lob*/ }, { /*datetime -> XXX*/ cast_not_support, /*null*/ cast_not_support, /*int*/ cast_not_support, /*uint*/ cast_not_support, /*float*/ cast_not_support, /*double*/ cast_not_support, /*number*/ datetime_datetime, /*datetime*/ cast_not_support, /*date*/ cast_not_support, /*time*/ cast_not_support, /*year*/ datetime_string, /*string*/ cast_not_support, /*extend*/ cast_not_support, /*unknown*/ datetime_string, /*text*/ datetime_bit, /*bit*/ cast_not_expected, /*enumset*/ cast_not_expected, /*enumset_inner*/ datetime_otimestamp, /*otimestamp*/ cast_not_support, /*raw*/ cast_not_support, /*interval*/ cast_not_support, /*rowid*/ cast_inconsistent_types, /*lob*/ }, { /*date -> XXX*/ cast_not_expected, /*null*/ cast_not_expected, /*int*/ cast_not_expected, /*uint*/ cast_not_expected, /*float*/ cast_not_expected, /*double*/ cast_not_expected, /*number*/ cast_not_expected, /*datetime*/ cast_not_expected, /*date*/ cast_not_expected, /*time*/ cast_not_expected, /*year*/ cast_not_expected, /*string*/ cast_not_expected, /*extend*/ cast_not_expected, /*unknown*/ cast_not_expected, /*text*/ cast_not_expected, /*bit*/ cast_not_expected, /*enumset*/ cast_not_expected, /*enumset_inner*/ cast_not_expected, /*otimestamp*/ cast_not_expected, /*raw*/ cast_not_expected, /*interval*/ cast_not_expected, /*rowid*/ cast_not_expected, /*lob*/ }, { /*time -> XXX*/ cast_not_support, /*null*/ cast_not_expected, /*int*/ cast_not_expected, /*uint*/ cast_not_expected, /*float*/ cast_not_expected, /*double*/ cast_not_expected, /*number*/ cast_not_expected, /*datetime*/ cast_not_expected, /*date*/ cast_not_expected, /*time*/ cast_not_expected, /*year*/ cast_not_expected, /*string*/ cast_not_expected, /*extend*/ cast_not_expected, /*unknown*/ cast_not_expected, /*text*/ cast_not_expected, /*bit*/ cast_not_expected, /*enumset*/ cast_not_expected, /*enumset_inner*/ cast_not_expected, /*otimestamp*/ cast_not_expected, /*raw*/ cast_not_expected, /*interval*/ cast_not_expected, /*rowid*/ cast_not_expected, /*lob*/ }, { /*year -> XXX*/ cast_not_expected, /*null*/ cast_not_expected, /*int*/ cast_not_expected, /*uint*/ cast_not_expected, /*float*/ cast_not_expected, /*double*/ cast_not_expected, /*number*/ cast_not_expected, /*datetime*/ cast_not_expected, /*date*/ cast_not_expected, /*time*/ cast_not_expected, /*year*/ cast_not_expected, /*string*/ cast_not_expected, /*extend*/ cast_not_expected, /*unknown*/ cast_not_expected, /*text*/ cast_not_expected, /*bit*/ cast_not_expected, /*enumset*/ cast_not_expected, /*enumset_inner*/ cast_not_expected, /*otimestamp*/ cast_not_expected, /*raw*/ cast_not_expected, /*interval*/ cast_not_expected, /*rowid*/ cast_not_expected, /*lob*/ }, { /*string -> XXX*/ cast_not_support, /*null*/ string_int, /*int*/ string_uint, /*uint*/ string_float, /*float*/ string_double, /*double*/ string_number, /*number*/ string_datetime, /*datetime*/ cast_not_expected, /*date*/ cast_not_expected, /*time*/ cast_not_expected, /*year*/ string_string, /*string*/ cast_not_support, /*extend*/ cast_not_support, /*unknown*/ string_string, /*text*/ string_bit, /*bit*/ cast_not_expected, /*enumset*/ cast_not_expected, /*enumset_inner*/ string_otimestamp, /*otimestamp*/ string_raw, /*raw*/ string_interval, /*interval*/ string_rowid, /*rowid*/ cast_inconsistent_types, /*lob*/ }, { /*extend -> XXX*/ cast_not_support, /*null*/ cast_not_support, /*int*/ cast_not_support, /*uint*/ cast_not_support, /*float*/ cast_not_support, /*double*/ cast_not_support, /*number*/ cast_not_support, /*datetime*/ cast_not_support, /*date*/ cast_not_support, /*time*/ cast_not_support, /*year*/ cast_not_support, /*string*/ cast_identity, /*extend*/ cast_not_support, /*unknown*/ cast_not_support, /*text*/ cast_not_support, /*bit*/ cast_not_support, /*enumset*/ cast_not_support, /*enumset_inner*/ cast_not_support, /*otimestamp*/ cast_not_support, /*raw*/ cast_not_support, /*interval*/ cast_not_support, /*rowid*/ cast_not_support, /*lob*/ }, { /*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*/ cast_identity, /*unknown*/ cast_not_support, /*text*/ unknown_other, /*bit*/ unknown_other, /*enumset*/ unknown_other, /*enumsetInner*/ unknown_other, /*otimestamp*/ unknown_other, /*raw*/ unknown_other, /*interval*/ unknown_other, /*rowid*/ cast_not_support, /*lob*/ }, { /*text -> XXX*/ cast_not_support, /*null*/ string_int, /*int*/ string_uint, /*uint*/ string_float, /*float*/ string_double, /*double*/ string_number, /*number*/ string_datetime, /*datetime*/ cast_not_expected, /*date*/ cast_not_expected, /*time*/ cast_not_expected, /*year*/ string_string, /*string*/ cast_not_support, /*extend*/ cast_not_support, /*unknown*/ string_string, /*text*/ string_bit, /*bit*/ cast_not_expected, /*enumset*/ cast_not_expected, /*enumset_inner*/ string_otimestamp, /*otimestamp*/ cast_not_support, /*raw*/ string_interval, /*interval*/ cast_not_support, /*rowid*/ cast_inconsistent_types, /*lob*/ }, { /*bit -> XXX*/ cast_not_expected, /*null*/ cast_not_expected, /*int*/ cast_not_expected, /*uint*/ cast_not_expected, /*float*/ cast_not_expected, /*double*/ cast_not_expected, /*number*/ cast_not_expected, /*datetime*/ cast_not_expected, /*date*/ cast_not_expected, /*time*/ cast_not_expected, /*year*/ cast_not_expected, /*string*/ cast_not_expected, /*extend*/ cast_not_expected, /*unknown*/ cast_not_expected, /*text*/ cast_not_expected, /*bit*/ cast_not_expected, /*enumset*/ cast_not_expected, /*enumset_inner*/ cast_not_expected, /*otimestamp*/ cast_not_expected, /*raw*/ cast_not_expected, /*interval*/ cast_not_expected, /*rowid*/ cast_not_expected, /*lob*/ }, { /*enum -> XXX*/ cast_not_expected, /*null*/ cast_not_expected, /*int*/ cast_not_expected, /*uint*/ cast_not_expected, /*float*/ cast_not_expected, /*double*/ cast_not_expected, /*number*/ cast_not_expected, /*datetime*/ cast_not_expected, /*date*/ cast_not_expected, /*time*/ cast_not_expected, /*year*/ cast_not_expected, /*string*/ cast_not_expected, /*extend*/ cast_not_expected, /*unknown*/ cast_not_expected, /*text*/ cast_not_expected, /*bit*/ cast_not_expected, /*enumset*/ cast_not_expected, /*enumset_inner*/ cast_not_expected, /*otimestamp*/ cast_not_expected, /*raw*/ cast_not_expected, /*interval*/ cast_not_expected, /*rowid*/ cast_not_expected, /*lob*/ }, { /*enumset_inner -> XXX*/ cast_not_expected, /*null*/ cast_not_expected, /*int*/ cast_not_expected, /*uint*/ cast_not_expected, /*float*/ cast_not_expected, /*double*/ cast_not_expected, /*number*/ cast_not_expected, /*datetime*/ cast_not_expected, /*date*/ cast_not_expected, /*time*/ cast_not_expected, /*year*/ cast_not_expected, /*string*/ cast_not_expected, /*extend*/ cast_not_expected, /*unknown*/ cast_not_expected, /*text*/ cast_not_expected, /*bit*/ cast_not_expected, /*enumset*/ cast_not_expected, /*enumset_inner*/ cast_not_expected, /*otimestamp*/ cast_not_expected, /*raw*/ cast_not_expected, /*interval*/ cast_not_expected, /*rowid*/ cast_not_expected, /*lob*/ }, { /*otimestamp -> XXX*/ cast_not_support, /*null*/ cast_not_support, /*int*/ cast_not_support, /*uint*/ cast_not_support, /*float*/ cast_not_support, /*double*/ cast_not_support, /*number*/ otimestamp_datetime, /*datetime*/ cast_not_expected, /*date*/ cast_not_expected, /*time*/ cast_not_expected, /*year*/ otimestamp_string, /*string*/ cast_not_support, /*extend*/ cast_not_support, /*unknown*/ otimestamp_string, /*text*/ cast_not_support, /*bit*/ cast_not_expected, /*enumset*/ cast_not_expected, /*enumset_inner*/ otimestamp_otimestamp, /*otimestamp*/ cast_not_support, /*raw*/ cast_not_support, /*interval*/ cast_not_support, /*rowid*/ cast_inconsistent_types, /*lob*/ }, { /*raw -> XXX*/ cast_not_support, /*null*/ cast_not_support, /*int*/ cast_not_support, /*uint*/ cast_not_support, /*float*/ cast_not_support, /*double*/ cast_not_support, /*number*/ cast_not_support, /*datetime*/ cast_not_expected, /*date*/ cast_not_expected, /*time*/ cast_not_expected, /*year*/ raw_string, /*string*/ cast_not_support, /*extend*/ cast_not_support, /*unknown*/ raw_longtext, /*text*/ cast_not_support, /*bit*/ cast_not_expected, /*enumset*/ cast_not_expected, /*enumset_inner*/ cast_not_support, /*otimestamp*/ raw_raw, /*raw*/ cast_not_support, /*interval*/ cast_not_support, /*rowid*/ cast_inconsistent_types, /*lob*/ }, { /*interval -> XXX*/ cast_not_expected, /*null*/ cast_not_expected, /*int*/ cast_not_expected, /*uint*/ cast_not_expected, /*float*/ cast_not_expected, /*double*/ cast_not_expected, /*number*/ cast_not_expected, /*datetime*/ cast_not_expected, /*date*/ cast_not_expected, /*time*/ cast_not_expected, /*year*/ interval_string, /*string*/ cast_not_expected, /*extend*/ cast_not_expected, /*unknown*/ cast_not_expected, /*text*/ cast_not_expected, /*bit*/ cast_not_expected, /*enumset*/ cast_not_expected, /*enumset_inner*/ cast_not_expected, /*otimestamp*/ cast_not_expected, /*raw*/ interval_interval, /*interval*/ cast_not_support, /*rowid*/ cast_inconsistent_types, /*lob*/ }, { /*rowid -> XXX*/ cast_not_support, /*null*/ cast_not_support, /*int*/ cast_not_support, /*uint*/ cast_not_support, /*float*/ cast_not_support, /*double*/ cast_not_support, /*number*/ cast_not_support, /*datetime*/ cast_not_expected, /*date*/ cast_not_expected, /*time*/ cast_not_expected, /*year*/ rowid_string, /*string*/ cast_not_expected, /*extend*/ cast_not_expected, /*unknown*/ cast_not_expected, /*text*/ cast_not_expected, /*bit*/ cast_not_expected, /*enumset*/ cast_not_expected, /*enumset_inner*/ cast_not_support, /*otimestamp*/ cast_not_support, /*raw*/ cast_not_support, /*interval*/ rowid_rowid, /*rowid*/ cast_inconsistent_types, /*lob*/ }, { /*lob -> XXX*/ cast_not_support, /*null*/ lob_int, /*int*/ lob_uint, /*uint*/ lob_float, /*float*/ lob_double, /*double*/ lob_number, /*number*/ lob_datetime, /*datetime*/ cast_not_expected, /*date*/ cast_not_expected, /*time*/ cast_not_expected, /*year*/ lob_string, /*string*/ cast_not_support, /*extend*/ cast_not_support, /*unknown*/ lob_string, /*text*/ lob_bit, /*bit*/ cast_not_expected, /*enumset*/ cast_not_expected, /*enumset_inner*/ lob_otimestamp, /*otimestamp*/ cast_not_support, /*raw*/ lob_interval, /*interval*/ cast_not_support, /*rowid*/ cast_inconsistent_types, /*lob*/ }, }; /* * 1. I think not_support() means something we will support in future, and cast_not_expected() means * something wrong, so there is no not_support() appears in OBJ_CAST_ORACLE_IMPLICIT now. * 2. int and uint are needed in inner operation, for example, some system variable is uint, * like auto_increment_increment, which will be cast to uint in load_default_sys_variable(). * so this matrix allows cast from or to int / uint. * 3. we can't use ObObjOType as index of this matrix, because int / uint too. */ ObObjCastFunc OBJ_CAST_ORACLE_IMPLICIT[ObMaxTC][ObMaxTC] = { { /*null -> XXX*/ cast_identity, /*null*/ cast_identity, /*int*/ cast_identity, /*uint*/ cast_identity, /*float*/ cast_identity, /*double*/ cast_identity, /*number*/ cast_identity, /*datetime*/ cast_not_expected, /*date*/ cast_not_expected, /*time*/ cast_not_expected, /*year*/ cast_identity, /*string*/ cast_not_expected, /*extend*/ cast_not_expected, /*unknown*/ cast_identity, /*text*/ cast_not_expected, /*bit*/ cast_not_expected, /*enumset*/ cast_not_expected, /*enumsetInner*/ cast_identity, /*otimestamp*/ cast_identity, /*raw*/ cast_identity, /*interval*/ cast_identity, /*rowid*/ cast_identity, /*lob*/ }, { /*int -> XXX*/ cast_not_expected, /*null*/ int_int, /*int*/ int_uint, /*uint*/ int_float, /*float*/ int_double, /*double*/ int_number, /*number*/ cast_inconsistent_types, /*datetime*/ cast_not_expected, /*date*/ cast_not_expected, /*time*/ cast_not_expected, /*year*/ int_string, /*string*/ cast_not_expected, /*extend*/ cast_not_expected, /*unknown*/ cast_inconsistent_types, /*text*/ cast_not_expected, /*bit*/ cast_not_expected, /*enumset*/ cast_not_expected, /*enumset_inner*/ cast_inconsistent_types, /*otimestamp*/ cast_inconsistent_types, /*raw*/ cast_inconsistent_types, /*interval*/ cast_inconsistent_types, /*rowid*/ cast_inconsistent_types, /*lob*/ }, { /*uint -> XXX*/ cast_not_expected, /*null*/ uint_int, /*int*/ uint_uint, /*uint*/ uint_float, /*float*/ uint_double, /*double*/ uint_number, /*number*/ cast_inconsistent_types, /*datetime*/ cast_not_expected, /*date*/ cast_not_expected, /*time*/ cast_not_expected, /*year*/ uint_string, /*string*/ cast_not_expected, /*extend*/ cast_not_expected, /*unknown*/ cast_inconsistent_types, /*text*/ cast_not_expected, /*bit*/ cast_not_expected, /*enumset*/ cast_not_expected, /*enumset_inner*/ cast_inconsistent_types, /*otimestamp*/ cast_inconsistent_types, /*raw*/ cast_inconsistent_types, /*interval*/ cast_inconsistent_types, /*rowid*/ cast_inconsistent_types, /*lob*/ }, { /*float -> XXX*/ cast_not_expected, /*null*/ float_int, /*int*/ float_uint, /*uint*/ float_float, /*float*/ float_double, /*double*/ float_number, /*number*/ cast_inconsistent_types, /*datetime*/ cast_not_expected, /*date*/ cast_not_expected, /*time*/ cast_not_expected, /*year*/ float_string, /*string*/ cast_not_expected, /*extend*/ cast_not_expected, /*unknown*/ cast_inconsistent_types, /*text*/ cast_not_expected, /*bit*/ cast_not_expected, /*enumset*/ cast_not_expected, /*enumset_inner*/ cast_inconsistent_types, /*otimestamp*/ cast_inconsistent_types, /*raw*/ cast_inconsistent_types, /*interval*/ cast_inconsistent_types, /*rowid*/ cast_inconsistent_types, /*lob*/ }, { /*double -> XXX*/ cast_not_expected, /*null*/ double_int, /*int*/ double_uint, /*uint*/ double_float, /*float*/ double_double, /*double*/ double_number, /*number*/ cast_inconsistent_types, /*datetime*/ cast_not_expected, /*date*/ cast_not_expected, /*time*/ cast_not_expected, /*year*/ double_string, /*string*/ cast_not_expected, /*extend*/ cast_not_expected, /*unknown*/ cast_inconsistent_types, /*text*/ cast_not_expected, /*bit*/ cast_not_expected, /*enumset*/ cast_not_expected, /*enumset_inner*/ cast_inconsistent_types, /*otimestamp*/ cast_inconsistent_types, /*raw*/ cast_inconsistent_types, /*interval*/ cast_inconsistent_types, /*rowid*/ cast_inconsistent_types, /*lob*/ }, { /*number -> XXX*/ cast_not_expected, /*null*/ number_int, /*int*/ number_uint, /*uint*/ number_float, /*float*/ number_double, /*double*/ number_number, /*number*/ cast_inconsistent_types, /*datetime*/ cast_not_expected, /*date*/ cast_not_expected, /*time*/ cast_not_expected, /*year*/ number_string, /*string*/ cast_not_expected, /*extend*/ cast_not_expected, /*unknown*/ number_string, /*text*/ cast_not_expected, /*bit*/ cast_not_expected, /*enumset*/ cast_not_expected, /*enumset_inner*/ cast_inconsistent_types, /*otimestamp*/ cast_inconsistent_types, /*raw*/ cast_inconsistent_types, /*interval*/ cast_inconsistent_types, /*rowid*/ number_lob, /*lob*/ }, { /*datetime -> XXX*/ cast_not_expected, /*null*/ cast_inconsistent_types, /*int*/ cast_inconsistent_types, /*uint*/ cast_inconsistent_types, /*float*/ cast_inconsistent_types, /*double*/ cast_inconsistent_types, /*number*/ datetime_datetime, /*datetime*/ cast_not_expected, /*date*/ cast_not_expected, /*time*/ cast_not_expected, /*year*/ datetime_string, /*string*/ cast_not_expected, /*extend*/ cast_not_expected, /*unknown*/ cast_inconsistent_types, /*text*/ cast_not_expected, /*bit*/ cast_not_expected, /*enumset*/ cast_not_expected, /*enumset_inner*/ datetime_otimestamp, /*otimestamp*/ cast_inconsistent_types, /*raw*/ cast_inconsistent_types, /*interval*/ cast_inconsistent_types, /*rowid*/ cast_inconsistent_types, /*lob*/ }, { /*date -> XXX*/ cast_not_expected, /*null*/ cast_not_expected, /*int*/ cast_not_expected, /*uint*/ cast_not_expected, /*float*/ cast_not_expected, /*double*/ cast_not_expected, /*number*/ cast_not_expected, /*datetime*/ cast_not_expected, /*date*/ cast_not_expected, /*time*/ cast_not_expected, /*year*/ cast_not_expected, /*string*/ cast_not_expected, /*extend*/ cast_not_expected, /*unknown*/ cast_not_expected, /*text*/ cast_not_expected, /*bit*/ cast_not_expected, /*enumset*/ cast_not_expected, /*enumset_inner*/ cast_not_expected, /*otimestamp*/ cast_not_expected, /*raw*/ cast_not_expected, /*interval*/ cast_not_expected, /*rowid*/ cast_not_expected, /*lob*/ }, { /*time -> XXX*/ cast_not_expected, /*null*/ cast_not_expected, /*int*/ cast_not_expected, /*uint*/ cast_not_expected, /*float*/ cast_not_expected, /*double*/ cast_not_expected, /*number*/ cast_not_expected, /*datetime*/ cast_not_expected, /*date*/ cast_not_expected, /*time*/ cast_not_expected, /*year*/ cast_not_expected, /*string*/ cast_not_expected, /*extend*/ cast_not_expected, /*unknown*/ cast_not_expected, /*text*/ cast_not_expected, /*bit*/ cast_not_expected, /*enumset*/ cast_not_expected, /*enumset_inner*/ cast_not_expected, /*otimestamp*/ cast_not_expected, /*raw*/ cast_not_expected, /*interval*/ cast_not_expected, /*rowid*/ cast_not_expected, /*lob*/ }, { /*year -> XXX*/ cast_not_expected, /*null*/ cast_not_expected, /*int*/ cast_not_expected, /*uint*/ cast_not_expected, /*float*/ cast_not_expected, /*double*/ cast_not_expected, /*number*/ cast_not_expected, /*datetime*/ cast_not_expected, /*date*/ cast_not_expected, /*time*/ cast_not_expected, /*year*/ cast_not_expected, /*string*/ cast_not_expected, /*extend*/ cast_not_expected, /*unknown*/ cast_not_expected, /*text*/ cast_not_expected, /*bit*/ cast_not_expected, /*enumset*/ cast_not_expected, /*enumset_inner*/ cast_not_expected, /*otimestamp*/ cast_not_expected, /*raw*/ cast_not_expected, /*interval*/ cast_not_expected, /*rowid*/ cast_not_expected, /*lob*/ }, { /*string -> XXX*/ cast_not_expected, /*null*/ string_int, /*int*/ string_uint, /*uint*/ string_float, /*float*/ string_double, /*double*/ string_number, /*number*/ string_datetime, /*datetime*/ cast_not_expected, /*date*/ cast_not_expected, /*time*/ cast_not_expected, /*year*/ string_string, /*string*/ cast_not_expected, /*extend*/ cast_not_expected, /*unknown*/ string_string, /*text*/ cast_not_expected, /*bit*/ cast_not_expected, /*enumset*/ cast_not_expected, /*enumset_inner*/ string_otimestamp, /*otimestamp*/ string_raw, /*raw*/ string_interval, /*interval*/ string_rowid, /*rowid*/ string_lob, /*lob*/ }, { /*extend -> XXX*/ cast_not_expected, /*null*/ cast_not_expected, /*int*/ cast_not_expected, /*uint*/ cast_not_expected, /*float*/ cast_not_expected, /*double*/ cast_not_expected, /*number*/ cast_not_expected, /*datetime*/ cast_not_expected, /*date*/ cast_not_expected, /*time*/ cast_not_expected, /*year*/ cast_not_expected, /*string*/ cast_identity, /*extend*/ cast_not_expected, /*unknown*/ cast_not_expected, /*text*/ cast_not_expected, /*bit*/ cast_not_expected, /*enumset*/ cast_not_expected, /*enumset_inner*/ cast_not_expected, /*otimestamp*/ cast_not_expected, /*raw*/ cast_not_expected, /*interval*/ cast_not_expected, /*rowid*/ cast_not_expected, /*lob*/ }, { /*unknown -> XXX*/ cast_not_expected, /*null*/ cast_not_expected, /*int*/ cast_not_expected, /*uint*/ cast_not_expected, /*float*/ cast_not_expected, /*double*/ cast_not_expected, /*number*/ cast_not_expected, /*datetime*/ cast_not_expected, /*date*/ cast_not_expected, /*time*/ cast_not_expected, /*year*/ cast_not_expected, /*string*/ cast_not_expected, /*extend*/ cast_not_expected, /*unknown*/ cast_not_expected, /*text*/ cast_not_expected, /*bit*/ cast_not_expected, /*enumset*/ cast_not_expected, /*enumset_inner*/ cast_not_expected, /*otimestamp*/ cast_not_expected, /*raw*/ cast_not_expected, /*interval*/ cast_not_expected, /*rowid*/ cast_not_expected, /*lob*/ }, { /*text -> XXX*/ cast_not_expected, /*null*/ string_int, /*int*/ string_uint, /*uint*/ string_float, /*float*/ string_double, /*double*/ cast_not_support, /*number*/ string_datetime, /*datetime*/ cast_not_expected, /*date*/ cast_not_expected, /*time*/ cast_not_expected, /*year*/ string_string, /*string*/ cast_not_expected, /*extend*/ cast_not_expected, /*unknown*/ string_string, /*text*/ cast_not_expected, /*bit*/ cast_not_expected, /*enumset*/ cast_not_expected, /*enumset_inner*/ string_otimestamp, /*otimestamp*/ cast_inconsistent_types, /*raw*/ string_interval, /*interval*/ string_rowid, /*rowid*/ string_lob, /*lob*/ }, { /*bit -> XXX*/ cast_not_expected, /*null*/ cast_not_expected, /*int*/ cast_not_expected, /*uint*/ cast_not_expected, /*float*/ cast_not_expected, /*double*/ cast_not_expected, /*number*/ cast_not_expected, /*datetime*/ cast_not_expected, /*date*/ cast_not_expected, /*time*/ cast_not_expected, /*year*/ cast_not_expected, /*string*/ cast_not_expected, /*extend*/ cast_not_expected, /*unknown*/ cast_not_expected, /*text*/ cast_not_expected, /*bit*/ cast_not_expected, /*enumset*/ cast_not_expected, /*enumset_inner*/ cast_not_expected, /*otimestamp*/ cast_not_expected, /*raw*/ cast_not_expected, /*interval*/ cast_not_expected, /*rowid*/ cast_not_expected, /*lob*/ }, { /*enum -> XXX*/ cast_not_expected, /*null*/ cast_not_expected, /*int*/ cast_not_expected, /*uint*/ cast_not_expected, /*float*/ cast_not_expected, /*double*/ cast_not_expected, /*number*/ cast_not_expected, /*datetime*/ cast_not_expected, /*date*/ cast_not_expected, /*time*/ cast_not_expected, /*year*/ cast_not_expected, /*string*/ cast_not_expected, /*extend*/ cast_not_expected, /*unknown*/ cast_not_expected, /*text*/ cast_not_expected, /*bit*/ cast_not_expected, /*enumset*/ cast_not_expected, /*enumset_inner*/ cast_not_expected, /*otimestamp*/ cast_not_expected, /*raw*/ cast_not_expected, /*interval*/ cast_not_expected, /*rowid*/ cast_not_expected, /*lob*/ }, { /*enumset_inner -> XXX*/ cast_not_expected, /*null*/ cast_not_expected, /*int*/ cast_not_expected, /*uint*/ cast_not_expected, /*float*/ cast_not_expected, /*double*/ cast_not_expected, /*number*/ cast_not_expected, /*datetime*/ cast_not_expected, /*date*/ cast_not_expected, /*time*/ cast_not_expected, /*year*/ cast_not_expected, /*string*/ cast_not_expected, /*extend*/ cast_not_expected, /*unknown*/ cast_not_expected, /*text*/ cast_not_expected, /*bit*/ cast_not_expected, /*enumset*/ cast_not_expected, /*enumset_inner*/ cast_not_expected, /*otimestamp*/ cast_not_expected, /*raw*/ cast_not_expected, /*interval*/ cast_not_expected, /*rowid*/ cast_not_expected, /*lob*/ }, { /*otimestamp -> XXX*/ cast_not_expected, /*null*/ cast_inconsistent_types, /*int*/ cast_inconsistent_types, /*uint*/ cast_inconsistent_types, /*float*/ cast_inconsistent_types, /*double*/ cast_inconsistent_types, /*number*/ otimestamp_datetime, /*datetime*/ cast_not_expected, /*date*/ cast_not_expected, /*time*/ cast_not_expected, /*year*/ otimestamp_string, /*string*/ cast_not_expected, /*extend*/ cast_not_expected, /*unknown*/ cast_inconsistent_types, /*text*/ cast_not_expected, /*bit*/ cast_not_expected, /*enumset*/ cast_not_expected, /*enumset_inner*/ otimestamp_otimestamp, /*otimestamp*/ cast_inconsistent_types, /*raw*/ cast_inconsistent_types, /*interval*/ cast_inconsistent_types, /*rowid*/ cast_inconsistent_types, /*lob*/ }, { /*raw -> XXX*/ cast_not_expected, /*null*/ cast_inconsistent_types, /*int*/ cast_inconsistent_types, /*uint*/ cast_inconsistent_types, /*float*/ cast_inconsistent_types, /*double*/ cast_inconsistent_types, /*number*/ cast_inconsistent_types, /*datetime*/ cast_not_expected, /*date*/ cast_not_expected, /*time*/ cast_not_expected, /*year*/ raw_string, /*string*/ cast_not_expected, /*extend*/ cast_not_expected, /*unknown*/ raw_longtext, /*text*/ cast_not_expected, /*bit*/ cast_not_expected, /*enumset*/ cast_not_expected, /*enumset_inner*/ cast_inconsistent_types, /*otimestamp*/ raw_raw, /*raw*/ cast_inconsistent_types, /*interval*/ cast_inconsistent_types, /*rowid*/ raw_lob, /*lob*/ }, { /*interval -> XXX*/ cast_not_expected, /*null*/ cast_inconsistent_types, /*int*/ cast_inconsistent_types, /*uint*/ cast_inconsistent_types, /*float*/ cast_inconsistent_types, /*double*/ cast_inconsistent_types, /*number*/ cast_inconsistent_types, /*datetime*/ cast_not_expected, /*date*/ cast_not_expected, /*time*/ cast_not_expected, /*year*/ interval_string, /*string*/ cast_not_expected, /*extend*/ cast_not_expected, /*unknown*/ cast_inconsistent_types, /*text*/ cast_not_expected, /*bit*/ cast_not_expected, /*enumset*/ cast_not_expected, /*enumset_inner*/ cast_inconsistent_types, /*otimestamp*/ cast_inconsistent_types, /*raw*/ interval_interval, /*interval*/ cast_inconsistent_types, /*rowid*/ cast_inconsistent_types, /*lob*/ }, { /* rowid -> XXX */ cast_not_expected, /*null*/ cast_inconsistent_types, /*int*/ cast_inconsistent_types, /*uint*/ cast_inconsistent_types, /*float*/ cast_inconsistent_types, /*double*/ cast_inconsistent_types, /*number*/ cast_inconsistent_types, /*datetime*/ cast_not_expected, /*date*/ cast_not_expected, /*time*/ cast_not_expected, /*year*/ rowid_string, /*string*/ cast_not_expected, /*extend*/ cast_not_expected, /*unknown*/ cast_inconsistent_types, /*text*/ cast_not_expected, /*bit*/ cast_not_expected, /*enumset*/ cast_not_expected, /*enumset_inner*/ cast_inconsistent_types, /*otimestamp*/ cast_inconsistent_types, /*raw*/ cast_inconsistent_types, /*interval*/ rowid_rowid, /*rowid*/ cast_inconsistent_types, /*lob*/ }, { /*lob -> XXX*/ cast_not_expected, /*null*/ lob_int, /*int*/ lob_uint, /*uint*/ lob_float, /*float*/ lob_double, /*double*/ cast_not_support, /*number*/ lob_datetime, /*datetime*/ cast_not_expected, /*date*/ cast_not_expected, /*time*/ cast_not_expected, /*year*/ lob_string, /*string*/ cast_not_expected, /*extend*/ cast_not_expected, /*unknown*/ lob_string, /*text*/ cast_not_expected, /*bit*/ cast_not_expected, /*enumset*/ cast_not_expected, /*enumset_inner*/ lob_otimestamp, /*otimestamp*/ cast_inconsistent_types, /*raw*/ lob_interval, /*interval*/ lob_rowid, /*rowid*/ lob_lob, /*lob*/ }, }; //////////////////////////////////////////////////////////////// bool cast_supported(const ObObjType orig_type, const ObCollationType orig_cs_type, const ObObjType expect_type, const ObCollationType expect_cs_type) { bool bret = false; bool clob_in = ob_is_clob(orig_type, orig_cs_type) || ob_is_clob_locator(orig_type, orig_cs_type); bool blob_out = ob_is_blob(expect_type, expect_cs_type) || ob_is_blob_locator(expect_type, expect_cs_type); if (OB_UNLIKELY(ob_is_invalid_obj_type(orig_type) || ob_is_invalid_obj_type(expect_type))) { LOG_WARN("invalid cast type", K(orig_type), K(expect_type)); // number can be casted to clob, but can not casted to blob, // OB_OBJ_CAST and OBJ_CAST_ORACLE_IMPLICIT can not support this rule. } else if (is_oracle_mode() && (clob_in || ob_is_number_tc(orig_type)) && blob_out) { bret = false; } else { ObObjTypeClass orig_tc = ob_obj_type_class(orig_type); ObObjTypeClass expect_tc = ob_obj_type_class(expect_type); if (ObIntervalTC == orig_tc && ObIntervalTC == expect_tc && orig_type != expect_type) { bret = false; LOG_WARN("cast between intervalYM and intervalDS not allowed", K(bret), K(orig_type), K(expect_type)); } else { ObObjCastFunc cast_func = lib::is_oracle_mode() ? OBJ_CAST_ORACLE_IMPLICIT[orig_tc][expect_tc] : OB_OBJ_CAST[orig_tc][expect_tc]; bret = (cast_func != cast_not_support && cast_func != cast_inconsistent_types); } } return bret; } int float_range_check(ObObjCastParams& params, 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 (lib::is_oracle_mode() && 0.0 == value) { value = 0.0; buf_obj.set_float(obj.get_type(), value); res_obj = &buf_obj; } else { 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& params, 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 (lib::is_oracle_mode() && 0.0 == value) { value = 0.0; buf_obj.set_double(obj.get_type(), value); res_obj = &buf_obj; } else 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& params, 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 number_range_check_for_oracle(ObObjCastParams& params, 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 (number::ObNumber::MAX_PRECISION >= precision && number::ObNumber::MAX_SCALE >= scale && precision >= 1 && scale >= number::ObNumber::MIN_SCALE) { // make min and max numbers. number::ObNumber min_num; number::ObNumber max_num; number::ObNumber in_val = obj.get_number(); bool trunc_max_zero = false; bool trunc_min_zero = false; // prepare string like "99.999". char buf[BUFFER_SIZE] = {0}; int pos = 0; buf[pos++] = '-'; if (precision >= scale && scale >= 0) { /* number(3, 1) => legal range(-99.95, 99.95) */ if (precision == scale) { buf[pos++] = '0'; } MEMSET(buf + pos, '9', precision + 1); buf[pos + precision - scale] = '.'; buf[pos + precision + 1] = '5'; if (OB_FAIL(min_num.from(buf, allocator))) { } else if (OB_FAIL(max_num.from(buf + 1, allocator))) { } } else { if (scale < 0) { /* number(2, -3) => legal range: (-99500, 99500) */ MEMSET(buf + pos, '9', precision); buf[pos + precision] = '5'; MEMSET(buf + pos + precision + 1, '0', 0 - scale - 1); if (OB_FAIL(min_num.from(buf, allocator))) { } else if (OB_FAIL(max_num.from(buf + 1, allocator))) { } } else { // number(2, 3) => legal range:[0, 0.0995) && (-0.00995, 0] buf[pos++] = '0'; buf[pos++] = '.'; MEMSET(buf + pos, '0', scale - precision); MEMSET(buf + pos + scale - precision, '9', precision); buf[pos + scale] = '5'; if (in_val.is_negative()) { trunc_max_zero = true; if (OB_FAIL(min_num.from(buf, allocator))) { LOG_DEBUG("fail to get num from ", K(buf)); } else { MEMSET(buf + pos + scale - precision, '0', precision); if (OB_FAIL(max_num.from(buf, allocator))) { LOG_DEBUG("fail to get num from ", K(buf)); } } } else { trunc_min_zero = true; if (OB_FAIL(max_num.from(buf + 1, allocator))) { LOG_DEBUG("fail to get num from ", K(buf + 1)); } else { MEMSET(buf + pos + scale - precision, '0', precision); if (OB_FAIL(min_num.from(buf + 1, allocator))) { LOG_DEBUG("fail to get num from ", K(buf + 1)); } } } } } LOG_DEBUG("BUF", KP(buf), K(precision), K(scale), K(min_num), K(max_num), K(trunc_min_zero), K(trunc_max_zero)); number::ObNumber out_val; if (OB_SUCC(ret)) { if (in_val <= min_num) { if (trunc_min_zero) { min_num.set_zero(); LOG_DEBUG("set min zero"); } else { cast_ret = OB_DATA_OUT_OF_RANGE; } buf_obj.set_number(obj.get_type(), min_num); } else if (in_val >= max_num) { if (trunc_max_zero) { max_num.set_zero(); } else { 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 if (ORA_NUMBER_SCALE_UNKNOWN_YET == scale && PRECISION_UNKNOWN_YET == precision) { buf_obj.set_number(obj.get_type(), obj.get_number()); res_obj = &buf_obj; LOG_DEBUG("unknown scale and precision", K(obj.get_scale()), K(obj), K(buf_obj)); } else { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arguments", K(ret), K(precision), K(scale)); } } return ret; } int number_range_check_v2(ObObjCastParams& params, const ObAccuracy& accuracy, const ObObj& obj, ObObj& buf_obj, const ObObj*& res_obj, const ObCastMode cast_mode) { int ret = OB_SUCCESS; res_obj = NULL; 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; const number::ObNumber& in_val = obj.get_number(); const number::ObNumber* min_check_num = NULL; const number::ObNumber* max_check_num = NULL; const number::ObNumber* min_num_mysql = NULL; const number::ObNumber* max_num_mysql = NULL; number::ObNumber out_val; bool is_finish = false; if (obj.is_number_float()) { if (OB_MIN_NUMBER_FLOAT_PRECISION <= precision && precision <= OB_MAX_NUMBER_FLOAT_PRECISION) { const int64_t number_precision = static_cast(floor(precision * OB_PRECISION_BINARY_TO_DECIMAL_FACTOR)); if (OB_FAIL(out_val.from(in_val, allocator))) { } else if (OB_FAIL(out_val.round_precision(number_precision))) { } else { buf_obj.set_number(obj.get_type(), out_val); res_obj = &buf_obj; is_finish = true; } LOG_DEBUG("finish round_precision", K(in_val), K(number_precision), K(precision), K(buf_obj)); } else if (PRECISION_UNKNOWN_YET == precision) { buf_obj.set_number(obj.get_type(), in_val); res_obj = &buf_obj; is_finish = true; } else { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arguments", K(ret), K(precision), K(scale)); } } else if (lib::is_oracle_mode()) { if (OB_MAX_NUMBER_PRECISION >= precision && precision >= OB_MIN_NUMBER_PRECISION && number::ObNumber::MAX_SCALE >= scale && scale >= number::ObNumber::MIN_SCALE) { min_check_num = &(ObNumberConstValue::ORACLE_CHECK_MIN[precision][scale + ObNumberConstValue::MAX_ORACLE_SCALE_DELTA]); max_check_num = &(ObNumberConstValue::ORACLE_CHECK_MAX[precision][scale + ObNumberConstValue::MAX_ORACLE_SCALE_DELTA]); } else if (ORA_NUMBER_SCALE_UNKNOWN_YET == scale && PRECISION_UNKNOWN_YET == precision) { buf_obj.set_number(obj.get_type(), in_val); res_obj = &buf_obj; is_finish = true; } else if (PRECISION_UNKNOWN_YET == precision && number::ObNumber::MAX_SCALE >= scale && scale >= number::ObNumber::MIN_SCALE) { number::ObNumber num; if (OB_FAIL(num.from(obj.get_number(), allocator))) { } else if (OB_FAIL(num.round(scale))) { } else { buf_obj.set_number(obj.get_type(), num); res_obj = &buf_obj; is_finish = true; } } else { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arguments", K(ret), K(precision), K(scale)); } } else { if (OB_UNLIKELY(precision < scale)) { ret = OB_ERR_M_BIGGER_THAN_D; } else if (number::ObNumber::MAX_PRECISION >= precision && precision >= OB_MIN_DECIMAL_PRECISION && number::ObNumber::MAX_SCALE >= scale && scale >= 0) { min_check_num = &(ObNumberConstValue::MYSQL_CHECK_MIN[precision][scale]); max_check_num = &(ObNumberConstValue::MYSQL_CHECK_MAX[precision][scale]); min_num_mysql = &(ObNumberConstValue::MYSQL_MIN[precision][scale]); max_num_mysql = &(ObNumberConstValue::MYSQL_MAX[precision][scale]); } else { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arguments", K(ret), K(precision), K(scale)); } } if (OB_SUCC(ret) && !is_finish) { if (OB_ISNULL(min_check_num) || OB_ISNULL(max_check_num) || (!lib::is_oracle_mode() && (OB_ISNULL(min_num_mysql) || OB_ISNULL(max_num_mysql)))) { ret = OB_ERR_UNEXPECTED; LOG_WARN("min_num or max_num is null", K(ret), KPC(min_check_num), KPC(max_check_num)); } else if (in_val <= *min_check_num) { if (lib::is_oracle_mode()) { cast_ret = OB_ERR_VALUE_LARGER_THAN_ALLOWED; } else { cast_ret = OB_DATA_OUT_OF_RANGE; buf_obj.set_number(obj.get_type(), *min_num_mysql); } } else if (in_val >= *max_check_num) { if (lib::is_oracle_mode()) { cast_ret = OB_ERR_VALUE_LARGER_THAN_ALLOWED; } else { cast_ret = OB_DATA_OUT_OF_RANGE; buf_obj.set_number(obj.get_type(), *max_num_mysql); } // need round } 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); } } } LOG_DEBUG("succ to number_range_check_v2", K(ret), K(cast_ret), K(is_finish), K(precision), K(scale), KPC(min_check_num), KPC(max_check_num), KPC(min_num_mysql), KPC(max_num_mysql), K(in_val), K(obj), K(buf_obj)); res_obj = &buf_obj; } return ret; } int number_range_check_only(const ObAccuracy& accuracy, const ObObj& obj) { int ret = OB_SUCCESS; UNUSED(obj); ObPrecision precision = accuracy.get_precision(); ObScale scale = accuracy.get_scale(); 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) { ret = OB_NOT_SUPPORTED; LOG_WARN("number range check not supported", K(ret)); } else { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid arguments", K(ret), K(precision), K(scale)); } return ret; } int datetime_scale_check(ObObjCastParams& params, 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; LOG_USER_ERROR(OB_ERR_TOO_BIG_PRECISION, scale, "CAST", static_cast(MAX_SCALE_FOR_TEMPORAL)); } else if (OB_UNLIKELY(0 <= scale && scale < MAX_SCALE_FOR_TEMPORAL)) { int64_t value = obj.get_datetime(); ObTimeConverter::round_datetime(scale, value); if (ObTimeConverter::is_valid_datetime(value)) { buf_obj.set_datetime(obj.get_type(), value); } else { buf_obj.set_null(); } res_obj = &buf_obj; } else { res_obj = &obj; } UNUSED(params); UNUSED(cast_mode); return ret; } int otimestamp_scale_check(ObObjCastParams& params, 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_ORACLE_TEMPORAL)) { ret = OB_ERR_TOO_BIG_PRECISION; LOG_USER_ERROR(OB_ERR_TOO_BIG_PRECISION, scale, "CAST", static_cast(MAX_SCALE_FOR_ORACLE_TEMPORAL)); } else if (OB_UNLIKELY(0 <= scale && scale < MAX_SCALE_FOR_ORACLE_TEMPORAL)) { ObOTimestampData ot_data = ObTimeConverter::round_otimestamp(scale, obj.get_otimestamp_value()); if (ObTimeConverter::is_valid_otimestamp(ot_data.time_us_, static_cast(ot_data.time_ctx_.tail_nsec_))) { buf_obj.set_otimestamp_value(obj.get_type(), ot_data); buf_obj.set_scale(scale); } else { OB_LOG(DEBUG, "invalid otimestamp, set it null ", K(ot_data), K(scale), "orig_date", obj.get_otimestamp_value()); buf_obj.set_null(); } res_obj = &buf_obj; } else { res_obj = &obj; } UNUSED(params); UNUSED(cast_mode); return ret; } int interval_scale_check(ObObjCastParams& params, const ObAccuracy& accuracy, const ObObj& obj, ObObj& buf_obj, const ObObj*& res_obj, const ObCastMode cast_mode) { UNUSED(cast_mode); UNUSED(params); int ret = OB_SUCCESS; res_obj = NULL; ObScale expected_scale = accuracy.get_scale(); buf_obj = obj; if (obj.is_interval_ym()) { int8_t expected_year_scale = ObIntervalScaleUtil::ob_scale_to_interval_ym_year_scale(static_cast(expected_scale)); int8_t input_year_scale = obj.get_interval_ym().calc_leading_scale(); if (OB_UNLIKELY(expected_year_scale < input_year_scale)) { ret = OB_ERR_THE_LEADING_PRECISION_OF_THE_INTERVAL_IS_TOO_SMALL; LOG_WARN("interval obj scale check", K(ret), K(expected_year_scale), K(input_year_scale)); } } else if (obj.is_interval_ds()) { ObIntervalDSValue value = obj.get_interval_ds(); int8_t expected_day_scale = ObIntervalScaleUtil::ob_scale_to_interval_ds_day_scale(static_cast(expected_scale)); int8_t expected_fs_scale = ObIntervalScaleUtil::ob_scale_to_interval_ds_second_scale(static_cast(expected_scale)); if (OB_FAIL(ObTimeConverter::round_interval_ds(expected_fs_scale, value))) { LOG_WARN("fail to round interval ds", K(ret), K(value)); } else { int8_t input_day_scale = value.calc_leading_scale(); if (OB_UNLIKELY(expected_day_scale < input_day_scale)) { ret = OB_ERR_THE_LEADING_PRECISION_OF_THE_INTERVAL_IS_TOO_SMALL; LOG_WARN("interval obj scale check", K(ret), K(expected_day_scale), K(input_day_scale)); } else { buf_obj.set_interval_ds(value); } } } else { ret = OB_ERR_UNEXPECTED; } if (OB_SUCC(ret)) { buf_obj.set_scale(expected_scale); res_obj = &buf_obj; } return ret; } int datetime_scale_check_only(const ObAccuracy& accuracy, const ObObj& obj) { int ret = OB_SUCCESS; ObScale scale = accuracy.get_scale(); if (OB_UNLIKELY(scale > MAX_SCALE_FOR_TEMPORAL)) { ret = OB_ERR_TOO_BIG_PRECISION; LOG_USER_ERROR(OB_ERR_TOO_BIG_PRECISION, scale, "CAST", static_cast(MAX_SCALE_FOR_TEMPORAL)); } else if (OB_UNLIKELY(0 <= scale && scale < MAX_SCALE_FOR_TEMPORAL)) { int64_t value = obj.get_datetime(); if (!ObTimeConverter::is_valid_datetime(value)) { ret = OB_INVALID_DATA; LOG_WARN("invalid datetime value", K(ret), K(value)); } } return ret; } int time_scale_check(ObObjCastParams& params, 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 time_scale_check_only(const ObAccuracy& accuracy, const ObObj& obj) { int ret = OB_SUCCESS; UNUSED(accuracy); UNUSED(obj); return ret; } int get_bit_len(const ObString& str, int32_t& bit_len) { int ret = OB_SUCCESS; if (str.empty()) { bit_len = 1; } else { const char* ptr = str.ptr(); uint32_t uneven_value = reinterpret_cast(ptr[0]); int32_t len = str.length(); if (0 == uneven_value) { if (len > 8) { // Compatible with MySQL, if the length of bit string greater than 8 Bytes, // it would be considered too long. We set bit_len to OB_MAX_BIT_LENGTH + 1. bit_len = OB_MAX_BIT_LENGTH + 1; } else { bit_len = 1; } } else { // Built-in Function: int __builtin_clz (unsigned int x). // Returns the number of leading 0-bits in x, starting at the most significant bit position. // If x is 0, the result is undefined. int32_t uneven_len = static_cast(sizeof(unsigned int) * 8 - __builtin_clz(uneven_value)); bit_len = uneven_len + 8 * (len - 1); } } return ret; } int get_bit_len(uint64_t value, int32_t& bit_len) { int ret = OB_SUCCESS; if (0 == value) { bit_len = 1; } else { bit_len = static_cast(sizeof(unsigned long long) * 8 - __builtin_clzll(value)); } return ret; } int string_length_check(ObObjCastParams& params, 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; const ObLength max_accuracy_len = accuracy.get_length(); const int32_t str_len_byte = obj.get_string_len(); bool is_oracle = is_oracle_mode(); if (max_accuracy_len <= 0 || str_len_byte > max_accuracy_len) { int& cast_ret = (CM_IS_ERROR_ON_FAIL(cast_mode) && !is_oracle) ? ret : params.warning_; const char* str = obj.get_string_ptr(); int32_t str_len_char = -1; if (max_accuracy_len == DEFAULT_STR_LENGTH) { res_obj = &obj; } else if (OB_UNLIKELY(max_accuracy_len <= 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_accuracy_len && str_len_byte > 0)) { cast_ret = OB_ERR_DATA_TOO_LONG; str_len_char = obj.is_lob() ? str_len_byte : static_cast(ObCharset::strlen_char(cs_type, str, str_len_byte)); OB_LOG(WARN, "char type length is too long", K(obj), K(max_accuracy_len), K(str_len_char)); } } else { int32_t trunc_len_byte = -1; int32_t trunc_len_char = -1; if (obj.is_varbinary() || obj.is_binary() || obj.is_blob()) { str_len_char = obj.is_lob() ? str_len_byte : static_cast(ObCharset::strlen_char(cs_type, str, str_len_byte)); if (OB_UNLIKELY(str_len_char > max_accuracy_len)) { cast_ret = OB_ERR_DATA_TOO_LONG; LOG_WARN("binary type length is too long", K(max_accuracy_len), K(str_len_char), K(obj)); } } else if (is_oracle_byte_length(is_oracle, accuracy.get_length_semantics())) { const ObLength max_len_byte = accuracy.get_length(); if (OB_UNLIKELY(str_len_byte > max_len_byte)) { cast_ret = OB_ERR_DATA_TOO_LONG; LOG_WARN("char type length is too long", K(str_len_byte), K(max_len_byte), K(obj)); } } else if (is_oracle && obj.is_fixed_len_char_type()) { const int32_t str_len_char = static_cast(ObCharset::strlen_char(cs_type, str, str_len_byte)); if (OB_UNLIKELY(str_len_byte > OB_MAX_ORACLE_CHAR_LENGTH_BYTE)) { cast_ret = OB_ERR_DATA_TOO_LONG; LOG_WARN("char byte length is too long", K(str_len_byte), K(OB_MAX_ORACLE_CHAR_LENGTH_BYTE), K(obj)); } else if (OB_UNLIKELY(str_len_char > max_accuracy_len)) { cast_ret = OB_ERR_DATA_TOO_LONG; LOG_WARN("char char length is too long", K(str_len_char), K(max_accuracy_len), K(obj)); } } else { // mysql, oracle varchar(char) // trunc_len_char > max_accuracy_len means an error or warning, without tail ' ', otherwise // str_len_char > max_accuracy_len means only warning, even in strict mode. // lengthsp() - returns the length of the given string without trailing spaces. trunc_len_byte = static_cast(ObCharset::strlen_byte_no_sp(cs_type, str, str_len_byte)); trunc_len_char = obj.is_lob() ? trunc_len_byte : static_cast(ObCharset::strlen_char(cs_type, str, trunc_len_byte)); if (is_oracle && OB_UNLIKELY(str_len_byte > OB_MAX_ORACLE_VARCHAR_LENGTH)) { cast_ret = OB_ERR_DATA_TOO_LONG; LOG_WARN("varchar2 byte length is too long", K(str_len_byte), K(OB_MAX_ORACLE_VARCHAR_LENGTH), K(obj)); } else if (OB_UNLIKELY(trunc_len_char > max_accuracy_len)) { cast_ret = OB_ERR_DATA_TOO_LONG; LOG_WARN("char type length is too long", K(max_accuracy_len), K(trunc_len_char), K(obj)); } else { str_len_char = obj.is_lob() ? str_len_byte : static_cast(ObCharset::strlen_char(cs_type, str, str_len_byte)); if (OB_UNLIKELY(str_len_char > max_accuracy_len)) { params.warning_ = OB_ERR_DATA_TOO_LONG; LOG_WARN("char type length is too long", K(max_accuracy_len), K(str_len_char), K(obj)); } } } if (OB_SUCC(ret)) { if (OB_UNLIKELY(OB_ERR_DATA_TOO_LONG == params.warning_)) { // when warning, always trunc to max_accuracy_len 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'. if (obj.is_text()) { int64_t char_len = 0; trunc_len_byte = static_cast( ObCharset::max_bytes_charpos(cs_type, str, str_len_byte, max_accuracy_len, char_len)); } else { trunc_len_byte = static_cast(ObCharset::charpos(cs_type, str, str_len_byte, max_accuracy_len)); } if (is_oracle) { // select cast(' a' as char) from dual // the query above return ' ' in oracle. } else if (obj.is_fixed_len_char_type() && !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; } if (is_oracle) { ret = params.warning_; } } else if (OB_SUCC(params.warning_) && is_oracle) { ret = params.warning_; } else { res_obj = &obj; } } } } else { res_obj = &obj; } return ret; } // no truncate int string_length_check_only(const ObAccuracy& accuracy, const ObCollationType cs_type, const ObObj& obj) { int ret = OB_SUCCESS; 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)) { if (OB_UNLIKELY(0 == max_len_char && str_len_byte > 0)) { 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 if (OB_UNLIKELY(str_len_char > max_len_char)) { ret = OB_ERR_DATA_TOO_LONG; LOG_WARN("string length is too long", K(max_len_char), K(str_len_char), K(obj)); } return ret; } int raw_length_check(ObObjCastParams& params, const ObAccuracy& accuracy, const ObCollationType cs_type, const ObObj& obj, ObObj& buf_obj, const ObObj*& res_obj, const ObCastMode cast_mode) { UNUSED(params); UNUSED(cs_type); UNUSED(buf_obj); UNUSED(cast_mode); int ret = OB_SUCCESS; const ObLength max_accuracy_len = accuracy.get_length(); const int32_t str_len_byte = obj.get_string_len(); if (OB_UNLIKELY(max_accuracy_len >= 0 && str_len_byte > max_accuracy_len)) { ret = OB_ERR_DATA_TOO_LONG; LOG_WARN("char type length is too long", K(ret), K(str_len_byte), K(max_accuracy_len), K(obj)); } else { res_obj = &obj; } return ret; } int bit_length_check(ObObjCastParams& params, const ObAccuracy& accuracy, const ObObj& obj, ObObj& buf_obj, const ObObj*& res_obj, const ObCastMode cast_mode) { int ret = OB_SUCCESS; res_obj = NULL; uint64_t value = obj.get_bit(); int32_t bit_len = 0; int32_t dst_bit_len = accuracy.get_precision(); if (OB_FAIL(get_bit_len(value, bit_len))) { LOG_WARN("fail to get_bit_length", K(ret), K(value), K(bit_len)); } else if (OB_UNLIKELY(bit_len <= 0)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("bit length is negative", K(ret), K(value), K(bit_len), K(obj)); } else { if (OB_UNLIKELY(bit_len > dst_bit_len)) { ret = OB_ERR_DATA_TOO_LONG; LOG_WARN("bit type length is too long", K(ret), K(bit_len), K(dst_bit_len), K(value)); } else { buf_obj.set_bit(value); } if (OB_FAIL(ret) && CM_IS_WARN_ON_FAIL(cast_mode)) { params.warning_ = OB_DATA_OUT_OF_RANGE; ret = OB_SUCCESS; uint64_t max_value = (1ULL << dst_bit_len) - 1; buf_obj.set_bit(max_value); } if (OB_SUCC(ret)) { res_obj = &buf_obj; } } return ret; } int bit_length_check_only(const ObAccuracy& accuracy, const ObObj& obj) { int ret = OB_SUCCESS; uint64_t value = obj.get_bit(); int32_t bit_len = 0; int32_t dst_bit_len = accuracy.get_precision(); if (OB_FAIL(get_bit_len(value, bit_len))) { LOG_WARN("fail to get_bit_length", K(ret), K(value), K(bit_len)); } else if (OB_UNLIKELY(bit_len <= 0)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("bit length is negative", K(ret), K(value), K(bit_len), K(obj)); } else { if (OB_UNLIKELY(bit_len > dst_bit_len)) { ret = OB_ERR_DATA_TOO_LONG; LOG_WARN("bit type length is too long", K(ret), K(bit_len), K(dst_bit_len), K(value)); } } 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_type(obj.get_type()) && !ob_is_lob_locator(obj.get_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; if (ob_is_lob_locator(obj.get_type())) { if (OB_FAIL(obj.get_string(str))) { LOG_WARN("Failed to get payload from lob locator", K(ret), K(obj)); } } else { if (OB_FAIL(obj.get_string(str))) { LOG_WARN("Failed to get payload from string", K(ret), K(obj)); } } if (OB_FAIL(ret)) { } else 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), KPHEX(str.ptr(), str.length())); 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)); if (ob_is_lob_locator(obj.get_type())) { if (OB_ISNULL(obj.get_lob_locator())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("Unepected null lob locator", K(ret), K(obj)); } else { (const_cast(obj.get_lob_locator()))->payload_size_ = str.length(); } } else { 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 urwoid_length_check_only(const ObAccuracy& accuracy, const ObObj& obj) { int ret = OB_SUCCESS; ObURowIDData urowid_data = obj.get_urowid(); if (OB_UNLIKELY(urowid_data.rowid_len_ <= 0)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("invalid urowid data length", K(ret), K(urowid_data.rowid_len_)); } else if (OB_UNLIKELY(urowid_data.rowid_len_ > accuracy.get_precision())) { ret = OB_ERR_DATA_TOO_LONG; LOG_WARN("urowid data length us too long", K(ret), K(accuracy.get_precision()), K(urowid_data.rowid_len_)); } 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; LOG_DEBUG("obj_accuracy_check before", K(obj), K(accuracy), K(cs_type)); switch (obj.get_type_class()) { case ObFloatTC: { ret = float_range_check(cast_ctx, accuracy, obj, buf_obj, res_obj, cast_ctx.cast_mode_); break; } case ObDoubleTC: { ret = double_check_precision(cast_ctx, accuracy, obj, buf_obj, res_obj, cast_ctx.cast_mode_); break; } case ObNumberTC: { ret = number_range_check_v2(cast_ctx, accuracy, obj, buf_obj, res_obj, cast_ctx.cast_mode_); break; } case ObDateTimeTC: { ret = datetime_scale_check(cast_ctx, accuracy, obj, buf_obj, res_obj, cast_ctx.cast_mode_); break; } case ObOTimestampTC: { ret = otimestamp_scale_check(cast_ctx, accuracy, obj, buf_obj, res_obj, cast_ctx.cast_mode_); break; } case ObTimeTC: { ret = time_scale_check(cast_ctx, accuracy, obj, buf_obj, res_obj, cast_ctx.cast_mode_); break; } case ObStringTC: { ret = string_length_check(cast_ctx, accuracy, cs_type, obj, buf_obj, res_obj, cast_ctx.cast_mode_); break; } case ObRawTC: { ret = raw_length_check(cast_ctx, accuracy, cs_type, obj, buf_obj, res_obj, cast_ctx.cast_mode_); break; } case ObTextTC: { // TODO texttc share with stringtc temporarily ret = string_length_check(cast_ctx, accuracy, cs_type, obj, buf_obj, res_obj, cast_ctx.cast_mode_); break; } case ObBitTC: { ret = bit_length_check(cast_ctx, accuracy, obj, buf_obj, res_obj, cast_ctx.cast_mode_); break; } case ObIntervalTC: { ret = interval_scale_check(cast_ctx, accuracy, obj, buf_obj, res_obj, cast_ctx.cast_mode_); break; } case ObRowIDTC: { ret = string_length_check(cast_ctx, accuracy, cs_type, obj, buf_obj, res_obj, cast_ctx.cast_mode_); break; } case ObLobTC: { // TODO:shanting lob length check } default: { // LOG_WARN("unexpected type class to check", K(obj)); break; } } return ret; } int ob_obj_accuracy_check_only(const ObAccuracy& accuracy, const ObCollationType cs_type, const ObObj& obj) { int ret = OB_SUCCESS; switch (obj.get_type_class()) { case ObFloatTC: { switch (obj.get_type()) { case ObFloatType: ret = real_range_check_only(accuracy, obj.get_float()); break; case ObUFloatType: { double value = obj.get_ufloat(); ret = numeric_negative_check(value); if (OB_SUCC(ret)) { ret = real_range_check_only(accuracy, obj.get_ufloat()); } break; } default: break; } break; } case ObDoubleTC: { switch (obj.get_type()) { case ObDoubleType: ret = real_range_check_only(accuracy, obj.get_double()); break; case ObUDoubleType: { double value = obj.get_udouble(); ret = numeric_negative_check(value); if (OB_SUCC(ret)) { ret = real_range_check_only(accuracy, obj.get_udouble()); } break; } default: break; } break; } case ObNumberTC: ret = number_range_check_only(accuracy, obj); break; case ObDateTimeTC: ret = datetime_scale_check_only(accuracy, obj); break; case ObTimeTC: ret = time_scale_check_only(accuracy, obj); break; case ObStringTC: ret = string_length_check_only(accuracy, cs_type, obj); break; case ObTextTC: ret = string_length_check_only(accuracy, cs_type, obj); break; case ObBitTC: ret = bit_length_check_only(accuracy, obj); break; case ObIntTC: { int64_t value = obj.get_int(); ret = int_range_check(obj.get_type(), value, value); } break; case ObUIntTC: { uint64_t value = obj.get_uint64(); ret = uint_upper_check(obj.get_type(), value); } break; default: break; } return ret; } int ob_obj_to_ob_time_with_date( const ObObj& obj, const ObTimeZoneInfo* tz_info, ObTime& ob_time, const int64_t cur_ts_value, bool is_dayofmonth /*false*/) { 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, is_dayofmonth); break; } case ObOTimestampTC: { ret = ObTimeConverter::otimestamp_to_ob_time(obj.get_type(), obj.get_otimestamp_value(), tz_info, 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: { int64_t datetime_val = 0; if (OB_FAIL( ObTimeConverter::time_to_datetime(obj.get_time(), cur_ts_value, NULL, datetime_val, ObDateTimeType))) { LOG_WARN("time_to_datetime failed", K(ret), K(obj), K(cur_ts_value)); } else if (OB_FAIL(ObTimeConverter::datetime_to_ob_time(datetime_val, NULL, ob_time))) { LOG_WARN("datetime to time failed", K(ret)); } break; ret = ObTimeConverter::time_to_ob_time(obj.get_time(), ob_time); break; } case ObTextTC: // TODO texttc share with the stringtc temporarily case ObStringTC: { ret = ObTimeConverter::str_to_ob_time_with_date(obj.get_string(), ob_time, NULL, is_dayofmonth); break; } case ObLobTC: { ObString payload; if (OB_FAIL(obj.get_string(payload))) { STORAGE_LOG(WARN, "Failed to get payload from lob locator", K(ret), K(obj)); } else { ret = ObTimeConverter::str_to_ob_time_with_date(payload, ob_time, NULL, is_dayofmonth); } break; } case ObNumberTC: { int64_t int_part = 0; int64_t dec_part = 0; const number::ObNumber num = obj.get_number(); if (num.is_negative()) { ret = OB_INVALID_DATE_FORMAT; LOG_WARN("invalid date format", K(ret), K(num)); } else if (!num.is_int_parts_valid_int64(int_part, dec_part)) { ret = OB_INVALID_DATE_FORMAT; LOG_WARN("invalid date format", K(ret), K(num)); } else { ret = ObTimeConverter::int_to_ob_time_with_date(int_part, ob_time, is_dayofmonth); } 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: { if (OB_FAIL(ObTimeConverter::int_to_ob_time_without_date(obj.get_int(), ob_time))) { LOG_WARN("int to ob time without date failed", K(ret)); } else { const int64_t time_max_val = 3020399 * 1000000LL; // 838:59:59 . int64_t value = ObTimeConverter::ob_time_to_time(ob_time); if (value > time_max_val) { ret = OB_INVALID_DATE_VALUE; } } break; } case ObOTimestampTC: { ret = ObTimeConverter::otimestamp_to_ob_time(obj.get_type(), obj.get_otimestamp_value(), tz_info, 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 ObTextTC: // TODO texttc share with the stringtc temporarily case ObStringTC: { ret = ObTimeConverter::str_to_ob_time_without_date(obj.get_string(), ob_time); break; } case ObLobTC: { ObString payload; if (OB_FAIL(obj.get_string(payload))) { STORAGE_LOG(WARN, "Failed to get payload from lob locator", K(ret), K(obj)); } else { ret = ObTimeConverter::str_to_ob_time_without_date(payload, ob_time); } break; } case ObNumberTC: { const char *num_format = obj.get_number().format(); if (OB_ISNULL(num_format)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("number format value is null", K(ret)); } else { ObString num_str(num_format); ret = ObTimeConverter::str_to_ob_time_without_date(num_str, ob_time); } break; } default: { ret = OB_NOT_SUPPORTED; } } return ret; } int ObObjCaster::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; ObObjType in_type = in_obj.get_type(); bool is_string = ob_is_string_type(in_type) || ob_is_lob_locator(in_type); if (OB_UNLIKELY((expect_type == in_type && (!is_string)) || ObNullType == in_type)) { buf_obj = in_obj; res_obj = &buf_obj; } else if (in_obj.get_collation_type() == cast_ctx.dest_collation_ && (ObVarcharType == in_type || ObCharType == in_type || ob_is_nstring_type(in_type)) && (ObVarcharType == expect_type || ObCharType == expect_type || ob_is_nstring_type(expect_type)) && NULL == cast_ctx.zf_info_ && NULL == cast_ctx.res_accuracy_) { // fast path for char/varchar string_string cast. buf_obj = in_obj; const_cast(buf_obj.get_meta()).set_type_simple(expect_type); res_obj = &buf_obj; } else if (OB_FAIL(to_type(expect_type, (is_string && share::is_mysql_mode()) ? in_obj.get_collation_type() : cast_ctx.dest_collation_, 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 ObObjCaster::to_datetime( const ObObjType expect_type, ObCastCtx& cast_ctx, const ObObj& in_obj, ObObj& buf_obj, const ObObj*& res_obj) { int ret = OB_SUCCESS; if (ObDateTimeType == in_obj.get_type()) { res_obj = &in_obj; } else { cast_ctx.warning_ = OB_SUCCESS; switch (in_obj.get_type_class()) { case ObIntTC: { ret = int_datetime_interval(expect_type, cast_ctx, in_obj, buf_obj, cast_ctx.cast_mode_); break; } case ObFloatTC: { ret = float_datetime_interval(expect_type, cast_ctx, in_obj, buf_obj, cast_ctx.cast_mode_); break; } case ObDoubleTC: { ret = double_datetime_interval(expect_type, cast_ctx, in_obj, buf_obj, cast_ctx.cast_mode_); break; } case ObNumberTC: { ret = number_datetime_interval(expect_type, cast_ctx, in_obj, buf_obj, cast_ctx.cast_mode_); break; } case ObOTimestampTC: { ret = otimestamp_datetime(expect_type, cast_ctx, in_obj, buf_obj, cast_ctx.cast_mode_); break; } default: { ret = OB_ERR_UNEXPECTED; LOG_WARN("it should not arrive here", K(ret), K(in_obj), K(expect_type), K(in_obj.get_type_class())); } } if (OB_FAIL(ret)) { 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; } // ObInnerEnumType and ObInnerSetType are not supported. int ObObjCaster::to_type( const ObExpectType& 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; ObObjType dest_type = expect_type.get_type(); cast_ctx.expect_obj_collation_ = expect_type.get_collation_type(); if (OB_UNLIKELY((dest_type == in_obj.get_type() && cast_ctx.dest_collation_ == in_obj.get_collation_type()) || ObNullType == in_obj.get_type())) { res_obj = &in_obj; } else if (ObEnumType == dest_type || ObSetType == dest_type) { if (OB_FAIL(to_type(expect_type, cast_ctx, in_obj, buf_obj))) { LOG_WARN("fail to cast to enum or set", K(expect_type), K(in_obj), K(cast_ctx.cast_mode_), K(ret)); } else { res_obj = &buf_obj; } } else if (OB_FAIL(to_type(dest_type, expect_type.get_collation_type(), cast_ctx, in_obj, buf_obj))) { LOG_WARN("failed to cast obj", K(in_obj), K(expect_type), K(cast_ctx.cast_mode_), K(ret)); } else { res_obj = &buf_obj; } return ret; } int ObObjCaster::to_type(const ObObjType expect_type, ObCastCtx& cast_ctx, const ObObj& in_obj, ObObj& out_obj) { int ret = OB_SUCCESS; ObObjType in_type = in_obj.get_type(); bool is_string = ob_is_string_type(in_type) || ob_is_lob_locator(in_type); if (OB_UNLIKELY((expect_type == in_type && (!is_string)) || ObNullType == in_type)) { out_obj = in_obj; } else if (in_obj.get_collation_type() == cast_ctx.dest_collation_ && (ObVarcharType == in_type || ObCharType == in_type || ob_is_nstring_type(in_type)) && (ObVarcharType == expect_type || ObCharType == expect_type || ob_is_nstring_type(expect_type)) && NULL == cast_ctx.zf_info_ && NULL == cast_ctx.res_accuracy_) { // fast path for char/varchar string_string cast. out_obj = in_obj; const_cast(out_obj.get_meta()).set_type_simple(expect_type); } else { if (share::is_oracle_mode() && in_obj.is_character_type()) { ObCollationType dest_collation = ob_is_nstring_type(expect_type) ? cast_ctx.dtc_params_.nls_collation_nation_ : cast_ctx.dtc_params_.nls_collation_; if (CS_TYPE_INVALID != dest_collation) { cast_ctx.dest_collation_ = dest_collation; } } ret = to_type( expect_type, is_string ? in_obj.get_collation_type() : cast_ctx.dest_collation_, cast_ctx, in_obj, out_obj); } return ret; } int ObObjCaster::to_type(const ObObjType expect_type, 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 (CS_TYPE_INVALID != cast_ctx.dest_collation_) { expect_cs_type = cast_ctx.dest_collation_; } else { cast_ctx.dest_collation_ = expect_cs_type; } 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 (lib::is_oracle_mode()) { /*if (CM_IS_EXPLICIT_CAST(cast_ctx.cast_mode_)) { if (OB_FAIL(OBJ_CAST_ORACLE_EXPLICIT[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(in_tc), K(out_tc), K(expect_type), K(cast_ctx.cast_mode_)); } } else {*/ if (OB_FAIL(OBJ_CAST_ORACLE_IMPLICIT[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(in_tc), K(out_tc), K(expect_type), K(cast_ctx.cast_mode_)); } //} } 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(in_tc), K(out_tc), K(expect_type), K(cast_ctx.cast_mode_)); } } if (OB_SUCC(ret)) { if (ObStringTC == out_tc || ObTextTC == out_tc || ObLobTC == out_tc) { if (ObStringTC == in_tc || ObTextTC == in_tc || ObLobTC == out_tc) { out_obj.set_collation_level(in_obj.get_collation_level()); } else { out_obj.set_collation_level(CS_LEVEL_COERCIBLE); } if (OB_LIKELY(expect_cs_type != CS_TYPE_INVALID)) { out_obj.set_collation_type(expect_cs_type); } else { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected collation type", K(ret), K(in_obj), K(out_obj), K(expect_cs_type), K(common::lbt())); } } } LOG_DEBUG("succ to to_type", K(ret), "in_type", in_obj.get_type(), K(in_obj), K(expect_type), K(out_obj), K(lbt())); return ret; } // use for cast to enum or set type int ObObjCaster::to_type(const ObExpectType& expect_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 ObObjType out_type = expect_type.get_type(); if (OB_UNLIKELY(!ob_is_enumset_tc(expect_type.get_type())) || OB_UNLIKELY(ob_is_invalid_obj_tc(in_tc))) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected expect_type", K(ret), K(expect_type), K(in_obj)); } else if (OB_FAIL(OB_CAST_ENUM_OR_SET[in_tc][ObSetType == out_type](expect_type, cast_ctx, in_obj, out_obj))) { LOG_WARN("fail to cast to enum or set", K(ret), K(in_obj), K(expect_type)); } else { LOG_DEBUG("succ to to_type", K(expect_type), K(in_obj), K(out_obj)); } return ret; } int ObObjCaster::get_zero_value(const ObObjType expect_type, ObCollationType expect_cs_type, ObObj& zero_obj) { int ret = OB_SUCCESS; // we need a ObObjCastParams object with warning is 1 to use SET_RES_XXX macro. ObObjCastParams params; ObCastMode cast_mode = CM_WARN_ON_FAIL; params.warning_ = 1; if (ob_is_string_tc(expect_type)) { zero_obj.set_string(expect_type, ""); } else if (ob_is_int_tc(expect_type)) { int64_t value = 0; SET_RES_INT(zero_obj); } else if (ob_is_uint_tc(expect_type)) { uint64_t value = 0; SET_RES_UINT(zero_obj); } else if (ob_is_float_tc(expect_type)) { double value = 0.0; SET_RES_FLOAT(zero_obj); } else if (ob_is_double_tc(expect_type)) { double value = 0.0; SET_RES_DOUBLE(zero_obj); } else if (ob_is_number_tc(expect_type)) { number::ObNumber value; value.set_zero(); SET_RES_NUMBER(zero_obj); } else if (ob_is_datetime_tc(expect_type)) { int64_t value = 0; SET_RES_DATETIME(zero_obj); } else if (ob_is_date_tc(expect_type)) { int32_t value = 0; SET_RES_DATE(zero_obj); } else if (ob_is_time_tc(expect_type)) { int32_t value = 0; SET_RES_TIME(zero_obj); } else if (ob_is_year_tc(expect_type)) { int64_t value = 0; SET_RES_YEAR(zero_obj); } else if (ob_is_bit_tc(expect_type)) { uint64_t value = 0; SET_RES_BIT(zero_obj); } else if (ObEnumType == expect_type) { uint64_t value = 0; SET_RES_ENUM(zero_obj); } else if (ObSetType == expect_type) { uint64_t value = 0; SET_RES_SET(zero_obj); } else if (ob_is_otimestampe_tc(expect_type)) { ObOTimestampData value; SET_RES_OTIMESTAMP(zero_obj); } else if (ob_is_interval_ym(expect_type)) { ObIntervalYMValue value; SET_RES_INTERVAL_YM(zero_obj); } else if (ob_is_interval_ds(expect_type)) { ObIntervalDSValue value; SET_RES_INTERVAL_DS(zero_obj); } else if (ob_is_urowid(expect_type)) { ret = OB_NOT_SUPPORTED; LOG_WARN("urowid with default value not supported"); } if (OB_SUCC(ret)) { zero_obj.set_collation_type(expect_cs_type); } return ret; } int ObObjCaster::enumset_to_inner(const ObObjMeta& expect_meta, const ObObj& in_obj, ObObj& out_obj, common::ObIAllocator& allocator, const common::ObIArray& str_values) { int ret = OB_SUCCESS; if (ObEnumType != in_obj.get_type() && ObSetType != in_obj.get_type()) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected expect_type", K(ret), K(in_obj)); } else { const ObObjType expect_type = (ObEnumType == in_obj.get_type() ? ObEnumInnerType : ObSetInnerType); const int64_t element_num = str_values.count(); const uint64_t element_val = in_obj.get_enum(); if (ObEnumInnerType == expect_type) { int64_t element_idx = static_cast(element_val - 1); // enum value start from 1 ObString element_str; if (OB_UNLIKELY(element_num < 1)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("str_values_ should not be empty", K(str_values), K(ret)); } else if (OB_UNLIKELY(0 == element_val)) { // do nothing just keep element_string empty } else { if (OB_UNLIKELY(element_idx > element_num - 1)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("invalid enum value", K(element_idx), K(element_num), K(element_val), K(in_obj), K(ret)); } else { element_str = str_values.at(element_idx); } } if (OB_SUCC(ret)) { ObEnumSetInnerValue inner_value(element_val, element_str); char* buf = NULL; const int64_t BUF_LEN = inner_value.get_serialize_size(); int64_t pos = 0; if (OB_ISNULL(buf = static_cast(allocator.alloc(BUF_LEN)))) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("alloc memory failed", K(ret), KP(buf), K(BUF_LEN)); } else if (OB_FAIL(inner_value.serialize(buf, BUF_LEN, pos))) { LOG_WARN("failed to serialize inner_value", K(BUF_LEN), K(ret)); } else { out_obj.set_varchar(buf, static_cast(pos)); out_obj.set_type(expect_type); out_obj.set_collation(expect_meta); } } } else { // to setinner static const int64_t EFFECTIVE_COUNT = 64; if (OB_UNLIKELY(element_num < 1)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("invalid element_num", K(str_values), K(element_num), K(ret)); } else if (OB_UNLIKELY(element_num < EFFECTIVE_COUNT) && OB_UNLIKELY(element_val >= (1ULL << element_num))) { // check the validation of element_val ret = OB_ERR_UNEXPECTED; LOG_WARN("set value out of range", K(element_val), K(element_num)); } ObSqlString sql_string; uint64_t index = 1ULL; const ObString& sep = ObCharsetUtils::get_const_str(expect_meta.get_collation_type(), ','); for (int64_t i = 0; OB_SUCC(ret) && i < element_num && i < EFFECTIVE_COUNT && element_val >= index; ++i, index = index << 1) { if (element_val & (index)) { const ObString& tmp_val = str_values.at(i); if (OB_FAIL(sql_string.append(tmp_val))) { LOG_WARN("fail to deep copy str", K(element_val), K(i), K(ret)); } else if ((element_val >= (index << 1)) && (OB_FAIL(sql_string.append(sep)))) { LOG_WARN("fail to deep copy comma", K(element_val), K(tmp_val), K(i), K(ret)); } } } if (OB_SUCC(ret)) { ObString string_value(sql_string.length(), sql_string.ptr()); ObEnumSetInnerValue inner_value(element_val, string_value); char* buf = NULL; const int64_t BUF_LEN = inner_value.get_serialize_size(); int64_t pos = 0; if (OB_ISNULL(buf = static_cast(allocator.alloc(BUF_LEN)))) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("alloc memory failed", K(ret), KP(buf), K(BUF_LEN)); } else if (OB_FAIL(inner_value.serialize(buf, BUF_LEN, pos))) { LOG_WARN("failed to serialize inner_value", K(BUF_LEN), K(ret)); } else { out_obj.set_varchar(buf, static_cast(pos)); out_obj.set_type(expect_type); out_obj.set_collation(expect_meta); } } } } 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 ObObjCaster::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; } /* * c1 = 'A' check if c1 can be ordering */ int ObObjCaster::is_const_consistent(const ObObjMeta& const_mt, const ObObjMeta& column_mt, const ObObjType calc_type, const ObCollationType calc_collation, bool& result) { int ret = OB_SUCCESS; result = false; ObObjTypeClass tc1 = const_mt.get_type_class(); ObObjTypeClass tc2 = column_mt.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(const_mt), K(column_mt)); } else if (const_mt.is_string_or_lob_locator_type() && column_mt.is_string_or_lob_locator_type()) { if (column_mt.get_collation_type() == calc_collation) { result = true; } else { // false } } else { if (OB_FAIL(ObObjCaster::is_cast_monotonic(column_mt.get_type(), calc_type, result))) { LOG_WARN("check is cast monotonic failed", K(ret)); } else if (!result) { // false } else if (OB_FAIL(ObObjCaster::is_cast_monotonic(calc_type, column_mt.get_type(), result))) { LOG_WARN("check is cast monotonic failed", K(ret)); } else { // do nothing } } return ret; } /* make sure that you have read the doc before you call these functions ! * * doc: http://www.atatech.org/articles/56575 */ int ObObjCaster::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_or_lob_locator_type() && to.is_string_or_lob_locator_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 ObObjCaster::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_or_lob_locator_type() && to.is_string_or_lob_locator_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; } // more than 40 bytes: scientific notation. // less or equal to 40 bytes: print directly. int ObObjCaster::oracle_number_to_char(const number::ObNumber& number_val, const bool is_from_number_type, const int16_t scale, const int64_t len, char* buf, int64_t& pos) { int ret = OB_SUCCESS; const int64_t COSNT_BUF_SIZE = 256; char ptr[COSNT_BUF_SIZE]; int64_t str_len = 0; int64_t origin = pos; const int64_t SCI_NUMBER_LENGTH = 40; if (OB_UNLIKELY(pos > len || len < 0 || pos < 0 || NULL == buf)) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid value", K(ret), K(pos), K(len), KP(buf)); } else if (is_from_number_type) { if (OB_FAIL(number_val.format_with_oracle_limit(ptr, COSNT_BUF_SIZE, str_len, scale))) { LOG_WARN("fail to format", K(ret)); } } else { if (OB_FAIL(number_val.format(ptr, COSNT_BUF_SIZE, str_len, scale))) { LOG_WARN("failed to format number to string", K(ret)); } } if (OB_FAIL(ret)) { } else if (str_len <= SCI_NUMBER_LENGTH) { if (OB_UNLIKELY(str_len + pos > len)) { ret = OB_INVALID_ARGUMENT; LOG_WARN("the length of buffer is not enough", K(ret)); } else { MEMCPY(buf + pos, ptr, str_len); pos += str_len; } } else if (OB_UNLIKELY(len - pos < SCI_NUMBER_LENGTH)) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid value", K(ret), K(pos)); } else { int64_t raw_pos = 0; char pow_str[6]; int64_t pow_index = 0; bool pre_dot = false; pow_str[pow_index++] = 'E'; pow_str[pow_index++] = '+'; if ('-' == ptr[raw_pos]) { raw_pos++; buf[pos++] = '-'; } if ('.' == ptr[raw_pos]) { raw_pos++; pre_dot = true; pow_str[pow_index - 1] = '-'; } int64_t zero_count = 0; while ('0' == ptr[raw_pos] && raw_pos < str_len) { raw_pos++; zero_count++; } buf[pos++] = ptr[raw_pos++]; buf[pos++] = '.'; if (pre_dot) { if (OB_FAIL(databuff_printf(pow_str, sizeof(pow_str), pow_index, "%ld", zero_count + 1))) { LOG_WARN("fail to generate pow str", K(ret)); } else { // pad zero to 40 bytes. while (pos < SCI_NUMBER_LENGTH - pow_index + origin) { if (raw_pos >= str_len) { buf[pos++] = '0'; } else { buf[pos++] = ptr[raw_pos++]; } } } } else if (!pre_dot && 0 == zero_count) { int64_t count = 0; bool enable_count = true; int64_t width_count = 0; while (pos < SCI_NUMBER_LENGTH - pow_index - width_count + origin) { if (raw_pos >= str_len) { buf[pos++] = '0'; } else if ('.' == ptr[raw_pos]) { raw_pos++; enable_count = false; } else { if (enable_count) { count++; if (count >= 0 && count <= 9) { width_count = 1; } else if (count >= 10 && count <= 99) { width_count = 2; } else { width_count = 3; } } buf[pos++] = ptr[raw_pos++]; } } for (int64_t i = raw_pos; enable_count && i < str_len && ptr[i] != '.'; ++i) { count++; } if (OB_FAIL(databuff_printf(pow_str, sizeof(pow_str), pow_index, "%ld", count))) { LOG_WARN("fail to generate pow str", K(ret)); } } else { ret = OB_ERR_UNEXPECTED; LOG_WARN("the number raw str is unexpected", K(ret)); } // round the last digit and handle the carry. if (OB_SUCC(ret)) { int64_t carry = 0; int64_t carry_pos = pos; if (raw_pos < str_len && ptr[raw_pos] >= '5' && ptr[raw_pos] <= '9') { carry = 1; carry_pos--; while (carry && carry_pos >= origin && OB_SUCC(ret)) { if (buf[carry_pos] >= '0' && buf[carry_pos] <= '8') { buf[carry_pos] = (char)((int)buf[carry_pos] + carry); carry = 0; carry_pos--; } else if ('9' == buf[carry_pos]) { carry = 1; buf[carry_pos--] = '0'; } else if ('.' == buf[carry_pos]) { carry_pos--; } else { ret = OB_ERR_UNEXPECTED; LOG_WARN("It's unexpected to round the number sci", K(ret)); } } // right shift if get carry here. if (1 == carry && origin - 1 == carry_pos && OB_SUCC(ret)) { for (int64_t i = pos - 1; i >= origin + 1; --i) { buf[i] = buf[i - 1]; } buf[origin] = '1'; } } } // print power if (OB_SUCC(ret)) { for (int i = 0; i < pow_index; ++i) { buf[pos++] = pow_str[i]; } } // check pos if (OB_SUCC(ret)) { if (str_len > SCI_NUMBER_LENGTH && pos - origin != SCI_NUMBER_LENGTH) { ret = OB_INVALID_ARGUMENT; LOG_WARN("the value of pos is invalid after number to char in oracle mode", K(pos), K(origin), K(ret)); } } } return ret; } int ObObjCaster::can_cast_in_oracle_mode(const ObObjTypeClass expect_type, const ObObjTypeClass obj_type) { int ret = OB_SUCCESS; if (cast_not_expected == OBJ_CAST_ORACLE_IMPLICIT[obj_type][expect_type]) { ret = OB_ERR_UNEXPECTED; LOG_WARN("not expected obj type convert", K(obj_type), K(expect_type), K(ret)); } else if (cast_inconsistent_types == OBJ_CAST_ORACLE_IMPLICIT[obj_type][expect_type]) { ret = OB_ERR_INVALID_TYPE_FOR_OP; LOG_WARN("inconsistent datatypes", "expected", expect_type, "got", obj_type, K(ret)); } return ret; } const bool ObObjCaster::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, // text false, // bit false, // enumset false, // enumsetinner false, // OTimestamp false, // raw false, // interval false, // rowid false, // lob }, // int { false, // null true, // int true, // uint false, // float false, // double true, // number false, // datetime false, // date false, // time false, // year false, // string false, // extend false, // unknown false, // text true, // bit false, // enumset false, // enumsetInner false, // OTimestamp false, // raw false, // interval false, // rowid false, // lob }, // uint { false, // null true, // int true, // uint false, // float false, // double true, // number false, // datetime false, // date false, // time false, // year false, // string false, // extend false, // unknown false, // text true, // bit false, // enumset false, // enumsetInner false, // OTimestamp false, // raw false, // interval false, // rowid 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, // text false, // enumset false, // enumsetInner true, // bit false, // OTimestamp false, // raw false, // interval false, // rowid 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, // text true, // bit false, // enumset false, // enumsetInner false, // OTimestamp false, // raw false, // interval false, // rowid 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, // text true, // bit false, // enumset false, // enumsetInner false, // OTimestamp false, // raw false, // interval false, // rowid 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, // text true, // bit false, // enumset false, // enumsetInner true, // OTimestamp false, // raw false, // interval false, // rowid 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, // text true, // bit false, // enumset false, // enumsetInner true, // OTimestamp false, // raw false, // interval false, // rowid 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, // text true, // bit false, // enumset false, // enumsetInner true, // OTimestamp false, // raw false, // interval false, // rowid 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, // text true, // bit false, // enumset false, // enumsetInner true, // OTimestamp false, // raw false, // interval false, // rowid 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, // text false, // bit false, // enumset false, // enumsetInner false, // OTimestamp true, // raw true, // interval true, // rowid 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, // text false, // bit false, // enumset false, // enumsetInner false, // OTimestamp false, // raw false, // interval false, // rowid 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, // text false, // bit false, // enumset false, // enumsetInner false, // OTimestamp false, // raw false, // interval false, // rowid false, // lob }, // text { 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, // text false, // bit false, // enumset false, // enumsetInner false, // OTimestamp false, // raw false, // interval false, // rowid true, // lob }, // bit { 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, // text true, // bit false, // enumset false, // enumsetInner false, // OTimestamp false, // raw false, // interval false, // rowid false, // lob }, // enumset { 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, // text false, // bit false, // enumset false, // enumsetInner false, // OTimestamp false, // raw false, // interval false, // rowid false, // lob }, // enumsetinner { 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, // text false, // bit false, // enumset false, // enumsetInner false, // OTimestamp false, // raw false, // interval false, // rowid false, // text }, // OTimestamp { 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, // text true, // bit false, // enumset false, // enumsetInner true, // OTimestamp false, // raw false, // interval false, // rowid true, // lob }, // raw { 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 false, // text false, // bit false, // enumset false, // enumsetInner false, // OTimestamp true, // raw false, // interval, false, // rowid false, // lob }, // interval { 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, // text false, // bit false, // enumset false, // enumsetInner false, // OTimestamp false, // raw true, // interval, false, // rowid false, // lob }, // rowid { 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 false, // text false, // bit false, // enumset false, // enumsetInner false, // OTimestamp false, // raw false, // interval, true, // rowid 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, // text false, // bit false, // enumset false, // enumsetInner false, // OTimestamp false, // raw false, // interval false, // rowid true, // lob }, }; const bool ObObjCaster::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 false, // bit false, // enumset false, // enumsetInner false, // OTimestamp false, // raw }, // 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 true, // bit true, // enumset false, // enumsetInner false, // OTimestamp false, // raw }, // 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 true, // bit true, // enumset false, // enumsetInner false, // OTimestamp false, // raw }, // 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 false, // bit false, // enumset false, // enumsetInner false, // OTimestamp false, // raw }, // 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 false, // bit false, // enumset false, // enumsetInner false, // OTimestamp false, // raw }, // 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 true, // bit true, // enumset false, // enumsetInner false, // OTimestamp false, // raw }, // 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 false, // bit false, // enumset false, // enumsetInner true, // OTimestamp false, // raw }, // 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 false, // bit false, // enumset false, // enumsetInner true, // OTimestamp false, // raw }, // 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 false, // bit false, // enumset false, // enumsetInner true, // OTimestamp false, // raw }, // 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 true, // bit true, // enumset false, // enumsetInner false, // OTimestamp false, // raw }, // 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 false, // bit false, // enumset false, // enumsetInner false, // OTimestamp false, // raw }, // 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 false, // bit false, // enumset false, // enumsetInner false, // OTimestamp false, // raw }, // 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 false, // bit false, // enumset false, // enumsetInner false, // OTimestamp false, // raw }, // 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 false, // bit false, // enumset false, // enumsetInner false, // OTimestamp false, // raw }, // bit { 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 true, // bit true, // enumset false, // enumsetInner false, // OTimestamp false, // raw }, // enumset { 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 true, // bit true, // enumset false, // enumsetInner false, // OTimestamp false, // raw }, // enumsetInner { 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 false, // bit false, // enumset false, // enumsetInner false, // OTimestamp false, // raw }, // OTimestamp { 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 false, // bit false, // enumset false, // enumsetInner true, // OTimestamp false, // raw }, // raw { 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 false, // bit false, // enumset false, // enumsetInner false, // OTimestamp false, // raw }, }; const bool ObObjCaster::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}, {false, false, false}, {false, false, false}, }, // CS_TYPE_UTF8MB4_BIN { // ci //utf8bin //bin {true, true, true}, {false, true, true}, {false, true, true}, }, // CS_TYPE_BINARY { // ci //utf8bin //bin {true, true, true}, {false, true, true}, {false, true, true}, }, }; const bool ObObjCaster::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 false, // bit false, // enumset false, // enumsetInner false, // OTimestamp false, // raw }, // 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 true, // bit true, // enumset false, // enumsetInner true, // OTimestamp false, // raw }, // 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 true, // bit true, // enumset false, // enumsetInner true, // OTimestamp false, // raw }, // 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 false, // bit false, // enumset false, // enumsetInner true, // OTimestamp false, // raw }, // 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 false, // bit false, // enumset false, // enumsetInner true, // OTimestamp false, // raw }, // 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 true, // bit true, // enumset false, // enumsetInner true, // OTimestamp false, // raw }, // 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 false, // bit false, // enumset false, // enumsetInner true, // OTimestamp false, // raw }, // 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 false, // bit false, // enumset false, // enumsetInner true, // OTimestamp false, // raw }, // 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 false, // bit false, // enumset false, // enumsetInner true, // OTimestamp false, // raw }, // 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 true, // bit true, // enumset false, // enumsetInner true, // OTimestamp false, // raw }, // 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 true, // bit true, // enumset false, // enumsetInner true, // OTimestamp false, // raw }, // 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 false, // bit false, // enumset false, // enumsetInner false, // OTimestamp false, // raw }, // 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 false, // bit false, // enumset false, // enumsetInner false, // OTimestamp false, // raw }, // 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 true, // bit true, // enumset false, // enumsetInner true, // OTimestamp false, // raw }, // bit { 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 true, // bit true, // enumset false, // enumsetInner true, // OTimestamp false, // raw }, // setenum { 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 true, // bit true, // enumset false, // enumsetInner false, // OTimestamp false, // raw }, // setenumInner { 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 false, // bit false, // enumset false, // enumsetInner false, // OTimestamp false, // raw }, // OTimestamp { 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 false, // bit false, // enumset false, // enumsetInner true, // OTimestamp false, // raw }, // raw { 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 true, // bit true, // enumset false, // enumsetInner true, // OTimestamp false, // raw }, }; const bool ObObjCaster::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 }}; int ObObjEvaluator::is_true(const ObObj& obj, ObCastMode cast_mode, bool& result) { int ret = OB_SUCCESS; result = false; if (obj.is_null()) { // result is unkown // do nothing } else if (obj.is_numeric_type()) { result = !obj.is_zero(); } else if (lib::is_oracle_mode() && obj.is_varchar_or_char() && 0 == obj.get_string_len()) { result = true; } else { ObArenaAllocator allocator(ObModIds::BLOCK_ALLOC); ObCastCtx cast_ctx(&allocator, NULL, cast_mode, CS_TYPE_INVALID); ObObj buf_obj; const ObObj* res_obj = NULL; if (OB_FAIL(ObObjCaster::to_type(ObNumberType, cast_ctx, obj, buf_obj, res_obj))) { LOG_WARN("failed to cast object to tinyint", K(ret), K(obj)); } else if (NULL == res_obj || (!(res_obj->is_number()))) { ret = OB_ERR_UNEXPECTED; LOG_WARN("res_obj is NULL or unexpected obj type", K(ret), K(obj), K(res_obj)); } else { result = !(res_obj->is_zero_number()); } } return ret; } int ObObjEvaluator::is_false(const ObObj& obj, ObCastMode cast_mode, bool& b_result) { int ret = OB_SUCCESS; b_result = true; if (OB_FAIL(is_true(obj, cast_mode, b_result))) { LOG_WARN("fail to evaluate obj", K(ret)); } else { b_result = !b_result; } if (OB_SUCC(ret)) { if (obj.is_null()) { // result is unkown, unkown != false b_result = false; } } return ret; } } // end namespace common } // end namespace oceanbase