/** * 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 SQL #include #include "lib/charset/ob_dtoa.h" #include "lib/utility/ob_fast_convert.h" #include "share/object/ob_obj_cast_util.h" #include "share/object/ob_obj_cast.h" #include "sql/engine/expr/ob_datum_cast.h" #include "sql/engine/ob_exec_context.h" #include "sql/engine/expr/ob_expr_util.h" #include "sql/engine/ob_serializable_function.h" #include "lib/json_type/ob_json_tree.h" #include "lib/json_type/ob_json_bin.h" #include "lib/json_type/ob_json_base.h" #include "lib/json_type/ob_json_parse.h" #include "share/ob_lob_access_utils.h" #include "sql/engine/expr/ob_expr_lob_utils.h" #include "sql/engine/expr/ob_expr_json_func_helper.h" #include "lib/geo/ob_geometry_cast.h" #include "sql/engine/expr/ob_geo_expr_utils.h" namespace oceanbase { namespace sql { using namespace oceanbase::common; //// common function and macro #define CAST_FUNC_NAME(intype, outtype) \ int intype##_##outtype(const sql::ObExpr &expr, \ sql::ObEvalCtx &ctx, \ sql::ObDatum &res_datum) #define CAST_ENUMSET_FUNC_NAME(intype, outtype) \ int intype##_##outtype(const sql::ObExpr &expr, \ const common::ObIArray &str_values,\ const uint64_t cast_mode, \ sql::ObEvalCtx &ctx, \ sql::ObDatum &res_datum) // OB_ISNULL(expr.args_[0]), arg_cnt_ == 1, OB_ISNULL(child_res->ptr_)不会做check #define EVAL_ARG() \ int ret = OB_SUCCESS; \ ObDatum *child_res = NULL; \ if (OB_FAIL(expr.args_[0]->eval(ctx, child_res))) { \ LOG_WARN("eval arg failed", K(ret), K(ctx)); \ } else if (child_res->is_null()) { \ res_datum.set_null(); \ } else #define EVAL_ARG_FOR_CAST_TO_JSON() \ int ret = OB_SUCCESS; \ ObDatum *child_res = NULL; \ ObObjType in_type = expr.args_[0]->datum_meta_.type_; \ if (OB_FAIL(expr.args_[0]->eval(ctx, child_res))) { \ LOG_WARN("eval arg failed", K(ret)); \ } else if (child_res->is_null()) { \ res_datum.set_null(); \ } else if (lib::is_mysql_mode() && CM_IS_COLUMN_CONVERT(expr.extra_) && is_mysql_unsupported_json_column_conversion(in_type)) { \ ret = OB_ERR_INVALID_JSON_TEXT; \ LOG_USER_ERROR(OB_ERR_INVALID_JSON_TEXT); \ } else //oracle模式除了longtext类型的空串不等同于null,其他string类型的空串都等于null #define EVAL_STRING_ARG() \ int ret = OB_SUCCESS; \ ObDatum *child_res = NULL; \ if (OB_FAIL(expr.args_[0]->eval(ctx, child_res))) { \ LOG_WARN("eval arg failed", K(ret), K(ctx)); \ } else if (child_res->is_null() || \ (lib::is_oracle_mode() && 0 == child_res->len_ \ && ObLongTextType != expr.args_[0]->datum_meta_.type_)) { \ res_datum.set_null(); \ } else #define DEF_IN_OUT_TYPE() \ int warning = OB_SUCCESS; \ ObObjType in_type = expr.args_[0]->datum_meta_.type_; \ ObObjType out_type = expr.datum_meta_.type_; \ UNUSEDx(warning, in_type, out_type); // 如果使用ObDatum::get_xxx(),需要多传递一个参数,指明函数名字,所以下面的宏直接cast #define DEF_IN_OUT_VAL(in_type, out_type, init_val) \ int warning = OB_SUCCESS; \ UNUSED(warning); \ in_type in_val = *(reinterpret_cast(child_res->ptr_)); \ out_type out_val = (init_val); #define CAST_FAIL(stmt) \ (OB_UNLIKELY((OB_SUCCESS != (ret = get_cast_ret((expr.extra_), (stmt), warning))))) // 与CAST_FAIL类似,但是上面的宏会将expr.extra_作为cast_mode,这样使用时少写一个参数 #define CAST_FAIL_CM(stmt, cast_mode) \ (OB_UNLIKELY((OB_SUCCESS != (ret = get_cast_ret((cast_mode), (stmt), warning))))) #define GET_SESSION() \ ObBasicSessionInfo *session = ctx.exec_ctx_.get_my_session(); \ if (OB_ISNULL(session)) { \ ret = OB_ERR_UNEXPECTED; \ LOG_WARN("session is NULL", K(ret)); \ } else #define INT32_MAX_DIGITS_LEN 10 static const int64_t power_of_10[INT32_MAX_DIGITS_LEN] = { 1L, 10L, 100L, 1000L, 10000L, 100000L, 1000000L, 10000000L, 100000000L, 1000000000L, //2147483647 }; static 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 && CM_IS_WARN_ON_FAIL(cast_mode)) { warning = ret; ret = OB_SUCCESS; } return ret; } // 出现错误时,处理如下: // 如果只设置了WARN_ON_FAIL,会覆盖错误码 // 如果设置了WARN_ON_FAIL和ZERO_ON_WARN,会覆盖错误码,且结果被置为0 // 如果设置了WARN_ON_FAIL和NULL_ON_WARN,会覆盖错误码,且结果被置为null #define SET_RES_OBJ(cast_mode, func_val, zero_value, value) \ do { \ if (OB_SUCC(ret)) { \ if (OB_SUCCESS == warning \ || OB_ERR_TRUNCATED_WRONG_VALUE == warning \ || OB_DATA_OUT_OF_RANGE == warning \ || OB_ERR_DATA_TRUNCATED == warning \ || OB_ERR_DOUBLE_TRUNCATED == warning \ || OB_ERR_TRUNCATED_WRONG_VALUE_FOR_FIELD == warning) { \ res_datum.set_##func_val(value); \ } else if (CM_IS_ZERO_ON_WARN(cast_mode)) { \ res_datum.set_##func_val(zero_value); \ } else { \ res_datum.set_null(); \ } \ } else { \ res_datum.set_##func_val(value); \ } \ } while (0) // 用于设置timestamp nano以及timestamp ltz的宏 #define SET_RES_OTIMESTAMP_10BYTE(value) \ do { \ if (OB_SUCC(ret)) { \ if (OB_SUCCESS == warning \ || OB_ERR_TRUNCATED_WRONG_VALUE == warning \ || OB_DATA_OUT_OF_RANGE == warning \ || OB_ERR_DATA_TRUNCATED == warning \ || OB_ERR_DOUBLE_TRUNCATED == warning \ || OB_ERR_TRUNCATED_WRONG_VALUE_FOR_FIELD == warning) { \ res_datum.set_otimestamp_tiny(value); \ } else if (CM_IS_ZERO_ON_WARN(expr.extra_)) { \ res_datum.set_otimestamp_tiny(ObOTimestampData()); \ } else { \ res_datum.set_null(); \ } \ } else { \ res_datum.set_otimestamp_tiny(value); \ } \ } while (0) #define SET_RES_INT(value) \ SET_RES_OBJ(expr.extra_, int, 0, value) #define SET_RES_BIT(value) \ SET_RES_OBJ(expr.extra_, uint, 0, value) #define SET_RES_UINT(value) \ SET_RES_OBJ(expr.extra_, uint,0, value) #define SET_RES_DATE(value) \ SET_RES_OBJ(expr.extra_, date, ObTimeConverter::ZERO_DATE, value) #define SET_RES_TIME(value) \ SET_RES_OBJ(expr.extra_, time, ObTimeConverter::ZERO_TIME, value) #define SET_RES_YEAR(value) \ SET_RES_OBJ(expr.extra_, year, ObTimeConverter::ZERO_YEAR, value) #define SET_RES_FLOAT(value) \ SET_RES_OBJ(expr.extra_, float, 0.0, value) #define SET_RES_DOUBLE(value) \ SET_RES_OBJ(expr.extra_, double, 0.0, value) #define SET_RES_ENUM(value) \ SET_RES_OBJ(expr.extra_, enum, 0, value) #define SET_RES_SET(value) \ SET_RES_OBJ(expr.extra_, set, 0, value) #define SET_RES_OTIMESTAMP(value) \ SET_RES_OBJ(expr.extra_, otimestamp_tz, ObOTimestampData(), value) #define SET_RES_INTERVAL_YM(value) \ SET_RES_OBJ(expr.extra_, interval_nmonth, 0, value) #define SET_RES_INTERVAL_DS(value) \ SET_RES_OBJ(expr.extra_, interval_ds, ObIntervalDSValue(), value) #define SET_RES_DATETIME(value) \ SET_RES_OBJ(expr.extra_, datetime,ObTimeConverter::ZERO_DATETIME, value) static const int64_t MAX_DOUBLE_STRICT_PRINT_SIZE = 512; static OB_INLINE int serialize_obnumber(number::ObNumber &nmb, ObIAllocator &allocator, ObString &out_str) { int ret = OB_SUCCESS; const number::ObNumber::Desc &nmb_desc = nmb.get_desc(); uint32_t *digits = nmb.get_digits(); char *buf = NULL; int64_t buf_len = sizeof(nmb_desc) + nmb_desc.len_ * sizeof(uint32_t); if (OB_ISNULL(buf = reinterpret_cast(allocator.alloc(buf_len)))) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("alloc memory failed", K(ret), K(buf_len)); } else { MEMCPY(buf, &nmb_desc, sizeof(nmb_desc)); MEMCPY(buf + sizeof(nmb_desc), digits, nmb_desc.len_ * sizeof(uint32_t)); out_str.assign_ptr(buf, static_cast(buf_len)); } return ret; } int ObDatumHexUtils::hex(const ObExpr &expr, const ObString &in_str, ObEvalCtx &ctx, ObIAllocator &calc_alloc, ObDatum &res_datum, bool upper_case) { int ret = OB_SUCCESS; if (in_str.empty()) { if (lib::is_oracle_mode()) { res_datum.set_null(); } else { if (!ob_is_text_tc(expr.datum_meta_.type_)) { res_datum.set_string(NULL, 0); } else if (OB_FAIL(ObTextStringHelper::string_to_templob_result(expr, ctx, res_datum, in_str))) { // build temp lob; LOG_WARN("build empty lob failed", K(ret), K(in_str)); } } } else { char *buf = NULL; bool need_convert = false; ObCollationType def_cs = ObCharset::get_system_collation(); ObCollationType dst_cs = expr.datum_meta_.cs_type_; ObExprStrResAlloc res_alloc(expr, ctx); // check if need convert first, and setup alloc. we can avoid copy converted res str. if (ObExprUtil::need_convert_string_collation(def_cs, dst_cs, need_convert)) { LOG_WARN("check need convert cs type failed", K(ret), K(def_cs), K(dst_cs)); } else if (OB_SUCC(ret)) { const int32_t alloc_length = in_str.length() * 2; int64_t buf_len = 0; ObTextStringDatumResult output_result(expr.datum_meta_.type_, &expr, &ctx, &res_datum); if (need_convert) { buf = reinterpret_cast(calc_alloc.alloc(alloc_length)); } else { if (OB_FAIL(output_result.init(alloc_length))) { LOG_WARN("init text or string result failed", K(ret), K(alloc_length)); } else if (OB_FAIL(output_result.get_reserved_buffer(buf, buf_len))) { LOG_WARN("get reserved buffer for text or string failed", K(ret), K(alloc_length), K(buf_len)); } } if (OB_FAIL(ret)) { } else if (OB_ISNULL(buf)) { res_datum.set_null(); ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("alloc memory failed", K(ret), K(alloc_length)); } else { const char *HEXCHARS = upper_case ? "0123456789ABCDEF" : "0123456789abcdef"; int32_t pos = 0; for (int32_t i = 0; i < in_str.length(); ++i) { buf[pos++] = HEXCHARS[in_str[i] >> 4 & 0xF]; buf[pos++] = HEXCHARS[in_str[i] & 0xF]; } ObString res_str; if (need_convert) { static const int32_t CharConvertFactorNum = 4; const int32_t alloc_length = pos * CharConvertFactorNum; //最多使用4字节存储一个字符 char *res_buf = NULL; if (output_result.is_init()) { OB_ASSERT(0); // should not inited if need_convert } else if (OB_FAIL(output_result.init(alloc_length))) { LOG_WARN("init text or string result failed", K(ret), K(alloc_length)); } else if (OB_FAIL(output_result.get_reserved_buffer(res_buf, buf_len))) { LOG_WARN("get reserved buffer of text or string result failed", K(ret), K(alloc_length), K(buf_len)); } else if (OB_ISNULL(buf)) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("alloc memory failed", K(ret), K(alloc_length)); } else { ObDataBuffer data_buf(res_buf, buf_len); if (OB_FAIL(ObExprUtil::convert_string_collation(ObString(pos, buf), def_cs, res_str, dst_cs, data_buf))) { LOG_WARN("convert string collation failed", K(ret)); } else if (OB_FAIL(output_result.lseek(res_str.length(), 0))) { LOG_WARN("lseek text or string result failed", K(ret), K(res_str.length())); } else { output_result.set_result(); } } } else { if (OB_FAIL(output_result.lseek(pos, 0))) { LOG_WARN("lseek text or string result failed", K(ret), K(pos)); } else { output_result.set_result(); } } } } } return ret; } static OB_INLINE int common_construct_otimestamp(const ObObjType type, const ObDatum &in_datum, ObOTimestampData &out_val); int ObDatumHexUtils::rawtohex(const ObExpr &expr, const ObString &in_str, ObEvalCtx &ctx, ObDatum &res_datum) { int ret = OB_SUCCESS; ObObjType in_type = expr.args_[0]->datum_meta_.type_; if (0 >= in_str.length()) { res_datum.set_null(); } else if (!(ObNullType < in_type && in_type < ObMaxType)) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid in type", K(ret), K(in_type)); } else { ObEvalCtx::TempAllocGuard alloc_guard(ctx); ObIAllocator &tmp_alloc = alloc_guard.get_allocator(); ObString out_str; ObOTimestampData time_in_val; switch (in_type) { //TODO::this should same as oracle, and support dump func @yanhua case ObTinyIntType: case ObSmallIntType: case ObInt32Type: case ObIntType: { // 虽然tiny/small/int32/int实际占用空间不到个字节, // 但是CG阶段还是会为其分配8个字节的空间 // 所以这里reinterpret_cast为int64_t的指针是没问题的 int64_t in_val = *(reinterpret_cast(in_str.ptr())); number::ObNumber nmb; if (OB_FAIL(nmb.from(in_val, tmp_alloc))) { LOG_WARN("fail to int_number", K(ret), K(in_val), "type", in_type); } else if (OB_FAIL(serialize_obnumber(nmb, tmp_alloc, out_str))) { LOG_WARN("serialize_obnumber failed", K(ret), K(nmb)); } break; } case ObFloatType: { float in_val = *(reinterpret_cast(in_str.ptr())); ObPrecision res_precision = -1; ObScale res_scale = -1; char buf[MAX_DOUBLE_STRICT_PRINT_SIZE]; MEMSET(buf, 0, MAX_DOUBLE_STRICT_PRINT_SIZE); int64_t length = ob_gcvt_opt(in_val, OB_GCVT_ARG_FLOAT, static_cast(sizeof(buf) - 1), buf, NULL, TRUE, TRUE); ObString float_str(sizeof(buf), static_cast(length), buf); number::ObNumber nmb; if (OB_FAIL(nmb.from_sci_opt(float_str.ptr(), float_str.length(), tmp_alloc, &res_precision, &res_scale))) { LOG_WARN("fail to from str to number", K(ret), K(float_str)); } else if (OB_FAIL(serialize_obnumber(nmb, tmp_alloc, out_str))) { LOG_WARN("serialize_obnumber failed", K(ret), K(nmb)); } break; } case ObDoubleType: { double in_val = *(reinterpret_cast(in_str.ptr())); ObPrecision res_precision = -1; ObScale res_scale = -1; char buf[MAX_DOUBLE_STRICT_PRINT_SIZE]; MEMSET(buf, 0, MAX_DOUBLE_STRICT_PRINT_SIZE); int64_t length = ob_gcvt_opt(in_val, OB_GCVT_ARG_DOUBLE, static_cast(sizeof(buf) - 1), buf, NULL, TRUE, TRUE); ObString double_str(sizeof(buf), static_cast(length), buf); number::ObNumber nmb; if (OB_FAIL(nmb.from_sci_opt(double_str.ptr(), double_str.length(), tmp_alloc, &res_precision, &res_scale))) { LOG_WARN("fail to from str to number", K(ret), K(double_str)); } else if (OB_FAIL(serialize_obnumber(nmb, tmp_alloc, out_str))) { LOG_WARN("serialize_obnumber failed", K(ret), K(nmb)); } break; } case ObNumberFloatType: case ObNumberType: { // 参数传进来的in_str是从子节点的datum空间来的,里面是已经序列化好的ObNumber // 直接拷贝即可 out_str = in_str; break; } case ObDateTimeType: { // shallow copy is ok. unhex accept const argument out_str = in_str; break; } case ObNVarchar2Type: case ObNCharType: case ObVarcharType: case ObCharType: case ObLongTextType: case ObJsonType: case ObGeometryType: 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 out_str = in_str; break; } case ObTimestampTZType: case ObTimestampLTZType: case ObTimestampNanoType: { // ObTimestampTZType占用12字节,ObTimestampLTZType和ObTimestampNanoType占用10字节 // 所以需要进行区分 ObDatum tmp_datum; tmp_datum.ptr_ = in_str.ptr(); tmp_datum.pack_ = static_cast(in_str.length()); if (OB_FAIL(common_construct_otimestamp(in_type, tmp_datum, time_in_val))) { LOG_WARN("common_construct_otimestamp failed", K(ret)); } else { out_str.assign_ptr(reinterpret_cast(&time_in_val), static_cast(in_str.length())); } break; } default: { ret = OB_ERR_INVALID_HEX_NUMBER; LOG_WARN("invalid hex number", K(ret), K(in_str), "type", in_type); } } if (OB_SUCC(ret)) { if (OB_FAIL(hex(expr, out_str, ctx, tmp_alloc, res_datum))) { LOG_WARN("fail to convert to hex", K(ret), K(out_str)); } } } return ret; } int ObDatumHexUtils::hextoraw_string(const ObExpr &expr, const ObString &in_str, ObEvalCtx &ctx, ObDatum &res_datum, bool &has_set_res) { int ret = OB_SUCCESS; if (0 == in_str.length()) { res_datum.set_null(); } else if (OB_FAIL(unhex(expr, in_str, ctx, res_datum, has_set_res))) { LOG_WARN("unhex failed", K(ret), K(in_str), K(ctx)); } return ret; } static int common_json_bin(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &res_datum, ObString &raw_bin) { int ret = OB_SUCCESS; ObTextStringDatumResult text_result(ObJsonType, &expr, &ctx, &res_datum); if (OB_FAIL(text_result.init(raw_bin.length()))) { LOG_WARN("Lob: init lob result failed"); } else if (OB_FAIL(text_result.append(raw_bin.ptr(), raw_bin.length()))) { LOG_WARN("failed to append realdata", K(ret), K(raw_bin), K(text_result)); } else { text_result.set_result(); } return ret; } static int common_gis_wkb(const ObExpr &expr, ObEvalCtx &ctx, ObDatum &res_datum, ObString &wkb) { int ret = OB_SUCCESS; ObTextStringDatumResult text_result(ObGeometryType, &expr, &ctx, &res_datum); if (OB_FAIL(text_result.init(wkb.length()))) { LOG_WARN("Lob: init lob result failed"); } else if (OB_FAIL(text_result.append(wkb.ptr(), wkb.length()))) { LOG_WARN("failed to append realdata", K(ret), K(wkb), K(text_result)); } else { text_result.set_result(); } return ret; } static int common_copy_string(const ObExpr &expr, const ObString &src, ObEvalCtx &ctx, ObDatum &res_datum, const int64_t align_offset = 0); int ObDatumHexUtils::hextoraw(const ObExpr &expr, const ObDatum &in, const ObObjType &in_type, const ObCollationType &in_cs_type, ObEvalCtx &ctx, ObDatum &res) { int ret = OB_SUCCESS; if (ob_is_text_tc(in_type)) { ret = OB_ERR_INVALID_TYPE_FOR_OP; LOG_WARN("lob as param not support in hextoraw", K(ret), K(in_type)); } else if (in.is_null()) { res.set_null(); } else if (ob_is_numeric_type(in_type)) { number::ObNumber res_nmb; ObNumStackOnceAlloc tmp_alloc; if (OB_FAIL(get_uint(in_type, in, tmp_alloc, res_nmb))) { LOG_WARN("fail to get uint64", K(ret)); } else if (OB_FAIL(uint_to_raw(res_nmb, expr, ctx, res))) { LOG_WARN("fail to convert to hex", K(ret), K(res_nmb)); } } else if (ob_is_character_type(in_type, in_cs_type) || ob_is_varbinary_or_binary(in_type, in_cs_type)) { const ObString &in_str = in.get_string(); bool has_set_res = false; if (OB_FAIL(hextoraw_string(expr, in_str, ctx, res, has_set_res))) { LOG_WARN("hextoraw_string failed", K(ret), K(in_str), K(ctx)); } } else if (ob_is_raw(in_type)) { ObString in_str(in.get_string()); if (OB_FAIL(common_copy_string(expr, in_str, ctx, res))) { LOG_WARN("common_copy_string failed", K(ret), K(in_str), K(ctx)); } } else { ret = OB_ERR_INVALID_HEX_NUMBER; LOG_WARN("invalid hex number", K(ret), K(in_type)); } return ret; } int ObDatumHexUtils::uint_to_raw(const number::ObNumber &uint_num, const ObExpr &expr, ObEvalCtx &ctx, ObDatum &res_datum) { 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)); bool has_set_res = false; if (OB_FAIL(unhex(expr, uint_str, ctx, res_datum, has_set_res))) { LOG_WARN("fail to str_to_raw", K(ret), K(uint_str)); } } return ret; } int ObDatumHexUtils::get_uint(const ObObjType &in_type, const ObDatum &in, ObIAllocator &alloc, number::ObNumber &out) { int ret = OB_SUCCESS; if (OB_UNLIKELY(!ob_is_accurate_numeric_type(in_type))) { ret = OB_ERR_INVALID_HEX_NUMBER; LOG_WARN("invalid hex number", K(ret), K(in_type)); } else if (ObNumberType == in_type || ObUNumberType == in_type) { const number::ObNumber value(in.get_number()); if (OB_FAIL(out.from(value, alloc))) { LOG_WARN("deep copy failed", K(ret), K(value)); } 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(in.get_int() < 0)) { ret = OB_ERR_INVALID_HEX_NUMBER; LOG_WARN("invalid hex number", K(ret), K(in.get_int())); } else if (OB_FAIL(out.from(in.get_int(), alloc))) { LOG_WARN("deep copy failed", K(ret), K(in.get_int())); } } return ret; } // 相比于common_copy_string_zf,不考虑zerofill。直接将src中的内容拷贝到res_datum // %align_offset is used in mysql mode to align blob to other charset. static int common_copy_string(const ObExpr &expr, const ObString &src, ObEvalCtx &ctx, ObDatum &res_datum, const int64_t align_offset /* = 0 */) { int ret = OB_SUCCESS; char *out_ptr = NULL; int64_t len = align_offset + src.length(); if (OB_ISNULL(out_ptr = expr.get_str_res_mem(ctx, len))) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("allocate memory failed", K(ret)); } else { MEMMOVE(out_ptr + align_offset, src.ptr(), len - align_offset); MEMSET(out_ptr, 0, align_offset); res_datum.set_string(out_ptr, len); } return ret; } // 将src中的内容拷贝到res_datum中,拷贝过程需要考虑res_datum空间是否足够,以及zero fill填0 // 参数expr的作用是为了获取cast表达式的相关信息,例如res_buf_len_/max_length_/extra_ static int common_copy_string_zf(const ObExpr &expr, const ObString &src, ObEvalCtx &ctx, ObDatum &res_datum, const int64_t align_offset = 0) { int ret = OB_SUCCESS; int64_t out_len = static_cast(expr.datum_meta_.scale_); if (out_len <= 0) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected zf length", K(ret), K(out_len), K(expr.datum_meta_.scale_)); //这里原来做了对oracle模式空串对处理,将oracle模式空串转为null。 //一般情况下oracle模式空串等同于null,但是支持empty_lob之后,longtext/lob类型的空串不等同于null // 其他类型转到string类型时会调用common_copy_string_zf,当in_type不是string时,in_str的length不会为0 // in_type是string时,在cast方法入口已经判断了是否要将空串转换为null,因此删去原来的转换逻辑。 } else if (CM_IS_ZERO_FILL(expr.extra_) && out_len > src.length()) { char *out_ptr = NULL; // out_ptr may overlap with src, so memmove is used. if (OB_ISNULL(out_ptr = expr.get_str_res_mem(ctx, out_len))) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("allocate memory failed", K(ret)); } else { int64_t zf_len = out_len - src.length(); if (0 < zf_len) { MEMMOVE(out_ptr + zf_len, src.ptr(), src.length()); MEMSET(out_ptr, '0', zf_len); } else { MEMMOVE(out_ptr, src.ptr(), out_len); } res_datum.set_string(ObString(out_len, out_ptr)); } } else { if (OB_FAIL(common_copy_string(expr, src, ctx, res_datum, align_offset))) { LOG_WARN("common_copy_string failed", K(ret), K(src), K(expr), K(ctx)); } } return ret; } int ObDatumHexUtils::unhex(const ObExpr &expr, const ObString &in_str, ObEvalCtx &ctx, ObDatum &res_datum, bool &has_set_res) { int ret = OB_SUCCESS; UNUSED(expr); char *buf = NULL; int64_t buf_len = 0; const bool need_fill_zero = (1 == in_str.length() % 2); const int32_t tmp_length = in_str.length() / 2 + need_fill_zero; int32_t alloc_length = (0 == tmp_length ? 1 : tmp_length); ObTextStringDatumResult output_result(expr.datum_meta_.type_, &expr, &ctx, &res_datum); if (OB_FAIL(output_result.init(alloc_length))) { LOG_WARN("init text or string result failed", K(ret), K(alloc_length)); } else if (OB_FAIL(output_result.get_reserved_buffer(buf, buf_len))) { LOG_WARN("get reserved buffer of text or string result failed", K(ret), K(alloc_length), K(buf_len)); } else if (OB_ISNULL(buf)) { res_datum.set_null(); ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("alloc memory failed", K(alloc_length), K(ret)); } else { int32_t i = 0; char c1 = 0; char c2 = 0; if (in_str.length() > 0) { if (need_fill_zero) { c1 = '0'; c2 = in_str[0]; i = 0; } else { c1 = in_str[0]; c2 = in_str[1]; i = 1; } } while (OB_SUCC(ret) && i < in_str.length()) { if (isxdigit(c1) && isxdigit(c2)) { buf[i / 2] = (char)((get_xdigit(c1) << 4) | get_xdigit(c2)); if (i + 2 < in_str.length()) { c1 = in_str[++i]; c2 = in_str[++i]; } else { break; } } else { ret = OB_ERR_INVALID_HEX_NUMBER; LOG_WARN("invalid hex number", K(ret), K(c1), K(c2), K(in_str)); } } if (OB_SUCC(ret)) { if (OB_FAIL(output_result.lseek(tmp_length, 0))) { LOG_WARN("lseek text or string result failed", K(ret), K(tmp_length)); } else { output_result.set_result(); has_set_res = true; } } } return ret; } // 根据in_type,force_use_standard_format信息,从session中获取fromat_str int common_get_nls_format(const ObBasicSessionInfo *session, const ObObjType in_type, const bool force_use_standard_format, ObString &format_str) { int ret = OB_SUCCESS; if (OB_ISNULL(session)) { ret = OB_INVALID_ARGUMENT; LOG_WARN("session is NULL", K(ret)); } else { ObString nls_format; switch (in_type) { case ObDateTimeType: nls_format = session->get_local_nls_date_format(); format_str = (force_use_standard_format ? ObTimeConverter::COMPAT_OLD_NLS_DATE_FORMAT : (nls_format.empty() ? ObTimeConverter::DEFAULT_NLS_DATE_FORMAT : nls_format)); break; case ObTimestampNanoType: case ObTimestampLTZType: nls_format = session->get_local_nls_timestamp_format(); format_str = (force_use_standard_format ? ObTimeConverter::COMPAT_OLD_NLS_TIMESTAMP_FORMAT : (nls_format.empty() ? ObTimeConverter::DEFAULT_NLS_TIMESTAMP_FORMAT : nls_format)); break; case ObTimestampTZType: nls_format = session->get_local_nls_timestamp_tz_format(); format_str = (force_use_standard_format ? ObTimeConverter::COMPAT_OLD_NLS_TIMESTAMP_TZ_FORMAT : (nls_format.empty() ? ObTimeConverter::DEFAULT_NLS_TIMESTAMP_TZ_FORMAT : nls_format)); break; default: ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected in_type", K(in_type), K(ret)); break; } } return ret; } static int common_int_datetime(const ObExpr &expr, const int64_t in_val, ObEvalCtx &ctx, ObDatum &res_datum) { int ret = OB_SUCCESS; GET_SESSION() { int64_t out_val = 0; int warning = OB_SUCCESS; if (0 > in_val) { ret = OB_INVALID_DATE_FORMAT; } else { ObDateSqlMode date_sql_mode; date_sql_mode.allow_invalid_dates_ = CM_IS_EXPLICIT_CAST(expr.extra_) ? false : CM_IS_ALLOW_INVALID_DATES(expr.extra_); date_sql_mode.no_zero_date_ = CM_IS_EXPLICIT_CAST(expr.extra_) ? false : CM_IS_NO_ZERO_DATE(expr.extra_); ObTimeConvertCtx cvrt_ctx(session->get_timezone_info(), ObTimestampType == expr.datum_meta_.type_); ret = ObTimeConverter::int_to_datetime(in_val, 0, cvrt_ctx, out_val, date_sql_mode); } if (CAST_FAIL(ret)) { LOG_WARN("int_datetime failed", K(ret)); } else { SET_RES_DATETIME(out_val); } } return ret; } static OB_INLINE int common_int_number(const ObExpr &expr, int64_t in_val, ObIAllocator &alloc, number::ObNumber &nmb) { int ret = OB_SUCCESS; int warning = OB_SUCCESS; ObObjType out_type = expr.datum_meta_.type_; if ((ObUNumberType == out_type) && CAST_FAIL(numeric_negative_check(in_val))) { LOG_WARN("numeric_negative_check faield", K(ret), K(in_val)); } else if (nmb.from(in_val, alloc)) { LOG_WARN("nmb.from failed", K(ret), K(in_val)); } return ret; } static OB_INLINE int common_int_date(const ObExpr &expr, const int64_t in_val, ObDatum &res_datum) { int ret = OB_SUCCESS; int warning = OB_SUCCESS; int32_t out_val = 0; ObDateSqlMode date_sql_mode; date_sql_mode.allow_invalid_dates_ = CM_IS_EXPLICIT_CAST(expr.extra_) ? false : CM_IS_ALLOW_INVALID_DATES(expr.extra_); date_sql_mode.no_zero_date_ = CM_IS_EXPLICIT_CAST(expr.extra_) ? false : CM_IS_NO_ZERO_DATE(expr.extra_); if (CAST_FAIL(ObTimeConverter::int_to_date(in_val, out_val, date_sql_mode))) { LOG_WARN("int_to_date failed", K(ret), K(in_val), K(out_val)); } else { SET_RES_DATE(out_val); } return ret; } static OB_INLINE int common_int_time(const ObExpr &expr, const int64_t in_val, ObDatum &res_datum) { int ret = OB_SUCCESS; int warning = OB_SUCCESS; int64_t out_val = 0; if (CAST_FAIL(ObTimeConverter::int_to_time(in_val, out_val))) { LOG_WARN("int_to_date failed", K(ret), K(in_val), K(out_val)); } else { SET_RES_TIME(out_val); } return ret; } static OB_INLINE int common_int_year(const ObExpr &expr, const int64_t in_val, ObDatum &res_datum, int &warning) { int ret = OB_SUCCESS; uint8_t out_val = 0; if (CAST_FAIL(ObTimeConverter::int_to_year(in_val, out_val))) { LOG_WARN("int_to_date failed", K(ret), K(in_val), K(out_val)); } else { SET_RES_YEAR(out_val); } return ret; } static OB_INLINE int common_int_year(const ObExpr &expr, const int64_t in_val, ObDatum &res_datum) { int warning = OB_SUCCESS; return common_int_year(expr, in_val, res_datum, warning); } static OB_INLINE int common_uint_int(const ObExpr &expr, const ObObjType &out_type, uint64_t in_val, ObEvalCtx &ctx, int64_t &out_val) { int ret = OB_SUCCESS; int warning = OB_SUCCESS; out_val = static_cast(in_val); UNUSED(ctx); if (CM_NEED_RANGE_CHECK(expr.extra_) && CAST_FAIL(int_upper_check(out_type, in_val, out_val))) { LOG_WARN("int_upper_check failed", K(ret), K(in_val), K(ctx)); } return ret; } static int common_string_int(const ObExpr &expr, const uint64_t &extra, const ObString &in_str, const bool is_str_integer_cast, ObDatum &res_datum, int &warning) { int ret = OB_SUCCESS; ObObjType in_type = expr.args_[0]->datum_meta_.type_; ObCollationType in_cs_type = expr.args_[0]->datum_meta_.cs_type_; ObObjType out_type = expr.datum_meta_.type_; int64_t out_val = 0; ret = common_string_integer(extra, in_type, in_cs_type, in_str, is_str_integer_cast, out_val); if (CAST_FAIL_CM(ret, extra)) { LOG_WARN("string_int failed", K(ret)); } else if (out_type < ObIntType && CAST_FAIL_CM(int_range_check(out_type, out_val, out_val), extra)) { LOG_WARN("int_range_check failed", K(ret)); } else { SET_RES_INT(out_val); } return ret; } static int common_string_int(const ObExpr &expr, const uint64_t &extra, const ObString &in_str, const bool is_str_integer_cast, ObDatum &res_datum) { int warning = OB_SUCCESS; return common_string_int(expr, extra, in_str, is_str_integer_cast, res_datum, warning); } static int common_string_uint(const ObExpr &expr, const ObString &in_str, const bool is_str_integer_cast, ObDatum &res_datum) { int ret = OB_SUCCESS; uint64_t out_val = 0; DEF_IN_OUT_TYPE(); ret = common_string_unsigned_integer(expr.extra_, in_type, expr.args_[0]->datum_meta_.cs_type_, in_str, is_str_integer_cast, out_val); if (CAST_FAIL(ret)) { LOG_WARN("string_int failed", K(ret)); } else if (out_type < ObUInt64Type && CM_NEED_RANGE_CHECK(expr.extra_) && CAST_FAIL(uint_upper_check(out_type, out_val))) { LOG_WARN("uint_upper_check failed", K(ret)); } else { SET_RES_UINT(out_val); } return ret; } int common_string_double(const ObExpr &expr, const ObObjType &in_type, const ObCollationType &in_cs_type, const ObObjType &out_type, const ObString &in_str, ObDatum &res_datum) { int ret = OB_SUCCESS; int warning = OB_SUCCESS; double out_val = 0.0; if (ObHexStringType == in_type) { out_val = static_cast(hex_to_uint64(in_str)); } else { int err = 0; char *endptr = NULL; out_val = ObCharset::strntodv2(in_str.ptr(), in_str.length(), &endptr, &err); if (EOVERFLOW == err && (-DBL_MAX == out_val || DBL_MAX == out_val)) { ret = OB_DATA_OUT_OF_RANGE; } else { ObString tmp_str = in_str; ObString trimed_str = tmp_str.trim(); if (lib::is_mysql_mode() && 0 == trimed_str.length()) { if (!CM_IS_COLUMN_CONVERT(expr.extra_)) { // mysql 模式下不在 convert_column 里遇到空字符串或者全是空格的字符串转 double 时,不报错 // skip } else { ret = OB_ERR_DOUBLE_TRUNCATED; LOG_WARN("convert string to double failed", K(ret), K(in_str)); } } else if (OB_FAIL(check_convert_str_err(in_str.ptr(), endptr, in_str.length(), err, in_cs_type))) { LOG_WARN("failed to check_convert_str_err", K(ret), K(in_str), K(out_val), K(err), K(in_cs_type)); ret = OB_ERR_DOUBLE_TRUNCATED; if (CM_IS_WARN_ON_FAIL(expr.extra_)) { LOG_USER_WARN(OB_ERR_DOUBLE_TRUNCATED, in_str.length(), in_str.ptr()); } } } } if (CAST_FAIL(ret)) { LOG_WARN("string_double failed", K(ret)); } else if (ObUDoubleType == out_type && CAST_FAIL(numeric_negative_check(out_val))) { LOG_WARN("numeric_negative_check failed", K(ret), K(out_val)); } else { SET_RES_DOUBLE(out_val); } LOG_DEBUG("common_string_double", K(ret), K(warning), K(out_val), K(in_str)); return ret; } static OB_INLINE int common_double_float(const ObExpr &expr, const double in_val, float &out_val) { int ret = OB_SUCCESS; int warning = OB_SUCCESS; out_val = static_cast(in_val); ObObjType out_type = expr.datum_meta_.type_; // oracle support float/double infiniy, no need to verify data overflow. // C language would cast value to infinity, which is correct behavor in oracle mode if (lib::is_mysql_mode() && CAST_FAIL(real_range_check(out_type, in_val, out_val))) { LOG_WARN("real_range_check failed", K(ret), K(in_val)); } return ret; } static OB_INLINE int common_string_float(const ObExpr &expr, const ObString &in_str, float &out_val) { int ret = OB_SUCCESS; double tmp_double = 0.0; ObDatum tmp_datum; tmp_datum.ptr_ = reinterpret_cast(&tmp_double); tmp_datum.pack_ = sizeof(double); DEF_IN_OUT_TYPE(); if (OB_FAIL(common_string_double(expr, in_type, expr.args_[0]->datum_meta_.cs_type_, out_type, in_str, tmp_datum))) { LOG_WARN("common_string_double failed", K(ret), K(in_str)); } else if (OB_FAIL(common_double_float(expr, tmp_double, out_val))) { LOG_WARN("common_double_float failed", K(ret), K(tmp_double)); } return ret; } static OB_INLINE int common_string_date(const ObExpr &expr, const ObString &in_str, ObDatum &res_datum) { int ret = OB_SUCCESS; int warning = OB_SUCCESS; int32_t out_val = 0; ObDateSqlMode date_sql_mode; date_sql_mode.allow_invalid_dates_ = CM_IS_ALLOW_INVALID_DATES(expr.extra_); date_sql_mode.no_zero_date_ = CM_IS_NO_ZERO_DATE(expr.extra_); if (CAST_FAIL(ObTimeConverter::str_to_date(in_str, out_val, date_sql_mode))) { LOG_WARN("str_to_date failed", K(ret), K(in_str)); } else if (CM_IS_ERROR_ON_SCALE_OVER(expr.extra_) && out_val == ObTimeConverter::ZERO_DATE) { // check zero date for scale over mode ret = OB_INVALID_DATE_VALUE; LOG_USER_ERROR(OB_INVALID_DATE_VALUE, in_str.length(), in_str.ptr(), ""); } else { SET_RES_DATE(out_val); } return ret; } static OB_INLINE int common_string_time(const ObExpr &expr, const ObString &in_str, ObDatum &res_datum) { int ret = OB_SUCCESS; int warning = OB_SUCCESS; int64_t out_val = 0; ObScale res_scale; // useless // support sqlmode TIME_TRUNCATE_FRACTIONAL const ObCastMode cast_mode = expr.extra_; bool need_truncate = CM_IS_COLUMN_CONVERT(cast_mode) ? CM_IS_TIME_TRUNCATE_FRACTIONAL(cast_mode) : false; if (CAST_FAIL(ObTimeConverter::str_to_time(in_str, out_val, &res_scale, need_truncate))) { LOG_WARN("str_to_time failed", K(ret), K(in_str)); } else { SET_RES_TIME(out_val); } return ret; } static OB_INLINE int common_string_year(const ObExpr &expr, const ObString &in_str, ObDatum &res_datum) { int ret = OB_SUCCESS; int warning = OB_SUCCESS; const bool is_str_int_cast = false; // eg: insert into t1(col_year) values('201a'); // will give out of range error by common_int_year(because in_val is 201, invalid year) // so need to unset warn on fail when do string_int cast. const uint64_t extra = CM_UNSET_STRING_INTEGER_TRUNC(CM_SET_WARN_ON_FAIL(expr.extra_)); // datum size of year type is one byte! int64_t tmp_int = 0; ObDatum tmp_res; tmp_res.int_ = &tmp_int; tmp_res.pack_ = sizeof(tmp_int); if (OB_FAIL(common_string_int(expr, extra, in_str, is_str_int_cast, tmp_res, warning))) { LOG_WARN("common_string_int failed", K(ret), K(in_str)); } else if (0 == tmp_int) { // cast '0000' to year, result is 0. cast '0'/'00'/'00000' to year, result is 2000. if (OB_SUCCESS != warning || 4 == in_str.length()) { SET_RES_YEAR(ObTimeConverter::ZERO_YEAR); } else { const uint8_t base_year = 100; SET_RES_YEAR(base_year); } CAST_FAIL(warning); } else { if (CAST_FAIL(common_int_year(expr, tmp_int, res_datum, warning))) { LOG_WARN("common_int_year failed", K(ret), K(tmp_int)); } else { int tmp_warning = warning; UNUSED(CAST_FAIL(tmp_warning)); } } return ret; } static OB_INLINE int common_string_number(const ObExpr &expr, const ObString &in_str, ObIAllocator &alloc, number::ObNumber &nmb) { int ret = OB_SUCCESS; DEF_IN_OUT_TYPE(); if (ObHexStringType == in_type) { ret = nmb.from(hex_to_uint64(in_str), alloc); } else if (0 == in_str.length()) { // in mysql mode, this err will be ignored(because default cast_mode is WARN_ON_FAIL) nmb.set_zero(); ret = OB_ERR_TRUNCATED_WRONG_VALUE_FOR_FIELD; } else { ObPrecision res_precision; // useless ObScale res_scale; ret = nmb.from_sci_opt(in_str.ptr(), in_str.length(), alloc, &res_precision, &res_scale); // bug: 4263211. 兼容mysql string转number超过最值域范围的行为 // select cast('1e500' as decimal); -> max_val // select cast('-1e500' as decimal); -> min_val if (OB_NUMERIC_OVERFLOW == ret) { int64_t i = 0; while (i < in_str.length() && isspace(in_str[i])) { ++i; } bool is_neg = (in_str[i] == '-'); int tmp_ret = OB_SUCCESS; const ObAccuracy &def_acc = ObAccuracy::DDL_DEFAULT_ACCURACY2[0][out_type]; const ObPrecision prec = def_acc.get_precision(); const ObScale scale = def_acc.get_scale(); const number::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 = nmb.from(*bound_num, alloc))) { LOG_WARN("copy min number failed", K(ret), K(tmp_ret), KPC(bound_num)); } } } const ObCastMode cast_mode = expr.extra_; if (CAST_FAIL(ret)) { LOG_WARN("string_number failed", K(ret), K(in_type), K(out_type), K(cast_mode), K(in_str)); } else if (ObUNumberType == out_type && CAST_FAIL(numeric_negative_check(nmb))) { LOG_WARN("numeric_negative_check failed", K(ret), K(in_type), K(cast_mode), K(in_str)); } return ret; } static OB_INLINE int common_string_datetime(const ObExpr &expr, const ObString &in_str, ObEvalCtx &ctx, ObDatum &res_datum) { int ret = OB_SUCCESS; int warning = OB_SUCCESS; int64_t out_val = 0; GET_SESSION() { const ObCastMode cast_mode = expr.extra_; bool need_truncate = CM_IS_COLUMN_CONVERT(cast_mode) ? CM_IS_TIME_TRUNCATE_FRACTIONAL(cast_mode) : false; ObTimeConvertCtx cvrt_ctx(session->get_timezone_info(), ObTimestampType == expr.datum_meta_.type_, need_truncate); if (lib::is_oracle_mode()) { if (OB_FAIL(common_get_nls_format(session, expr.datum_meta_.type_, CM_IS_FORCE_USE_STANDARD_NLS_FORMAT(expr.extra_), cvrt_ctx.oracle_nls_format_))) { LOG_WARN("common_get_nls_format failed", K(ret)); } else if (CAST_FAIL(ObTimeConverter::str_to_date_oracle(in_str, cvrt_ctx, out_val))) { LOG_WARN("str_to_date_oracle failed", K(ret)); } } else { ObScale res_scale; // useless ObDateSqlMode date_sql_mode; date_sql_mode.allow_invalid_dates_ = CM_IS_ALLOW_INVALID_DATES(expr.extra_); date_sql_mode.no_zero_date_ = CM_IS_NO_ZERO_DATE(expr.extra_); if (CAST_FAIL(ObTimeConverter::str_to_datetime(in_str, cvrt_ctx, out_val, &res_scale, date_sql_mode))) { LOG_WARN("str_to_datetime failed", K(ret), K(in_str)); } else { // check zero date for scale over mode if (CM_IS_ERROR_ON_SCALE_OVER(expr.extra_) && (out_val == ObTimeConverter::ZERO_DATE || out_val == ObTimeConverter::ZERO_DATETIME)) { ret = OB_INVALID_DATE_VALUE; LOG_USER_ERROR(OB_INVALID_DATE_VALUE, in_str.length(), in_str.ptr(), ""); } } } if (OB_SUCC(ret)) { SET_RES_DATETIME(out_val); } } return ret; } static OB_INLINE int common_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; } static int common_string_bit(const ObExpr &expr, const ObString &in_str, ObEvalCtx &ctx, ObDatum &res_datum) { int ret = OB_SUCCESS; UNUSED(ctx); int warning = OB_SUCCESS; int32_t bit_len = 0; if (OB_FAIL(common_get_bit_len(in_str, bit_len))) { LOG_WARN("common_get_bit_len failed", K(ret)); } else { ObObjType in_type = expr.args_[0]->datum_meta_.type_; uint64_t out_val = 0; if (ObHexStringType == in_type && in_str.empty()) { ret = OB_ERR_TRUNCATED_WRONG_VALUE_FOR_FIELD; LOG_WARN("hex string is empty, can't cast to bit", K(ret), K(in_str)); } else if (bit_len > OB_MAX_BIT_LENGTH) { out_val = UINT64_MAX; ret = OB_ERR_DATA_TOO_LONG; LOG_WARN("bit type length is too long", K(ret), K(in_str), K(OB_MAX_BIT_LENGTH), K(bit_len)); } else { //将str按照二进制值转换为相应的uint64 out_val = hex_to_uint64(in_str); } if (OB_FAIL(ret) && CM_IS_WARN_ON_FAIL(expr.extra_)) { warning = OB_DATA_OUT_OF_RANGE; ret = OB_SUCCESS; } if (OB_SUCC(ret)) { SET_RES_BIT(out_val); } } return ret; } // lob类型和其他类型互相转换时,会把longtext类型作为中间类型,并且调用一些原有的longtext相关的转换函数 // 这些函数把转换结果放到了get_str_res_mem, 也就是string类型的表达式存放结果的地方。 // 因此添加了下面这个函数,把结果先从get_str_res_mem拷贝到get_reset_tmp_alloc空间中。 int copy_datum_str_with_tmp_alloc(ObEvalCtx &ctx, ObDatum &res_datum, ObString &res_str) { int ret = OB_SUCCESS; ObEvalCtx::TempAllocGuard alloc_guard(ctx); ObIAllocator &calc_alloc = alloc_guard.get_allocator(); char *tmp_res = NULL; const ObString str = res_datum.get_string(); if (0 == str.length()) { res_str.assign_ptr(NULL, 0); } else if (OB_ISNULL(tmp_res = static_cast(calc_alloc.alloc(str.length())))) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("allocate memory failed", K(ret)); } else { MEMMOVE(tmp_res, str.ptr(), str.length()); res_str.assign_ptr(tmp_res, str.length()); } return ret; } int common_check_convert_string(const ObExpr &expr, ObEvalCtx &ctx, const ObString &in_str, ObDatum &res_datum, bool &has_set_res) { int ret = OB_SUCCESS; ObObjType out_type = expr.datum_meta_.type_; ObCollationType out_cs_type = expr.datum_meta_.cs_type_; ObObjType in_type = expr.args_[0]->datum_meta_.type_; ObCollationType in_cs_type = expr.args_[0]->datum_meta_.cs_type_; if (lib::is_oracle_mode() && (ob_is_blob(out_type, out_cs_type) || ob_is_blob_locator(out_type, out_cs_type)) && !(ob_is_blob(in_type, in_cs_type) || ob_is_blob_locator(in_type, in_cs_type) || ob_is_raw(in_type))) { // !blob -> blob if (ObCharType == in_type || ObVarcharType == in_type) { if (OB_FAIL(ObDatumHexUtils::hextoraw_string(expr, in_str, ctx, res_datum, has_set_res))) { LOG_WARN("fail to hextoraw_string for blob", K(ret), K(in_str)); } } else { ret = OB_NOT_SUPPORTED; LOG_ERROR("invalid use of blob type", K(ret), K(in_str), K(out_type)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "cast to blob type"); } } else { // When convert blob/binary/varbinary to other charset, need to align to mbminlen of destination charset // by add '\0' prefix in mysql mode. (see mysql String::copy) const ObCharsetInfo *cs = NULL; int64_t align_offset = 0; if (CS_TYPE_BINARY == in_cs_type && lib::is_mysql_mode() && (NULL != (cs = ObCharset::get_charset(out_cs_type)))) { if (cs->mbminlen > 0 && in_str.length() % cs->mbminlen != 0) { align_offset = cs->mbminlen - in_str.length() % cs->mbminlen; } } if (OB_FAIL(common_copy_string_zf(expr, in_str, ctx, res_datum, align_offset))) { LOG_WARN("common_copy_string_zf failed", K(ret), K(in_str)); } } return ret; } static int common_string_string(const ObExpr &expr, const ObObjType in_type, const ObCollationType in_cs_type, const ObObjType out_type, const ObCollationType out_cs_type, const ObString &in_str, ObEvalCtx &ctx, ObDatum &res_datum, bool& has_set_res) { int ret = OB_SUCCESS; if (lib::is_oracle_mode() && ob_is_clob(in_type, in_cs_type) && (0 == in_str.length()) && !ob_is_clob(out_type, out_cs_type)) { // oracle 模式下的 empty_clob 被 cast 成其他类型时结果是 NULL res_datum.set_null(); } else if (CS_TYPE_BINARY != in_cs_type && CS_TYPE_BINARY != out_cs_type && (ObCharset::charset_type_by_coll(in_cs_type) != ObCharset::charset_type_by_coll(out_cs_type))) { // handle !blob->!blob char *buf = NULL; //latin1 1bytes,utf8mb4 4bytes,the factor should be 4 int64_t buf_len = in_str.length() * ObCharset::CharConvertFactorNum; uint32_t result_len = 0; buf = expr.get_str_res_mem(ctx, buf_len); if (OB_ISNULL(buf)) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("alloc memory failed", K(ret)); } else if (OB_FAIL(ObCharset::charset_convert(in_cs_type, in_str.ptr(), in_str.length(), out_cs_type, buf, buf_len, result_len))) { if (CM_IS_IGNORE_CHARSET_CONVERT_ERR(expr.extra_)) { ObString question_mark = ObCharsetUtils::get_const_str(out_cs_type, '?'); int32_t str_offset = 0; int64_t buf_offset = 0; while (str_offset < in_str.length() && buf_offset + question_mark.length() <= buf_len) { int64_t offset = ObCharset::charpos(in_cs_type, in_str.ptr() + str_offset, in_str.length() - str_offset, 1); if (OB_UNLIKELY(0 == offset)) { break; } ret = ObCharset::charset_convert(in_cs_type, in_str.ptr() + str_offset, offset, out_cs_type, 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 (buf_offset > buf_len) { ret = OB_ERR_UNEXPECTED; LOG_WARN("buf_offset > buf_len, unexpected", K(ret)); } else { result_len = buf_offset; ret = OB_SUCCESS; LOG_WARN("charset convert failed", K(ret), K(in_cs_type), K(out_cs_type)); res_datum.set_string(buf, result_len); } } } else { res_datum.set_string(buf, result_len); } } else { if (CS_TYPE_BINARY == in_cs_type || CS_TYPE_BINARY == out_cs_type) { // just copy string when in_cs_type or out_cs_type is binary if (OB_FAIL(common_check_convert_string(expr, ctx, in_str, res_datum, has_set_res))) { LOG_WARN("fail to common_check_convert_string", K(ret), K(in_str)); } } else if (lib::is_oracle_mode() && ob_is_clob(in_type, in_cs_type)) { res_datum.set_string(in_str.ptr(), in_str.length()); } else if (lib::is_oracle_mode() && ob_is_clob(out_type, out_cs_type)) { res_datum.set_string(in_str.ptr(), in_str.length()); } else { ret = OB_ERR_UNEXPECTED; LOG_WARN("same charset should not be here, just use cast_eval_arg", K(ret), K(in_type), K(out_type), K(in_cs_type), K(out_cs_type)); } } LOG_DEBUG("string_string cast", K(ret), K(in_str), K(ObString(res_datum.len_, res_datum.ptr_))); return ret; } static int common_string_otimestamp(const ObExpr &expr, const ObString &in_str, ObEvalCtx &ctx, ObDatum &res_datum) { int ret = OB_SUCCESS; GET_SESSION() { int warning = OB_SUCCESS; ObOTimestampData out_val; ObTimeConvertCtx cvrt_ctx(session->get_timezone_info(), true); ObScale res_scale = 0; // useless if (OB_FAIL(common_get_nls_format(session, expr.datum_meta_.type_, CM_IS_FORCE_USE_STANDARD_NLS_FORMAT(expr.extra_), cvrt_ctx.oracle_nls_format_))) { LOG_WARN("common_get_nls_format failed", K(ret)); } else if (CAST_FAIL(ObTimeConverter::str_to_otimestamp(in_str, cvrt_ctx, expr.datum_meta_.type_, out_val, res_scale))) { LOG_WARN("str_to_otimestamp failed", K(ret), K(in_str)); } else { if (ObTimestampTZType == expr.datum_meta_.type_) { SET_RES_OTIMESTAMP(out_val); } else { SET_RES_OTIMESTAMP_10BYTE(out_val); } } } return ret; } static int common_string_interval(const ObExpr &expr, const ObString &in_str, ObEvalCtx &ctx, ObDatum &res_datum) { int ret = OB_SUCCESS; UNUSED(ctx); int warning = OB_SUCCESS; ObObjType out_type = expr.datum_meta_.type_; if (ObIntervalYMType == out_type) { ObIntervalYMValue out_val; //don't know the scale, use the max scale and return the real scale ObScale res_scale = ObAccuracy::MAX_ACCURACY2[ORACLE_MODE][ObIntervalYMType].get_scale(); if (CAST_FAIL(ObTimeConverter::str_to_interval_ym(in_str, out_val, res_scale))) { LOG_WARN("str_to_interval_ym failed", K(ret), K(in_str)); } else { SET_RES_INTERVAL_YM(out_val.nmonth_); } } else { ObIntervalDSValue out_val; //don't know the scale, use the max scale and return the real scale ObScale res_scale = ObAccuracy::MAX_ACCURACY2[ORACLE_MODE][ObIntervalDSType].get_scale(); if (CAST_FAIL(ObTimeConverter::str_to_interval_ds(in_str, out_val, res_scale))) { LOG_WARN("str_to_interval_ds failed", K(ret), K(in_str)); } else { SET_RES_INTERVAL_DS(out_val); } } return ret; } static int common_string_rowid(const ObExpr &expr, const ObString &base64_str, ObEvalCtx &ctx, ObDatum &res_datum) { int ret = OB_SUCCESS; ObURowIDData urowid_data; ObExprStrResAlloc alloc(expr, ctx); // TODO(lihongqin.lhq): distinguish between rowid and urowid. if (OB_FAIL(ObURowIDData::decode2urowid(base64_str.ptr(), base64_str.length(), alloc, urowid_data))) { LOG_WARN("failed to decode to urowid", K(ret)); } else { res_datum.set_urowid(urowid_data); } return ret; } static int common_string_lob(const ObExpr &expr, const ObString &in_str, ObEvalCtx &ctx, const ObLobLocator *lob_locator, ObDatum &res_datum) { int ret = OB_SUCCESS; ObObjType in_type = expr.args_[0]->datum_meta_.type_; ObObjType out_type = ObLongTextType; ObCollationType in_cs_type = expr.args_[0]->datum_meta_.cs_type_; ObCollationType out_cs_type = expr.datum_meta_.cs_type_; bool has_set_res = false; if (OB_FAIL(common_string_string(expr, in_type, in_cs_type, out_type, out_cs_type, in_str, ctx, res_datum, has_set_res))) { LOG_WARN("fail to cast string to longtext", K(ret), K(in_str), K(expr)); } else if (res_datum.is_null()) { // do nothing } else { ObString res_str; if (OB_FAIL(copy_datum_str_with_tmp_alloc(ctx, res_datum, res_str))) { LOG_WARN("copy datum str with tmp alloc", K(ret)); } else { char *buf = nullptr; ObLobLocator *result = nullptr; const int64_t buf_len = sizeof(ObLobLocator) + (NULL == lob_locator ? 0 : lob_locator->payload_offset_) + res_str.length(); if (OB_ISNULL(buf = expr.get_str_res_mem(ctx, buf_len))) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("Failed to allocate memory for lob locator", K(ret), K(buf_len)); } else if (FALSE_IT(result = reinterpret_cast (buf))) { } else if (NULL == lob_locator || lob_locator->is_fake_locator()) { if (OB_FAIL(result->init(res_str))) { STORAGE_LOG(WARN, "Failed to init lob locator", K(ret), K(res_str), KPC(result)); } } else if (NULL != lob_locator) { ObString rowid; 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, res_str))) { STORAGE_LOG(WARN, "Failed to init lob locator", K(ret), K(res_str), KPC(result)); } } if (OB_SUCC(ret)) { res_datum.set_lob_locator(*result); } } } return ret; } static int get_text_full_data(const sql::ObExpr &expr, sql::ObEvalCtx &ctx, ObIAllocator *allocator, ObDatum* in_datum, ObString &data) { int ret = OB_SUCCESS; ObObjType in_type = expr.args_[0]->datum_meta_.type_; ObCollationType in_cs_type = expr.args_[0]->datum_meta_.cs_type_; if (ob_is_text_tc(in_type)) { bool has_lob_header = expr.args_[0]->obj_meta_.has_lob_header(); ObTextStringIter instr_iter(in_type, in_cs_type, in_datum->get_string(), has_lob_header); if (OB_FAIL(instr_iter.init(0, ctx.exec_ctx_.get_my_session(), allocator))) { LOG_WARN("Lob: init lob str iter failed", K(ret), K(in_type), K(*in_datum)); } else if (OB_FAIL(instr_iter.get_full_data(data))) { LOG_WARN("Lob: get lob str iter full data failed ", K(ret), K(in_type), K(*in_datum)); } else {/* do nothing */} } return ret; } static int common_copy_string_to_text_result(const ObExpr &expr, const ObString &src, ObEvalCtx &ctx, ObDatum &res_datum, const int64_t align_offset = 0) { int ret = OB_SUCCESS; char *out_ptr = NULL; int64_t len = align_offset + src.length(); ObTextStringDatumResult str_result(expr.datum_meta_.type_, &expr, &ctx, &res_datum); if (OB_FAIL(str_result.init(len))) { LOG_WARN("Lob: init lob result failed"); } else if (align_offset > 0) { if (OB_FAIL(str_result.fill(0, 0, align_offset))) { } else if (OB_FAIL(str_result.lseek(align_offset, 0))) { } else { /* do nothing */ }; } if (OB_FAIL(ret)) { } else if (OB_FAIL(str_result.append(src.ptr(), len - align_offset))) { LOG_WARN("Lob: append data to temp lob failed"); } else { str_result.set_result(); // fillzero is padding before numbers, not padding after,e.g. 0050 } return ret; } static int common_copy_string_zf_to_text_result(const ObExpr &expr, const ObString &src, ObEvalCtx &ctx, ObDatum &res_datum, const int64_t align_offset = 0) { int ret = OB_SUCCESS; int64_t out_len = static_cast(expr.datum_meta_.scale_); if (out_len <= 0) { ret = OB_ERR_UNEXPECTED; LOG_WARN("Lob: unexpected zf length", K(ret), K(out_len), K(expr.datum_meta_.scale_)); } else if (CM_IS_ZERO_FILL(expr.extra_) && out_len > src.length()) { ObTextStringDatumResult str_result(expr.datum_meta_.type_, &expr, &ctx, &res_datum); if (OB_FAIL(str_result.init(out_len))) { LOG_WARN("Lob: init lob result failed"); } else { int64_t zf_len = out_len - src.length(); if (0 < zf_len) { if (OB_FAIL(str_result.fill(0, '0', zf_len))) { } else if (OB_FAIL(str_result.lseek(zf_len, 0))) { } else { /* do nothing */ }; } if (OB_FAIL(ret)) { } else if (OB_FAIL(str_result.append(src.ptr(), src.length()))) { LOG_WARN("Lob: append data to temp lob failed"); } else { str_result.set_result(); } } } else { if (OB_FAIL(common_copy_string_to_text_result(expr, src, ctx, res_datum, align_offset))) { LOG_WARN("Lob: common_copy_string_zf_to_text_result failed", K(ret), K(src), K(expr), K(ctx)); } } return ret; } static void string_lob_debug(ObObjType in_type, ObCollationType in_cs, bool has_lob_header, ObObjType out_type, ObCollationType out_cs, ObString &res_str, ObDatum &res_datum, int in_ret) { int ret = OB_SUCCESS; if (!ob_enable_datum_cast_debug_log()) { } else if (OB_FAIL(in_ret)) { LOG_WARN("Lob: string to lob failed", K(in_type), K(out_type), K(in_ret)); } else if (res_datum.get_string().length() == 0) { LOG_WARN("Lob: empty result in string to lob", K(in_type), K(out_type), K(res_str), K(res_datum.get_string())); } else { ObString tmp; ObString lobinrow_data; tmp.assign_ptr(res_datum.get_string().ptr(), res_datum.get_string().length()); ObLobLocatorV2 loc(tmp, has_lob_header); loc.get_inrow_data(lobinrow_data); LOG_WARN("Lob: string to lob", K(in_type), K(out_type), K(res_str), K(lobinrow_data)); } } static void lob_string_debug(ObObjType in_type, ObCollationType in_cs, ObObjType out_type, ObCollationType out_cs, ObString &in_string, ObDatum &res_datum, int in_ret) { int ret = OB_SUCCESS; if (!ob_enable_datum_cast_debug_log()) { } else if (OB_FAIL(in_ret)) { LOG_WARN("Lob: string to lob failed", K(in_type), K(out_type), K(in_ret)); } else if (in_string.length() == 0) { LOG_WARN("Lob: empty result in string to lob", K(in_type), K(out_type), K(in_string), K(res_datum.get_string())); } else { LOG_WARN("Lob: string to lob", K(in_type), K(out_type), K(res_datum.get_string()), K(in_string)); } } static int common_string_text(const ObExpr &expr, const ObString &in_str, ObEvalCtx &ctx, const ObLobLocatorV2 *lob_locator, ObDatum &res_datum) { int ret = OB_SUCCESS; ObObjType in_type = expr.args_[0]->datum_meta_.type_; ObObjType out_type = expr.datum_meta_.type_; // ObLongTextType ObCollationType in_cs_type = expr.args_[0]->datum_meta_.cs_type_; ObCollationType out_cs_type = expr.datum_meta_.cs_type_; ObString res_str = in_str; bool is_final_res = false; bool is_different_charset_type = (ObCharset::charset_type_by_coll(in_cs_type) != ObCharset::charset_type_by_coll(out_cs_type)); OB_ASSERT(ob_is_text_tc(out_type)); if (is_different_charset_type) { if (OB_FAIL(common_string_string(expr, in_type, in_cs_type, out_type, out_cs_type, in_str, ctx, res_datum, is_final_res))) { LOG_WARN("Lob: fail to cast string to longtext", K(ret), K(in_str), K(expr)); } else if (res_datum.is_null()) { // only for blob cast to other types in oracle mode, in/out type/collation type must be different. is_final_res = true; } else if (is_final_res) { // is_final_res = true; // hex to text } else if (OB_FAIL(copy_datum_str_with_tmp_alloc(ctx, res_datum, res_str))) { LOG_WARN("Lob: copy datum str with tmp alloc", K(ret)); } else { /* do nothing */ } } if (OB_SUCC(ret) && !is_final_res) { ObTextStringDatumResult str_result(expr.datum_meta_.type_, &expr, &ctx, &res_datum); if (lob_locator == NULL) { if (OB_FAIL(str_result.init(res_str.length()))) { LOG_WARN("Lob: init lob result failed"); } else if (OB_FAIL(str_result.append(res_str.ptr(), res_str.length()))) { LOG_WARN("Lob: append lob result failed"); } else { /* do nothing */ } } else if (OB_FAIL(str_result.copy(lob_locator))) { LOG_WARN("Lob: copy lob result failed"); } else { /* do nothing*/ } str_result.set_result(); } string_lob_debug(in_type, in_cs_type, expr.obj_meta_.has_lob_header(), out_type, out_cs_type, res_str, res_datum, ret); return ret; } static int common_uint_bit(const ObExpr &expr, const uint64_t &in_value, ObEvalCtx &ctx, ObDatum &res_datum) { int ret = OB_SUCCESS; int warning = OB_SUCCESS; UNUSED(expr); UNUSED(ctx); int32_t bit_len = 0; if (OB_FAIL(get_bit_len(in_value, bit_len))) { LOG_WARN("fail to get bit len", K(ret), K(in_value), K(bit_len)); } else { uint64_t out_val = in_value; SET_RES_BIT(out_val); } return ret; } static OB_INLINE int common_number_uint(const ObExpr &expr, const ObDatum &child_res, ObDatum &res_datum) { int ret = OB_SUCCESS; const number::ObNumber nmb(child_res.get_number()); const char *nmb_buf = nmb.format(); if (OB_ISNULL(nmb_buf)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("nmb_buf is NULL", K(ret)); } else { ObString num_str(strlen(nmb_buf), nmb_buf); const bool is_str_int_cast = false; if (OB_FAIL(common_string_uint(expr, num_str, is_str_int_cast, res_datum))) { LOG_WARN("common_string_uint failed", K(ret), K(num_str)); } } return ret; } static OB_INLINE int common_number_string(const ObExpr &expr, const ObDatum &child_res, ObEvalCtx &ctx, ObDatum &res_datum) { int ret = OB_SUCCESS; const number::ObNumber nmb(child_res.get_number()); char buf[OB_CAST_TO_VARCHAR_MAX_LENGTH] = {0}; ObScale in_scale = expr.args_[0]->datum_meta_.scale_; int64_t len = 0; if (lib::is_oracle_mode() && CM_IS_FORMAT_NUMBER_WITH_LIMIT(expr.extra_)) { if (OB_FAIL(nmb.format_with_oracle_limit(buf, sizeof(buf), len, in_scale))) { LOG_WARN("fail to format", K(ret), K(nmb)); } } else { if (OB_FAIL(nmb.format(buf, sizeof(buf), len, in_scale))) { LOG_WARN("fail to format", K(ret), K(nmb)); } } if (OB_SUCC(ret)) { ObString in_str(len, buf); bool has_set_res = false; if (OB_FAIL(common_check_convert_string(expr, ctx, in_str, res_datum, has_set_res))) { LOG_WARN("fail to common_check_convert_string", K(ret), K(in_str)); } } return ret; } static int common_json_string(const ObExpr &expr, ObEvalCtx &ctx, ObIAllocator& allocator, const ObDatum &in, ObString& res_str) { int ret = OB_SUCCESS; int warning = OB_SUCCESS; ObCastMode cast_mode = expr.extra_; ObString j_bin_str = in.get_string(); if (OB_FAIL(ObTextStringHelper::read_real_string_data(allocator, in, expr.args_[0]->datum_meta_, expr.args_[0]->obj_meta_.has_lob_header(), j_bin_str))) { LOG_WARN("fail to get real data.", K(ret), K(j_bin_str)); } else { ObJsonBin j_bin(j_bin_str.ptr(), j_bin_str.length()); ObIJsonBase *j_base = &j_bin; ObJsonBuffer j_buf(&allocator); ObString j_str; bool has_set_res = false; // get json string if (OB_FAIL(j_bin.reset_iter())) { LOG_WARN("failed to reset json bin iter", K(ret), K(j_bin_str)); } else if (CAST_FAIL(j_base->print(j_buf, true))) { LOG_WARN("fail to convert json to string", K(ret), K(j_bin_str)); ret = OB_ERR_INVALID_JSON_VALUE_FOR_CAST; LOG_USER_ERROR(OB_ERR_INVALID_JSON_VALUE_FOR_CAST); } else { j_str.assign_ptr(j_buf.ptr(), j_buf.length()); // convert charset if nesscary ObObjType in_type = ObLongTextType; ObObjType out_type = expr.datum_meta_.type_; ObCollationType in_cs_type = expr.args_[0]->datum_meta_.cs_type_; ObCollationType out_cs_type = expr.datum_meta_.cs_type_; // if out not binary but charset not same, convert bool is_need_charset_convert = ((CS_TYPE_BINARY != out_cs_type) && (ObCharset::charset_type_by_coll(in_cs_type) != ObCharset::charset_type_by_coll(out_cs_type))); if (!is_need_charset_convert) { res_str = j_str; } else { ObDatum tmp_datum; if (OB_FAIL(common_string_string(expr, in_type, in_cs_type, out_type, out_cs_type, j_str, ctx, tmp_datum, has_set_res))) { LOG_WARN("fail charset convert", K(ret), K(j_str), K(expr)); } else if (tmp_datum.is_null()) { // do nothing } else if (OB_FAIL(copy_datum_str_with_tmp_alloc(ctx, tmp_datum, res_str))) { LOG_WARN("copy datum str with tmp alloc", K(ret)); } } } } return ret; } static const double ROUND_DOUBLE = 0.5; template static OB_INLINE int common_floating_int(IN_TYPE &in_val, OUT_TYPE &out_val) { int ret = OB_SUCCESS; out_val = 0; if (in_val < 0) { out_val = static_cast(in_val - ROUND_DOUBLE); } else if (in_val > 0) { out_val = static_cast(in_val + ROUND_DOUBLE); } else { out_val = static_cast(in_val); } return ret; } template static int common_floating_number(const IN_TYPE in_val, const ob_gcvt_arg_type arg_type, ObIAllocator &alloc, number::ObNumber &number) { int ret = OB_SUCCESS; char buf[MAX_DOUBLE_STRICT_PRINT_SIZE]; MEMSET(buf, 0, MAX_DOUBLE_STRICT_PRINT_SIZE); int64_t length = 0; if (lib::is_oracle_mode() || OB_GCVT_ARG_DOUBLE == arg_type) { length = ob_gcvt_opt(in_val, arg_type, static_cast(sizeof(buf) - 1), buf, NULL, lib::is_oracle_mode(), TRUE); } else { length = ob_gcvt(in_val, OB_GCVT_ARG_DOUBLE, sizeof(buf) - 1, buf, NULL); } ObString str(sizeof(buf), static_cast(length), buf); ObScale res_scale; // useless ObPrecision res_precision; if (OB_FAIL(number.from_sci_opt(str.ptr(), str.length(), alloc, &res_precision, &res_scale))) { LOG_WARN("fail to from str to number", K(ret), K(str)); } return ret; } template static bool is_ieee754_nan_inf(const IN_TYPE in_val, char buf[], int64_t &length) { bool is_nan_inf = true; if (lib::is_oracle_mode()) { // buf size is 256, nan or infinity string length is no more than 4 bytes. // Never hit overflow if (in_val == -INFINITY) { length = strlen("-Inf"); strncpy(buf, "-Inf", length); } else if (in_val == INFINITY) { length = strlen("Inf"); strncpy(buf, "Inf", length); } else if (isnan(in_val)) { length = strlen("Nan"); strncpy(buf, "Nan", length); } else { is_nan_inf = false; } } else { is_nan_inf = false; } return is_nan_inf; } template static int common_floating_string(const ObExpr &expr, const IN_TYPE in_val, const ob_gcvt_arg_type arg_type, ObEvalCtx &ctx, ObDatum &res_datum) { int ret = OB_SUCCESS; char buf[OB_CAST_TO_VARCHAR_MAX_LENGTH] = {0}; int64_t length = 0; ObScale scale = expr.args_[0]->datum_meta_.scale_; bool nan_or_inf = is_ieee754_nan_inf(in_val, buf, length); if (nan_or_inf) { LOG_DEBUG("Infinity or NaN value is", K(in_val)); } else { if (0 <= scale) { length = ob_fcvt(in_val, scale, sizeof(buf) - 1, buf, NULL); } else { length = ob_gcvt_opt(in_val, arg_type, static_cast(sizeof(buf) - 1), buf, NULL, lib::is_oracle_mode(), TRUE); } } ObString in_str(sizeof(buf), static_cast(length), buf); bool has_set_res = false; if (OB_FAIL(common_check_convert_string(expr, ctx, in_str, res_datum, has_set_res))) { LOG_WARN("fail to common_check_convert_string", K(ret), K(in_str)); } return ret; } static int common_number_datetime(const number::ObNumber nmb, const ObTimeConvertCtx &cvrt_ctx, int64_t &out_val, const ObCastMode cast_mode); static OB_INLINE int common_double_datetime(const ObExpr &expr, const double val_double, ObEvalCtx &ctx, ObDatum &res_datum) { int ret = OB_SUCCESS; int warning = OB_SUCCESS; ObBasicSessionInfo *session = ctx.exec_ctx_.get_my_session(); if (OB_ISNULL(session)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("session is NULL", K(ret)); } else { int64_t out_val = 0; ObObjType out_type = expr.datum_meta_.type_; ObTimeConvertCtx cvrt_ctx(session->get_timezone_info(), ObTimestampType == out_type); ObNumStackOnceAlloc tmp_alloc; number::ObNumber number; if (OB_FAIL(common_floating_number(val_double, OB_GCVT_ARG_DOUBLE, tmp_alloc, number))) { LOG_WARN("cast float to number failed", K(ret), K(expr.extra_)); if (CM_IS_WARN_ON_FAIL(expr.extra_)) { ret = OB_SUCCESS; if (CM_IS_ZERO_ON_WARN(expr.extra_)) { res_datum.set_datetime(ObTimeConverter::ZERO_DATETIME); } else { res_datum.set_null(); } } else { ret = OB_INVALID_DATE_VALUE; } } else { ret = common_number_datetime(number, cvrt_ctx, out_val, expr.extra_); if (CAST_FAIL(ret)) { LOG_WARN("str_to_datetime failed", K(ret)); } else { SET_RES_DATETIME(out_val); } } } return ret; } static int common_double_time(const ObExpr &expr, const double val_double, ObDatum &res_datum) { int ret = OB_SUCCESS; int warning = OB_SUCCESS; int64_t out_val = 0; char buf[MAX_DOUBLE_PRINT_SIZE]; MEMSET(buf, 0, MAX_DOUBLE_PRINT_SIZE); int64_t length = ob_gcvt(val_double, OB_GCVT_ARG_DOUBLE, sizeof(buf) - 1, buf, NULL); ObString str(sizeof(buf), static_cast(length), buf); ObScale res_scale; if (CAST_FAIL(ObTimeConverter::str_to_time(str, out_val, &res_scale))) { LOG_WARN("str_to_time failed", K(ret)); } else { SET_RES_TIME(out_val); } return ret; } int common_datetime_string(const ObObjType in_type, const ObObjType out_type, const ObScale in_scale, bool force_use_std_nls_format, const int64_t in_val, ObEvalCtx &ctx, char *buf, int64_t buf_len, int64_t &out_len) { int ret = OB_SUCCESS; UNUSED(out_type); ObBasicSessionInfo *session = ctx.exec_ctx_.get_my_session(); if (OB_ISNULL(session)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("session is NULL", K(ret)); } else { const ObTimeZoneInfo *tz_info = (ObTimestampType == in_type) ? session->get_timezone_info() : NULL; ObString nls_format; if (lib::is_oracle_mode() && !force_use_std_nls_format) { if (OB_FAIL(common_get_nls_format(session, in_type, force_use_std_nls_format, nls_format))) { LOG_WARN("common_get_nls_format failed", K(ret)); } } if (OB_SUCC(ret) && OB_FAIL(ObTimeConverter::datetime_to_str(in_val, tz_info, nls_format, in_scale, buf, buf_len, out_len))) { LOG_WARN("failed to convert datetime to string", K(ret), K(in_val), KP(tz_info), K(nls_format), K(in_scale), K(buf), K(out_len)); } } return ret; } static int common_year_int(const ObExpr &expr, const ObObjType &out_type, const uint8_t in_val, int64_t &out_val) { int ret = OB_SUCCESS; int warning = OB_SUCCESS; if (OB_FAIL(ObTimeConverter::year_to_int(in_val, out_val))) { LOG_WARN("year_to_int failed", K(ret)); } else if (out_type < ObSmallIntType && CAST_FAIL(int_range_check(out_type, out_val, out_val))) { LOG_WARN("int_range_check failed", K(ret)); } return ret; } // trunc_min_value和trunc_max_value分别是in大于最大值和小于最小值时应该trunc成的值。 // float转int时,如果超过LLONG_MAX应该trunc成LLONG_MIN,而double转int时超过LLONG_MAX应该trunc成LLONG_MAX 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)) { // 把相等的情况放进来处理,是因为和LLONG_MAX相等的浮点数转int时结果可能是LLONG_MIN或LLONG_MAX。 // double转int,以及作为insert value时的float转int,结果是LLONG_MAX; // 其他情况下float转int结果为LLONG_MIN。 不报错的行为也是与mysql兼容 out = trunc_max_value; if (in > static_cast(LLONG_MAX)) { ret = OB_DATA_OUT_OF_RANGE; } } else { out = static_cast(rint(in)); } return ret; } // 根据type,从ptr指向的空间中构建ObOTimestampData对象 // ObTimestampTZType需要12字节,ObTimestampLTZType和ObTimestampNanoType需要10字节 // 所以构造逻辑有区别 static OB_INLINE int common_construct_otimestamp(const ObObjType type, const ObDatum &in_datum, ObOTimestampData &out_val) { int ret = OB_SUCCESS; if (ObTimestampTZType == type) { out_val = in_datum.get_otimestamp_tz(); } else if (ObTimestampLTZType == type || ObTimestampNanoType == type) { out_val = in_datum.get_otimestamp_tiny(); } else { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid in type", K(ret), K(type)); } return ret; } static int common_number_datetime(const number::ObNumber nmb, const ObTimeConvertCtx &cvrt_ctx, int64_t &out_val, const ObCastMode cast_mode) { int ret = OB_SUCCESS; int64_t int_part = 0; int64_t dec_part = 0; const int64_t three_digit_min = 100; const int64_t eight_digit_max = 99999999; if (nmb.is_negative()) { ret = OB_INVALID_DATE_VALUE; LOG_WARN("invalid datetime value", K(ret), K(nmb)); } else if (!nmb.is_int_parts_valid_int64(int_part, dec_part)) { ret = OB_INVALID_DATE_VALUE; LOG_WARN("invalid date format", K(ret), K(nmb)); // Maybe we need a new framework to make precise control on whether we report an error, // instead of calling a function and check the return value and cast_mode, // then we can move this logic to ObTimeConverter::int_to_datetime. } else if (OB_UNLIKELY(dec_part != 0 && ((0 == int_part && cvrt_ctx.is_timestamp_) || (int_part >= three_digit_min && int_part <= eight_digit_max)))) { if (CM_IS_COLUMN_CONVERT(cast_mode) && !CM_IS_WARN_ON_FAIL(cast_mode)) { ret = OB_INVALID_DATE_VALUE; LOG_WARN("invalid date value", K(ret), K(nmb)); } else { dec_part = 0; } } if (OB_SUCC(ret)) { ObDateSqlMode date_sql_mode; date_sql_mode.allow_invalid_dates_ = CM_IS_EXPLICIT_CAST(cast_mode) ? false : CM_IS_ALLOW_INVALID_DATES(cast_mode); date_sql_mode.no_zero_date_ = CM_IS_EXPLICIT_CAST(cast_mode) ? false : CM_IS_NO_ZERO_DATE(cast_mode); ret = ObTimeConverter::int_to_datetime( int_part, dec_part, cvrt_ctx, out_val, date_sql_mode); } return ret; } int cast_not_expected(const sql::ObExpr &expr, sql::ObEvalCtx &ctx, sql::ObDatum &res_datum) { int ret = lib::is_oracle_mode() ? OB_ERR_INVALID_TYPE_FOR_OP : OB_ERR_UNEXPECTED; UNUSED(ctx); UNUSED(res_datum); ObObjType in_type = expr.args_[0]->datum_meta_.type_; ObObjType out_type = expr.datum_meta_.type_; LOG_WARN("cast_not_expected", K(ret), K(in_type), K(out_type), K(expr.extra_)); return ret; } int cast_not_support(const sql::ObExpr &expr, sql::ObEvalCtx &ctx, sql::ObDatum &res_datum) { int ret = OB_NOT_SUPPORTED; UNUSED(ctx); UNUSED(res_datum); ObObjType in_type = expr.args_[0]->datum_meta_.type_; ObObjType out_type = expr.datum_meta_.type_; LOG_WARN("cast_not_supported", K(ret), K(in_type), K(out_type), K(expr.extra_)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "type casting"); return ret; } int cast_inconsistent_types(const sql::ObExpr &expr, sql::ObEvalCtx &ctx, sql::ObDatum &res_datum) { int ret = OB_ERR_INVALID_TYPE_FOR_OP; UNUSED(ctx); UNUSED(res_datum); ObObjType in_type = expr.args_[0]->datum_meta_.type_; ObObjType out_type = expr.datum_meta_.type_; LOG_WARN("inconsistent datatypes", K(ret), K(in_type), K(out_type), K(expr.extra_)); return ret; } int cast_inconsistent_types_json(const sql::ObExpr &expr, sql::ObEvalCtx &ctx, sql::ObDatum &res_datum) { UNUSED(ctx); UNUSED(res_datum); int ret = OB_SUCCESS; ObObjType in_type = expr.args_[0]->datum_meta_.type_; ObObjType out_type = expr.datum_meta_.type_; if (CM_IS_IMPLICIT_CAST(expr.extra_)) { ret = OB_ERR_INVALID_INPUT; LOG_WARN("invalid input in implicit cast", K(ret)); } else { LOG_WARN("inconsistent datatypes", K(ret), K(in_type), K(out_type), K(expr.extra_)); ret = OB_ERR_INVALID_TYPE_FOR_OP; } return ret; } int cast_identity_enum_set(const sql::ObExpr &expr, const ObIArray &str_values, const uint64_t cast_mode, sql::ObEvalCtx &ctx, sql::ObDatum &res_datum) { UNUSED(cast_mode); UNUSED(str_values); EVAL_ARG() { res_datum.set_enum(child_res->get_enum()); } return OB_SUCCESS; } int cast_not_support_enum_set(const sql::ObExpr &expr, const ObIArray &str_values, const uint64_t cast_mode, sql::ObEvalCtx &ctx, sql::ObDatum &res_datum) { int ret = OB_NOT_SUPPORTED; UNUSED(ctx); UNUSED(res_datum); ObObjType in_type = expr.args_[0]->datum_meta_.type_; ObObjType out_type = expr.datum_meta_.type_; LOG_WARN("not support datatypes", K(in_type), K(out_type), K(cast_mode), K(str_values), K(expr)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "cast to enum or set type"); return ret; } int cast_not_expected_enum_set(const sql::ObExpr &expr, const ObIArray &str_values, const uint64_t cast_mode, sql::ObEvalCtx &ctx, sql::ObDatum &res_datum) { int ret = OB_ERR_UNEXPECTED; UNUSED(ctx); UNUSED(res_datum); ObObjType in_type = expr.args_[0]->datum_meta_.type_; ObObjType out_type = expr.datum_meta_.type_; LOG_WARN("not expected obj type convert", K(ret), K(in_type), K(out_type), K(expr), K(cast_mode),K(str_values), K(lbt())); return ret; } CAST_FUNC_NAME(unknown, other) { return cast_not_support(expr, ctx, res_datum); } // 有的cast没有实际的逻辑,只需要计算子节点的值即可 // 例如int -> bit,cast结果直接使用子节点的结果即可,不需要进行计算 // 注意:如果有新类型的转换使用该函数,一定要在is_trivial_cast()方法中更新这种转换 // 以保证cast表达式的res_datum的指针是指向参数的空间!!! int cast_eval_arg(const sql::ObExpr &expr, sql::ObEvalCtx &ctx, sql::ObDatum &res_datum) { int ret = OB_SUCCESS; UNUSED(res_datum); ObDatum *child_res = NULL; if (OB_FAIL(expr.args_[0]->eval(ctx, child_res))) { LOG_WARN("eval arg failed", K(ret)); } else { // TODO: CG部分加了优化后, 就不用赋值 res_datum.set_datum(*child_res); } return ret; } // TODO:@xiaofeng.lby, need to modify cast expr in batch mode // cast in batch mode will degrade into single row mode now int cast_eval_arg_batch(const ObExpr &expr, ObEvalCtx &ctx, const ObBitVector &skip, const int64_t batch_size) { LOG_DEBUG("eval cast in batch mode", K(batch_size)); int ret = OB_SUCCESS; ObDatum *results = expr.locate_batch_datums(ctx); if (OB_FAIL(expr.args_[0]->eval_batch(ctx, skip, batch_size))) { LOG_WARN("eval args_[0] failed", K(ret)); } else if (OB_FAIL(expr.args_[1]->eval_batch(ctx, skip, batch_size))) { LOG_WARN("eval args_[1] failed", K(ret)); } else { ObEvalCtx::BatchInfoScopeGuard batch_info_guard(ctx); batch_info_guard.set_batch_size(batch_size); ObBitVector &eval_flags = expr.get_evaluated_flags(ctx); for (int64_t i = 0; OB_SUCC(ret) && i < batch_size; ++i) { batch_info_guard.set_batch_idx(i); ObDatum *result = &results[i]; if (skip.at(i) || eval_flags.at(i)) { continue; } else if (OB_FAIL(expr.eval(ctx, result))) { LOG_WARN("fail to eval one row", K(ret), K(i)); } else { eval_flags.set(i); } } } return ret; } CAST_FUNC_NAME(int, int) { EVAL_ARG() { DEF_IN_OUT_TYPE(); int64_t val_int = child_res->get_int(); if (in_type > out_type && CAST_FAIL(int_range_check(out_type, val_int, val_int))) { LOG_WARN("int_range_check failed", K(ret), K(out_type), K(val_int)); } else { res_datum.set_int(val_int); } } return ret; } CAST_FUNC_NAME(int, uint) { EVAL_ARG() { if (CM_SKIP_CAST_INT_UINT(expr.extra_)) { LOG_DEBUG("skip cast int uint", K(ret)); } else { ObObjType out_type = expr.datum_meta_.type_; DEF_IN_OUT_VAL(int64_t, uint64_t, static_cast(in_val)); if (CM_NEED_RANGE_CHECK(expr.extra_) && CAST_FAIL(uint_range_check(out_type, in_val, out_val))) { } else { res_datum.set_uint(out_val); } } } return ret; } CAST_FUNC_NAME(int, float) { EVAL_ARG() { ObObjType out_type = expr.datum_meta_.type_; DEF_IN_OUT_VAL(int64_t, float, static_cast(static_cast(in_val))); if (ObUFloatType == out_type && CAST_FAIL(numeric_negative_check(out_val))) { LOG_WARN("numeric_negative_check failed", K(ret), K(in_val)); } else { res_datum.set_float(out_val); } } return ret; } CAST_FUNC_NAME(int, double) { EVAL_ARG() { ObObjType out_type = expr.datum_meta_.type_; DEF_IN_OUT_VAL(int64_t, double, static_cast(in_val)); if (ObUDoubleType == out_type && CAST_FAIL(numeric_negative_check(out_val))) { LOG_WARN("numeric_negative_check failed", K(ret), K(in_val), K(out_val)); } else { res_datum.set_double(out_val); } } return ret; } CAST_FUNC_NAME(int, number) { EVAL_ARG() { int64_t in_val = child_res->get_int(); ObNumStackOnceAlloc tmp_alloc; number::ObNumber nmb; OZ(common_int_number(expr, in_val, tmp_alloc, nmb), in_val); OX(res_datum.set_number(nmb)); } return ret; } CAST_FUNC_NAME(int, datetime) { EVAL_ARG() { int64_t in_val = child_res->get_int(); OZ(common_int_datetime(expr, in_val, ctx, res_datum), in_val); } return ret; } CAST_FUNC_NAME(int, date) { EVAL_ARG() { int64_t in_val = child_res->get_int(); OZ(common_int_date(expr, in_val, res_datum), in_val); } return ret; } CAST_FUNC_NAME(int, time) { EVAL_ARG() { int64_t in_val = child_res->get_int(); OZ(common_int_time(expr, in_val, res_datum), in_val); } return ret; } CAST_FUNC_NAME(int, year) { EVAL_ARG() { int64_t in_val = child_res->get_int(); OZ(common_int_year(expr, in_val, res_datum), in_val); } return ret; } CAST_FUNC_NAME(int, string) { EVAL_ARG() { int64_t in_val = child_res->get_int(); ObFastFormatInt ffi(in_val); if (OB_FAIL(common_copy_string_zf(expr, ObString(ffi.length(), ffi.ptr()), ctx, res_datum))) { LOG_WARN("common_copy_string_zf failed", K(ret)); } } return ret; } // about cast for text tc, observer 4.0 always use xxx_string and string_xxx // 4.1 always use xxx_text and text_xxx CAST_FUNC_NAME(int, text) { EVAL_ARG() { int64_t in_val = child_res->get_int(); ObFastFormatInt ffi(in_val); if (OB_FAIL(common_copy_string_zf_to_text_result(expr, ObString(ffi.length(), ffi.ptr()), ctx, res_datum))) { LOG_WARN("common_copy_string_zf_to_text_result failed", K(ret)); } } return ret; } CAST_FUNC_NAME(int, lob) { EVAL_ARG() { int64_t in_val = child_res->get_int(); ObFastFormatInt ffi(in_val); ObString res_str; if (OB_FAIL(common_copy_string_zf(expr, ObString(ffi.length(), ffi.ptr()), ctx, res_datum))) { LOG_WARN("common_copy_string_zf failed", K(ret)); } else if (OB_FAIL(copy_datum_str_with_tmp_alloc(ctx, res_datum, res_str))) { LOG_WARN("copy datum string with tmp allocator failed", K(ret)); } else if (OB_FAIL(common_string_lob(expr, res_str, ctx, NULL, res_datum))) { LOG_WARN("cast string to lob failed", K(ret)); } } return ret; } CAST_FUNC_NAME(int, json) { EVAL_ARG_FOR_CAST_TO_JSON() { ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); ObIJsonBase *j_base = NULL; int64_t in_val = child_res->get_int(); ObObjType in_type = expr.args_[0]->datum_meta_.type_; bool bool_val = (in_val == 1) ? true : false; ObJsonBoolean j_bool(bool_val); ObJsonInt j_int(in_val); if (expr.args_[0]->is_boolean_ == 1) { j_base = &j_bool; } else { j_base = &j_int; } ObString raw_bin; if (OB_FAIL(j_base->get_raw_binary(raw_bin, &temp_allocator))) { LOG_WARN("fail to get int json binary", K(ret), K(in_type), K(in_val)); } else if (OB_FAIL(common_json_bin(expr, ctx, res_datum, raw_bin))) { LOG_WARN("fail to fill json bin lob locator", K(ret)); } } return ret; } CAST_FUNC_NAME(int, geometry) { EVAL_ARG() { ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); ObGeometry *geo = NULL; omt::ObSrsCacheGuard srs_guard; const ObSrsItem *srs = NULL; int64_t in_val = child_res->get_int(); ObFastFormatInt ffi(in_val); ObGeoType dst_geo_type = ObGeoCastUtils::get_geo_type_from_cast_mode(expr.extra_); const char *cast_name = ObGeometryTypeCastUtil::get_cast_name(dst_geo_type); ObString str(ffi.length(), ffi.ptr()); if (OB_FAIL(ObGeoExprUtils::get_srs_item(ctx, srs_guard, str, srs, true, cast_name))) { LOG_WARN("fail to get srs item", K(ret), K(str)); } else if (OB_FAIL(ObGeoExprUtils::build_geometry(temp_allocator, str, geo, srs, cast_name))) { LOG_WARN("fail to parse geometry", K(ret), K(in_val), K(dst_geo_type)); } else { ObString res_wkb; if (OB_FAIL(ObGeoTypeUtil::to_wkb(temp_allocator, *geo, srs, res_wkb))) { LOG_WARN("fail to get wkb", K(ret), K(dst_geo_type)); } else if (OB_FAIL(common_gis_wkb(expr, ctx, res_datum, res_wkb))){ LOG_WARN("fail to copy string", K(ret), K(dst_geo_type)); } } if (OB_FAIL(ret) && CM_IS_COLUMN_CONVERT(expr.extra_) && ObGeoType::GEOMETRY == dst_geo_type) { // adapt mysql ret = OB_ERR_CANT_CREATE_GEOMETRY_OBJECT; LOG_USER_ERROR(OB_ERR_CANT_CREATE_GEOMETRY_OBJECT); } } return ret; } CAST_FUNC_NAME(uint, int) { EVAL_ARG() { uint64_t in_val = child_res->get_uint(); int64_t out_val = 0; if (OB_FAIL(common_uint_int(expr, expr.datum_meta_.type_, in_val, ctx, out_val))) { LOG_WARN("common_uint_int failed", K(ret)); } else { res_datum.set_int(out_val); } } return ret; } CAST_FUNC_NAME(uint, uint) { EVAL_ARG() { DEF_IN_OUT_TYPE(); uint64_t in_val = child_res->get_uint(); if (in_type > out_type && CAST_FAIL(uint_upper_check(out_type, in_val))) { LOG_WARN("int_upper_check failed", K(ret), K(in_val)); } else { res_datum.set_uint(in_val); } } return ret; } CAST_FUNC_NAME(uint, double) { EVAL_ARG() { uint64_t in_val = child_res->get_uint(); res_datum.set_double(static_cast(in_val)); } return ret; } CAST_FUNC_NAME(uint, float) { EVAL_ARG() { uint64_t in_val = child_res->get_uint(); res_datum.set_float(static_cast(static_cast(in_val))); } return ret; } CAST_FUNC_NAME(uint, number) { EVAL_ARG() { uint64_t in_val = child_res->get_uint(); ObNumStackOnceAlloc tmp_alloc; number::ObNumber number; if (OB_FAIL(number.from(in_val, tmp_alloc))) { LOG_WARN("number.from failed", K(ret), K(in_val)); } else { res_datum.set_number(number); } } return ret; } CAST_FUNC_NAME(uint, datetime) { EVAL_ARG() { uint64_t in_val = child_res->get_uint(); int64_t out_val = 0; if (OB_FAIL(common_uint_int(expr, ObIntType, in_val, ctx, out_val))) { LOG_WARN("common_uint_int failed", K(ret)); } else if (OB_FAIL(common_int_datetime(expr, out_val, ctx, res_datum))) { LOG_WARN("common_int_datetime failed", K(ret)); } } return ret; } CAST_FUNC_NAME(uint, date) { EVAL_ARG() { uint64_t in_val = child_res->get_uint(); int64_t out_val = 0; if (OB_FAIL(common_uint_int(expr, ObIntType, in_val, ctx, out_val))) { LOG_WARN("common_uint_int failed", K(ret)); } else if (OB_FAIL(common_int_date(expr, out_val, res_datum))) { LOG_WARN("common_int_date failed", K(ret)); } } return ret; } CAST_FUNC_NAME(uint, time) { EVAL_ARG() { uint64_t in_val = child_res->get_uint(); int64_t val_int = 0; if (OB_FAIL(common_uint_int(expr, ObIntType, in_val, ctx, val_int))) { LOG_WARN("common_uint_int failed", K(ret), K(in_val)); } else if (OB_FAIL(common_int_time(expr, val_int, res_datum))) { LOG_WARN("common_int_time failed", K(ret), K(val_int)); } } return ret; } CAST_FUNC_NAME(uint, year) { EVAL_ARG() { uint64_t in_val = child_res->get_uint(); int64_t val_int = 0; if (OB_FAIL(common_uint_int(expr, ObIntType, in_val, ctx, val_int))) { LOG_WARN("common_uint_int failed", K(ret), K(in_val)); } else if (OB_FAIL(common_int_year(expr, val_int, res_datum))) { LOG_WARN("common_int_time failed", K(ret), K(val_int)); } } return ret; } CAST_FUNC_NAME(uint, string) { EVAL_ARG() { uint64_t in_val = child_res->get_uint(); ObFastFormatInt ffi(in_val); if (OB_FAIL(common_copy_string_zf(expr, ObString(ffi.length(), ffi.ptr()), ctx, res_datum))) { LOG_WARN("common_copy_string_zf failed", K(ret), K(ObString(ffi.length(), ffi.ptr()))); } } return ret; } CAST_FUNC_NAME(uint, text) { EVAL_ARG() { uint64_t in_val = child_res->get_uint(); ObFastFormatInt ffi(in_val); if (OB_FAIL(common_copy_string_zf_to_text_result(expr, ObString(ffi.length(), ffi.ptr()), ctx, res_datum))) { LOG_WARN("common_copy_string_zf_to_text_result failed", K(ret), K(ObString(ffi.length(), ffi.ptr()))); } } return ret; } CAST_FUNC_NAME(uint, lob) { EVAL_ARG() { uint64_t in_val = child_res->get_uint(); ObFastFormatInt ffi(in_val); ObString res_str; if (OB_FAIL(common_copy_string_zf(expr, ObString(ffi.length(), ffi.ptr()), ctx, res_datum))) { LOG_WARN("common_copy_string_zf failed", K(ret), K(ObString(ffi.length(), ffi.ptr()))); } else if (OB_FAIL(copy_datum_str_with_tmp_alloc(ctx, res_datum, res_str))) { LOG_WARN("copy datum string with tmp allocator failed", K(ret)); } else if (OB_FAIL(common_string_lob(expr, res_str, ctx, NULL, res_datum))) { LOG_WARN("cast string to lob failed", K(ret)); } } return ret; } CAST_FUNC_NAME(uint, json) { EVAL_ARG_FOR_CAST_TO_JSON() { uint64_t in_val = child_res->get_uint(); ObObjType in_type = expr.args_[0]->datum_meta_.type_; ObJsonUint j_uint(in_val); ObIJsonBase *j_base = &j_uint; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); ObString raw_bin; if (OB_FAIL(j_base->get_raw_binary(raw_bin, &temp_allocator))) { LOG_WARN("fail to get uint json binary", K(ret), K(in_type), K(in_val)); } else if (OB_FAIL(common_json_bin(expr, ctx, res_datum, raw_bin))) { LOG_WARN("fail to fill json bin lob locator", K(ret)); } } return ret; } CAST_FUNC_NAME(uint, geometry) { EVAL_ARG() { ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); ObGeometry *geo = NULL; omt::ObSrsCacheGuard srs_guard; const ObSrsItem *srs = NULL; uint64_t in_val = child_res->get_uint(); ObFastFormatInt ffi(in_val); ObGeoType dst_geo_type = ObGeoCastUtils::get_geo_type_from_cast_mode(expr.extra_); const char *cast_name = ObGeometryTypeCastUtil::get_cast_name(dst_geo_type); ObString str(ffi.length(), ffi.ptr()); if (OB_FAIL(ObGeoExprUtils::get_srs_item(ctx, srs_guard, str, srs, true, cast_name))) { LOG_WARN("fail to get srs item", K(ret), K(str)); } else if (OB_FAIL(ObGeoExprUtils::build_geometry(temp_allocator, str, geo, srs, cast_name))) { LOG_WARN("fail to parse geometry", K(ret), K(in_val), K(dst_geo_type)); } else { ObString res_wkb; if (OB_FAIL(ObGeoTypeUtil::to_wkb(temp_allocator, *geo, srs, res_wkb))) { LOG_WARN("fail to get wkb", K(ret), K(dst_geo_type)); } else if (OB_FAIL(common_gis_wkb(expr, ctx, res_datum, res_wkb))){ LOG_WARN("fail to copy string", K(ret), K(dst_geo_type)); } } if (OB_FAIL(ret) && CM_IS_COLUMN_CONVERT(expr.extra_) && ObGeoType::GEOMETRY == dst_geo_type) { // adapt mysql ret = OB_ERR_CANT_CREATE_GEOMETRY_OBJECT; LOG_USER_ERROR(OB_ERR_CANT_CREATE_GEOMETRY_OBJECT); } } return ret; } CAST_FUNC_NAME(string, int) { EVAL_STRING_ARG() { ObString in_str(child_res->len_, child_res->ptr_); const bool is_str_int_cast = true; OZ(common_string_int(expr, expr.extra_, in_str, is_str_int_cast, res_datum)); } return ret; } CAST_FUNC_NAME(string, uint) { EVAL_STRING_ARG() { ObString in_str(child_res->len_, child_res->ptr_); const bool is_str_int_cast = true; OZ(common_string_uint(expr, in_str, is_str_int_cast, res_datum)); } return ret; } CAST_FUNC_NAME(string, float) { EVAL_STRING_ARG() { float out_val = 0; OZ(common_string_float(expr, ObString(child_res->len_, child_res->ptr_), out_val)); OX(res_datum.set_float(out_val)); } return ret; } CAST_FUNC_NAME(string, double) { EVAL_STRING_ARG() { DEF_IN_OUT_TYPE(); ObString in_str = ObString(child_res->len_, child_res->ptr_); OZ(common_string_double(expr, in_type, expr.args_[0]->datum_meta_.cs_type_, out_type, in_str, res_datum)); } return ret; } CAST_FUNC_NAME(string, number) { EVAL_STRING_ARG() { number::ObNumber nmb; ObNumStackOnceAlloc tmp_alloc; OZ(common_string_number(expr, ObString(child_res->len_, child_res->ptr_), tmp_alloc, nmb)); OX(res_datum.set_number(nmb)); } return ret; } CAST_FUNC_NAME(string, datetime) { EVAL_STRING_ARG() { OZ(common_string_datetime(expr, ObString(child_res->len_, child_res->ptr_), ctx, res_datum)); } return ret; } CAST_FUNC_NAME(string, date) { EVAL_STRING_ARG() { OZ(common_string_date(expr, ObString(child_res->len_, child_res->ptr_), res_datum)); } return ret; } CAST_FUNC_NAME(string, time) { EVAL_STRING_ARG() { OZ(common_string_time(expr, ObString(child_res->len_, child_res->ptr_), res_datum)); } return ret; } CAST_FUNC_NAME(string, year) { EVAL_STRING_ARG() { OZ(common_string_year(expr, ObString(child_res->len_, child_res->ptr_), res_datum)); } return ret; } CAST_FUNC_NAME(string, bit) { EVAL_STRING_ARG() { OZ(common_string_bit(expr, ObString(child_res->len_, child_res->ptr_), ctx, res_datum)); } return ret; } CAST_FUNC_NAME(string, string) { EVAL_STRING_ARG() { ObObjType in_type = expr.args_[0]->datum_meta_.type_; ObObjType out_type = expr.datum_meta_.type_; ObCollationType in_cs_type = expr.args_[0]->datum_meta_.cs_type_; ObCollationType out_cs_type = expr.datum_meta_.cs_type_; ObString in_str(child_res->len_, child_res->ptr_); bool has_set_res = false; OZ(common_string_string(expr, in_type, in_cs_type, out_type, out_cs_type, in_str, ctx, res_datum, has_set_res)); } return ret; } CAST_FUNC_NAME(string, text) { EVAL_STRING_ARG() { ObObjType in_type = expr.args_[0]->datum_meta_.type_; ObObjType out_type = expr.datum_meta_.type_; ObCollationType in_cs_type = expr.args_[0]->datum_meta_.cs_type_; ObCollationType out_cs_type = expr.datum_meta_.cs_type_; ObString in_str(child_res->len_, child_res->ptr_); OZ(common_string_text(expr, in_str, ctx, NULL, res_datum)); } return ret; } CAST_FUNC_NAME(string, otimestamp) { EVAL_STRING_ARG() { ObString in_str(child_res->len_, child_res->ptr_); OZ(common_string_otimestamp(expr, in_str, ctx, res_datum)); } return ret; } CAST_FUNC_NAME(string, raw) { EVAL_STRING_ARG() { ObString in_str(child_res->len_, child_res->ptr_); bool has_set_res = false; OZ(ObDatumHexUtils::hextoraw_string(expr, in_str, ctx, res_datum, has_set_res)); } return ret; } CAST_FUNC_NAME(string, interval) { EVAL_STRING_ARG() { ObString in_str(child_res->len_, child_res->ptr_); OZ(common_string_interval(expr, in_str, ctx, res_datum)); } return ret; } CAST_FUNC_NAME(string, rowid) { EVAL_STRING_ARG() { ObString in_str(child_res->len_, child_res->ptr_); OZ(common_string_rowid(expr, in_str, ctx, res_datum)); } return ret; } CAST_FUNC_NAME(string, lob) { int ret = OB_SUCCESS; ObDatum *child_res = NULL; if (OB_FAIL(expr.args_[0]->eval(ctx, child_res))) { LOG_WARN("eval arg failed", K(ret)); } else if (child_res->is_null() || (lib::is_oracle_mode() && ObLongTextType != expr.args_[0]->datum_meta_.type_ && 0 == child_res->len_)) { res_datum.set_null(); } else { ObString in_str(child_res->len_, child_res->ptr_); OZ(common_string_lob(expr, in_str, ctx, NULL, res_datum)); } return ret; } static int common_string_json(const ObExpr &expr, const ObString &in_str, ObEvalCtx &ctx, ObDatum &res_datum) { int ret = OB_SUCCESS; ObObjType in_type = expr.args_[0]->datum_meta_.type_; ObObjType out_type = ObLongTextType; ObCollationType in_cs_type = expr.args_[0]->datum_meta_.cs_type_; ObCollationType out_cs_type = expr.datum_meta_.cs_type_; bool has_set_res = false; // binary type will convert to json opaque, other types need convert charset to utf8 bool is_need_charset_convert = ((CS_TYPE_BINARY != in_cs_type) && (ObCharset::charset_type_by_coll(in_cs_type) != ObCharset::charset_type_by_coll(out_cs_type))); if (lib::is_mysql_mode() && (out_cs_type != CS_TYPE_UTF8MB4_BIN)) { ret = OB_ERR_INVALID_JSON_CHARSET; LOG_WARN("fail to cast string to json invalid outtype", K(ret), K(out_cs_type)); } else if (is_need_charset_convert && OB_FAIL(common_string_string(expr, in_type, in_cs_type, out_type, out_cs_type, in_str, ctx, res_datum, has_set_res))) { LOG_WARN("fail to cast string to longtext", K(ret), K(in_str), K(expr)); } else { ObString j_text; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); if (is_need_charset_convert && OB_FAIL(copy_datum_str_with_tmp_alloc(ctx, res_datum, j_text))) { LOG_WARN("copy datum str with tmp alloc", K(ret)); } else { if (is_need_charset_convert == false) { j_text.assign_ptr(in_str.ptr(), in_str.length()); } bool is_enumset_to_str = ((expr.args_[0]->type_ == T_FUN_SET_TO_STR) || (expr.args_[0]->type_ == T_FUN_ENUM_TO_STR)); ObIJsonBase *j_base = NULL; ObJsonOpaque j_opaque(j_text, in_type); ObJsonString j_string(j_text.ptr(), j_text.length()); ObJsonNull j_null; ObJsonNode *j_tree = NULL; bool is_null_res = false; bool relaxed_json = lib::is_oracle_mode() && !(CM_IS_STRICT_JSON(expr.extra_)); uint32_t parse_flag = ObJsonParser::JSN_STRICT_FLAG; ADD_FLAG_IF_NEED(relaxed_json, parse_flag, ObJsonParser::JSN_RELAXED_FLAG); ADD_FLAG_IF_NEED(lib::is_oracle_mode(), parse_flag, ObJsonParser::JSN_UNIQUE_FLAG); if (lib::is_mysql_mode() && in_cs_type == CS_TYPE_BINARY) { j_base = &j_opaque; } else if (lib::is_oracle_mode() && CM_IS_IMPLICIT_CAST(expr.extra_) && OB_ISNULL(j_text.ptr())) { res_datum.set_null(); is_null_res = true; } else if (is_enumset_to_str || (CM_IS_IMPLICIT_CAST(expr.extra_) && !CM_IS_COLUMN_CONVERT(expr.extra_) && !CM_IS_JSON_VALUE(expr.extra_) && ob_is_string_type(in_type))) { // consistent with mysql: TINYTEXT, TEXT, MEDIUMTEXT, and LONGTEXT. We want to treat them like strings j_base = &j_string; } else if (lib::is_oracle_mode() && (OB_ISNULL(j_text.ptr()) || j_text.length() == 0)) { j_base = &j_null; } else if (OB_FAIL(ObJsonParser::get_tree(&temp_allocator, j_text, j_tree, parse_flag))) { if (lib::is_mysql_mode() && CM_IS_IMPLICIT_CAST(expr.extra_) && !CM_IS_COLUMN_CONVERT(expr.extra_)) { ret = OB_SUCCESS; j_base = &j_string; } else { LOG_WARN("fail to parse string as json tree", K(ret), K(in_type), K(in_str)); if (CM_IS_COLUMN_CONVERT(expr.extra_)) { if (lib::is_mysql_mode()) { ret = OB_ERR_INVALID_JSON_TEXT; LOG_USER_ERROR(OB_ERR_INVALID_JSON_TEXT); } } else { ret = OB_ERR_INVALID_JSON_TEXT_IN_PARAM; LOG_USER_ERROR(OB_ERR_INVALID_JSON_TEXT_IN_PARAM); } } } else { j_base = j_tree; } if (OB_SUCC(ret) && !is_null_res) { ObString raw_bin; if (OB_FAIL(j_base->get_raw_binary(raw_bin, &temp_allocator))) { LOG_WARN("fail to get string json binary", K(ret), K(in_type), K(raw_bin)); } else if (OB_FAIL(common_json_bin(expr, ctx, res_datum, raw_bin))) { LOG_WARN("fail to fill json bin lob locator", K(ret)); } } } } return ret; } CAST_FUNC_NAME(string, json) { EVAL_ARG_FOR_CAST_TO_JSON() { ObDatum *child_res = NULL; if (OB_FAIL(expr.args_[0]->eval(ctx, child_res))) { LOG_WARN("eval arg failed", K(ret)); } else { ObString in_str = child_res->get_string(); ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); if (OB_FAIL(ObTextStringHelper::read_real_string_data(temp_allocator, *child_res, expr.args_[0]->datum_meta_, expr.args_[0]->obj_meta_.has_lob_header(), in_str))) { LOG_WARN("fail to get real data.", K(ret), K(in_str)); } else { ret = common_string_json(expr, in_str, ctx, res_datum); } } } return ret; } CAST_FUNC_NAME(text, int) { EVAL_STRING_ARG() { ObString in_str(child_res->len_, child_res->ptr_); ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); OZ(get_text_full_data(expr, ctx, &temp_allocator, child_res, in_str)); const bool is_str_int_cast = true; OZ(common_string_int(expr, expr.extra_, in_str, is_str_int_cast, res_datum)); } return ret; } CAST_FUNC_NAME(text, uint) { EVAL_STRING_ARG() { ObString in_str(child_res->len_, child_res->ptr_); ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); OZ(get_text_full_data(expr, ctx, &temp_allocator, child_res, in_str)); const bool is_str_int_cast = true; OZ(common_string_uint(expr, in_str, is_str_int_cast, res_datum)); } return ret; } CAST_FUNC_NAME(text, float) { EVAL_STRING_ARG() { ObString in_str(child_res->len_, child_res->ptr_); ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); OZ(get_text_full_data(expr, ctx, &temp_allocator, child_res, in_str)); float out_val = 0; OZ(common_string_float(expr, in_str, out_val)); OX(res_datum.set_float(out_val)); } return ret; } CAST_FUNC_NAME(text, double) { EVAL_STRING_ARG() { DEF_IN_OUT_TYPE(); ObString in_str = ObString(child_res->len_, child_res->ptr_); ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); OZ(get_text_full_data(expr, ctx, &temp_allocator, child_res, in_str)); OZ(common_string_double(expr, in_type, expr.args_[0]->datum_meta_.cs_type_, out_type, in_str, res_datum)); } return ret; } CAST_FUNC_NAME(text, number) { EVAL_STRING_ARG() { number::ObNumber nmb; ObNumStackOnceAlloc tmp_alloc; ObString in_str(child_res->len_, child_res->ptr_); ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); OZ(get_text_full_data(expr, ctx, &temp_allocator, child_res, in_str)); OZ(common_string_number(expr, in_str, tmp_alloc, nmb)); OX(res_datum.set_number(nmb)); } return ret; } CAST_FUNC_NAME(text, datetime) { EVAL_STRING_ARG() { ObString in_str; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); OZ(get_text_full_data(expr, ctx, &temp_allocator, child_res, in_str)); OZ(common_string_datetime(expr, in_str, ctx, res_datum)); } return ret; } CAST_FUNC_NAME(text, date) { EVAL_STRING_ARG() { ObString in_str; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); OZ(get_text_full_data(expr, ctx, &temp_allocator, child_res, in_str)); OZ(common_string_date(expr, in_str, res_datum)); } return ret; } CAST_FUNC_NAME(text, time) { EVAL_STRING_ARG() { ObString in_str; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); OZ(get_text_full_data(expr, ctx, &temp_allocator, child_res, in_str)); OZ(common_string_time(expr, in_str, res_datum)); } return ret; } CAST_FUNC_NAME(text, year) { EVAL_STRING_ARG() { ObString in_str; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); OZ(get_text_full_data(expr, ctx, &temp_allocator, child_res, in_str)); OZ(common_string_year(expr, in_str, res_datum)); } return ret; } CAST_FUNC_NAME(text, bit) { EVAL_STRING_ARG() { ObString in_str; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); OZ(get_text_full_data(expr, ctx, &temp_allocator, child_res, in_str)); OZ(common_string_bit(expr, in_str, ctx, res_datum)); } return ret; } CAST_FUNC_NAME(text, string) { EVAL_STRING_ARG() { ObObjType in_type = expr.args_[0]->datum_meta_.type_; ObObjType out_type = expr.datum_meta_.type_; ObCollationType in_cs_type = expr.args_[0]->datum_meta_.cs_type_; ObCollationType out_cs_type = expr.datum_meta_.cs_type_; const bool has_lob_header = expr.args_[0]->obj_meta_.has_lob_header(); const bool is_same_charset = (ObCharset::charset_type_by_coll(in_cs_type) == ObCharset::charset_type_by_coll(out_cs_type)); ObString data; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); ObExprStrResAlloc res_alloc(expr, ctx); ObTextStringIter instr_iter(in_type, in_cs_type, child_res->get_string(), has_lob_header); if (OB_FAIL(instr_iter.init(0, ctx.exec_ctx_.get_my_session(), is_same_charset ? reinterpret_cast(&res_alloc) : &temp_allocator))) { LOG_WARN("init lob str iter failed ", K(ret), K(in_type)); } else if (OB_FAIL(instr_iter.get_full_data(data, &temp_allocator))) { LOG_WARN("init lob str iter failed ", K(ret), K(in_type)); } else if (lib::is_oracle_mode() && ob_is_clob(in_type, in_cs_type) && (0 == data.length()) && !ob_is_clob(out_type, out_cs_type)) { // in oracle mode, empty clob cast to other types, result is NULL res_datum.set_null(); } else if (is_same_charset) { res_datum.set_string(data.ptr(), data.length()); } else { bool has_set_res = false; OZ(common_string_string(expr, in_type, in_cs_type, out_type, out_cs_type, data, ctx, res_datum, has_set_res)); } ObString in_str(child_res->len_, child_res->ptr_); lob_string_debug(in_type, in_cs_type, out_type, out_cs_type, in_str, res_datum, ret); } return ret; } CAST_FUNC_NAME(text, text) { EVAL_STRING_ARG() { ObObjType in_type = expr.args_[0]->datum_meta_.type_; ObObjType out_type = expr.datum_meta_.type_; ObCollationType in_cs_type = expr.args_[0]->datum_meta_.cs_type_; ObCollationType out_cs_type = expr.datum_meta_.cs_type_; const bool has_lob_header = expr.args_[0]->obj_meta_.has_lob_header(); const bool is_same_charset = (ObCharset::charset_type_by_coll(in_cs_type) == ObCharset::charset_type_by_coll(out_cs_type)); const bool is_cs_any = (in_cs_type == CS_TYPE_ANY || out_cs_type == CS_TYPE_ANY); const bool is_tiny_to_others = ((in_type == ObTinyTextType && out_type != ObTinyTextType) || (in_type != ObTinyTextType && out_type == ObTinyTextType)); ObString in_str(child_res->len_, child_res->ptr_); ObString data; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); ObLobLocatorV2 input_locator; input_locator.assign_buffer(in_str.ptr(), in_str.length(), has_lob_header); bool is_valid = input_locator.is_valid(); bool is_delta_lob = is_valid && input_locator.is_delta_temp_lob(); bool is_persist = is_valid && input_locator.is_persist_lob(); if (!is_tiny_to_others && (is_same_charset || is_delta_lob || (is_persist && is_cs_any))) { // persist with cs_any only in pl? res_datum.set_string(in_str.ptr(), in_str.length()); } else { ObTextStringIter instr_iter(in_type, in_cs_type, in_str, has_lob_header); if (OB_FAIL(instr_iter.init(0, ctx.exec_ctx_.get_my_session(), &temp_allocator))) { LOG_WARN("init lob str iter failed ", K(ret), K(in_type)); } else if (OB_FAIL(instr_iter.get_full_data(data))) { LOG_WARN("init lob str iter failed ", K(ret), K(in_type)); } else { OZ(common_string_text(expr, data, ctx, NULL, res_datum)); // ToDo: streaming convert } } } return ret; } CAST_FUNC_NAME(text, otimestamp) { EVAL_STRING_ARG() { ObString in_str; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); OZ(get_text_full_data(expr, ctx, &temp_allocator, child_res, in_str)); OZ(common_string_otimestamp(expr, in_str, ctx, res_datum)); } return ret; } CAST_FUNC_NAME(text, raw) { EVAL_STRING_ARG() { ObString in_str; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); OZ(get_text_full_data(expr, ctx, &temp_allocator, child_res, in_str)); if (OB_FAIL(ret)) { } else if (expr.datum_meta_.cs_type_ != CS_TYPE_BINARY) { bool has_set_res = false; OZ(ObDatumHexUtils::hextoraw_string(expr, in_str, ctx, res_datum, has_set_res)); } else { // blob to raw res_datum.set_string(in_str.ptr(), in_str.length()); } } return ret; } CAST_FUNC_NAME(text, interval) { EVAL_STRING_ARG() { ObString in_str; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); OZ(get_text_full_data(expr, ctx, &temp_allocator, child_res, in_str)); OZ(common_string_interval(expr, in_str, ctx, res_datum)); } return ret; } CAST_FUNC_NAME(text, rowid) { EVAL_STRING_ARG() { ObString in_str; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); OZ(get_text_full_data(expr, ctx, &temp_allocator, child_res, in_str)); OZ(common_string_rowid(expr, in_str, ctx, res_datum)); } return ret; } CAST_FUNC_NAME(text, lob) { EVAL_STRING_ARG() { int ret = OB_SUCCESS; ObObjType in_type = expr.args_[0]->datum_meta_.type_; ObObjType out_type = expr.datum_meta_.type_; ObCollationType in_cs_type = expr.args_[0]->datum_meta_.cs_type_; ObCollationType out_cs_type = expr.datum_meta_.cs_type_; const bool has_lob_header = expr.args_[0]->obj_meta_.has_lob_header(); ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); ObTextStringIter instr_iter(in_type, in_cs_type, child_res->get_string(), has_lob_header); ObString data_str; if (OB_FAIL(instr_iter.init(0, ctx.exec_ctx_.get_my_session(), &temp_allocator))) { LOG_WARN("init lob str iter failed ", K(ret), K(in_type)); } else if (OB_FAIL(instr_iter.get_full_data(data_str))) { LOG_WARN("init lob str iter failed ", K(ret), K(in_type)); } OZ(common_string_lob(expr, data_str, ctx, NULL, res_datum)); } return ret; } CAST_FUNC_NAME(geometry, geometry); // declare advance CAST_FUNC_NAME(string, geometry) { EVAL_STRING_ARG() { int warning = OB_SUCCESS; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); ObString in_str = child_res->get_string(); ObGeoType dst_geo_type = ObGeoCastUtils::get_geo_type_from_cast_mode(expr.extra_); const char *cast_name = ObGeometryTypeCastUtil::get_cast_name(dst_geo_type); ObGeometry *geo = NULL; omt::ObSrsCacheGuard srs_guard; const ObSrsItem *srs = NULL; if (OB_FAIL(ObTextStringHelper::read_real_string_data(temp_allocator, *child_res, expr.args_[0]->datum_meta_, expr.args_[0]->obj_meta_.has_lob_header(), in_str))) { LOG_WARN("fail to get real data.", K(ret), K(in_str)); } else if (OB_FAIL(ObGeoExprUtils::get_srs_item(ctx, srs_guard, in_str, srs, true, cast_name))) { LOG_WARN("fail to get srs item", K(ret), K(in_str)); } else if (OB_FAIL(ObGeoExprUtils::build_geometry(temp_allocator, in_str, geo, srs, cast_name))) { LOG_WARN("fail to parse geometry", K(ret), K(in_str), K(dst_geo_type)); } else if (ObGeoType::GEOMETRY == dst_geo_type || ObGeoType::GEOTYPEMAX == dst_geo_type) { if (OB_FAIL(common_gis_wkb(expr, ctx, res_datum, in_str))){ LOG_WARN("fail to copy string", K(ret), K(dst_geo_type)); } } else if (OB_FAIL(geometry_geometry(expr, ctx, res_datum))) { LOG_WARN("fail to cast geometry", K(ret), K(in_str), K(dst_geo_type)); } if (OB_FAIL(ret) && CM_IS_COLUMN_CONVERT(expr.extra_) && ObGeoType::GEOMETRY == dst_geo_type) { // adapt mysql ret = OB_ERR_CANT_CREATE_GEOMETRY_OBJECT; LOG_USER_ERROR(OB_ERR_CANT_CREATE_GEOMETRY_OBJECT); } } return ret; } CAST_FUNC_NAME(number, int) { EVAL_ARG() { const number::ObNumber nmb(child_res->get_number()); const char *nmb_buf = nmb.format(); if (OB_ISNULL(nmb_buf)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("nmb_buf is NULL", K(ret)); } else { ObString num_str(strlen(nmb_buf), nmb_buf); const bool is_str_int_cast = false; if (OB_FAIL(common_string_int(expr, expr.extra_, num_str, is_str_int_cast, res_datum))) { LOG_WARN("common_string_int failed", K(ret), K(num_str)); } } } return ret; } CAST_FUNC_NAME(number, uint) { EVAL_ARG() { OZ(common_number_uint(expr, *child_res, res_datum)); } return ret; } CAST_FUNC_NAME(number, float) { EVAL_ARG() { const number::ObNumber nmb(child_res->get_number()); const char *nmb_buf = nmb.format(); if (OB_ISNULL(nmb_buf)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("nmb_buf is NULL", K(ret)); } else { ObString num_str(strlen(nmb_buf), nmb_buf); float out_val = 0; if (OB_FAIL(common_string_float(expr, num_str, out_val))) { LOG_WARN("common_string_float failed", K(ret), K(num_str)); } else { res_datum.set_float(out_val); } } } return ret; } CAST_FUNC_NAME(number, double) { EVAL_ARG() { if (child_res->is_null()) { res_datum.set_null(); } else { const number::ObNumber nmb(child_res->get_number()); const char *nmb_buf = nmb.format(); if (OB_ISNULL(nmb_buf)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("nmb_buf is NULL", K(ret)); } else { ObString num_str(strlen(nmb_buf), nmb_buf); DEF_IN_OUT_TYPE(); if (OB_FAIL(common_string_double(expr, in_type, expr.args_[0]->datum_meta_.cs_type_, out_type, num_str, res_datum))) { LOG_WARN("common_string_double failed", K(ret), K(num_str)); } } } } return ret; } CAST_FUNC_NAME(number, number) { EVAL_ARG() { int warning = OB_SUCCESS; const number::ObNumber nmb(child_res->get_number()); if (ObUNumberType == expr.datum_meta_.type_) { ObNumStackOnceAlloc tmp_alloc; number::ObNumber buf_nmb; if (OB_FAIL(buf_nmb.from(nmb, tmp_alloc))) { LOG_WARN("construct buf_nmb failed", K(ret), K(nmb)); } else if (CAST_FAIL(numeric_negative_check(buf_nmb))) { LOG_WARN("numeric_negative_check failed", K(ret)); } else { res_datum.set_number(buf_nmb); } } else { res_datum.set_number(nmb); } } return ret; } CAST_FUNC_NAME(number, string) { EVAL_ARG() { if (OB_FAIL(common_number_string(expr, *child_res, ctx, res_datum))) { LOG_WARN("common_number_string failed", K(ret)); } } return ret; } CAST_FUNC_NAME(number, text) { EVAL_ARG() { ObString res_str; if (OB_FAIL(common_number_string(expr, *child_res, ctx, res_datum))) { LOG_WARN("common_number_string failed", K(ret)); } else if (OB_FAIL(copy_datum_str_with_tmp_alloc(ctx, res_datum, res_str))) { LOG_WARN("copy datum string with tmp allocator failed", K(ret)); } else if (OB_FAIL(common_string_text(expr, res_str, ctx, NULL, res_datum))) { LOG_WARN("cast string to lob failed", K(ret)); } } return ret; } CAST_FUNC_NAME(number, time) { EVAL_ARG() { const number::ObNumber nmb(child_res->get_number()); const char *nmb_buf = nmb.format(); if (OB_ISNULL(nmb_buf)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("null pointer", K(ret), K(nmb_buf)); } else if (OB_FAIL(common_string_time(expr, ObString(strlen(nmb_buf), nmb_buf), res_datum))) { LOG_WARN("common_string_time failed", K(ret)); } } return ret; } CAST_FUNC_NAME(number, year) { EVAL_ARG() { const number::ObNumber nmb(child_res->get_number()); const char *nmb_buf = nmb.format(); if (OB_ISNULL(nmb_buf)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("null pointer", K(ret), K(nmb_buf)); } else if (nmb.is_negative()) { // the year shouldn't accept a negative number, if we use the common_string_year. // number like -0.4 could be converted to year, which should raise error in mysql if (OB_FAIL(common_int_year(expr, INT_MIN, res_datum))) { LOG_WARN("common_int_year failed", K(ret)); } } else if (OB_FAIL(common_string_year(expr, ObString(strlen(nmb_buf), nmb_buf), res_datum))) { LOG_WARN("common_string_year failed", K(ret)); } } return ret; } CAST_FUNC_NAME(number, datetime) { EVAL_ARG() { GET_SESSION() { const number::ObNumber nmb(child_res->get_number()); ObObjType out_type = expr.datum_meta_.type_; ObTimeConvertCtx cvrt_ctx(session->get_timezone_info(), ObTimestampType == out_type); int64_t out_val = 0; ret = common_number_datetime(nmb, cvrt_ctx, out_val, expr.extra_); int warning = OB_SUCCESS; if (CAST_FAIL(ret)) { } else { SET_RES_DATETIME(out_val); } } } return ret; } CAST_FUNC_NAME(number, date) { EVAL_ARG() { int32_t out_val = 0; int warning = OB_SUCCESS; const number::ObNumber nmb(child_res->get_number()); int64_t int_part = 0; int64_t dec_part = 0; 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 { ObDateSqlMode date_sql_mode; date_sql_mode.allow_invalid_dates_ = CM_IS_EXPLICIT_CAST(expr.extra_) ? false : CM_IS_ALLOW_INVALID_DATES(expr.extra_); date_sql_mode.no_zero_date_ = CM_IS_EXPLICIT_CAST(expr.extra_) ? false : CM_IS_NO_ZERO_DATE(expr.extra_); ret = ObTimeConverter::int_to_date(int_part, out_val, date_sql_mode); if (OB_SUCC(ret) && OB_UNLIKELY(dec_part > 0)) { if (CM_IS_COLUMN_CONVERT(expr.extra_) && !CM_IS_WARN_ON_FAIL(expr.extra_)) { ret = OB_INVALID_DATE_VALUE; LOG_WARN("invalid date value with decimal part", K(ret)); } } } if (CAST_FAIL(ret)) { } else { SET_RES_DATE(out_val); } } return ret; } CAST_FUNC_NAME(number, bit) { EVAL_ARG() { if (OB_FAIL(common_number_uint(expr, *child_res, res_datum))) { LOG_WARN("common_number_uint failed", K(ret)); } } return ret; } CAST_FUNC_NAME(number, lob) { EVAL_ARG() { ObString res_str; if (OB_FAIL(common_number_string(expr, *child_res, ctx, res_datum))) { LOG_WARN("common_number_string failed", K(ret)); } else if (OB_FAIL(copy_datum_str_with_tmp_alloc(ctx, res_datum, res_str))) { LOG_WARN("copy datum string with tmp allocator failed", K(ret)); } else if (OB_FAIL(common_string_lob(expr, res_str, ctx, NULL, res_datum))) { LOG_WARN("cast string to lob failed", K(ret)); } } return ret; } CAST_FUNC_NAME(number, json) { EVAL_ARG() { const number::ObNumber nmb(child_res->get_number()); ObObjType in_type = expr.args_[0]->datum_meta_.type_; if (lib::is_oracle_mode() && !number::ObNumber::is_zero_number(nmb.get_desc())) { if (CM_IS_IMPLICIT_CAST(expr.extra_)) { ret = OB_ERR_INVALID_INPUT; LOG_WARN("invalid input in implicit cast", K(ret)); } else { LOG_WARN("inconsistent datatypes", K(ret), K(in_type), K("json"), K(expr.extra_)); ret = OB_ERR_INVALID_TYPE_FOR_OP; } } else { ObPrecision prec = expr.args_[0]->datum_meta_.precision_; ObScale scale = expr.args_[0]->datum_meta_.scale_; ObJsonDecimal j_dec(nmb, prec, scale); ObIJsonBase *j_base = &j_dec; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); ObString raw_bin; if (OB_FAIL(j_base->get_raw_binary(raw_bin, &temp_allocator))) { LOG_WARN("fail to get number json binary", K(ret), K(in_type), K(nmb)); } else if (OB_FAIL(common_json_bin(expr, ctx, res_datum, raw_bin))) { LOG_WARN("fail to fill json bin lob locator", K(ret)); } } } return ret; } CAST_FUNC_NAME(number, geometry) { EVAL_ARG() { ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); ObGeometry *geo = NULL; omt::ObSrsCacheGuard srs_guard; const ObSrsItem *srs = NULL; const number::ObNumber nmb(child_res->get_number()); char buf[OB_CAST_TO_VARCHAR_MAX_LENGTH] = {0}; ObScale in_scale = expr.args_[0]->datum_meta_.scale_; int64_t len = 0; ObGeoType dst_geo_type = ObGeoCastUtils::get_geo_type_from_cast_mode(expr.extra_); const char *cast_name = ObGeometryTypeCastUtil::get_cast_name(dst_geo_type); if (OB_FAIL(nmb.format(buf, sizeof(buf), len, in_scale))) { LOG_WARN("fail to format number", K(ret), K(nmb)); } else if (OB_FAIL(ObGeoExprUtils::get_srs_item(ctx, srs_guard, ObString(len, buf), srs, true, cast_name))) { LOG_WARN("fail to get srs item", K(ret)); } else if (OB_FAIL(ObGeoExprUtils::build_geometry(temp_allocator, ObString(len, buf), geo, srs, cast_name))) { LOG_WARN("fail to parse geometry", K(ret), K(nmb), K(dst_geo_type)); } else { ObString res_wkb; if (OB_FAIL(ObGeoTypeUtil::to_wkb(temp_allocator, *geo, srs, res_wkb))) { LOG_WARN("fail to get wkb", K(ret), K(dst_geo_type)); } else if (OB_FAIL(common_gis_wkb(expr, ctx, res_datum, res_wkb))){ LOG_WARN("fail to copy string", K(ret), K(dst_geo_type)); } } if (OB_FAIL(ret) && CM_IS_COLUMN_CONVERT(expr.extra_) && ObGeoType::GEOMETRY == dst_geo_type) { // adapt mysql ret = OB_ERR_CANT_CREATE_GEOMETRY_OBJECT; LOG_USER_ERROR(OB_ERR_CANT_CREATE_GEOMETRY_OBJECT); } } return ret; } CAST_FUNC_NAME(float, int) { EVAL_ARG() if (OB_SUCC(ret)) { DEF_IN_OUT_VAL(float, int64_t, 0); if (CAST_FAIL(common_double_int(in_val, out_val, LLONG_MIN, CM_IS_COLUMN_CONVERT(expr.extra_) ? LLONG_MAX : LLONG_MIN))) { LOG_WARN("common_floating_int failed", K(ret)); } else if (CAST_FAIL(int_range_check(expr.datum_meta_.type_, out_val, out_val))) { LOG_WARN("int_range_check failed", K(ret)); } else { res_datum.set_int(out_val); } } return ret; } CAST_FUNC_NAME(float, uint) { EVAL_ARG() { DEF_IN_OUT_VAL(float, uint64_t, 0); if (in_val <= static_cast(LLONG_MIN) || in_val >= static_cast(ULLONG_MAX)) { out_val = static_cast(LLONG_MIN); ret = OB_DATA_OUT_OF_RANGE; } else { if (CM_IS_COLUMN_CONVERT(expr.extra_)) { out_val = static_cast(rint(in_val)); } else { out_val = static_cast(static_cast(rint(in_val))); } if (in_val < 0 && out_val != 0) { // 这里处理[LLONG_MIN, 0)范围内的in,转换为unsigned应该报OB_DATA_OUT_OF_RANGE。 // out不等于0避免[-0.5, 0)内的值被误判,因为它们round后的值是0,处于合法范围内。 ret = OB_DATA_OUT_OF_RANGE; } } if (CAST_FAIL(ret)) { LOG_WARN("cast float to uint failed", K(ret), K(in_val), K(out_val)); } else if (CM_NEED_RANGE_CHECK(expr.extra_) && CAST_FAIL(uint_range_check(expr.datum_meta_.type_, out_val, out_val))) { LOG_WARN("int_range_check failed", K(ret)); } else { res_datum.set_uint(out_val); } } return ret; } CAST_FUNC_NAME(float, float) { EVAL_ARG() { int warning = OB_SUCCESS; float val_float = child_res->get_float(); ObObjType out_type = expr.datum_meta_.type_; if (ObUFloatType == out_type && CAST_FAIL(numeric_negative_check(val_float))) { LOG_WARN("numeric_negative_check failed", K(ret)); } else { res_datum.set_float(val_float); } } return ret; } CAST_FUNC_NAME(float, double) { EVAL_ARG() { DEF_IN_OUT_VAL(float, double, static_cast(in_val)); ObObjType out_type = expr.datum_meta_.type_; if (ObUDoubleType == out_type && CAST_FAIL(numeric_negative_check(out_val))) { LOG_WARN("numeric_negative_check failed", K(ret)); } else { res_datum.set_double(out_val); } } return ret; } CAST_FUNC_NAME(float, number) { EVAL_ARG() { float in_val = child_res->get_float(); if (isnan(in_val)) { ret = OB_INVALID_NUMERIC; LOG_WARN("float_number failed ", K(ret), K(in_val)); } else if (isinf(in_val)) { ret = OB_NUMERIC_OVERFLOW; LOG_WARN("float_number failed", K(ret), K(in_val)); } else { ObObjType out_type = expr.datum_meta_.type_; int warning = OB_SUCCESS; ObNumStackOnceAlloc tmp_alloc; number::ObNumber number; if (ObUNumberType == out_type && CAST_FAIL(numeric_negative_check(in_val))) { LOG_WARN("numeric_negative_check failed", K(ret), K(out_type), K(in_val)); } else if (OB_FAIL(common_floating_number(in_val, OB_GCVT_ARG_FLOAT, tmp_alloc, number))) { LOG_WARN("common_float_number failed", K(ret), K(in_val)); } else { res_datum.set_number(number); } } } return ret; } CAST_FUNC_NAME(float, datetime) { EVAL_ARG() { float in_val = child_res->get_float(); double val_double = static_cast(in_val); if (OB_FAIL(common_double_datetime(expr, val_double, ctx, res_datum))) { LOG_WARN("common_double_datetime failed", K(ret), K(val_double)); } } return ret; } CAST_FUNC_NAME(float, date) { EVAL_ARG() { DEF_IN_OUT_VAL(float, int64_t, 0); if (OB_FAIL(common_floating_int(in_val, out_val))) { LOG_WARN("common_double_int failed", K(ret)); } else if (OB_FAIL(common_int_date(expr, out_val, res_datum))) { LOG_WARN("common_int_date failed", K(ret)); } } return ret; } CAST_FUNC_NAME(float, time) { EVAL_ARG() { double in_val = static_cast(child_res->get_float()); if (OB_FAIL(common_double_time(expr, in_val, res_datum))) { LOG_WARN("common_double_time failed", K(ret)); } } return ret; } CAST_FUNC_NAME(float, string) { EVAL_ARG() { float in_val = child_res->get_float(); if (OB_FAIL(common_floating_string(expr, in_val, OB_GCVT_ARG_FLOAT, ctx, res_datum))) { LOG_WARN("common_floating_string failed", K(ret), K(in_val)); } } return ret; } CAST_FUNC_NAME(float, text) { EVAL_ARG() { ObString res_str; float in_val = child_res->get_float(); if (OB_FAIL(common_floating_string(expr, in_val, OB_GCVT_ARG_FLOAT, ctx, res_datum))) { LOG_WARN("common_floating_string failed", K(ret), K(in_val)); } else if (OB_FAIL(copy_datum_str_with_tmp_alloc(ctx, res_datum, res_str))) { LOG_WARN("copy datum string with tmp allocator failed", K(ret)); } else if (OB_FAIL(common_string_text(expr, res_str, ctx, NULL, res_datum))) { LOG_WARN("cast string to lob failed", K(ret)); } } return ret; } CAST_FUNC_NAME(float, lob) { EVAL_ARG() { float in_val = child_res->get_float(); ObString res_str; if (OB_FAIL(common_floating_string(expr, in_val, OB_GCVT_ARG_FLOAT, ctx, res_datum))) { LOG_WARN("common_floating_string failed", K(ret), K(in_val)); } else if (OB_FAIL(copy_datum_str_with_tmp_alloc(ctx, res_datum, res_str))) { LOG_WARN("copy datum string with tmp allocator failed", K(ret)); } else if (OB_FAIL(common_string_lob(expr, res_str, ctx, NULL, res_datum))) { LOG_WARN("cast string to lob failed", K(ret)); } } return ret; } CAST_FUNC_NAME(float, json) { EVAL_ARG_FOR_CAST_TO_JSON() { float in_val = child_res->get_float(); ObObjType in_type = expr.args_[0]->datum_meta_.type_; ObJsonDouble j_float(in_val); ObIJsonBase *j_base = &j_float; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); ObString raw_bin; if (OB_FAIL(j_base->get_raw_binary(raw_bin, &temp_allocator))) { LOG_WARN("fail to get float json binary", K(ret), K(in_type), K(in_val)); } else if (OB_FAIL(common_json_bin(expr, ctx, res_datum, raw_bin))) { LOG_WARN("fail to fill json bin lob locator", K(ret)); } } return ret; } CAST_FUNC_NAME(float, geometry) { EVAL_ARG() { ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); ObGeometry *geo = NULL; omt::ObSrsCacheGuard srs_guard; const ObSrsItem *srs = NULL; float in_val = child_res->get_float(); char buf[OB_CAST_TO_VARCHAR_MAX_LENGTH] = {0}; ObScale scale = expr.args_[0]->datum_meta_.scale_; int64_t len = 0; ObGeoType dst_geo_type = ObGeoCastUtils::get_geo_type_from_cast_mode(expr.extra_); bool nan_or_inf = is_ieee754_nan_inf(in_val, buf, len); if (nan_or_inf) { LOG_DEBUG("Infinity or NaN value is", K(in_val)); } else { if (0 <= scale) { len = ob_fcvt(in_val, scale, sizeof(buf) - 1, buf, NULL); } else { len = ob_gcvt_opt(in_val, OB_GCVT_ARG_FLOAT, sizeof(buf) - 1, buf, NULL, false, TRUE); } } ObString in_str(sizeof(buf), static_cast(len), buf); if (OB_FAIL(ObGeoExprUtils::get_srs_item(ctx, srs_guard, in_str, srs, true))) { LOG_WARN("fail to get srs item", K(ret), K(in_str)); } else if (OB_FAIL(ObGeoExprUtils::build_geometry(temp_allocator, in_str, geo, srs, ObGeometryTypeCastUtil::get_cast_name(dst_geo_type)))) { LOG_WARN("fail to parse geometry", K(ret), K(in_val), K(dst_geo_type)); } else { ObString res_wkb; if (OB_FAIL(ObGeoTypeUtil::to_wkb(temp_allocator, *geo, srs, res_wkb))) { LOG_WARN("fail to get wkb", K(ret), K(dst_geo_type)); } else if (OB_FAIL(common_gis_wkb(expr, ctx, res_datum, res_wkb))){ LOG_WARN("fail to copy string", K(ret), K(dst_geo_type)); } } if (OB_FAIL(ret) && CM_IS_COLUMN_CONVERT(expr.extra_) && ObGeoType::GEOMETRY == dst_geo_type) { // adapt mysql ret = OB_ERR_CANT_CREATE_GEOMETRY_OBJECT; LOG_USER_ERROR(OB_ERR_CANT_CREATE_GEOMETRY_OBJECT); } } return ret; } CAST_FUNC_NAME(float, bit) { EVAL_ARG() { float val_float = child_res->get_float(); // 这里没必要调用SET_RES_BIT,因为ret一定为OB_SUCCESS res_datum.set_bit(static_cast(val_float)); } return ret; } CAST_FUNC_NAME(double, int) { EVAL_ARG() { DEF_IN_OUT_VAL(double, int64_t, 0); if (CAST_FAIL(common_double_int(in_val, out_val, LLONG_MIN, LLONG_MAX))) { LOG_WARN("common double to in failed", K(ret), K(in_val)); } else if (CM_NEED_RANGE_CHECK(expr.extra_) && CAST_FAIL(int_range_check(expr.datum_meta_.type_, out_val, out_val))) { LOG_WARN("int_range_check failed", K(ret)); } else { res_datum.set_int(out_val); } } return ret; } CAST_FUNC_NAME(double, uint) { EVAL_ARG() { DEF_IN_OUT_VAL(double, uint64_t, 0); if (in_val <= static_cast(LLONG_MIN)) { out_val = static_cast(LLONG_MIN); ret = OB_DATA_OUT_OF_RANGE; } else if (in_val >= static_cast(ULLONG_MAX)) { out_val = static_cast(LLONG_MAX); ret = OB_DATA_OUT_OF_RANGE; } else { if (CM_IS_COLUMN_CONVERT(expr.extra_)) { out_val = static_cast(rint(in_val)); } else if (in_val >= static_cast(LLONG_MAX)) { out_val = static_cast(LLONG_MAX); } else { out_val = static_cast(static_cast(rint(in_val))); } if (in_val < 0 && out_val != 0) { // 这里处理[LLONG_MIN, 0)范围内的in,转换为unsigned应该报OB_DATA_OUT_OF_RANGE。 // out不等于0避免[-0.5, 0)内的值被误判,因为它们round后的值是0,处于合法范围内。 ret = OB_DATA_OUT_OF_RANGE; } } if (CAST_FAIL(ret)) { LOG_WARN("cast float to uint failed", K(ret), K(in_val), K(out_val)); } else if (CM_NEED_RANGE_CHECK(expr.extra_) && CAST_FAIL(uint_range_check(expr.datum_meta_.type_, out_val, out_val))) { LOG_WARN("int_range_check failed", K(ret)); } else { res_datum.set_uint(out_val); } } return ret; } CAST_FUNC_NAME(double, float) { EVAL_ARG() { double in_val = child_res->get_double(); float out_val = static_cast(in_val); if (OB_FAIL(common_double_float(expr, in_val, out_val))) { LOG_WARN("common_double_float failed", K(ret), K(in_val)); } else { res_datum.set_float(out_val); } } return ret; } CAST_FUNC_NAME(double, double) { EVAL_ARG() { int warning = OB_SUCCESS; double val_double = child_res->get_double(); ObObjType out_type = expr.datum_meta_.type_; if (ObUDoubleType == out_type && CAST_FAIL(numeric_negative_check(val_double))) { LOG_WARN("numeric_negative_check failed", K(ret)); } else { res_datum.set_double(val_double); } } return ret; } CAST_FUNC_NAME(double, number) { EVAL_ARG() { ObObjType out_type = expr.datum_meta_.type_; double in_val = child_res->get_double(); if (isnan(in_val) && lib::is_oracle_mode()) { ret = OB_INVALID_NUMERIC; LOG_WARN("float_number failed ", K(ret), K(in_val)); } else if (isinf(in_val) && lib::is_oracle_mode()) { ret = OB_NUMERIC_OVERFLOW; LOG_WARN("float_number failed", K(ret), K(in_val)); } else { int warning = OB_SUCCESS; ObNumStackOnceAlloc tmp_alloc; number::ObNumber number; if (ObUNumberType == out_type && CAST_FAIL(numeric_negative_check(in_val))) { LOG_WARN("numeric_negative_check failed", K(ret), K(out_type), K(in_val)); } else if (OB_FAIL(common_floating_number(in_val, OB_GCVT_ARG_DOUBLE, tmp_alloc, number))) { LOG_WARN("common_float_number failed", K(ret), K(in_val)); } else { res_datum.set_number(number); } } } return ret; } CAST_FUNC_NAME(double, datetime) { EVAL_ARG() { double in_val = child_res->get_double(); if (OB_FAIL(common_double_datetime(expr, in_val, ctx, res_datum))) { LOG_WARN("common_double_datetime failed", K(ret)); } } return ret; } CAST_FUNC_NAME(double, date) { EVAL_ARG() { DEF_IN_OUT_VAL(double, int64_t, 0); if (OB_FAIL(common_floating_int(in_val, out_val))) { LOG_WARN("common_double_int failed", K(ret)); } else if (OB_FAIL(common_int_date(expr, out_val, res_datum))) { LOG_WARN("common_int_date failed", K(ret)); } } return ret; } CAST_FUNC_NAME(double, time) { EVAL_ARG() { double in_val = child_res->get_double(); if (OB_FAIL(common_double_time(expr, in_val, res_datum))) { LOG_WARN("common_double_time failed", K(ret)); } } return ret; } CAST_FUNC_NAME(double, year) { EVAL_ARG() { // When we insert 999999999999999999999.9(larger than max int) into a year field in mysql // Mysql raise the same error as we insert 100 into a year field (1264). // So the cast from double to int won't raise extra error. That's why we directly use // static_cast here. Mysql will convert the double to nearest int and insert it to the year field. double in_val = child_res->get_double(); in_val = in_val < 0 ? INT_MIN : in_val + 0.5; int64_t val_int = static_cast(in_val); if (OB_FAIL(common_int_year(expr, val_int, res_datum))) { LOG_WARN("common_int_time failed", K(ret), K(val_int)); } } return ret; } CAST_FUNC_NAME(double, string) { EVAL_ARG() { double in_val = child_res->get_double(); if (OB_FAIL(common_floating_string(expr, in_val, OB_GCVT_ARG_DOUBLE, ctx, res_datum))) { LOG_WARN("common_floating_string failed", K(ret), K(in_val)); } } return ret; } CAST_FUNC_NAME(double, text) { EVAL_ARG() { ObString res_str; double in_val = child_res->get_double(); if (OB_FAIL(common_floating_string(expr, in_val, OB_GCVT_ARG_DOUBLE, ctx, res_datum))) { LOG_WARN("common_floating_string failed", K(ret), K(in_val)); } else if (OB_FAIL(copy_datum_str_with_tmp_alloc(ctx, res_datum, res_str))) { LOG_WARN("copy datum string with tmp allocator failed", K(ret)); } else if (OB_FAIL(common_string_text(expr, res_str, ctx, NULL, res_datum))) { LOG_WARN("cast string to lob failed", K(ret)); } } return ret; } CAST_FUNC_NAME(double, lob) { EVAL_ARG() { double in_val = child_res->get_double(); ObString res_str; if (OB_FAIL(common_floating_string(expr, in_val, OB_GCVT_ARG_DOUBLE, ctx, res_datum))) { LOG_WARN("common_floating_string failed", K(ret), K(in_val)); } else if (OB_FAIL(copy_datum_str_with_tmp_alloc(ctx, res_datum, res_str))) { LOG_WARN("copy datum string with tmp allocator failed", K(ret)); } else if (OB_FAIL(common_string_lob(expr, res_str, ctx, NULL, res_datum))) { LOG_WARN("cast string to lob failed", K(ret)); } } return ret; } CAST_FUNC_NAME(double, bit) { EVAL_ARG() { res_datum.set_bit(static_cast(child_res->get_double())); } return ret; } CAST_FUNC_NAME(double, json) { EVAL_ARG_FOR_CAST_TO_JSON() { double in_val = child_res->get_double(); ObObjType in_type = expr.args_[0]->datum_meta_.type_; ObJsonDouble j_double(in_val); ObIJsonBase *j_base = &j_double; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); ObString raw_bin; if (OB_FAIL(j_base->get_raw_binary(raw_bin, &temp_allocator))) { LOG_WARN("fail to get double json binary", K(ret), K(in_type), K(in_val)); } else if (OB_FAIL(common_json_bin(expr, ctx, res_datum, raw_bin))) { LOG_WARN("fail to fill json bin lob locator", K(ret)); } } return ret; } CAST_FUNC_NAME(double, geometry) { EVAL_ARG() { ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); ObGeometry *geo = NULL; omt::ObSrsCacheGuard srs_guard; const ObSrsItem *srs = NULL; double in_val = child_res->get_double(); char buf[OB_CAST_TO_VARCHAR_MAX_LENGTH] = {0}; ObScale scale = expr.args_[0]->datum_meta_.scale_; int64_t len = 0; ObGeoType dst_geo_type = ObGeoCastUtils::get_geo_type_from_cast_mode(expr.extra_); const char *cast_name = ObGeometryTypeCastUtil::get_cast_name(dst_geo_type); bool nan_or_inf = is_ieee754_nan_inf(in_val, buf, len); if (nan_or_inf) { LOG_DEBUG("Infinity or NaN value is", K(in_val)); } else { if (0 <= scale) { len = ob_fcvt(in_val, scale, sizeof(buf) - 1, buf, NULL); } else { len = ob_gcvt_opt(in_val, OB_GCVT_ARG_DOUBLE, sizeof(buf) - 1, buf, NULL, false, TRUE); } } ObString in_str(sizeof(buf), static_cast(len), buf); if (OB_FAIL(ObGeoExprUtils::get_srs_item(ctx, srs_guard, in_str, srs, true, cast_name))) { LOG_WARN("fail to get srs item", K(ret), K(in_str)); } else if (OB_FAIL(ObGeoExprUtils::build_geometry(temp_allocator, in_str, geo, srs, cast_name))) { LOG_WARN("fail to parse geometry", K(ret), K(in_val), K(dst_geo_type)); } else { ObString res_wkb; if (OB_FAIL(ObGeoTypeUtil::to_wkb(temp_allocator, *geo, srs, res_wkb))) { LOG_WARN("fail to get wkb", K(ret), K(dst_geo_type)); } else if (OB_FAIL(common_gis_wkb(expr, ctx, res_datum, res_wkb))){ LOG_WARN("fail to copy string", K(ret), K(dst_geo_type)); } } if (OB_FAIL(ret) && CM_IS_COLUMN_CONVERT(expr.extra_) && ObGeoType::GEOMETRY == dst_geo_type) { // adapt mysql ret = OB_ERR_CANT_CREATE_GEOMETRY_OBJECT; LOG_USER_ERROR(OB_ERR_CANT_CREATE_GEOMETRY_OBJECT); } } return ret; } CAST_FUNC_NAME(datetime, int) { EVAL_ARG() { GET_SESSION() { DEF_IN_OUT_TYPE(); const ObTimeZoneInfo *tz_info = (ObTimestampType == in_type) ? session->get_timezone_info() : NULL; int64_t in_val = child_res->get_int(); int64_t out_val = 0; if (OB_FAIL(ObTimeConverter::datetime_to_int(in_val, tz_info, out_val))) { LOG_WARN("datetime_to_int failed", K(ret), K(in_val)); } else if (out_type < ObIntType && CAST_FAIL(int_range_check(out_type, out_val, out_val))) { LOG_WARN("int_range_check failed", K(ret)); } else { res_datum.set_int(out_val); } } } return ret; } CAST_FUNC_NAME(datetime, uint) { EVAL_ARG() { GET_SESSION() { DEF_IN_OUT_TYPE(); const ObTimeZoneInfo *tz_info = (ObTimestampType == in_type) ? session->get_timezone_info() : NULL; int64_t in_val = child_res->get_int(); int64_t val_int = 0; uint64_t out_val = 0; if (OB_FAIL(ObTimeConverter::datetime_to_int(in_val, tz_info, val_int))) { LOG_WARN("datetime_to_int failed", K(ret), K(in_val)); } else { out_val = static_cast(val_int); if (out_type < ObUInt64Type && CAST_FAIL(uint_range_check(out_type, val_int, out_val))) { LOG_WARN("int_range_check failed", K(ret)); } else { res_datum.set_uint(out_val); } } } } return ret; } CAST_FUNC_NAME(datetime, double) { EVAL_ARG() { GET_SESSION() { int64_t in_val = child_res->get_int(); double out_val = 0.0; ObObjType in_type = expr.args_[0]->datum_meta_.type_; const ObTimeZoneInfo *tz_info = (ObTimestampType == in_type) ? session->get_timezone_info() : NULL; if (OB_FAIL(ObTimeConverter::datetime_to_double(in_val, tz_info, out_val))) { LOG_WARN("datetime_to_double failed", K(ret), K(in_val)); } else { res_datum.set_double(out_val); } } } return ret; } CAST_FUNC_NAME(datetime, float) { EVAL_ARG() { GET_SESSION() { int64_t in_val = child_res->get_int(); double out_val = 0.0; ObObjType in_type = expr.args_[0]->datum_meta_.type_; const ObTimeZoneInfo *tz_info = (ObTimestampType == in_type) ? session->get_timezone_info() : NULL; if (OB_FAIL(ObTimeConverter::datetime_to_double(in_val, tz_info, out_val))) { LOG_WARN("datetime_to_double failed", K(ret), K(in_val)); } else { res_datum.set_float(static_cast(out_val)); } } } return ret; } CAST_FUNC_NAME(datetime, number) { EVAL_ARG() { GET_SESSION() { int warning = OB_SUCCESS; ObObjType in_type = expr.args_[0]->datum_meta_.type_; int64_t in_val = child_res->get_int(); ObString nls_format; char buf[OB_CAST_TO_VARCHAR_MAX_LENGTH] = {0}; int64_t len = 0; ObNumStackOnceAlloc tmp_alloc; number::ObNumber number; ObPrecision res_precision; // useless ObScale res_scale; // useless ObScale in_scale = expr.args_[0]->datum_meta_.scale_; const ObTimeZoneInfo *tz_info = (ObTimestampType == in_type) ? session->get_timezone_info() : NULL; if (OB_FAIL(ObTimeConverter::datetime_to_str(in_val, tz_info, nls_format, in_scale, buf, sizeof(buf), len, false))) { LOG_WARN("failed to convert datetime to string", K(ret)); } else if (CAST_FAIL(number.from(buf, len, tmp_alloc, &res_precision, &res_scale))) { LOG_WARN("failed to convert string to number", K(ret)); } else { res_datum.set_number(number); } } } return ret; } CAST_FUNC_NAME(datetime, datetime) { EVAL_ARG() { GET_SESSION() { int64_t in_val = child_res->get_int(); int64_t out_val = in_val; ObObjType in_type = expr.args_[0]->datum_meta_.type_; ObObjType out_type = expr.datum_meta_.type_; if (ObDateTimeType == in_type && ObTimestampType == out_type) { ret = ObTimeConverter::datetime_to_timestamp(in_val, session->get_timezone_info(), out_val); ret = OB_ERR_UNEXPECTED_TZ_TRANSITION == ret ? OB_INVALID_DATE_VALUE : ret; } else if (ObTimestampType == in_type && ObDateTimeType == out_type) { ret = ObTimeConverter::timestamp_to_datetime(out_val, session->get_timezone_info(), out_val); } if (OB_FAIL(ret)) { } else { res_datum.set_datetime(out_val); } } } return ret; } CAST_FUNC_NAME(datetime, date) { EVAL_ARG() { GET_SESSION() { int64_t in_val = child_res->get_int(); int32_t out_val = 0; ObObjType in_type = expr.args_[0]->datum_meta_.type_; const ObTimeZoneInfo *tz_info = (ObTimestampType == in_type) ? session->get_timezone_info() : NULL; if (OB_FAIL(ObTimeConverter::datetime_to_date(in_val, tz_info, out_val))) { LOG_WARN("datetime_to_date failed", K(ret), K(in_val)); } else { res_datum.set_date(out_val); } LOG_DEBUG("in datetime date cast", K(ret), K(out_val), K(in_val)); } } return ret; } CAST_FUNC_NAME(datetime, time) { EVAL_ARG() { GET_SESSION() { int64_t in_val = child_res->get_int(); int64_t out_val = 0; ObObjType in_type = expr.args_[0]->datum_meta_.type_; const ObTimeZoneInfo *tz_info = (ObTimestampType == in_type) ? session->get_timezone_info() : NULL; if (OB_FAIL(ObTimeConverter::datetime_to_time(in_val, tz_info, out_val))) { } else { res_datum.set_time(out_val); } } } return ret; } CAST_FUNC_NAME(datetime, year) { EVAL_ARG() { GET_SESSION() { DEF_IN_OUT_VAL(int64_t, uint8_t, 0); ObObjType in_type = expr.args_[0]->datum_meta_.type_; const ObTimeZoneInfo *tz_info = (ObTimestampType == in_type) ? session->get_timezone_info() : NULL; if (CAST_FAIL(ObTimeConverter::datetime_to_year(in_val, tz_info, out_val))) { } else { res_datum.set_year(out_val); } } } return ret; } CAST_FUNC_NAME(datetime, string) { EVAL_ARG() { char buf[OB_CAST_TO_VARCHAR_MAX_LENGTH] = {0}; int64_t len = 0; int64_t in_val = child_res->get_int(); if (OB_FAIL(common_datetime_string(expr.args_[0]->datum_meta_.type_, expr.datum_meta_.type_, expr.args_[0]->datum_meta_.scale_, CM_IS_FORCE_USE_STANDARD_NLS_FORMAT(expr.extra_), in_val, ctx, buf, sizeof(buf), len))) { LOG_WARN("common_datetime_string failed", K(ret)); } else { ObString str(len, buf); if (OB_FAIL(common_copy_string(expr, str, ctx, res_datum))) { LOG_WARN("common_copy_string failed", K(ret)); } } } return ret; } CAST_FUNC_NAME(datetime, text) { EVAL_ARG() { char buf[OB_CAST_TO_VARCHAR_MAX_LENGTH] = {0}; int64_t len = 0; int64_t in_val = child_res->get_int(); if (OB_FAIL(common_datetime_string(expr.args_[0]->datum_meta_.type_, expr.datum_meta_.type_, expr.args_[0]->datum_meta_.scale_, CM_IS_FORCE_USE_STANDARD_NLS_FORMAT(expr.extra_), in_val, ctx, buf, sizeof(buf), len))) { LOG_WARN("common_datetime_string failed", K(ret)); } else { ObString str(len, buf); if (OB_FAIL(common_copy_string_to_text_result(expr, str, ctx, res_datum))) { LOG_WARN("common_copy_string_to_lob failed", K(ret)); } } } return ret; } CAST_FUNC_NAME(datetime, bit) { EVAL_ARG() { char buf[OB_CAST_TO_VARCHAR_MAX_LENGTH] = {0}; int64_t len = 0; int64_t in_val = child_res->get_int(); if (OB_FAIL(common_datetime_string(expr.args_[0]->datum_meta_.type_, expr.datum_meta_.type_, expr.args_[0]->datum_meta_.scale_, CM_IS_FORCE_USE_STANDARD_NLS_FORMAT(expr.extra_), in_val, ctx, buf, sizeof(buf), len))) { LOG_WARN("common_datetime_string failed", K(ret)); } else if (OB_FAIL(common_string_bit(expr, ObString(len, buf), ctx, res_datum))) { LOG_WARN("common_string_bit failed", K(ret)); } } return ret; } CAST_FUNC_NAME(datetime, otimestamp) { EVAL_ARG() { GET_SESSION() { DEF_IN_OUT_TYPE(); const ObTimeZoneInfo *tz_info = session->get_timezone_info(); int64_t in_val = child_res->get_int(); ObOTimestampData out_val; if (OB_FAIL(ObTimeConverter::odate_to_otimestamp(in_val, tz_info, out_type, out_val))) { LOG_WARN("fail to timestamp_to_timestamp_tz", K(ret), K(in_val), K(in_type), K(out_type)); } else { if (ObTimestampTZType == out_type) { SET_RES_OTIMESTAMP(out_val); } else { SET_RES_OTIMESTAMP_10BYTE(out_val); } } } } return ret; } CAST_FUNC_NAME(datetime, lob) { EVAL_ARG() { char buf[OB_CAST_TO_VARCHAR_MAX_LENGTH] = {0}; int64_t len = 0; int64_t in_val = child_res->get_int(); if (OB_FAIL(common_datetime_string(expr.args_[0]->datum_meta_.type_, ObLongTextType, expr.args_[0]->datum_meta_.scale_, CM_IS_FORCE_USE_STANDARD_NLS_FORMAT(expr.extra_), in_val, ctx, buf, sizeof(buf), len))) { LOG_WARN("common_datetime_string failed", K(ret)); } else { ObString str(len, buf); ObString res_str; if (OB_FAIL(common_copy_string(expr, str, ctx, res_datum))) { LOG_WARN("common_copy_string failed", K(ret)); } else if (OB_FAIL(copy_datum_str_with_tmp_alloc(ctx, res_datum, res_str))) { LOG_WARN("copy datum string with tmp allocator failed", K(ret)); } else if (OB_FAIL(common_string_lob(expr, res_str, ctx, NULL, res_datum))) { LOG_WARN("cast string to lob failed", K(ret)); } } } return ret; } CAST_FUNC_NAME(datetime, json) { EVAL_ARG_FOR_CAST_TO_JSON() { GET_SESSION() { int64_t in_val = child_res->get_datetime(); ObObjType in_type = expr.args_[0]->datum_meta_.type_; ObTime ob_time(DT_TYPE_DATETIME); const ObTimeZoneInfo *tz_info = (ObTimestampType == in_type) ? session->get_timezone_info() : NULL; if (OB_FAIL(ObTimeConverter::datetime_to_ob_time(in_val, tz_info, ob_time))) { LOG_WARN("fail to create datetime from int failed", K(ret), K(in_type), K(in_val)); } else { ObJsonNodeType node_type = (ObTimestampType == in_type) ? ObJsonNodeType::J_TIMESTAMP : ObJsonNodeType::J_DATETIME; ObJsonDatetime j_datetime(node_type, ob_time); ObIJsonBase *j_base = &j_datetime; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); ObString raw_bin; if (OB_FAIL(j_base->get_raw_binary(raw_bin, &temp_allocator))) { LOG_WARN("fail to get datetime json binary", K(ret), K(in_type), K(in_val)); } else if (OB_FAIL(common_json_bin(expr, ctx, res_datum, raw_bin))) { LOG_WARN("fail to fill json bin lob locator", K(ret)); } } } } return ret; } CAST_FUNC_NAME(datetime, geometry) { EVAL_ARG() { char buf[OB_CAST_TO_VARCHAR_MAX_LENGTH] = {0}; int64_t len = 0; int64_t in_val = child_res->get_int(); if (OB_FAIL(common_datetime_string(expr.args_[0]->datum_meta_.type_, expr.datum_meta_.type_, expr.args_[0]->datum_meta_.scale_, CM_IS_FORCE_USE_STANDARD_NLS_FORMAT(expr.extra_), in_val, ctx, buf, sizeof(buf), len))) { LOG_WARN("common_datetime_string failed", K(ret)); } else { ObString in_str(sizeof(buf), static_cast(len), buf); ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); ObGeometry *geo = NULL; omt::ObSrsCacheGuard srs_guard; const ObSrsItem *srs = NULL; ObGeoType dst_geo_type = ObGeoCastUtils::get_geo_type_from_cast_mode(expr.extra_); const char *cast_name = ObGeometryTypeCastUtil::get_cast_name(dst_geo_type); if (OB_FAIL(ObGeoExprUtils::get_srs_item(ctx, srs_guard, in_str, srs, true, cast_name))) { LOG_WARN("fail to get srs item", K(ret), K(in_str)); } else if (OB_FAIL(ObGeoExprUtils::build_geometry(temp_allocator, in_str, geo, srs, cast_name))) { LOG_WARN("fail to parse geometry", K(ret), K(in_val), K(dst_geo_type)); } else { ObString res_wkb; if (OB_FAIL(ObGeoTypeUtil::to_wkb(temp_allocator, *geo, srs, res_wkb))) { LOG_WARN("fail to get wkb", K(ret), K(dst_geo_type)); } else if (OB_FAIL(common_gis_wkb(expr, ctx, res_datum, res_wkb))){ LOG_WARN("fail to copy string", K(ret), K(dst_geo_type)); } } if (OB_FAIL(ret) && CM_IS_COLUMN_CONVERT(expr.extra_) && ObGeoType::GEOMETRY == dst_geo_type) { // adapt mysql ret = OB_ERR_CANT_CREATE_GEOMETRY_OBJECT; LOG_USER_ERROR(OB_ERR_CANT_CREATE_GEOMETRY_OBJECT); } } } return ret; } CAST_FUNC_NAME(date, int) { EVAL_ARG() { DEF_IN_OUT_VAL(int32_t, int64_t, 0); ObObjType out_type = expr.datum_meta_.type_; if (OB_FAIL(ObTimeConverter::date_to_int(in_val, out_val))) { LOG_WARN("date_to_int failed", K(ret)); } else if (out_type < ObInt32Type && CAST_FAIL(int_range_check(out_type, out_val, out_val))) { LOG_WARN("int_range_check failed", K(ret)); } else { res_datum.set_int(out_val); } } return ret; } CAST_FUNC_NAME(date, uint) { EVAL_ARG() { DEF_IN_OUT_VAL(int32_t, uint64_t, 0); int64_t val_int = 0; ObObjType out_type = expr.datum_meta_.type_; if (OB_FAIL(ObTimeConverter::date_to_int(in_val, val_int))) { LOG_WARN("date_to_int failed", K(ret), K(in_val), K(val_int)); } else { out_val = static_cast(val_int); if (out_type < ObUInt32Type && CAST_FAIL(uint_range_check(out_type, val_int, out_val))) { LOG_WARN("uint_range_check failed", K(ret), K(val_int), K(out_val)); } else { res_datum.set_uint(out_val); } } } return ret; } CAST_FUNC_NAME(date, float) { EVAL_ARG() { int32_t in_val = child_res->get_date(); int64_t out_val = 0; if (OB_FAIL(ObTimeConverter::date_to_int(in_val, out_val))) { } else { res_datum.set_float(static_cast(out_val)); } } return ret; } CAST_FUNC_NAME(date, double) { EVAL_ARG() { int32_t in_val = child_res->get_date(); int64_t out_val = 0; if (OB_FAIL(ObTimeConverter::date_to_int(in_val, out_val))) { } else { res_datum.set_double(static_cast(out_val)); } } return ret; } CAST_FUNC_NAME(date, number) { EVAL_ARG() { DEF_IN_OUT_VAL(int32_t, int64_t, 0); ObNumStackOnceAlloc tmp_alloc; number::ObNumber number; if (OB_FAIL(ObTimeConverter::date_to_int(in_val, out_val))) { LOG_WARN("date_to_int failed", K(ret)); } else if (CAST_FAIL(numeric_negative_check(out_val))) { LOG_WARN("numeric_negative_check failed", K(ret), K(out_val)); } else if (OB_FAIL(number.from(out_val, tmp_alloc))) { LOG_WARN("number.from failed", K(ret), K(out_val)); } else { res_datum.set_number(number); } } return ret; } CAST_FUNC_NAME(date, datetime) { EVAL_ARG() { GET_SESSION() { ObObjType out_type = expr.datum_meta_.type_; ObTimeConvertCtx cvrt_ctx(session->get_timezone_info(), ObTimestampType == out_type); int32_t in_val = child_res->get_date(); int64_t out_val = 0; if (OB_FAIL(ObTimeConverter::date_to_datetime(in_val, cvrt_ctx, out_val))) { LOG_WARN("date_to_datetime failed", K(ret), K(in_val)); } else { res_datum.set_datetime(out_val); } } } return ret; } CAST_FUNC_NAME(date, time) { EVAL_ARG() { res_datum.set_time(ObTimeConverter::ZERO_TIME); } return ret; } CAST_FUNC_NAME(date, year) { EVAL_ARG() { DEF_IN_OUT_VAL(int32_t, uint8_t, 0); if (CAST_FAIL(ObTimeConverter::date_to_year(in_val, out_val))) { LOG_WARN("date_to_year failed", K(ret)); } else { SET_RES_YEAR(out_val); } } return ret; } CAST_FUNC_NAME(date, string) { EVAL_ARG() { int32_t in_val = child_res->get_date(); char buf[OB_CAST_TO_VARCHAR_MAX_LENGTH] = {0}; int64_t len = 0; if (OB_FAIL(ObTimeConverter::date_to_str(in_val, buf, sizeof(buf), len))) { LOG_WARN("date_to_str failed", K(ret)); } else { ObString in_str(len, buf); if (OB_FAIL(common_copy_string(expr, in_str, ctx, res_datum))) { LOG_WARN("common_copy_string failed", K(ret)); } } } return ret; } CAST_FUNC_NAME(date, text) { EVAL_ARG() { int32_t in_val = child_res->get_date(); char buf[OB_CAST_TO_VARCHAR_MAX_LENGTH] = {0}; int64_t len = 0; if (OB_FAIL(ObTimeConverter::date_to_str(in_val, buf, sizeof(buf), len))) { LOG_WARN("date_to_str failed", K(ret)); } else { ObString in_str(len, buf); if (OB_FAIL(common_copy_string_to_text_result(expr, in_str, ctx, res_datum))) { LOG_WARN("common_copy_string failed", K(ret)); } } } return ret; } CAST_FUNC_NAME(date, bit) { EVAL_ARG() { int32_t in_val = child_res->get_date(); char buf[OB_CAST_TO_VARCHAR_MAX_LENGTH] = {0}; int64_t len = 0; if (OB_FAIL(ObTimeConverter::date_to_str(in_val, buf, sizeof(buf), len))) { LOG_WARN("date_to_str failed", K(ret)); } else { ObString in_str(len, buf); if (OB_FAIL(common_string_bit(expr, in_str, ctx, res_datum))) { LOG_WARN("common_string_bit failed", K(ret)); } } } return ret; } CAST_FUNC_NAME(date, json) { EVAL_ARG_FOR_CAST_TO_JSON() { int32_t in_val = child_res->get_date(); ObObjType in_type = expr.args_[0]->datum_meta_.type_; if (lib::is_oracle_mode() && in_val != 0) { if (CM_IS_IMPLICIT_CAST(expr.extra_)) { ret = OB_ERR_INVALID_INPUT; LOG_WARN("invalid input in implicit cast", K(ret)); } else { LOG_WARN("inconsistent datatypes", K(ret), K(in_type), K("json"), K(expr.extra_)); ret = OB_ERR_INVALID_TYPE_FOR_OP; } } else { ObTime ob_time(DT_TYPE_DATE); if (OB_FAIL(ObTimeConverter::date_to_ob_time(in_val, ob_time))) { LOG_WARN("fail to create ob time from date failed", K(ret), K(in_type), K(in_val)); } else { ObJsonDatetime j_date(ObJsonNodeType::J_DATE, ob_time); ObIJsonBase *j_base = &j_date; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); ObString raw_bin; if (OB_FAIL(j_base->get_raw_binary(raw_bin, &temp_allocator))) { LOG_WARN("fail to get date json binary", K(ret), K(in_type), K(in_val)); } else if (OB_FAIL(common_json_bin(expr, ctx, res_datum, raw_bin))) { LOG_WARN("fail to fill json bin lob locator", K(ret)); } } } } return ret; } CAST_FUNC_NAME(date, geometry) { EVAL_ARG() { int32_t in_val = child_res->get_int32(); char buf[OB_CAST_TO_VARCHAR_MAX_LENGTH] = {0}; int64_t len = 0; if (OB_FAIL(ObTimeConverter::date_to_str(in_val, buf, sizeof(buf), len))) { LOG_WARN("date_to_str failed", K(ret)); } else { ObString in_str(len, buf); ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); ObGeometry *geo = NULL; omt::ObSrsCacheGuard srs_guard; const ObSrsItem *srs = NULL; ObGeoType dst_geo_type = ObGeoCastUtils::get_geo_type_from_cast_mode(expr.extra_); const char *cast_name = ObGeometryTypeCastUtil::get_cast_name(dst_geo_type); if (OB_FAIL(ObGeoExprUtils::get_srs_item(ctx, srs_guard, in_str, srs, true, cast_name))) { LOG_WARN("fail to get srs item", K(ret), K(in_str)); } else if (OB_FAIL(ObGeoExprUtils::build_geometry(temp_allocator, in_str, geo, srs, cast_name))) { LOG_WARN("fail to parse geometry", K(ret), K(in_val), K(dst_geo_type)); } else { ObString res_wkb; if (OB_FAIL(ObGeoTypeUtil::to_wkb(temp_allocator, *geo, srs, res_wkb))) { LOG_WARN("fail to get wkb", K(ret), K(dst_geo_type)); } else if (OB_FAIL(common_gis_wkb(expr, ctx, res_datum, res_wkb))){ LOG_WARN("fail to copy string", K(ret), K(dst_geo_type)); } } if (OB_FAIL(ret) && CM_IS_COLUMN_CONVERT(expr.extra_) && ObGeoType::GEOMETRY == dst_geo_type) { // adapt mysql ret = OB_ERR_CANT_CREATE_GEOMETRY_OBJECT; LOG_USER_ERROR(OB_ERR_CANT_CREATE_GEOMETRY_OBJECT); } } } return ret; } CAST_FUNC_NAME(year, int) { EVAL_ARG() { uint8_t in_val = child_res->get_year(); int64_t out_val = 0; ObObjType out_type = expr.datum_meta_.type_; if (OB_FAIL(common_year_int(expr, out_type, in_val, out_val))) { LOG_WARN("common_year_int failed", K(ret)); } else { res_datum.set_int(out_val); } } return ret; } CAST_FUNC_NAME(year, uint) { EVAL_ARG() { DEF_IN_OUT_VAL(uint8_t, uint64_t, 0); int64_t val_int = 0; ObObjType out_type = expr.datum_meta_.type_; if (OB_FAIL(ObTimeConverter::year_to_int(in_val, val_int))) { LOG_WARN("year_to_int failed", K(ret)); } else { out_val = static_cast(val_int); if (out_type < ObUSmallIntType && CAST_FAIL(uint_range_check(out_type, val_int, out_val))) { LOG_WARN("uint_range_check failed", K(ret)); } else { res_datum.set_uint(out_val); } } } return ret; } CAST_FUNC_NAME(year, float) { EVAL_ARG() { uint8_t in_val = child_res->get_year(); int64_t val_int = 0; if (OB_FAIL(ObTimeConverter::year_to_int(in_val, val_int))) { LOG_WARN("year_to_int failed", K(ret), K(in_val)); } else { res_datum.set_float(static_cast(val_int)); } } return ret; } CAST_FUNC_NAME(year, double) { EVAL_ARG() { uint8_t in_val = child_res->get_year(); int64_t val_int = 0; if (OB_FAIL(ObTimeConverter::year_to_int(in_val, val_int))) { LOG_WARN("year_to_int failed", K(ret), K(in_val)); } else { res_datum.set_double(static_cast(val_int)); } } return ret; } CAST_FUNC_NAME(year, number) { EVAL_ARG() { uint8_t in_val = child_res->get_year(); int64_t val_int = 0; ObNumStackOnceAlloc tmp_alloc; number::ObNumber number; if (OB_FAIL(common_year_int(expr, ObIntType, in_val, val_int))) { LOG_WARN("common_year_int failed", K(ret), K(in_val)); } else if (OB_FAIL(common_int_number(expr, val_int, tmp_alloc, number))) { LOG_WARN("common_int_number failed", K(ret), K(val_int)); } else { res_datum.set_number(number); } } return ret; } CAST_FUNC_NAME(year, string) { EVAL_ARG() { char buf[OB_CAST_TO_VARCHAR_MAX_LENGTH] = {0}; int64_t len = 0; uint8_t in_val = child_res->get_year(); if (OB_FAIL(ObTimeConverter::year_to_str(in_val, buf, sizeof(buf), len))) { LOG_WARN("year_to_str failed", K(ret), K(in_val)); } else { ObString in_str(len, buf); if (OB_FAIL(common_copy_string(expr, in_str, ctx, res_datum))) { LOG_WARN("common_copy_string failed", K(ret)); } } } return ret; } CAST_FUNC_NAME(year, text) { EVAL_ARG() { char buf[OB_CAST_TO_VARCHAR_MAX_LENGTH] = {0}; int64_t len = 0; uint8_t in_val = child_res->get_year(); if (OB_FAIL(ObTimeConverter::year_to_str(in_val, buf, sizeof(buf), len))) { LOG_WARN("year_to_str failed", K(ret), K(in_val)); } else { ObString in_str(len, buf); if (OB_FAIL(common_copy_string_to_text_result(expr, in_str, ctx, res_datum))) { LOG_WARN("common_copy_string_to_text_result failed", K(ret)); } } } return ret; } CAST_FUNC_NAME(year, datetime) { EVAL_ARG() { uint8_t in_val = child_res->get_year(); int64_t val_int = 0; if (OB_FAIL(common_year_int(expr, ObIntType, in_val, val_int))) { LOG_WARN("common_year_int failed", K(ret), K(in_val)); } else if (OB_FAIL(common_int_datetime(expr, val_int, ctx, res_datum))) { LOG_WARN("common_int_datetime failed", K(ret), K(val_int)); } } return ret; } CAST_FUNC_NAME(year, date) { EVAL_ARG() { uint8_t in_val = child_res->get_year(); int64_t val_int = 0; if (OB_FAIL(common_year_int(expr, ObIntType, in_val, val_int))) { LOG_WARN("common_year_int failed", K(ret), K(in_val)); } else if (OB_FAIL(common_int_date(expr, val_int, res_datum))) { LOG_WARN("common_int_date failed", K(ret), K(val_int)); } } return ret; } CAST_FUNC_NAME(year, bit) { EVAL_ARG() { int64_t year_int = 0; uint8_t in_val = child_res->get_year(); if (OB_FAIL(ObTimeConverter::year_to_int(in_val, year_int))) { LOG_WARN("year_to_int failed", K(ret), K(in_val)); } else if (OB_FAIL(common_uint_bit(expr, year_int, ctx, res_datum))) { LOG_WARN("common_uint_bit failed", K(ret), K(year_int)); } } return ret; } CAST_FUNC_NAME(year, json) { EVAL_ARG_FOR_CAST_TO_JSON() { uint8_t in_val = child_res->get_year(); ObObjType in_type = expr.args_[0]->datum_meta_.type_; int64_t full_year = 0; if (OB_FAIL(ObTimeConverter::year_to_int(in_val, full_year))) { LOG_WARN("convert year to int failed in year to json convert", K(ret), K(in_val)); } else { ObJsonInt j_year(full_year); ObIJsonBase *j_base = &j_year; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); ObString raw_bin; if (OB_FAIL(j_base->get_raw_binary(raw_bin, &temp_allocator))) { LOG_WARN("fail to get year json binary", K(ret), K(in_type), K(in_val)); } else if (OB_FAIL(common_json_bin(expr, ctx, res_datum, raw_bin))) { LOG_WARN("fail to fill json bin lob locator", K(ret)); } } } return ret; } CAST_FUNC_NAME(year, geometry) { EVAL_ARG() { char buf[OB_CAST_TO_VARCHAR_MAX_LENGTH] = {0}; int64_t len = 0; uint8_t in_val = child_res->get_uint8(); if (OB_FAIL(ObTimeConverter::year_to_str(in_val, buf, sizeof(buf), len))) { LOG_WARN("year_to_str failed", K(ret), K(in_val)); } else { ObString in_str(len, buf); ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); ObGeometry *geo = NULL; omt::ObSrsCacheGuard srs_guard; const ObSrsItem *srs = NULL; ObGeoType dst_geo_type = ObGeoCastUtils::get_geo_type_from_cast_mode(expr.extra_); const char *cast_name = ObGeometryTypeCastUtil::get_cast_name(dst_geo_type); if (OB_FAIL(ObGeoExprUtils::get_srs_item(ctx, srs_guard, in_str, srs, true, cast_name))) { LOG_WARN("fail to get srs item", K(ret), K(in_str)); } else if (OB_FAIL(ObGeoExprUtils::build_geometry(temp_allocator, in_str, geo, srs, cast_name))) { LOG_WARN("fail to parse geometry", K(ret), K(in_val), K(dst_geo_type)); } else { ObString res_wkb; if (OB_FAIL(ObGeoTypeUtil::to_wkb(temp_allocator, *geo, srs, res_wkb))) { LOG_WARN("fail to get wkb", K(ret), K(dst_geo_type)); } else if (OB_FAIL(common_gis_wkb(expr, ctx, res_datum, res_wkb))){ LOG_WARN("fail to copy string", K(ret), K(dst_geo_type)); } } if (OB_FAIL(ret) && CM_IS_COLUMN_CONVERT(expr.extra_) && ObGeoType::GEOMETRY == dst_geo_type) { // adapt mysql ret = OB_ERR_CANT_CREATE_GEOMETRY_OBJECT; LOG_USER_ERROR(OB_ERR_CANT_CREATE_GEOMETRY_OBJECT); } } } return ret; } CAST_FUNC_NAME(bit, int) { EVAL_ARG() { DEF_IN_OUT_VAL(uint64_t, int64_t, static_cast(in_val)); ObObjType out_type = expr.datum_meta_.type_; if (out_type < ObIntType && CM_NEED_RANGE_CHECK(expr.extra_) && CAST_FAIL(int_range_check(out_type, in_val, out_val))) { LOG_WARN("int_range_check failed", K(ret)); } else { res_datum.set_int(out_val); } } return ret; } CAST_FUNC_NAME(bit, uint) { EVAL_ARG() { int warning = OB_SUCCESS; uint64_t out_val = child_res->get_uint(); ObObjType out_type = expr.datum_meta_.type_; if (out_type < ObUInt64Type && CM_NEED_RANGE_CHECK(expr.extra_) && CAST_FAIL(uint_upper_check(out_type, out_val))) { LOG_WARN("uint_upper_check failed", K(ret)); } else { SET_RES_UINT(out_val); } } return ret; } CAST_FUNC_NAME(bit, float) { EVAL_ARG() { uint64_t in_val = child_res->get_uint(); res_datum.set_float(static_cast(in_val)); } return ret; } CAST_FUNC_NAME(bit, double) { EVAL_ARG() { uint64_t in_val = child_res->get_uint(); res_datum.set_double(static_cast(in_val)); } return ret; } CAST_FUNC_NAME(bit, number) { EVAL_ARG() { int64_t in_val = child_res->get_uint(); ObNumStackOnceAlloc tmp_alloc; number::ObNumber number; if (OB_FAIL(number.from(in_val, tmp_alloc))) { LOG_WARN("number.from failed", K(ret), K(in_val)); } else { res_datum.set_number(number); } } return ret; } CAST_FUNC_NAME(bit, datetime) { EVAL_ARG() { GET_SESSION() { DEF_IN_OUT_VAL(uint64_t, int64_t, 0); ObDateSqlMode date_sql_mode; date_sql_mode.allow_invalid_dates_ = CM_IS_ALLOW_INVALID_DATES(expr.extra_); date_sql_mode.no_zero_date_ = CM_IS_NO_ZERO_DATE(expr.extra_); if (CM_IS_COLUMN_CONVERT(expr.extra_)) { // if cast mode is column convert, using bit as int64 to do cast. int64_t int64 = 0; if (OB_FAIL(common_uint_int(expr, ObIntType, in_val, ctx, int64))) { LOG_WARN("common_uint_int failed", K(ret)); } else if (OB_UNLIKELY(0 > int64)) { ret = OB_INVALID_DATE_FORMAT; LOG_WARN("invalid date", K(ret), K(int64)); } else { ObTimeConvertCtx cvrt_ctx(session->get_timezone_info(), ObTimestampType == expr.datum_meta_.type_); if (CAST_FAIL(ObTimeConverter::int_to_datetime(int64, 0, cvrt_ctx, out_val, date_sql_mode))) { LOG_WARN("int_datetime failed", K(ret), K(int64)); } } } else { // using bit as char array to do cast. const int32_t BUF_LEN = (OB_MAX_BIT_LENGTH + 7) / 8; int64_t pos = 0; char buf[BUF_LEN] = {0}; ObLengthSemantics length = expr.args_[0]->datum_meta_.length_semantics_; if (OB_FAIL(bit_to_char_array(in_val, length, buf, BUF_LEN, pos))) { LOG_WARN("fail to store val", K(buf), K(BUF_LEN), K(in_val), K(pos)); } else { ObObjType out_type = expr.datum_meta_.type_; ObString str(pos, buf); ObTimeConvertCtx cvrt_ctx(session->get_timezone_info(), ObTimestampType == out_type); ObScale res_scale; if (CAST_FAIL(ObTimeConverter::str_to_datetime(str, cvrt_ctx, out_val, &res_scale, date_sql_mode))) { LOG_WARN("str_to_datetime failed", K(ret)); } } } if (OB_SUCC(ret)) { SET_RES_DATETIME(out_val); } } } return ret; } CAST_FUNC_NAME(bit, date) { EVAL_ARG() { DEF_IN_OUT_VAL(uint64_t, int32_t, 0); ObDateSqlMode date_sql_mode; date_sql_mode.allow_invalid_dates_ = CM_IS_ALLOW_INVALID_DATES(expr.extra_); date_sql_mode.no_zero_date_ = CM_IS_NO_ZERO_DATE(expr.extra_); if (CM_IS_COLUMN_CONVERT(expr.extra_)) { // if cast mode is column convert, using bit as int64 to do cast. int64_t int64 = 0; if (OB_FAIL(common_uint_int(expr, ObIntType, in_val, ctx, int64))) { LOG_WARN("common_uint_int failed", K(ret)); } else if (CAST_FAIL(ObTimeConverter::int_to_date(int64, out_val, date_sql_mode))) { LOG_WARN("int_to_date failed", K(ret), K(int64), K(out_val)); } } else { // using bit as char array to do cast. const int32_t BUF_LEN = (OB_MAX_BIT_LENGTH + 7) / 8; int64_t pos = 0; char buf[BUF_LEN] = {0}; ObLengthSemantics length = expr.args_[0]->datum_meta_.length_semantics_; if (OB_FAIL(bit_to_char_array(in_val, length, buf, BUF_LEN, pos))) { LOG_WARN("fail to store val", K(buf), K(BUF_LEN), K(in_val), K(pos)); } else { ObString str(pos, buf); if (CAST_FAIL(ObTimeConverter::str_to_date(str, out_val, date_sql_mode))) { LOG_WARN("str_to_datetime failed", K(ret)); } } } if (OB_SUCC(ret)) { SET_RES_DATE(out_val); } } return ret; } CAST_FUNC_NAME(bit, time) { EVAL_ARG() { DEF_IN_OUT_VAL(uint64_t, int64_t, 0); if (CM_IS_COLUMN_CONVERT(expr.extra_)) { // if cast mode is column convert, using bit as int64 to do cast. int64_t int64 = 0; if (OB_FAIL(common_uint_int(expr, ObIntType, in_val, ctx, int64))) { LOG_WARN("common_uint_int failed", K(ret), K(in_val)); } else if (OB_FAIL(common_int_time(expr, int64, res_datum))) { LOG_WARN("common_int_time failed", K(ret), K(out_val)); } } else { // using bit as char array to do cast. const int32_t BUF_LEN = (OB_MAX_BIT_LENGTH + 7) / 8; int64_t pos = 0; char buf[BUF_LEN] = {0}; ObLengthSemantics length = expr.args_[0]->datum_meta_.length_semantics_; if (OB_FAIL(bit_to_char_array(in_val, length, buf, BUF_LEN, pos))) { LOG_WARN("fail to store val", K(buf), K(BUF_LEN), K(in_val), K(pos)); } else { ObString str(pos, buf); ObScale res_scale; if (CAST_FAIL(ObTimeConverter::str_to_time(str, out_val, &res_scale))) { LOG_WARN("str_to_datetime failed", K(ret)); } else { SET_RES_TIME(out_val); } } } } return ret; } CAST_FUNC_NAME(bit, year) { EVAL_ARG() { // same as uint to year uint64_t in_val = child_res->get_uint(); int64_t out_val = 0; if (OB_FAIL(common_uint_int(expr, ObIntType, in_val, ctx, out_val))) { LOG_WARN("common_uint_int failed", K(ret), K(in_val)); } else if (OB_FAIL(common_int_year(expr, out_val, res_datum))) { LOG_WARN("common_int_year failed", K(ret), K(out_val)); } } return ret; } CAST_FUNC_NAME(bit, string) { EVAL_ARG() { uint64_t in_val = child_res->get_uint(); if (CM_IS_COLUMN_CONVERT(expr.extra_)) { // if cast mode is column convert, using bit as int64 to do cast. ObFastFormatInt ffi(in_val); if (OB_FAIL(common_copy_string_zf(expr, ObString(ffi.length(), ffi.ptr()), ctx, res_datum))) { LOG_WARN("common_copy_string_zf failed", K(ret), K(ObString(ffi.length(), ffi.ptr()))); } } else { // using bit as char array to do cast. const int32_t BUF_LEN = (OB_MAX_BIT_LENGTH + 7) / 8; int64_t pos = 0; char buf[BUF_LEN] = {0}; ObLengthSemantics length = expr.args_[0]->datum_meta_.length_semantics_; if (OB_FAIL(bit_to_char_array(in_val, length, buf, BUF_LEN, pos))) { LOG_WARN("fail to store val", K(ret), K(in_val), K(length), K(buf), K(BUF_LEN), K(pos)); } else { ObString str(pos, buf); bool has_set_res = false; if (OB_FAIL(common_check_convert_string(expr, ctx, str, res_datum, has_set_res))) { LOG_WARN("common_check_convert_string failed", K(ret)); } } } } return ret; } CAST_FUNC_NAME(bit, text) { EVAL_ARG() { uint64_t in_val = child_res->get_uint(); if (CM_IS_COLUMN_CONVERT(expr.extra_)) { // if cast mode is column convert, using bit as int64 to do cast. ObFastFormatInt ffi(in_val); ObString res_str(ffi.length(), ffi.ptr()); if (OB_FAIL(common_copy_string_zf_to_text_result(expr, res_str, ctx, res_datum))) { LOG_WARN("common_copy_string_zf_to_text_result failed", K(ret), K(res_str)); } } else { // using bit as char array to do cast. const int32_t BUF_LEN = (OB_MAX_BIT_LENGTH + 7) / 8; int64_t pos = 0; char buf[BUF_LEN] = {0}; ObLengthSemantics length = expr.args_[0]->datum_meta_.length_semantics_; if (OB_FAIL(bit_to_char_array(in_val, length, buf, BUF_LEN, pos))) { LOG_WARN("fail to store val", K(ret), K(in_val), K(length), K(buf), K(BUF_LEN), K(pos)); } else { ObString str(pos, buf); ObString res_str; bool has_set_res = false; if (OB_FAIL(common_check_convert_string(expr, ctx, str, res_datum, has_set_res))) { LOG_WARN("common_check_convert_string failed", K(ret)); } else if (OB_FAIL(copy_datum_str_with_tmp_alloc(ctx, res_datum, res_str))) { LOG_WARN("copy datum string with tmp allocator failed", K(ret)); } else if (OB_FAIL(common_string_text(expr, res_str, ctx, NULL, res_datum))) { LOG_WARN("cast string to lob failed", K(ret)); } } } } return ret; } CAST_FUNC_NAME(bit, json) { EVAL_ARG_FOR_CAST_TO_JSON() { const int32_t BUF_LEN = (OB_MAX_BIT_LENGTH + 7) / 8; int64_t pos = 0; char buf[BUF_LEN] = {0}; uint64_t in_val = child_res->get_uint(); ObLengthSemantics length = expr.args_[0]->datum_meta_.length_semantics_; if (OB_FAIL(bit_to_char_array(in_val, length, buf, BUF_LEN, pos))) { LOG_WARN("fail to store val", K(ret), K(in_val), K(length), K(buf), K(BUF_LEN), K(pos)); } else { ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); common::ObString j_value(pos, buf); ObJsonOpaque j_opaque(j_value, ObBitType); ObIJsonBase *j_base = &j_opaque; ObString raw_bin; if (OB_FAIL(j_base->get_raw_binary(raw_bin, &temp_allocator))) { LOG_WARN("fail to get int json binary", K(ret), K(in_val), K(buf), K(BUF_LEN)); } else if (OB_FAIL(common_json_bin(expr, ctx, res_datum, raw_bin))) { LOG_WARN("fail to fill json bin lob locator", K(ret)); } } } return ret; } CAST_FUNC_NAME(bit, geometry) { EVAL_ARG() { ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); ObGeometry *geo = NULL; omt::ObSrsCacheGuard srs_guard; const ObSrsItem *srs = NULL; uint64_t in_val = child_res->get_uint(); ObFastFormatInt ffi(in_val); ObGeoType dst_geo_type = ObGeoCastUtils::get_geo_type_from_cast_mode(expr.extra_); const char *cast_name = ObGeometryTypeCastUtil::get_cast_name(dst_geo_type); ObString str(ffi.length(), ffi.ptr()); if (OB_FAIL(ObGeoExprUtils::get_srs_item(ctx, srs_guard, str, srs, true, cast_name))) { LOG_WARN("fail to get srs item", K(ret), K(str)); } else if (OB_FAIL(ObGeoExprUtils::build_geometry(temp_allocator, str, geo, srs, cast_name))) { LOG_WARN("fail to parse geometry", K(ret), K(in_val), K(dst_geo_type)); } else { ObString res_wkb; if (OB_FAIL(ObGeoTypeUtil::to_wkb(temp_allocator, *geo, srs, res_wkb))) { LOG_WARN("fail to get wkb", K(ret), K(dst_geo_type)); } else if (OB_FAIL(common_gis_wkb(expr, ctx, res_datum, res_wkb))){ LOG_WARN("fail to copy string", K(ret), K(dst_geo_type)); } } if (OB_FAIL(ret) && CM_IS_COLUMN_CONVERT(expr.extra_) && ObGeoType::GEOMETRY == dst_geo_type) { // adapt mysql ret = OB_ERR_CANT_CREATE_GEOMETRY_OBJECT; LOG_USER_ERROR(OB_ERR_CANT_CREATE_GEOMETRY_OBJECT); } } return ret; } CAST_FUNC_NAME(enumset, int) { EVAL_ARG() { uint64_t in_val = child_res->get_enumset(); int64_t out_val = 0; ObObjType out_type = expr.datum_meta_.type_; if (OB_FAIL(common_uint_int(expr, out_type, in_val, ctx, out_val))) { LOG_WARN("common_uint_int failed", K(ret)); } else { res_datum.set_int(out_val); } } return ret; } CAST_FUNC_NAME(enumset, uint) { EVAL_ARG() { DEF_IN_OUT_TYPE(); uint64_t in_val = child_res->get_enumset(); if (CAST_FAIL(uint_upper_check(out_type, in_val))) { LOG_WARN("int_upper_check failed", K(ret), K(in_val)); } else { res_datum.set_uint(in_val); } } return ret; } CAST_FUNC_NAME(enumset, float) { EVAL_ARG() { uint64_t in_val = child_res->get_enumset(); res_datum.set_float(static_cast(in_val)); } return ret; } CAST_FUNC_NAME(enumset, double) { EVAL_ARG() { uint64_t in_val = child_res->get_enumset(); res_datum.set_double(static_cast(in_val)); } return ret; } CAST_FUNC_NAME(enumset, number) { EVAL_ARG() { uint64_t in_val = child_res->get_enumset(); ObNumStackOnceAlloc tmp_alloc; number::ObNumber number; if (OB_FAIL(number.from(in_val, tmp_alloc))) { LOG_WARN("number.from failed", K(ret), K(in_val)); } else { res_datum.set_number(number); } } return ret; } CAST_FUNC_NAME(enumset, year) { EVAL_ARG() { uint64_t in_val = child_res->get_enumset(); int64_t val_int = 0; if (OB_FAIL(common_uint_int(expr, ObIntType, in_val, ctx, val_int))) { LOG_WARN("common_uint_int failed", K(ret), K(in_val)); } else if (OB_FAIL(common_int_year(expr, val_int, res_datum))) { LOG_WARN("common_int_time failed", K(ret), K(val_int)); } } return ret; } CAST_FUNC_NAME(enumset, bit) { EVAL_ARG() { uint64_t in_val = child_res->get_enumset(); if (OB_FAIL(common_uint_bit(expr, in_val, ctx, res_datum))) { LOG_WARN("fail to common_uint_bit", K(ret)); } } return ret; } CAST_FUNC_NAME(enumset_inner, int) { EVAL_ARG() { ObEnumSetInnerValue inner_value; int64_t out_val = 0; ObObjType out_type = expr.datum_meta_.type_; if (OB_FAIL(child_res->get_enumset_inner(inner_value))) { LOG_WARN("failed to inner_value", KPC(child_res), K(ret)); } else if (OB_FAIL(common_uint_int(expr, out_type, inner_value.numberic_value_, ctx, out_val))) { LOG_WARN("common_uint_int failed", K(ret)); } else { res_datum.set_int(out_val); } } return ret; } CAST_FUNC_NAME(enumset_inner, uint) { EVAL_ARG() { DEF_IN_OUT_TYPE(); ObEnumSetInnerValue inner_value; if (OB_FAIL(child_res->get_enumset_inner(inner_value))) { LOG_WARN("failed to inner_value", KPC(child_res), K(ret)); } else if (CAST_FAIL(uint_upper_check(out_type, inner_value.numberic_value_))) { LOG_WARN("int_upper_check failed", K(ret), K(inner_value.numberic_value_)); } else { res_datum.set_uint(inner_value.numberic_value_); } } return ret; } CAST_FUNC_NAME(enumset_inner, float) { EVAL_ARG() { ObEnumSetInnerValue inner_value; if (OB_FAIL(child_res->get_enumset_inner(inner_value))) { LOG_WARN("failed to inner_value", KPC(child_res), K(ret)); } else { res_datum.set_float(static_cast(inner_value.numberic_value_)); } } return ret; } CAST_FUNC_NAME(enumset_inner, double) { EVAL_ARG() { ObEnumSetInnerValue inner_value; if (OB_FAIL(child_res->get_enumset_inner(inner_value))) { LOG_WARN("failed to inner_value", KPC(child_res), K(ret)); } else { res_datum.set_float(static_cast(inner_value.numberic_value_)); } } return ret; } CAST_FUNC_NAME(enumset_inner, number) { EVAL_ARG() { ObEnumSetInnerValue inner_value; ObNumStackOnceAlloc tmp_alloc; number::ObNumber number; if (OB_FAIL(child_res->get_enumset_inner(inner_value))) { LOG_WARN("failed to inner_value", KPC(child_res), K(ret)); } else if (OB_FAIL(number.from(inner_value.numberic_value_, tmp_alloc))) { LOG_WARN("number.from failed", K(ret), K(inner_value.numberic_value_)); } else { res_datum.set_number(number); } } return ret; } CAST_FUNC_NAME(enumset_inner, year) { EVAL_ARG() { ObEnumSetInnerValue inner_value; int64_t val_int = 0; if (OB_FAIL(child_res->get_enumset_inner(inner_value))) { LOG_WARN("failed to inner_value", KPC(child_res), K(ret)); } else if (OB_FAIL(common_uint_int(expr, ObIntType, inner_value.numberic_value_, ctx, val_int))) { LOG_WARN("common_uint_int failed", K(ret), K(inner_value.numberic_value_)); } else if (OB_FAIL(common_int_year(expr, val_int, res_datum))) { LOG_WARN("common_int_time failed", K(ret), K(val_int)); } } return ret; } CAST_FUNC_NAME(enumset_inner, bit) { EVAL_ARG() { ObEnumSetInnerValue inner_value; if (OB_FAIL(child_res->get_enumset_inner(inner_value))) { LOG_WARN("failed to inner_value", KPC(child_res), K(ret)); } else if (OB_FAIL(common_uint_bit(expr, inner_value.numberic_value_, ctx, res_datum))) { LOG_WARN("fail to common_uint_bit", K(ret)); } } return ret; } CAST_FUNC_NAME(enumset_inner, datetime) { EVAL_ARG() { ObEnumSetInnerValue inner_value; if (OB_FAIL(child_res->get_enumset_inner(inner_value))) { LOG_WARN("failed to inner_value", KPC(child_res), K(ret)); } else if (OB_FAIL(common_string_datetime(expr, inner_value.string_value_, ctx, res_datum))) { LOG_WARN("failed to common_string_datetime", K(inner_value), K(ret)); } } return ret; } CAST_FUNC_NAME(enumset_inner, date) { EVAL_ARG() { ObEnumSetInnerValue inner_value; if (OB_FAIL(child_res->get_enumset_inner(inner_value))) { LOG_WARN("failed to inner_value", KPC(child_res), K(ret)); } else if (OB_FAIL(common_string_date( expr, inner_value.string_value_, res_datum))) { LOG_WARN("failed to common_string_date", K(inner_value), K(ret)); } } return ret; } CAST_FUNC_NAME(enumset_inner, time) { EVAL_ARG() { ObEnumSetInnerValue inner_value; if (OB_FAIL(child_res->get_enumset_inner(inner_value))) { LOG_WARN("failed to inner_value", KPC(child_res), K(ret)); } else if (OB_FAIL(common_string_time(expr, inner_value.string_value_, res_datum))) { LOG_WARN("failed to common_string_time", K(inner_value), K(ret)); } } return ret; } CAST_FUNC_NAME(enumset_inner, string) { EVAL_ARG() { ObEnumSetInnerValue inner_value; bool has_set_res = false; if (OB_FAIL(child_res->get_enumset_inner(inner_value))) { LOG_WARN("failed to inner_value", KPC(child_res), K(ret)); } else if (OB_FAIL(common_check_convert_string(expr, ctx, inner_value.string_value_, res_datum, has_set_res))) { LOG_WARN("fail to common_check_convert_string", K(ret), K(inner_value)); } } return ret; } CAST_FUNC_NAME(time, int) { EVAL_ARG() { DEF_IN_OUT_VAL(int64_t, int64_t, 0); ObObjType out_type = expr.datum_meta_.type_; if (OB_FAIL(ObTimeConverter::time_to_int(in_val, out_val))) { LOG_WARN("time_to_int failed", K(ret), K(in_val)); } else if (out_type < ObInt32Type && CAST_FAIL(int_range_check(out_type, out_val, out_val))) { LOG_WARN("int_range_check failed", K(ret), K(out_val)); } else { res_datum.set_int(out_val); } } return ret; } CAST_FUNC_NAME(time, uint) { EVAL_ARG() { DEF_IN_OUT_VAL(int64_t, uint64_t, 0); int64_t val_int = 0; ObObjType out_type = expr.datum_meta_.type_; if (OB_FAIL(ObTimeConverter::time_to_int(in_val, val_int))) { LOG_WARN("time_to_int failed", K(ret), K(in_val)); } else { out_val = static_cast(val_int); if (CM_NEED_RANGE_CHECK(expr.extra_) && CAST_FAIL(uint_range_check(out_type, val_int, out_val))) { LOG_WARN("int_range_check failed", K(ret), K(val_int)); } else { res_datum.set_uint(out_val); } } } return ret; } CAST_FUNC_NAME(time, float) { EVAL_ARG() { DEF_IN_OUT_VAL(int64_t, double, 0.0); ObObjType out_type = expr.datum_meta_.type_; if (OB_FAIL(ObTimeConverter::time_to_double(in_val, out_val))) { LOG_WARN("time_to_int failed", K(ret), K(in_val)); } else if (ObUFloatType == out_type && CAST_FAIL(numeric_negative_check(out_val))) { LOG_WARN("int_range_check failed", K(ret), K(out_val)); } else { res_datum.set_float(static_cast(out_val)); } } return ret; } CAST_FUNC_NAME(time, double) { EVAL_ARG() { DEF_IN_OUT_VAL(int64_t, double, 0.0); ObObjType out_type = expr.datum_meta_.type_; if (OB_FAIL(ObTimeConverter::time_to_double(in_val, out_val))) { LOG_WARN("time_to_int failed", K(ret), K(in_val)); } else if (ObUFloatType == out_type && CAST_FAIL(numeric_negative_check(out_val))) { LOG_WARN("int_range_check failed", K(ret), K(out_val)); } else { res_datum.set_double(out_val); } } return ret; } CAST_FUNC_NAME(time, number) { EVAL_ARG() { int64_t in_val = child_res->get_uint(); int warning = OB_SUCCESS; char buf[OB_CAST_TO_VARCHAR_MAX_LENGTH] = {0}; int64_t len = 0; ObNumStackOnceAlloc tmp_alloc; number::ObNumber number; ObScale in_scale = expr.args_[0]->datum_meta_.scale_; ObScale res_scale = 0; ObPrecision res_precision = 0; if (OB_FAIL(ObTimeConverter::time_to_str(in_val, in_scale, buf, sizeof(buf), len, false))) { LOG_WARN("time_to_str failed", K(ret), K(in_val)); } else if (CAST_FAIL(number.from(buf, len, tmp_alloc, &res_precision, &res_scale))) { LOG_WARN("number.from failed", K(ret)); } else { res_datum.set_number(number); } } return ret; } CAST_FUNC_NAME(time, datetime) { EVAL_ARG() { GET_SESSION() { int64_t in_val = child_res->get_int(); int64_t out_val = 0; ObObjType out_type = expr.datum_meta_.type_; ObPhysicalPlanCtx *phy_plan_ctx = ctx.exec_ctx_.get_physical_plan_ctx(); int64_t cur_time = phy_plan_ctx ? phy_plan_ctx->get_cur_time().get_datetime() : 0; if (OB_FAIL(ObTimeConverter::time_to_datetime(in_val, cur_time, session->get_timezone_info(), out_val, out_type))) { LOG_WARN("time_to_datetime failed", K(ret), K(in_val)); } else { res_datum.set_datetime(out_val); } } } return ret; } CAST_FUNC_NAME(time, date) { EVAL_ARG() { GET_SESSION() { int32_t out_val = 0; ObPhysicalPlanCtx *phy_plan_ctx = ctx.exec_ctx_.get_physical_plan_ctx(); int64_t cur_time = phy_plan_ctx ? phy_plan_ctx->get_cur_time().get_datetime() : 0; int64_t datetime_value = 0; int64_t in_val = child_res->get_time(); ObTimeConvertCtx cvrt_ctx(session->get_timezone_info(), false); if (OB_FAIL(ObTimeConverter::time_to_datetime(in_val, cur_time, session->get_timezone_info(), datetime_value, ObDateTimeType))) { LOG_WARN("datetime_to_date failed", K(ret), K(cur_time)); } else if (ObTimeConverter::datetime_to_date(datetime_value, NULL, out_val)) { LOG_WARN("date to datetime failed", K(ret), K(datetime_value)); } else { res_datum.set_date(out_val); } } } return ret; } CAST_FUNC_NAME(time, string) { EVAL_ARG() { int64_t in_val = child_res->get_int(); char buf[OB_CAST_TO_VARCHAR_MAX_LENGTH] = {0}; int64_t len = 0; ObScale in_scale = expr.args_[0]->datum_meta_.scale_; if (OB_FAIL(ObTimeConverter::time_to_str(in_val, in_scale, buf, sizeof(buf), len))) { LOG_WARN("time_to_str failed", K(ret), K(in_val)); } else if (OB_FAIL(common_copy_string(expr, ObString(len, buf), ctx, res_datum))) { LOG_WARN("common_copy_string failed", K(ret), K(ObString(len, buf))); } } return ret; } CAST_FUNC_NAME(time, text) { EVAL_ARG() { int64_t in_val = child_res->get_int(); char buf[OB_CAST_TO_VARCHAR_MAX_LENGTH] = {0}; int64_t len = 0; ObScale in_scale = expr.args_[0]->datum_meta_.scale_; if (OB_FAIL(ObTimeConverter::time_to_str(in_val, in_scale, buf, sizeof(buf), len))) { LOG_WARN("time_to_str failed", K(ret), K(in_val)); } else { ObString res_str(len, buf); if (OB_FAIL(common_copy_string_to_text_result(expr, res_str, ctx, res_datum))) { LOG_WARN("common_copy_string_to_text_result failed", K(ret), K(ObString(len, buf))); } } } return ret; } CAST_FUNC_NAME(time, bit) { EVAL_ARG() { int64_t in_val = child_res->get_int(); char buf[OB_CAST_TO_VARCHAR_MAX_LENGTH] = {0}; int64_t len = 0; ObScale in_scale = expr.args_[0]->datum_meta_.scale_; if (OB_FAIL(ObTimeConverter::time_to_str(in_val, in_scale, buf, sizeof(buf), len))) { LOG_WARN("time_to_str failed", K(ret), K(in_val)); } else if (OB_FAIL(common_string_bit(expr, ObString(len, buf), ctx, res_datum))) { LOG_WARN("common_string_bit failed", K(ret), K(ObString(len, buf))); } } return ret; } CAST_FUNC_NAME(time, json) { EVAL_ARG_FOR_CAST_TO_JSON() { int64_t in_val = child_res->get_int(); ObObjType in_type = expr.args_[0]->datum_meta_.type_; if (lib::is_oracle_mode() && in_val != 0) { if (CM_IS_IMPLICIT_CAST(expr.extra_)) { ret = OB_ERR_INVALID_INPUT; LOG_WARN("invalid input in implicit cast", K(ret)); } else { LOG_WARN("inconsistent datatypes", K(ret), K(in_type), K("json"), K(expr.extra_)); ret = OB_ERR_INVALID_TYPE_FOR_OP; } } else { ObTime ob_time(DT_TYPE_TIME); if (OB_FAIL(ObTimeConverter::time_to_ob_time(in_val, ob_time))) { LOG_WARN("fail to create ob time from time", K(ret), K(in_type), K(in_val)); } else { ObJsonDatetime j_time(ObJsonNodeType::J_TIME, ob_time); ObIJsonBase *j_base = &j_time; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); ObString raw_bin; if (OB_FAIL(j_base->get_raw_binary(raw_bin, &temp_allocator))) { LOG_WARN("fail to get time json binary", K(ret), K(in_type), K(in_val)); } else if (OB_FAIL(common_json_bin(expr, ctx, res_datum, raw_bin))) { LOG_WARN("fail to fill json bin lob locator", K(ret)); } } } } return ret; } CAST_FUNC_NAME(time, geometry) { EVAL_ARG() { ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); ObGeometry *geo = NULL; omt::ObSrsCacheGuard srs_guard; const ObSrsItem *srs = NULL; ObGeoType dst_geo_type = ObGeoCastUtils::get_geo_type_from_cast_mode(expr.extra_); const char *cast_name = ObGeometryTypeCastUtil::get_cast_name(dst_geo_type); int64_t in_val = child_res->get_int(); char buf[OB_CAST_TO_VARCHAR_MAX_LENGTH] = {0}; int64_t len = 0; ObScale in_scale = expr.args_[0]->datum_meta_.scale_; if (OB_FAIL(ObTimeConverter::time_to_str(in_val, in_scale, buf, sizeof(buf), len))) { LOG_WARN("time_to_str failed", K(ret), K(in_val)); } else if (OB_FAIL(ObGeoExprUtils::get_srs_item(ctx, srs_guard, ObString(len, buf), srs, true, cast_name))) { LOG_WARN("fail to get srs item", K(ret)); } else if (OB_FAIL(ObGeoExprUtils::build_geometry(temp_allocator, ObString(len, buf), geo, srs, cast_name))) { LOG_WARN("fail to parse geometry", K(ret), K(in_val), K(dst_geo_type)); } else { ObString res_wkb; if (OB_FAIL(ObGeoTypeUtil::to_wkb(temp_allocator, *geo, srs, res_wkb))) { LOG_WARN("fail to get wkb", K(ret), K(dst_geo_type)); } else if (OB_FAIL(common_gis_wkb(expr, ctx, res_datum, res_wkb))){ LOG_WARN("fail to copy string", K(ret), K(dst_geo_type)); } } if (OB_FAIL(ret) && CM_IS_COLUMN_CONVERT(expr.extra_) && ObGeoType::GEOMETRY == dst_geo_type) { // adapt mysql ret = OB_ERR_CANT_CREATE_GEOMETRY_OBJECT; LOG_USER_ERROR(OB_ERR_CANT_CREATE_GEOMETRY_OBJECT); } } return ret; } CAST_FUNC_NAME(otimestamp, datetime) { EVAL_ARG() { GET_SESSION() { int64_t usec = 0; ObObjType in_type = expr.args_[0]->datum_meta_.type_; ObOTimestampData in_val; if (OB_FAIL(common_construct_otimestamp(in_type, *child_res, in_val))) { LOG_WARN("common_construct_otimestamp failed", K(ret)); } else if (OB_FAIL(ObTimeConverter::otimestamp_to_odate(in_type, in_val, session->get_timezone_info(), usec))) { LOG_WARN("fail to timestamp_tz_to_timestamp", K(ret)); } else { ObTimeConverter::trunc_datetime(OB_MAX_DATE_PRECISION, usec); res_datum.set_datetime(usec); } } } return ret; } CAST_FUNC_NAME(otimestamp, string) { EVAL_ARG() { GET_SESSION() { ObObjType in_type = expr.args_[0]->datum_meta_.type_; ObOTimestampData in_val; char buf[OB_CAST_TO_VARCHAR_MAX_LENGTH] = {0}; int64_t len = 0; ObScale in_scale = expr.args_[0]->datum_meta_.scale_; const ObDataTypeCastParams dtc_params = ObBasicSessionInfo::create_dtc_params(session); if (OB_FAIL(common_construct_otimestamp(in_type, *child_res, in_val))) { LOG_WARN("common_construct_otimestamp failed", K(ret)); } else if (OB_FAIL(ObTimeConverter::otimestamp_to_str(in_val, dtc_params, in_scale, in_type, buf, OB_CAST_TO_VARCHAR_MAX_LENGTH, len))) { LOG_WARN("failed to convert otimestamp to string", K(ret)); } else { ObString in_str(sizeof(buf), static_cast(len), buf); bool has_set_res = false; if (OB_FAIL(common_check_convert_string(expr, ctx, in_str, res_datum, has_set_res))) { LOG_WARN("fail to common_check_convert_string", K(ret), K(in_str)); } } } } return ret; } CAST_FUNC_NAME(otimestamp, otimestamp) { EVAL_ARG() { GET_SESSION() { DEF_IN_OUT_TYPE(); ObOTimestampData in_val; ObOTimestampData out_val; if (OB_FAIL(common_construct_otimestamp(in_type, *child_res, in_val))) { LOG_WARN("common_construct_otimestamp failed", K(ret)); } else if (ObTimestampNanoType == in_type) { if (OB_FAIL(ObTimeConverter::odate_to_otimestamp(in_val.time_us_, session->get_timezone_info(), out_type, out_val))) { LOG_WARN("fail to odate_to_otimestamp", K(ret), K(out_type)); } else { out_val.time_ctx_.tail_nsec_ = in_val.time_ctx_.tail_nsec_; } } else if (ObTimestampNanoType == out_type) { if (OB_FAIL(ObTimeConverter::otimestamp_to_odate(in_type, in_val, session->get_timezone_info(), *(int64_t *)&out_val.time_us_))) { LOG_WARN("fail to otimestamp_to_odate", K(ret), K(out_type)); } else { out_val.time_ctx_.tail_nsec_ = in_val.time_ctx_.tail_nsec_; } } else { if (OB_FAIL(ObTimeConverter::otimestamp_to_otimestamp(in_type, in_val, session->get_timezone_info(), out_type, out_val))) { LOG_WARN("fail to otimestamp_to_otimestamp", K(ret), K(out_type)); } } if (OB_SUCC(ret)) { if (ObTimestampTZType == out_type) { SET_RES_OTIMESTAMP(out_val); } else { SET_RES_OTIMESTAMP_10BYTE(out_val); } } } } return ret; } CAST_FUNC_NAME(otimestamp, lob) { EVAL_ARG() { GET_SESSION() { ObObjType in_type = expr.args_[0]->datum_meta_.type_; ObOTimestampData in_val; char buf[OB_CAST_TO_VARCHAR_MAX_LENGTH] = {0}; int64_t len = 0; ObScale in_scale = expr.args_[0]->datum_meta_.scale_; if (OB_FAIL(common_construct_otimestamp(in_type, *child_res, in_val))) { LOG_WARN("common_construct_otimestamp failed", K(ret)); } else if (OB_FAIL(ObTimeConverter::otimestamp_to_str(in_val, session->get_timezone_info(), in_scale, in_type, buf, OB_CAST_TO_VARCHAR_MAX_LENGTH, len))) { LOG_WARN("failed to convert otimestamp to string", K(ret)); } else { ObString in_str(sizeof(buf), static_cast(len), buf); ObString res_str; bool has_set_res = false; if (OB_FAIL(common_check_convert_string(expr, ctx, in_str, res_datum, has_set_res))) { LOG_WARN("fail to common_check_convert_string", K(ret), K(in_str)); } else if (OB_FAIL(copy_datum_str_with_tmp_alloc(ctx, res_datum, res_str))) { LOG_WARN("copy datum string with tmp allocator failed", K(ret)); } else if (OB_FAIL(common_string_lob(expr, res_str, ctx, NULL, res_datum))) { LOG_WARN("cast string to lob failed", K(ret)); } } } } return ret; } CAST_FUNC_NAME(otimestamp, text) { EVAL_ARG() { GET_SESSION() { ObObjType in_type = expr.args_[0]->datum_meta_.type_; ObOTimestampData in_val; char buf[OB_CAST_TO_VARCHAR_MAX_LENGTH] = {0}; int64_t len = 0; ObScale in_scale = expr.args_[0]->datum_meta_.scale_; if (OB_FAIL(common_construct_otimestamp(in_type, *child_res, in_val))) { LOG_WARN("common_construct_otimestamp failed", K(ret)); } else if (OB_FAIL(ObTimeConverter::otimestamp_to_str(in_val, session->get_timezone_info(), in_scale, in_type, buf, OB_CAST_TO_VARCHAR_MAX_LENGTH, len))) { LOG_WARN("failed to convert otimestamp to string", K(ret)); } else { ObString in_str(sizeof(buf), static_cast(len), buf); ObString res_str; bool has_set_res = false; if (OB_FAIL(common_check_convert_string(expr, ctx, in_str, res_datum, has_set_res))) { LOG_WARN("fail to common_check_convert_string", K(ret), K(in_str)); } else if (OB_FAIL(copy_datum_str_with_tmp_alloc(ctx, res_datum, res_str))) { LOG_WARN("copy datum string with tmp allocator failed", K(ret)); } else if (OB_FAIL(common_string_text(expr, res_str, ctx, NULL, res_datum))) { LOG_WARN("cast string to lob failed", K(ret)); } } } } return ret; } CAST_FUNC_NAME(raw, json) { EVAL_ARG() { ObString in_str(child_res->len_, child_res->ptr_); ret = common_string_json(expr, in_str, ctx, res_datum); } return ret; } CAST_FUNC_NAME(raw, string) { EVAL_ARG() { ObString in_str(child_res->len_, child_res->ptr_); OZ(ObDatumHexUtils::rawtohex(expr, in_str, ctx, res_datum)); } return ret; } CAST_FUNC_NAME(raw, longtext) { EVAL_ARG() { ObString in_str(child_res->len_, child_res->ptr_); bool has_set_res = false; if (CS_TYPE_BINARY != expr.datum_meta_.cs_type_) { // raw to clob OZ(ObDatumHexUtils::rawtohex(expr, in_str, ctx, res_datum)); // mock check with content ObLobLocatorV2 lob(res_datum.get_string(), expr.obj_meta_.has_lob_header()); has_set_res = lob.ptr_ != nullptr && lob.size_ > 0 && lob.is_valid() && lob.is_full_temp_lob(); } else { // raw to blob res_datum.set_string(in_str.ptr(), in_str.length()); } if (OB_FAIL(ret)) { } else if (has_set_res) { // has set lob res? } else if (ob_is_text_tc(expr.datum_meta_.type_)) { ObString res_str; if (OB_FAIL(copy_datum_str_with_tmp_alloc(ctx, res_datum, res_str))) { LOG_WARN("copy datum string with tmp allocator failed", K(ret)); } else if (OB_FAIL(common_string_text(expr, res_str, ctx, NULL, res_datum))) { LOG_WARN("cast string to lob failed", K(ret)); } } } return ret; } CAST_FUNC_NAME(raw, lob) { EVAL_ARG() { ObString res_str; if (OB_FAIL(raw_longtext(expr, ctx, res_datum))) { LOG_WARN("raw_longtext failed", K(ret)); } else if (OB_FAIL(copy_datum_str_with_tmp_alloc(ctx, res_datum, res_str))) { LOG_WARN("copy datum string with tmp allocator failed", K(ret)); } else if (OB_FAIL(common_string_lob(expr, res_str, ctx, NULL, res_datum))) { LOG_WARN("cast string to lob failed", K(ret)); } } return ret; } CAST_FUNC_NAME(raw, raw) { EVAL_ARG() { ObString in_str(child_res->len_, child_res->ptr_); bool has_set_res = false; OZ(common_check_convert_string(expr, ctx, in_str, res_datum, has_set_res)); } return ret; } CAST_FUNC_NAME(interval, string) { EVAL_ARG() { ObObjType in_type = expr.args_[0]->datum_meta_.type_; ObScale in_scale = expr.args_[0]->datum_meta_.scale_; char buf[OB_CAST_TO_VARCHAR_MAX_LENGTH] = {0}; int64_t len = 0; bool is_explicit_cast = CM_IS_EXPLICIT_CAST(expr.extra_); if (ob_is_interval_ym(in_type)) { ObIntervalYMValue in_val(child_res->get_interval_nmonth()); if (OB_FAIL(ObTimeConverter::interval_ym_to_str(in_val, in_scale, buf, OB_CAST_TO_VARCHAR_MAX_LENGTH, len, is_explicit_cast))) { LOG_WARN("interval_ym_to_str failed", K(ret)); } } else { ObIntervalDSValue in_val(child_res->get_interval_ds()); if (OB_FAIL(ObTimeConverter::interval_ds_to_str(in_val, in_scale, buf, OB_CAST_TO_VARCHAR_MAX_LENGTH, len, is_explicit_cast))) { LOG_WARN("interval_ym_to_str failed", K(ret)); } } if (OB_SUCC(ret)) { ObString in_str(len, buf); bool has_set_res = false; if (OB_FAIL(common_check_convert_string(expr, ctx, in_str, res_datum, has_set_res))) { LOG_WARN("fail to common_check_convert_string", K(ret), K(in_str)); } } } return ret; } CAST_FUNC_NAME(interval, interval) { EVAL_ARG() { ObObjType in_type = expr.args_[0]->datum_meta_.type_; ObObjType out_type = expr.datum_meta_.type_; if (in_type != out_type) { ret = cast_inconsistent_types(expr, ctx, res_datum); } else { ret = OB_NOT_SUPPORTED; LOG_USER_ERROR(OB_NOT_SUPPORTED, "cast interval to interval type"); } } return ret; } CAST_FUNC_NAME(rowid, string) { EVAL_ARG() { ObURowIDData urowid_data(child_res->len_, reinterpret_cast(child_res->ptr_)); char *base64_buf = NULL; int64_t base64_buf_size = urowid_data.needed_base64_buffer_size(); int64_t pos = 0; if (OB_ISNULL(base64_buf = expr.get_str_res_mem(ctx, base64_buf_size))) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("failed to allocate memory", K(ret)); } else if (OB_FAIL(urowid_data.get_base64_str(base64_buf, base64_buf_size, pos))) { LOG_WARN("failed to get base64 str", K(ret)); } else { ObString in_str(pos, base64_buf); bool has_set_res = false; if (OB_FAIL(common_check_convert_string(expr, ctx, in_str, res_datum, has_set_res))) { LOG_WARN("fail to common_check_convert_string", K(ret), K(in_str)); } } } return ret; } CAST_FUNC_NAME(rowid, rowid) { EVAL_ARG() { ObObjType in_type = expr.args_[0]->datum_meta_.type_; ObObjType out_type = expr.datum_meta_.type_; if (in_type != out_type) { ret = cast_inconsistent_types(expr, ctx, res_datum); } else { res_datum.set_urowid(ObURowIDData(child_res->len_, reinterpret_cast(child_res->ptr_))); } } return ret; } //////////////////////////////////////////////////////////// // Lob -> XXX CAST_FUNC_NAME(lob, int) { EVAL_STRING_ARG() { const ObLobLocator &lob_locator = child_res->get_lob_locator(); ObString in_str(lob_locator.payload_size_, lob_locator.get_payload_ptr()); const bool is_str_int_cast = true; OZ(common_string_int(expr, expr.extra_, in_str, is_str_int_cast, res_datum)); } return ret; } CAST_FUNC_NAME(lob, uint) { EVAL_STRING_ARG() { const ObLobLocator &lob_locator = child_res->get_lob_locator(); ObString in_str(lob_locator.payload_size_, lob_locator.get_payload_ptr()); const bool is_str_int_cast = true; OZ(common_string_uint(expr, in_str, is_str_int_cast, res_datum)); } return ret; } CAST_FUNC_NAME(lob, float) { EVAL_STRING_ARG() { const ObLobLocator &lob_locator = child_res->get_lob_locator(); ObString in_str(lob_locator.payload_size_, lob_locator.get_payload_ptr()); float out_val = 0; OZ(common_string_float(expr, in_str, out_val)); OX(res_datum.set_float(out_val)); } return ret; } CAST_FUNC_NAME(lob, double) { EVAL_STRING_ARG() { const ObLobLocator &lob_locator = child_res->get_lob_locator(); ObString in_str(lob_locator.payload_size_, lob_locator.get_payload_ptr()); DEF_IN_OUT_TYPE(); OZ(common_string_double(expr, in_type, expr.args_[0]->datum_meta_.cs_type_, out_type, in_str, res_datum)); } return ret; } CAST_FUNC_NAME(lob, number) { EVAL_STRING_ARG() { const ObLobLocator &lob_locator = child_res->get_lob_locator(); ObString in_str(lob_locator.get_payload_length(), lob_locator.get_payload_ptr()); number::ObNumber nmb; ObNumStackOnceAlloc tmp_alloc; OZ(common_string_number(expr, in_str, tmp_alloc, nmb)); OX(res_datum.set_number(nmb)); } return ret; } CAST_FUNC_NAME(lob, datetime) { EVAL_STRING_ARG() { const ObLobLocator &lob_locator = child_res->get_lob_locator(); ObString in_str(lob_locator.payload_size_, lob_locator.get_payload_ptr()); OZ(common_string_datetime(expr, in_str, ctx, res_datum)); } return ret; } CAST_FUNC_NAME(lob, date) { EVAL_STRING_ARG() { const ObLobLocator &lob_locator = child_res->get_lob_locator(); ObString in_str(lob_locator.payload_size_, lob_locator.get_payload_ptr()); OZ(common_string_date(expr, in_str, res_datum)); } return ret; } CAST_FUNC_NAME(lob, time) { EVAL_STRING_ARG() { const ObLobLocator &lob_locator = child_res->get_lob_locator(); ObString in_str(lob_locator.payload_size_, lob_locator.get_payload_ptr()); OZ(common_string_time(expr, in_str, res_datum)); } return ret; } CAST_FUNC_NAME(lob, year) { EVAL_STRING_ARG() { const ObLobLocator &lob_locator = child_res->get_lob_locator(); ObString in_str(lob_locator.payload_size_, lob_locator.get_payload_ptr()); OZ(common_string_year(expr, in_str, res_datum)); } return ret; } CAST_FUNC_NAME(lob, bit) { EVAL_STRING_ARG() { const ObLobLocator &lob_locator = child_res->get_lob_locator(); ObString in_str(lob_locator.payload_size_, lob_locator.get_payload_ptr()); OZ(common_string_bit(expr, in_str, ctx, res_datum)); } return ret; } CAST_FUNC_NAME(lob, string) { EVAL_ARG() { const ObLobLocator &lob_locator = child_res->get_lob_locator(); ObString in_str(lob_locator.payload_size_, lob_locator.get_payload_ptr()); ObObjType in_type = ObLongTextType; ObObjType out_type = expr.datum_meta_.type_; ObCollationType in_cs_type = expr.args_[0]->datum_meta_.cs_type_; ObCollationType out_cs_type = expr.datum_meta_.cs_type_; bool has_set_res = false; OZ(common_string_string(expr, in_type, in_cs_type, out_type, out_cs_type, in_str, ctx, res_datum, has_set_res)); } return ret; } CAST_FUNC_NAME(lob, text) { EVAL_ARG() { const ObLobLocator &lob_locator = child_res->get_lob_locator(); ObString in_str(lob_locator.payload_size_, lob_locator.get_payload_ptr()); ObObjType in_type = ObLongTextType; ObObjType out_type = expr.datum_meta_.type_; ObCollationType in_cs_type = expr.args_[0]->datum_meta_.cs_type_; ObCollationType out_cs_type = expr.datum_meta_.cs_type_; OZ(common_string_text(expr, in_str, ctx, NULL, res_datum)); } return ret; } CAST_FUNC_NAME(lob, otimestamp) { EVAL_STRING_ARG() { const ObLobLocator &lob_locator = child_res->get_lob_locator(); ObString in_str(lob_locator.payload_size_, lob_locator.get_payload_ptr()); OZ(common_string_otimestamp(expr, in_str, ctx, res_datum)); } return ret; } CAST_FUNC_NAME(lob, raw) { EVAL_STRING_ARG() { const ObLobLocator &lob_locator = child_res->get_lob_locator(); if (lob_locator.payload_size_ > 0) { ObString in_str(lob_locator.payload_size_, lob_locator.get_payload_ptr()); char *res_buf = nullptr; if (OB_ISNULL(res_buf = expr.get_str_res_mem(ctx, in_str.length()))) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("failed to alloc buffer", K(in_str.length())); } else { MEMCPY(res_buf, in_str.ptr(), in_str.length()); res_datum.set_string(ObString(in_str.length(), res_buf)); } } else { res_datum.set_null(); } } return ret; } CAST_FUNC_NAME(lob, interval) { EVAL_STRING_ARG() { const ObLobLocator &lob_locator = child_res->get_lob_locator(); ObString in_str(lob_locator.payload_size_, lob_locator.get_payload_ptr()); OZ(common_string_interval(expr, in_str, ctx, res_datum)); } return ret; } CAST_FUNC_NAME(lob, rowid) { EVAL_STRING_ARG() { const ObLobLocator &lob_locator = child_res->get_lob_locator(); ObString in_str(lob_locator.payload_size_, lob_locator.get_payload_ptr()); OZ(common_string_rowid(expr, in_str, ctx, res_datum)); } return ret; } CAST_FUNC_NAME(lob, lob) { EVAL_STRING_ARG() { const ObLobLocator &lob_locator = child_res->get_lob_locator(); ObString in_str(lob_locator.payload_size_, lob_locator.get_payload_ptr()); OZ(common_string_lob(expr, in_str, ctx, &lob_locator, res_datum)); } return ret; } CAST_FUNC_NAME(lob, json) { EVAL_STRING_ARG() { const ObLobLocator &lob_locator = child_res->get_lob_locator(); ObString in_str(lob_locator.payload_size_, lob_locator.get_payload_ptr()); OZ(common_string_json(expr, in_str, ctx, res_datum)); } return ret; } CAST_FUNC_NAME(lob, geometry) { EVAL_STRING_ARG() { int warning = OB_SUCCESS; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); const ObLobLocator &lob_locator = child_res->get_lob_locator(); ObString in_str(lob_locator.payload_size_, lob_locator.get_payload_ptr()); ObGeoType dst_geo_type = ObGeoCastUtils::get_geo_type_from_cast_mode(expr.extra_); const char *cast_name = ObGeometryTypeCastUtil::get_cast_name(dst_geo_type); ObGeometry *geo = NULL; omt::ObSrsCacheGuard srs_guard; const ObSrsItem *srs = NULL; if (OB_FAIL(ObGeoExprUtils::get_srs_item(ctx, srs_guard, in_str, srs, true, cast_name))) { LOG_WARN("fail to get srs item", K(ret), K(in_str)); } else if (OB_FAIL(ObGeoExprUtils::build_geometry(temp_allocator, in_str, geo, srs, cast_name))) { LOG_WARN("fail to parse geometry", K(ret), K(in_str), K(dst_geo_type)); } else if (ObGeoType::GEOMETRY == dst_geo_type || ObGeoType::GEOTYPEMAX == dst_geo_type) { res_datum.set_string(in_str); } else if (OB_FAIL(geometry_geometry(expr, ctx, res_datum))) { LOG_WARN("fail to cast geometry", K(ret), K(in_str), K(dst_geo_type)); } if (OB_FAIL(ret) && CM_IS_COLUMN_CONVERT(expr.extra_) && ObGeoType::GEOMETRY == dst_geo_type) { // adapt mysql ret = OB_ERR_CANT_CREATE_GEOMETRY_OBJECT; LOG_USER_ERROR(OB_ERR_CANT_CREATE_GEOMETRY_OBJECT); } } return ret; } //////////////////////////////////////////////////////////// // Json -> XXX CAST_FUNC_NAME(json, int) { EVAL_STRING_ARG() { int warning = OB_SUCCESS; int64_t out_val = 0; ObObjType out_type = expr.datum_meta_.type_; const uint64_t extra = CM_UNSET_STRING_INTEGER_TRUNC(CM_SET_WARN_ON_FAIL(expr.extra_)); ObString j_bin_str = child_res->get_string(); ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); if (OB_FAIL(ObTextStringHelper::read_real_string_data(temp_allocator, *child_res, expr.args_[0]->datum_meta_, expr.args_[0]->obj_meta_.has_lob_header(), j_bin_str))) { LOG_WARN("fail to get real data.", K(ret), K(j_bin_str)); } else { ObJsonBin j_bin(j_bin_str.ptr(), j_bin_str.length()); ObIJsonBase *j_base = &j_bin; if (OB_FAIL(j_bin.reset_iter())) { LOG_WARN("failed to reset json bin iter", K(ret), K(j_bin_str)); } else if (CAST_FAIL(j_base->to_int(out_val))) { LOG_WARN("fail to cast json to int type", K(ret), K(j_bin_str)); ret = OB_ERR_INVALID_JSON_VALUE_FOR_CAST; LOG_USER_ERROR(OB_ERR_INVALID_JSON_VALUE_FOR_CAST); } else if (out_type < ObIntType && CAST_FAIL_CM(int_range_check(out_type, out_val, out_val), extra)) { LOG_WARN("range check failed", K(ret), K(out_type), K(out_val)); } else { SET_RES_INT(out_val); } } } return ret; } CAST_FUNC_NAME(json, uint) { EVAL_STRING_ARG() { int warning = OB_SUCCESS; uint64_t out_val = 0; ObObjType out_type = expr.datum_meta_.type_; ObString j_bin_str = child_res->get_string(); ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); if (OB_FAIL(ObTextStringHelper::read_real_string_data(temp_allocator, *child_res, expr.args_[0]->datum_meta_, expr.args_[0]->obj_meta_.has_lob_header(), j_bin_str))) { LOG_WARN("fail to get real data.", K(ret), K(j_bin_str)); } else { ObJsonBin j_bin(j_bin_str.ptr(), j_bin_str.length()); ObIJsonBase *j_base = &j_bin; if (OB_FAIL(j_bin.reset_iter())) { LOG_WARN("failed to reset json bin iter", K(ret), K(j_bin_str)); } else if (CAST_FAIL(j_base->to_uint(out_val))) { LOG_WARN("fail to cast json to uint type", K(ret), K(j_bin_str)); ret = OB_ERR_INVALID_JSON_VALUE_FOR_CAST; LOG_USER_ERROR(OB_ERR_INVALID_JSON_VALUE_FOR_CAST); } else if (out_type < ObUInt64Type && CM_NEED_RANGE_CHECK(expr.extra_) && CAST_FAIL(uint_upper_check(out_type, out_val))) { LOG_WARN("uint_upper_check failed", K(ret), K(out_type), K(out_val)); } else { SET_RES_UINT(out_val); } } } return ret; } CAST_FUNC_NAME(json, double) { EVAL_STRING_ARG() { int warning = OB_SUCCESS; double out_val = 0.0; ObObjType out_type = expr.datum_meta_.type_; ObString j_bin_str = child_res->get_string(); ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); if (OB_FAIL(ObTextStringHelper::read_real_string_data(temp_allocator, *child_res, expr.args_[0]->datum_meta_, expr.args_[0]->obj_meta_.has_lob_header(), j_bin_str))) { LOG_WARN("fail to get real data.", K(ret), K(j_bin_str)); } else { ObJsonBin j_bin(j_bin_str.ptr(), j_bin_str.length()); ObIJsonBase *j_base = &j_bin; if (OB_FAIL(j_bin.reset_iter())) { LOG_WARN("failed to reset json bin iter", K(ret), K(j_bin_str)); } else if (CAST_FAIL(j_base->to_double(out_val))) { LOG_WARN("fail to cast json to double type", K(ret), K(j_bin_str)); ret = OB_ERR_INVALID_JSON_VALUE_FOR_CAST; LOG_USER_ERROR(OB_ERR_INVALID_JSON_VALUE_FOR_CAST); } else if (ObUDoubleType == out_type && CAST_FAIL(numeric_negative_check(out_val))) { LOG_WARN("numeric_negative_check failed", K(ret), K(out_val)); } else { SET_RES_DOUBLE(out_val); } } } return ret; } CAST_FUNC_NAME(json, float) { EVAL_STRING_ARG() { int warning = OB_SUCCESS; double tmp_val = 0.0; float out_val = 0.0; ObObjType out_type = expr.datum_meta_.type_; ObString j_bin_str = child_res->get_string(); ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); if (OB_FAIL(ObTextStringHelper::read_real_string_data(temp_allocator, *child_res, expr.args_[0]->datum_meta_, expr.args_[0]->obj_meta_.has_lob_header(), j_bin_str))) { LOG_WARN("fail to get real data.", K(ret), K(j_bin_str)); } else { ObJsonBin j_bin(j_bin_str.ptr(), j_bin_str.length()); ObIJsonBase *j_base = &j_bin; if (OB_FAIL(j_bin.reset_iter())) { LOG_WARN("failed to reset json bin iter", K(ret), K(j_bin_str)); } else if (CAST_FAIL(j_base->to_double(tmp_val))) { LOG_WARN("fail to cast json to float type", K(ret), K(j_bin_str)); ret = OB_ERR_INVALID_JSON_VALUE_FOR_CAST; LOG_USER_ERROR(OB_ERR_INVALID_JSON_VALUE_FOR_CAST); } else { SET_RES_FLOAT(out_val); } } } return ret; } CAST_FUNC_NAME(json, number) { EVAL_STRING_ARG() { int warning = OB_SUCCESS; number::ObNumber out_val; ObObjType out_type = expr.datum_meta_.type_; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); ObString j_bin_str = child_res->get_string(); if (OB_FAIL(ObTextStringHelper::read_real_string_data(temp_allocator, *child_res, expr.args_[0]->datum_meta_, expr.args_[0]->obj_meta_.has_lob_header(), j_bin_str))) { LOG_WARN("fail to get real data.", K(ret), K(j_bin_str)); } else { ObJsonBin j_bin(j_bin_str.ptr(), j_bin_str.length()); ObIJsonBase *j_base = &j_bin; if (OB_FAIL(j_bin.reset_iter())) { LOG_WARN("failed to reset json bin iter", K(ret), K(j_bin_str)); } else if (CAST_FAIL(j_base->to_number(&temp_allocator, out_val))) { LOG_WARN("fail to cast json to number type", K(ret), K(j_bin_str)); ret = OB_ERR_INVALID_JSON_VALUE_FOR_CAST; LOG_USER_ERROR(OB_ERR_INVALID_JSON_VALUE_FOR_CAST); } else if (ObUNumberType == out_type && CAST_FAIL(numeric_negative_check(out_val))) { LOG_WARN("numeric_negative_check failed", K(ret), K(out_val)); } else { res_datum.set_number(out_val); } } } return ret; } CAST_FUNC_NAME(json, datetime) { EVAL_STRING_ARG() { int warning = OB_SUCCESS; int64_t out_val; ObObjType out_type = expr.datum_meta_.type_; ObString j_bin_str = child_res->get_string(); ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); if (OB_FAIL(ObTextStringHelper::read_real_string_data(temp_allocator, *child_res, expr.args_[0]->datum_meta_, expr.args_[0]->obj_meta_.has_lob_header(), j_bin_str))) { LOG_WARN("fail to get real data.", K(ret), K(j_bin_str)); } else { ObJsonBin j_bin(j_bin_str.ptr(), j_bin_str.length()); ObIJsonBase *j_base = &j_bin; if (OB_FAIL(j_bin.reset_iter())) { LOG_WARN("failed to reset json bin iter", K(ret), K(j_bin_str)); } else if (CAST_FAIL(j_base->to_datetime(out_val))) { LOG_WARN("fail to cast json to datetime type", K(ret), K(j_bin_str)); ret = OB_ERR_INVALID_JSON_VALUE_FOR_CAST; LOG_USER_ERROR(OB_ERR_INVALID_JSON_VALUE_FOR_CAST); } else { SET_RES_DATETIME(out_val); } } } return ret; } CAST_FUNC_NAME(json, date) { EVAL_STRING_ARG() { int warning = OB_SUCCESS; int32_t out_val; ObObjType out_type = expr.datum_meta_.type_; ObString j_bin_str = child_res->get_string(); ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); if (OB_FAIL(ObTextStringHelper::read_real_string_data(temp_allocator, *child_res, expr.args_[0]->datum_meta_, expr.args_[0]->obj_meta_.has_lob_header(), j_bin_str))) { LOG_WARN("fail to get real data.", K(ret), K(j_bin_str)); } else { ObJsonBin j_bin(j_bin_str.ptr(), j_bin_str.length()); ObIJsonBase *j_base = &j_bin; if (OB_FAIL(j_bin.reset_iter())) { LOG_WARN("failed to reset json bin iter", K(ret), K(j_bin_str)); } else if (CAST_FAIL(j_base->to_date(out_val))) { LOG_WARN("fail to cast json to date type", K(ret), K(j_bin_str)); ret = OB_ERR_INVALID_JSON_VALUE_FOR_CAST; LOG_USER_ERROR(OB_ERR_INVALID_JSON_VALUE_FOR_CAST); } else { SET_RES_DATE(out_val); } } } return ret; } CAST_FUNC_NAME(json, time) { EVAL_STRING_ARG() { int warning = OB_SUCCESS; int64_t out_val; ObObjType out_type = expr.datum_meta_.type_; ObString j_bin_str = child_res->get_string(); ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); if (OB_FAIL(ObTextStringHelper::read_real_string_data(temp_allocator, *child_res, expr.args_[0]->datum_meta_, expr.args_[0]->obj_meta_.has_lob_header(), j_bin_str))) { LOG_WARN("fail to get real data.", K(ret), K(j_bin_str)); } else { ObJsonBin j_bin(j_bin_str.ptr(), j_bin_str.length()); ObIJsonBase *j_base = &j_bin; if (OB_FAIL(j_bin.reset_iter())) { LOG_WARN("failed to reset json bin iter", K(ret), K(j_bin_str)); } else if (CAST_FAIL(j_base->to_time(out_val))) { LOG_WARN("fail to cast json to time type", K(ret), K(j_bin_str)); ret = OB_ERR_INVALID_JSON_VALUE_FOR_CAST; LOG_USER_ERROR(OB_ERR_INVALID_JSON_VALUE_FOR_CAST); } else { SET_RES_TIME(out_val); } } } return ret; } CAST_FUNC_NAME(json, year) { EVAL_STRING_ARG() { int warning = OB_SUCCESS; uint8_t out_val = 0; int64_t int_val; ObObjType out_type = expr.datum_meta_.type_; ObString j_bin_str = child_res->get_string(); ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); if (OB_FAIL(ObTextStringHelper::read_real_string_data(temp_allocator, *child_res, expr.args_[0]->datum_meta_, expr.args_[0]->obj_meta_.has_lob_header(), j_bin_str))) { LOG_WARN("fail to get real data.", K(ret), K(j_bin_str)); } else { ObJsonBin j_bin(j_bin_str.ptr(), j_bin_str.length()); ObIJsonBase *j_base = &j_bin; if (OB_FAIL(j_bin.reset_iter())) { LOG_WARN("failed to reset json bin iter", K(ret), K(j_bin_str)); } else if (CAST_FAIL(j_base->to_int(int_val, false, true))) { LOG_WARN("fail to cast json as year", K(ret), K(j_bin_str)); ret = OB_ERR_INVALID_JSON_VALUE_FOR_CAST; LOG_USER_ERROR(OB_ERR_INVALID_JSON_VALUE_FOR_CAST); } else if (CAST_FAIL(ObTimeConverter::int_to_year(int_val, out_val))){ LOG_WARN("fail to cast json int to year type", K(ret), K(int_val)); } else { if (lib::is_mysql_mode() && (warning == OB_DATA_OUT_OF_RANGE)) { res_datum.set_null(); // not change the behavior of int_year } else { SET_RES_YEAR(out_val); } } } } return ret; } CAST_FUNC_NAME(json, raw) { EVAL_STRING_ARG() { int warning = OB_SUCCESS; ObObjType out_type = expr.datum_meta_.type_; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); ObString j_bin_str = child_res->get_string(); ObJsonBin j_bin(j_bin_str.ptr(), j_bin_str.length()); ObIJsonBase *j_base = &j_bin; ObJsonBuffer j_buf(&temp_allocator); ObDatum t_res_datum; bool has_set_res = false; if (OB_FAIL(j_bin.reset_iter())) { LOG_WARN("failed to reset json bin iter", K(ret), K(j_bin_str)); } else if (CAST_FAIL(j_base->print(j_buf, true))) { LOG_WARN("fail to convert json to string", K(ret), K(j_bin_str)); ret = OB_ERR_INVALID_JSON_VALUE_FOR_CAST; LOG_USER_ERROR(OB_ERR_INVALID_JSON_VALUE_FOR_CAST); } else { ObObjType in_type = ObLongTextType; ObObjType out_type = expr.datum_meta_.type_; ObString temp_str_val(j_buf.length(), j_buf.ptr()); // 如果将json直接设置成binary,这里要做特殊处理,而且代码中的binary类型也要改了 ObCollationType in_cs_type = expr.args_[0]->datum_meta_.cs_type_; ObCollationType out_cs_type = expr.datum_meta_.cs_type_; bool is_need_string_string_convert = ((CS_TYPE_BINARY == out_cs_type) || (ObCharset::charset_type_by_coll(in_cs_type) != ObCharset::charset_type_by_coll(out_cs_type))); if (!is_need_string_string_convert) { // same collation type, just string copy result; OZ(common_copy_string(expr, temp_str_val, ctx, t_res_datum)); } else { // should do collation convert; OZ(common_string_string(expr, in_type, in_cs_type, out_type, out_cs_type, temp_str_val, ctx, t_res_datum, has_set_res)); } if (OB_SUCC(ret)) { ObString in_str = t_res_datum.get_string(); OZ(ObDatumHexUtils::hextoraw_string(expr, in_str, ctx, res_datum, has_set_res)); } } } return ret; } CAST_FUNC_NAME(json, string) { EVAL_STRING_ARG() { int warning = OB_SUCCESS; ObObjType out_type = expr.datum_meta_.type_; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); ObString j_bin_str = child_res->get_string(); if (OB_FAIL(ObTextStringHelper::read_real_string_data(temp_allocator, *child_res, expr.args_[0]->datum_meta_, expr.args_[0]->obj_meta_.has_lob_header(), j_bin_str))) { LOG_WARN("fail to get real data.", K(ret), K(j_bin_str)); } else { ObJsonBin j_bin(j_bin_str.ptr(), j_bin_str.length()); ObIJsonBase *j_base = &j_bin; ObJsonBuffer j_buf(&temp_allocator); if (OB_FAIL(j_bin.reset_iter())) { LOG_WARN("failed to reset json bin iter", K(ret), K(j_bin_str)); } else if (CAST_FAIL(j_base->print(j_buf, true))) { LOG_WARN("fail to convert json to string", K(ret), K(j_bin_str)); ret = OB_ERR_INVALID_JSON_VALUE_FOR_CAST; LOG_USER_ERROR(OB_ERR_INVALID_JSON_VALUE_FOR_CAST); } else { ObObjType in_type = ObLongTextType; ObObjType out_type = expr.datum_meta_.type_; ObString temp_str_val(j_buf.length(), j_buf.ptr()); // 如果将json直接设置成binary,这里要做特殊处理,而且代码中的binary类型也要改了 ObCollationType in_cs_type = expr.args_[0]->datum_meta_.cs_type_; ObCollationType out_cs_type = expr.datum_meta_.cs_type_; bool is_need_string_string_convert = ((CS_TYPE_BINARY == out_cs_type) || (ObCharset::charset_type_by_coll(in_cs_type) != ObCharset::charset_type_by_coll(out_cs_type))); if (!is_need_string_string_convert) { // same collation type, just string copy result; OZ(common_copy_string(expr, temp_str_val, ctx, res_datum)); } else { // should do collation convert; bool has_set_res = false; OZ(common_string_string(expr, in_type, in_cs_type, out_type, out_cs_type, temp_str_val, ctx, res_datum, has_set_res)); } if (OB_SUCC(ret) && ob_is_text_tc(out_type)) { ObString res_str; if (OB_FAIL(copy_datum_str_with_tmp_alloc(ctx, res_datum, res_str))) { LOG_WARN("copy datum string with tmp allocator failed", K(ret)); } else if (OB_FAIL(common_string_text(expr, res_str, ctx, NULL, res_datum))) { LOG_WARN("cast string to lob failed", K(ret)); } } } } } return ret; } CAST_FUNC_NAME(json, bit) { EVAL_STRING_ARG() { int warning = OB_SUCCESS; ObString j_bin_str = child_res->get_string(); ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); if (OB_FAIL(ObTextStringHelper::read_real_string_data(temp_allocator, *child_res, expr.args_[0]->datum_meta_, expr.args_[0]->obj_meta_.has_lob_header(), j_bin_str))) { LOG_WARN("fail to get real data.", K(ret), K(j_bin_str)); } else { ObJsonBin j_bin(j_bin_str.ptr(), j_bin_str.length()); ObIJsonBase *j_base = &j_bin; uint64_t out_val; ObObjType out_type = expr.datum_meta_.type_; if (OB_FAIL(j_bin.reset_iter())) { LOG_WARN("failed to reset json bin iter", K(ret), K(j_bin_str)); } else if (CAST_FAIL(j_base->to_bit(out_val))) { LOG_WARN("fail to cast json as bit", K(ret), K(j_bin_str)); ret = OB_ERR_INVALID_JSON_VALUE_FOR_CAST; LOG_USER_ERROR(OB_ERR_INVALID_JSON_VALUE_FOR_CAST); } else { SET_RES_BIT(out_val); } } } return ret; } CAST_FUNC_NAME(json, otimestamp) { EVAL_STRING_ARG() { int warning = OB_SUCCESS; int64_t datetime_val; ObObjType out_type = expr.datum_meta_.type_; ObString j_bin_str = child_res->get_string(); ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); if (OB_FAIL(ObTextStringHelper::read_real_string_data(temp_allocator, *child_res, expr.args_[0]->datum_meta_, expr.args_[0]->obj_meta_.has_lob_header(), j_bin_str))) { LOG_WARN("fail to get real data.", K(ret), K(j_bin_str)); } else { ObJsonBin j_bin(j_bin_str.ptr(), j_bin_str.length()); ObIJsonBase *j_base = &j_bin; if (OB_FAIL(j_bin.reset_iter())) { LOG_WARN("failed to reset json bin iter", K(ret), K(j_bin_str)); } else if (CAST_FAIL(j_base->to_datetime(datetime_val))) { LOG_WARN("fail to cast json as datetime", K(ret), K(j_bin_str)); ret = OB_ERR_INVALID_JSON_VALUE_FOR_CAST; LOG_USER_ERROR(OB_ERR_INVALID_JSON_VALUE_FOR_CAST); } else { GET_SESSION() { const ObTimeZoneInfo *tz_info = session->get_timezone_info(); ObOTimestampData out_val; if (OB_FAIL(ObTimeConverter::odate_to_otimestamp(datetime_val, tz_info, out_type, out_val))) { LOG_WARN("fail to timestamp_to_timestamp_tz", K(ret), K(datetime_val), K(out_type)); } else { if (ObTimestampTZType == out_type) { SET_RES_OTIMESTAMP(out_val); } else { SET_RES_OTIMESTAMP_10BYTE(out_val); } } } } } } return ret; } CAST_FUNC_NAME(json, lob) { EVAL_STRING_ARG() { ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); ObString res_str; if(OB_FAIL(common_json_string(expr, ctx, temp_allocator, *child_res, res_str))) { LOG_WARN("common json to string failed", K(ret)); } else { // add lob locator ObLobLocator *lob_locator = nullptr; const int64_t buf_len = sizeof(ObLobLocator) + res_str.length(); char *buf = nullptr; if (OB_ISNULL(buf = expr.get_str_res_mem(ctx, buf_len))) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("Failed to allocate memory for lob locator", K(ret), K(buf_len)); } else if (FALSE_IT(lob_locator = reinterpret_cast (buf))) { } else if (OB_FAIL(lob_locator->init(res_str))) { STORAGE_LOG(WARN, "Failed to init lob locator", K(ret), K(res_str), KPC(lob_locator)); } else { res_datum.set_lob_locator(*lob_locator); } } } return ret; } CAST_FUNC_NAME(json, text) { EVAL_STRING_ARG() { ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); ObString res_str; if(OB_FAIL(common_json_string(expr, ctx, temp_allocator, *child_res, res_str))) { LOG_WARN("common json to string failed", K(ret)); } else if(is_lob_storage(expr.datum_meta_.type_)) { ObTextStringDatumResult str_result(expr.datum_meta_.type_, &expr, &ctx, &res_datum); if (OB_FAIL(str_result.init(res_str.length()))) { LOG_WARN("Lob: init lob result failed", K(ret)); } else if (OB_FAIL(str_result.append(res_str.ptr(), res_str.length()))) { LOG_WARN("Lob: append lob result failed", K(ret)); } else { str_result.set_result(); } } else { res_datum.set_string(res_str); } } return ret; } CAST_FUNC_NAME(json, json) { EVAL_STRING_ARG() { ObString out_val = child_res->get_string(); res_datum.set_string(out_val); } return ret; } CAST_FUNC_NAME(json, geometry) { EVAL_ARG() { if (CM_IS_COLUMN_CONVERT(expr.extra_)) { // adapt mysql ret = OB_ERR_CANT_CREATE_GEOMETRY_OBJECT; LOG_USER_ERROR(OB_ERR_CANT_CREATE_GEOMETRY_OBJECT); } else { ret = OB_NOT_SUPPORTED; LOG_USER_ERROR(OB_NOT_SUPPORTED, "json, geometry"); } } return ret; } //////////////////////////////////////////////////////////// // geometry -> XXX CAST_FUNC_NAME(geometry, int) { EVAL_STRING_ARG() { if (CM_IS_IMPLICIT_CAST(expr.extra_)) { ObString in_str = child_res->get_string(); ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); if (OB_FAIL(ObTextStringHelper::read_real_string_data(temp_allocator, *child_res, expr.args_[0]->datum_meta_, expr.args_[0]->obj_meta_.has_lob_header(), in_str))) { LOG_WARN("fail to get real data.", K(ret), K(in_str)); } else if (OB_FAIL(common_string_int(expr, expr.extra_, in_str, true, res_datum))) { LOG_WARN("fail to cast string to int", K(ret)); } } else { ret = OB_INVALID_ARGUMENT; LOG_USER_ERROR(OB_INVALID_ARGUMENT, "cast_as_signed"); } } return ret; } CAST_FUNC_NAME(geometry, uint) { EVAL_STRING_ARG() { if (CM_IS_IMPLICIT_CAST(expr.extra_)) { ObString in_str = child_res->get_string(); ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); if (OB_FAIL(ObTextStringHelper::read_real_string_data(temp_allocator, *child_res, expr.args_[0]->datum_meta_, expr.args_[0]->obj_meta_.has_lob_header(), in_str))) { LOG_WARN("fail to get real data.", K(ret), K(in_str)); } else if (OB_FAIL(common_string_uint(expr, in_str, true, res_datum))) { LOG_WARN("fail to cast string to uint", K(ret)); } } else { ret = OB_INVALID_ARGUMENT; LOG_USER_ERROR(OB_INVALID_ARGUMENT, "cast_as_unsigned"); } } return ret; } CAST_FUNC_NAME(geometry, double) { EVAL_STRING_ARG() { // hash join will cast geometry to double, which has set CM_WARN_ON_FAIL. Skip it. if (CM_IS_IMPLICIT_CAST(expr.extra_) && !CM_IS_WARN_ON_FAIL(expr.extra_)) { ObString in_str = child_res->get_string(); ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); DEF_IN_OUT_TYPE(); if (OB_FAIL(ObTextStringHelper::read_real_string_data(temp_allocator, *child_res, expr.args_[0]->datum_meta_, expr.args_[0]->obj_meta_.has_lob_header(), in_str))) { LOG_WARN("fail to get real data.", K(ret), K(in_str)); } else if (OB_FAIL(common_string_double(expr, in_type, expr.args_[0]->datum_meta_.cs_type_, out_type, in_str, res_datum))) { LOG_WARN("fail to cast string to double", K(ret)); ret = OB_ERR_WARN_DATA_OUT_OF_RANGE; // adapt mysql } } else { res_datum.set_double(0); } } return ret; } CAST_FUNC_NAME(geometry, float) { EVAL_STRING_ARG() { if (CM_IS_IMPLICIT_CAST(expr.extra_)) { float out_val = 0; ObString in_str = child_res->get_string(); ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); if (OB_FAIL(ObTextStringHelper::read_real_string_data(temp_allocator, *child_res, expr.args_[0]->datum_meta_, expr.args_[0]->obj_meta_.has_lob_header(), in_str))) { LOG_WARN("fail to get real data.", K(ret), K(in_str)); } else if (OB_FAIL(common_string_float(expr, in_str, out_val))) { LOG_WARN("fail to cast string to float", K(ret)); ret = OB_ERR_WARN_DATA_OUT_OF_RANGE; // adapt mysql } else { res_datum.set_float(out_val); } } else { res_datum.set_float(0); } } return ret; } CAST_FUNC_NAME(geometry, number) { EVAL_STRING_ARG() { if (CM_IS_IMPLICIT_CAST(expr.extra_)) { number::ObNumber nmb; ObNumStackOnceAlloc tmp_alloc; ObString in_str = child_res->get_string(); ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); if (OB_FAIL(ObTextStringHelper::read_real_string_data(temp_allocator, *child_res, expr.args_[0]->datum_meta_, expr.args_[0]->obj_meta_.has_lob_header(), in_str))) { LOG_WARN("fail to get real data.", K(ret), K(in_str)); } else if (OB_FAIL(common_string_number(expr, in_str, tmp_alloc, nmb))) { LOG_WARN("fail to cast string to number", K(ret)); ret = OB_ERR_TRUNCATED_WRONG_VALUE_FOR_FIELD; // adapt mysql } else { res_datum.set_number(nmb); } } else { number::ObNumber nmb; nmb.set_zero(); OX(res_datum.set_number(nmb)); } } return ret; } CAST_FUNC_NAME(geometry, datetime) { EVAL_STRING_ARG() { if (CM_IS_IMPLICIT_CAST(expr.extra_)) { ObString in_str = child_res->get_string(); ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); if (OB_FAIL(ObTextStringHelper::read_real_string_data(temp_allocator, *child_res, expr.args_[0]->datum_meta_, expr.args_[0]->obj_meta_.has_lob_header(), in_str))) { LOG_WARN("fail to get real data.", K(ret), K(in_str)); } else if (OB_FAIL(common_string_datetime(expr, in_str, ctx, res_datum))) { LOG_WARN("fail to cast string to datetime", K(ret)); } } else { res_datum.set_null(); } } return ret; } CAST_FUNC_NAME(geometry, date) { EVAL_STRING_ARG() { if (CM_IS_IMPLICIT_CAST(expr.extra_)) { ObString in_str = child_res->get_string(); ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); if (OB_FAIL(ObTextStringHelper::read_real_string_data(temp_allocator, *child_res, expr.args_[0]->datum_meta_, expr.args_[0]->obj_meta_.has_lob_header(), in_str))) { LOG_WARN("fail to get real data.", K(ret), K(in_str)); } else if (OB_FAIL(common_string_date(expr, in_str, res_datum))) { LOG_WARN("fail to cast string to date", K(ret)); } } else { res_datum.set_null(); } } return ret; } CAST_FUNC_NAME(geometry, time) { EVAL_STRING_ARG() { if (CM_IS_NULL_ON_WARN(expr.extra_)) { // issue/42826593 res_datum.set_null(); } else if (CM_IS_IMPLICIT_CAST(expr.extra_)) { ObString in_str = child_res->get_string(); ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); if (OB_FAIL(ObTextStringHelper::read_real_string_data(temp_allocator, *child_res, expr.args_[0]->datum_meta_, expr.args_[0]->obj_meta_.has_lob_header(), in_str))) { LOG_WARN("fail to get real data.", K(ret), K(in_str)); } else if (OB_FAIL(common_string_time(expr, in_str, res_datum))) { LOG_WARN("fail to cast string to time", K(ret)); } } else { res_datum.set_null(); } } return ret; } CAST_FUNC_NAME(geometry, year) { EVAL_STRING_ARG() { if (CM_IS_IMPLICIT_CAST(expr.extra_)) { ObString in_str = child_res->get_string(); ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); if (OB_FAIL(ObTextStringHelper::read_real_string_data(temp_allocator, *child_res, expr.args_[0]->datum_meta_, expr.args_[0]->obj_meta_.has_lob_header(), in_str))) { LOG_WARN("fail to get real data.", K(ret), K(in_str)); } else if (OB_FAIL(common_string_year(expr, in_str, res_datum))) { LOG_WARN("fail to cast string to year", K(ret)); } } else { ret = OB_INVALID_ARGUMENT; LOG_USER_ERROR(OB_INVALID_ARGUMENT, "cast_as_year"); } } return ret; } CAST_FUNC_NAME(geometry, bit) { EVAL_STRING_ARG() { if (CM_IS_IMPLICIT_CAST(expr.extra_)) { ObString in_str = child_res->get_string(); ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); if (OB_FAIL(ObTextStringHelper::read_real_string_data(temp_allocator, *child_res, expr.args_[0]->datum_meta_, expr.args_[0]->obj_meta_.has_lob_header(), in_str))) { LOG_WARN("fail to get real data.", K(ret), K(in_str)); } else if (OB_FAIL(common_string_bit(expr, in_str, ctx, res_datum))) { LOG_WARN("fail to cast string to bit", K(ret)); } } else { ret = OB_ERR_PARSE_SQL; const char *err_msg = "bit"; int32_t str_len = static_cast(strlen(err_msg)); int32_t line_no = 1; LOG_USER_ERROR(OB_ERR_PARSE_SQL, ob_errpkt_strerror(OB_ERR_PARSER_SYNTAX, false), str_len, err_msg, line_no); } } return ret; } CAST_FUNC_NAME(geometry, otimestamp) { EVAL_STRING_ARG() { if (CM_IS_IMPLICIT_CAST(expr.extra_)) { ObString in_str = child_res->get_string(); ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); if (OB_FAIL(ObTextStringHelper::read_real_string_data(temp_allocator, *child_res, expr.args_[0]->datum_meta_, expr.args_[0]->obj_meta_.has_lob_header(), in_str))) { LOG_WARN("fail to get real data.", K(ret), K(in_str)); } else if (OB_FAIL(common_string_otimestamp(expr, in_str, ctx, res_datum))) { LOG_WARN("fail to cast string to otimestamp", K(ret)); } } else { ret = OB_ERR_PARSE_SQL; const char *err_msg = "timestamp"; int32_t str_len = static_cast(strlen(err_msg)); int32_t line_no = 1; LOG_USER_ERROR(OB_ERR_PARSE_SQL, ob_errpkt_strerror(OB_ERR_PARSER_SYNTAX, false), str_len, err_msg, line_no); } } return ret; } static int geom_copy_string(const ObExpr &expr, ObString &src, ObEvalCtx &ctx, ObDatum &res_datum) { int ret = OB_SUCCESS; char *out_ptr = NULL; int64_t len = src.length() - WKB_VERSION_SIZE; if (expr.obj_meta_.is_lob_storage()) { if (OB_FAIL(common_gis_wkb(expr, ctx, res_datum, src))) { LOG_WARN("fail to pack gis lob res", K(ret)); } } else { if (expr.res_buf_len_ < len) { if (OB_ISNULL(out_ptr = expr.get_str_res_mem(ctx, len))) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("allocate memory failed", K(ret)); } } else { out_ptr = const_cast(res_datum.ptr_); } if (OB_SUCC(ret)) { MEMMOVE(out_ptr, src.ptr(), WKB_GEO_SRID_SIZE); MEMMOVE(out_ptr + WKB_GEO_SRID_SIZE, src.ptr() + WKB_OFFSET, len - WKB_GEO_SRID_SIZE); res_datum.set_string(out_ptr, len); } } return ret; } CAST_FUNC_NAME(geometry, string) { EVAL_STRING_ARG() { ObString wkb = child_res->get_string(); ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); if (OB_FAIL(ObTextStringHelper::read_real_string_data(temp_allocator, *child_res, expr.args_[0]->datum_meta_, expr.args_[0]->obj_meta_.has_lob_header(), wkb))) { LOG_WARN("fail to get real data.", K(ret), K(wkb)); } else if (OB_FAIL(geom_copy_string(expr, wkb, ctx, res_datum))){ LOG_WARN("fail to copy string", K(ret)); } } return ret; } CAST_FUNC_NAME(geometry, json) { EVAL_STRING_ARG() { ret = OB_NOT_SUPPORTED; LOG_USER_ERROR(OB_NOT_SUPPORTED, "geomerty, json"); } return ret; } CAST_FUNC_NAME(geometry, geometry) { EVAL_STRING_ARG() { int warning = OB_SUCCESS; ObGeometry *src_tree = NULL; ObGeometry *dst_tree = NULL; ObString wkb = child_res->get_string(); ObObjType out_type = expr.datum_meta_.type_; ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); ObGeoType dst_geo_type = ObGeoCastUtils::get_geo_type_from_cast_mode(expr.extra_); const char *cast_name = ObGeometryTypeCastUtil::get_cast_name(dst_geo_type); omt::ObSrsCacheGuard srs_guard; const ObSrsItem *srs = NULL; ObGeometryTypeCast *geo_cast = NULL; ObGeoErrLogInfo log_info; if (ObGeoType::GEOMETRY == dst_geo_type) { res_datum.set_string(wkb); } else { if (OB_FAIL(ObTextStringHelper::read_real_string_data(temp_allocator, *child_res, expr.args_[0]->datum_meta_, expr.args_[0]->obj_meta_.has_lob_header(), wkb))) { LOG_WARN("fail to get real data.", K(ret), K(wkb)); } else if (OB_FAIL(ObGeoExprUtils::get_srs_item(ctx, srs_guard, wkb, srs, true, cast_name))) { LOG_WARN("fail to get srs item", K(ret), K(wkb)); } else if (OB_FAIL(ObGeometryTypeCastUtil::get_tree(temp_allocator, wkb, src_tree, srs, log_info, cast_name))) { LOG_WARN("fail to get tree", K(ret), K(wkb)); if (OB_ERR_GIS_INVALID_DATA == ret) { LOG_USER_ERROR(OB_ERR_GIS_INVALID_DATA, cast_name); } else if (OB_ERR_GEOMETRY_PARAM_LONGITUDE_OUT_OF_RANGE == ret) { LOG_USER_ERROR(OB_ERR_GEOMETRY_PARAM_LONGITUDE_OUT_OF_RANGE, cast_name, log_info.value_out_of_range_, log_info.min_long_val_, log_info.max_long_val_); } else if (OB_ERR_GEOMETRY_PARAM_LATITUDE_OUT_OF_RANGE == ret) { LOG_USER_ERROR(OB_ERR_GEOMETRY_PARAM_LATITUDE_OUT_OF_RANGE, cast_name, log_info.value_out_of_range_, log_info.min_lat_val_, log_info.max_lat_val_); } } else { ObSrsType srs_type = src_tree->get_srid() == 0 ? ObSrsType::PROJECTED_SRS : srs->srs_type(); if (OB_FAIL(ObGeoTypeUtil::create_geo_by_type(temp_allocator, dst_geo_type, ObSrsType::GEOGRAPHIC_SRS == srs_type, false, dst_tree, src_tree->get_srid()))) { LOG_WARN("fail to alloc dst geo tree", K(ret), K(dst_geo_type), K(srs_type)); } else if (OB_FAIL(ObGeometryTypeCastFactory::alloc(temp_allocator, dst_geo_type, geo_cast))) { LOG_WARN("fail to alloc geometry cast", K(ret), K(dst_geo_type)); } else { ObGeoErrLogInfo log_info; if (ObSrsType::PROJECTED_SRS == srs_type) { if (OB_FAIL(geo_cast->cast_geom(*src_tree, *dst_tree, srs, log_info, &temp_allocator))) { LOG_WARN("fail to cast geom", K(ret), K(src_tree->type()), K(dst_geo_type)); ObGeoCastUtils::geo_cast_error_handle(ret, src_tree->type(), dst_geo_type, log_info); } } else if (ObSrsType::GEOGRAPHIC_SRS == srs_type) { if (OB_FAIL(geo_cast->cast_geog(*src_tree, *dst_tree, srs, log_info, &temp_allocator))) { LOG_WARN("fail to cast geog", K(ret), K(src_tree->type()), K(dst_geo_type)); ObGeoCastUtils::geo_cast_error_handle(ret, src_tree->type(), dst_geo_type, log_info); } } else { ret = OB_ERR_UNEXPECTED; LOG_WARN("unknowed srs type", K(ret), K(srs_type)); } } } if (OB_SUCC(ret)) { ObString res_wkb; if (OB_FAIL(ObGeoTypeUtil::to_wkb(temp_allocator, *dst_tree, srs, res_wkb))) { LOG_WARN("fail to get wkb", K(ret), K(src_tree->type()), K(dst_geo_type)); } else if (OB_FAIL(common_gis_wkb(expr, ctx, res_datum, res_wkb))){ LOG_WARN("fail to copy string", K(ret), K(src_tree->type()), K(dst_geo_type)); } } } } return ret; } //////////////////////////////////////////////////////////// // XXX -> udt int cast_to_udt_not_support(const sql::ObExpr &expr, sql::ObEvalCtx &ctx, sql::ObDatum &res_datum) { UNUSED(ctx); UNUSED(res_datum); int ret = OB_SUCCESS; const ObObjMeta &in_obj_meta = expr.args_[0]->obj_meta_; const ObObjMeta &out_obj_meta = expr.obj_meta_; if (out_obj_meta.is_xml_sql_type()) { // only allow cast basic types to invalid CAST to a type that is not a nested table or VARRAY ret = OB_ERR_INVALID_CAST_UDT; LOG_WARN_RET(ret, "invalid CAST to a type that is not a nested table or VARRAY"); } else { // other udts // ORA-00932: inconsistent datatypes: expected PLSQL INDEX TABLE got NUMBER // currently other types to udt not supported ret = OB_ERR_UNEXPECTED; LOG_WARN_RET(ret, "not expected obj type convert", K(in_obj_meta), K(out_obj_meta), K(out_obj_meta.get_subschema_id()), K(expr.extra_)); } return ret; } //////////////////////////////////////////////////////////// // udt -> XXX int cast_udt_to_other_not_support(const sql::ObExpr &expr, sql::ObEvalCtx &ctx, sql::ObDatum &res_datum) { UNUSED(ctx); UNUSED(res_datum); int ret = OB_SUCCESS; const ObObjMeta &in_obj_meta = expr.args_[0]->obj_meta_; const ObObjMeta &out_obj_meta = expr.obj_meta_; if (in_obj_meta.is_xml_sql_type()) { // only allow cast basic types to invalid CAST to a type that is not a nested table or VARRAY ret = OB_ERR_INVALID_TYPE_FOR_OP; LOG_WARN_RET(ret, "inconsistent datatypes", K(in_obj_meta), K(out_obj_meta), K(out_obj_meta.get_subschema_id()), K(expr.extra_)); } else { // other udts // ORA-00932: inconsistent datatypes: expected PLSQL INDEX TABLE got NUMBER // currently other types to udt not supported ret = OB_ERR_UNEXPECTED; LOG_WARN_RET(ret, "not expected obj type convert", K(in_obj_meta), K(out_obj_meta), K(out_obj_meta.get_subschema_id()), K(expr.extra_)); } return ret; } CAST_FUNC_NAME(udt, string) { // udt(xmltype) can be null: select dump(xmlparse(document NULL)) from dual; EVAL_STRING_ARG() { ret = OB_NOT_SUPPORTED; } return ret; } CAST_FUNC_NAME(sql_udt, pl_extend) { // Convert sql udt type to pl udt type, currently only xmltype is supported // check source type subschema id for validation // For PL extend type, detaield udt id is stored in accurcy_ before code generation, // then only existed in the data after cg. int ret = OB_SUCCESS; ret = OB_NOT_SUPPORTED; return ret; } CAST_FUNC_NAME(pl_extend, sql_udt) { // Convert sql udt type to pl udt type, currently only xmltype is supported EVAL_STRING_ARG() { ret = OB_NOT_SUPPORTED; } return ret; } // 显式cast时,再次从parse node中获取accuracy信息(see ob_expr_cast.cpp) // 可能是因为cast类型推导不准,导致必须再次从parse node中获取 int get_accuracy_from_parse_node(const ObExpr &expr, ObEvalCtx &ctx, ObAccuracy &accuracy, ObObjType &dest_type) { int ret = OB_SUCCESS; ObDatum *dst_type_dat = NULL; ObExprResType dst_type; if (OB_UNLIKELY(2 != expr.arg_cnt_) || OB_ISNULL(expr.args_) || OB_ISNULL(expr.args_[1])) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected expr", K(ret), K(expr.arg_cnt_), KP(expr.args_)); } else if (OB_FAIL(expr.args_[1]->eval(ctx, dst_type_dat))) { LOG_WARN("eval dst type datum failed", K(ret)); } else { int64_t maxblen = ObCharset::CharConvertFactorNum; ParseNode node; node.value_ = dst_type_dat->get_int(); ObObjType obj_type = static_cast(node.int16_values_[OB_NODE_CAST_TYPE_IDX]); dst_type.set_collation_type(static_cast(node.int16_values_[OB_NODE_CAST_COLL_IDX])); dst_type.set_type(obj_type); int64_t text_length = node.int32_values_[1]; if (lib::is_mysql_mode() && !dst_type.is_binary() && !dst_type.is_varbinary()) { dst_type.set_full_length(node.int32_values_[OB_NODE_CAST_C_LEN_IDX], expr.datum_meta_.length_semantics_); if (dst_type.get_length() > OB_MAX_CAST_CHAR_VARCHAR_LENGTH && dst_type.get_length() <= OB_MAX_CAST_CHAR_TEXT_LENGTH) { dst_type.set_type(ObTextType); dst_type.set_length(OB_MAX_CAST_CHAR_TEXT_LENGTH); } else if (dst_type.get_length() > OB_MAX_CAST_CHAR_TEXT_LENGTH && dst_type.get_length() <= OB_MAX_CAST_CHAR_MEDIUMTEXT_LENGTH) { dst_type.set_type(ObMediumTextType); dst_type.set_length(OB_MAX_CAST_CHAR_MEDIUMTEXT_LENGTH); } else if (dst_type.get_length() > OB_MAX_CAST_CHAR_MEDIUMTEXT_LENGTH) { dst_type.set_type(ObLongTextType); dst_type.set_length(OB_MAX_LONGTEXT_LENGTH / maxblen); } text_length = dst_type.get_length(); } dest_type = dst_type.get_type(); ObObjTypeClass dest_tc = ob_obj_type_class(dest_type); if (ObStringTC == dest_tc) { // parser will abort all negative number // if length < 0 means DEFAULT_STR_LENGTH or OUT_OF_STR_LEN. accuracy.set_full_length(node.int32_values_[1], expr.datum_meta_.length_semantics_, lib::is_oracle_mode()); } else if (ObRawTC == dest_tc) { accuracy.set_length(node.int32_values_[1]); } else if(ObTextTC == dest_tc || ObJsonTC == dest_tc) { accuracy.set_length(text_length < 0 ? ObAccuracy::DDL_DEFAULT_ACCURACY[dest_type].get_length() : text_length); } else if (ObIntervalTC == dest_tc) { if (OB_UNLIKELY(!ObIntervalScaleUtil::scale_check(node.int16_values_[3]) || !ObIntervalScaleUtil::scale_check(node.int16_values_[2]))) { ret = OB_ERR_DATETIME_INTERVAL_PRECISION_OUT_OF_RANGE; } else { ObScale scale = (dest_type == ObIntervalYMType) ? ObIntervalScaleUtil::interval_ym_scale_to_ob_scale( static_cast(node.int16_values_[3])) : ObIntervalScaleUtil::interval_ds_scale_to_ob_scale( static_cast(node.int16_values_[2]), static_cast(node.int16_values_[3])); accuracy.set_scale(scale); } } else { const ObAccuracy &def_acc = ObAccuracy::DDL_DEFAULT_ACCURACY2[lib::is_oracle_mode()][dest_type]; if (ObNumberType == dest_type && 0 == node.int16_values_[2]) { accuracy.set_precision(def_acc.get_precision()); } else { accuracy.set_precision(node.int16_values_[2]); } accuracy.set_scale(node.int16_values_[3]); if (lib::is_oracle_mode() && ObDoubleType == dest_type) { accuracy.set_accuracy(def_acc.get_precision()); } } } return ret; } int uint_to_enum(const uint64_t input_value, const ObIArray &str_values, const ObCastMode &cast_mode, int &warning, uint64_t &output_value) { int ret = OB_SUCCESS; uint64_t value = input_value; if (OB_UNLIKELY(0 == value || value > str_values.count())) { if (CM_IS_WARN_ON_FAIL(cast_mode)) { value = 0; warning = OB_ERR_DATA_TRUNCATED; LOG_INFO("input value out of range, set zero", K(input_value), K(str_values.count()), K(warning)); } else { ret = OB_ERR_DATA_TRUNCATED; LOG_WARN("input value out of range", K(input_value), K(str_values.count()), K(ret)); } } output_value = value; LOG_DEBUG("finish uint_to_enum", K(ret), K(input_value), K(str_values), K(output_value), K(lbt())); return ret; } int uint_to_set(const uint64_t input_value, const ObIArray &str_values, const ObCastMode &cast_mode, int &warning, uint64_t &output_value) { int ret = OB_SUCCESS; uint64_t value = input_value; int64_t val_cnt = str_values.count(); if (val_cnt >= 64) { //do nothing } else if (val_cnt < 64 && value > ((1ULL << val_cnt) - 1)) { if (CM_IS_WARN_ON_FAIL(cast_mode)) { value = value & ((1ULL << val_cnt) - 1); warning = OB_ERR_DATA_TRUNCATED; LOG_INFO("input value out of range", K(input_value), K(value), K(val_cnt), K(warning)); } else { ret = OB_ERR_DATA_TRUNCATED; LOG_WARN("input value out of range", K(input_value), K(value), K(val_cnt), K(ret)); } } output_value = value; LOG_DEBUG("finish uint_to_set", K(ret), K(input_value), K(str_values), K(output_value), K(lbt())); return ret; } CAST_ENUMSET_FUNC_NAME(int, enum) { EVAL_ARG() { int warning = 0; if (child_res->is_null()) { res_datum.set_null(); } else { uint64_t val_uint = static_cast(child_res->get_int()); uint64_t value = 0; ret = uint_to_enum(val_uint, str_values, cast_mode, warning, value); SET_RES_ENUM(value); } } return ret; } CAST_ENUMSET_FUNC_NAME(int, set) { EVAL_ARG() { int warning = 0; uint64_t val_uint = static_cast(child_res->get_int()); uint64_t value = 0; ret = uint_to_set(val_uint, str_values, cast_mode, warning, value); SET_RES_SET(value); } return ret; } CAST_ENUMSET_FUNC_NAME(uint, enum) { EVAL_ARG() { if (child_res->is_null()) { res_datum.set_null(); } else { int warning = 0; uint64_t val_uint = child_res->get_uint(); uint64_t value = 0; ret = uint_to_enum(val_uint, str_values, cast_mode, warning, value); SET_RES_ENUM(value); } } return ret; } CAST_ENUMSET_FUNC_NAME(uint, set) { EVAL_ARG() { int warning = 0; uint64_t val_uint = child_res->get_uint(); uint64_t value = 0; ret = uint_to_set(val_uint, str_values, cast_mode, warning, value); SET_RES_SET(value); } return ret; } CAST_ENUMSET_FUNC_NAME(float, enum) { EVAL_ARG() { if (child_res->is_null()) { res_datum.set_null(); } else { int warning = 0; uint64_t val_uint = static_cast(static_cast(child_res->get_float())); uint64_t value = 0; ret = uint_to_enum(val_uint, str_values, cast_mode, warning, value); SET_RES_ENUM(value); } } return ret; } CAST_ENUMSET_FUNC_NAME(float, set) { EVAL_ARG() { int warning = 0; uint64_t val_uint = static_cast(static_cast(child_res->get_float())); uint64_t value = 0; ret = uint_to_set(val_uint, str_values, cast_mode, warning, value); SET_RES_SET(value); } return ret; } CAST_ENUMSET_FUNC_NAME(double, enum) { EVAL_ARG() { if (child_res->is_null()) { res_datum.set_null(); } else { int warning = 0; uint64_t val_uint = static_cast(static_cast(child_res->get_double())); uint64_t value = 0; ret = uint_to_enum(val_uint, str_values, cast_mode, warning, value); SET_RES_ENUM(value); } } return ret; } CAST_ENUMSET_FUNC_NAME(double, set) { EVAL_ARG() { int warning = 0; uint64_t val_uint = static_cast(static_cast(child_res->get_double())); uint64_t value = 0; ret = uint_to_set(val_uint, str_values, cast_mode, warning, value); SET_RES_SET(value); } return ret; } CAST_ENUMSET_FUNC_NAME(number, enum) { int ret = OB_SUCCESS; int warning = 0; if (OB_FAIL(number_double(expr, ctx, res_datum))) { LOG_WARN("fail to cast number to double", K(expr), K(ret)); } else if (res_datum.is_null()) { //do nothing } else { uint64_t val_uint = static_cast(static_cast(res_datum.get_double())); uint64_t value = 0; ret = uint_to_enum(val_uint, str_values, cast_mode, warning, value); SET_RES_ENUM(value); } return ret; } CAST_ENUMSET_FUNC_NAME(number, set) { int ret = OB_SUCCESS; int warning = 0; if (OB_FAIL(number_double(expr, ctx, res_datum))) { LOG_WARN("fail to cast number to double", K(expr), K(ret)); } else if (res_datum.is_null()) { //do nothing } else { uint64_t val_uint = static_cast(static_cast(res_datum.get_double())); uint64_t value = 0; ret = uint_to_set(val_uint, str_values, cast_mode, warning, value); SET_RES_SET(value); } return ret; } int string_to_enum(ObIAllocator &alloc, const ObString &orig_in_str, const ObCollationType in_cs_type, const ObIArray &str_values, const uint64_t cast_mode, const ObExpr &expr, int &warning, uint64_t &output_value) { int ret = OB_SUCCESS; const ObCollationType cs_type = expr.obj_meta_.get_collation_type(); uint64_t value = 0; int32_t pos = 0; ObString in_str; OZ(ObCharset::charset_convert(alloc, orig_in_str, in_cs_type, cs_type, in_str)); int32_t no_sp_len = static_cast(ObCharset::strlen_byte_no_sp(cs_type, in_str.ptr(), in_str.length())); ObString no_sp_val(0, static_cast(no_sp_len), in_str.ptr()); if (OB_FAIL(ret)) { } else if (OB_FAIL(find_type(str_values, cs_type, no_sp_val, pos))) { LOG_WARN("fail to find type", K(str_values), K(cs_type), K(no_sp_val), K(in_str), K(pos), K(ret)); } else if (OB_UNLIKELY(pos < 0)) { // Bug30666903: check implicit cast logic to handle number cases if (!in_str.is_numeric()) { ret = OB_ERR_DATA_TRUNCATED; } else { int err = 0; int64_t val_cnt = str_values.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(val_cnt), K(ret), K(err)); } } if (OB_FAIL(ret) && CM_IS_WARN_ON_FAIL(cast_mode)) { warning = ret; ret = OB_SUCCESS; } } else { value = pos + 1;//enum start from 1 } output_value = value; LOG_DEBUG("finish string_enum", K(ret), K(in_str), K(str_values), K(expr), K(output_value), K(lbt())); return ret; } CAST_ENUMSET_FUNC_NAME(string, enum) { EVAL_ARG() { int warning = 0; const ObString in_str = child_res->get_string(); uint64_t value = 0; ObEvalCtx::TempAllocGuard alloc_guard(ctx); ret = string_to_enum(alloc_guard.get_allocator(), in_str, expr.args_[0]->datum_meta_.cs_type_, str_values, cast_mode, expr, warning, value); SET_RES_ENUM(value); } return ret; } CAST_ENUMSET_FUNC_NAME(text, enum) { EVAL_STRING_ARG() { ObString in_str(child_res->len_, child_res->ptr_); ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); OZ(get_text_full_data(expr, ctx, &temp_allocator, child_res, in_str)); if (OB_SUCC(ret)) { int warning = 0; uint64_t value = 0; ObEvalCtx::TempAllocGuard alloc_guard(ctx); ret = string_to_enum(alloc_guard.get_allocator(), in_str, expr.args_[0]->datum_meta_.cs_type_, str_values, cast_mode, expr, warning, value); SET_RES_ENUM(value); } } return ret; } int string_to_set(ObIAllocator &alloc, const ObString &orig_in_str, const ObCollationType in_cs_type, const ObIArray &str_values, const uint64_t cast_mode, const ObExpr &expr, int &warning, uint64_t &output_value) { int ret = OB_SUCCESS; uint64_t value = 0; ObString in_str; const ObCollationType cs_type = expr.obj_meta_.get_collation_type(); OZ(ObCharset::charset_convert(alloc, orig_in_str, in_cs_type, cs_type, in_str)); if (OB_FAIL(ret)) { } else if (in_str.empty()) { //do noting } else { bool is_last_value = false; const ObString &sep = ObCharsetUtils::get_const_str(cs_type, ','); int32_t pos = 0; const char *remain = in_str.ptr(); int64_t remain_len = ObCharset::strlen_byte_no_sp(cs_type, in_str.ptr(), in_str.length()); ObString val_str; 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(str_values, cs_type, val_str, pos))) { LOG_WARN("fail to find type", K(str_values), K(cs_type), 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(str_values, cs_type, val_str, pos))) { LOG_WARN("fail to find type", K(str_values), K(cs_type), K(val_str), K(pos), K(ret)); } } if (OB_FAIL(ret)) { } else if (OB_UNLIKELY(pos < 0)) {//not found if (CM_IS_WARN_ON_FAIL(cast_mode)) { warning = OB_ERR_DATA_TRUNCATED; LOG_INFO("input value out of range, and set out value zero", K(pos), K(expr), K(val_str), K(in_str), K(warning)); } else { ret = OB_ERR_DATA_TRUNCATED; LOG_WARN("data truncate", K(pos), K(expr), K(val_str), K(in_str), K(ret)); } } else { pos %= 64;//MySQL中,如果value存在重复,则value_count可以大于64 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 || (OB_ERR_DATA_TRUNCATED == warning && 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 = str_values.count(); if (OB_UNLIKELY(val_cnt <= 0)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpect val_cnt", K(val_cnt), 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(val_cnt), K(ret)); } if (OB_FAIL(ret) && CM_IS_WARN_ON_FAIL(cast_mode)) { warning = OB_ERR_DATA_TRUNCATED; ret = OB_SUCCESS; } } else { value = 0; } } output_value = value; LOG_DEBUG("finish string_set", K(ret), K(in_str), K(str_values), K(expr), K(output_value), K(lbt())); return ret; } CAST_ENUMSET_FUNC_NAME(string, set) { EVAL_ARG() { int warning = 0; const ObString in_str = child_res->get_string(); uint64_t value = 0; ObEvalCtx::TempAllocGuard alloc_guard(ctx); ret = string_to_set(alloc_guard.get_allocator(), in_str, expr.args_[0]->datum_meta_.cs_type_, str_values, cast_mode, expr, warning, value); SET_RES_SET(value); } return ret; } CAST_ENUMSET_FUNC_NAME(text, set) { EVAL_STRING_ARG() { ObString in_str(child_res->len_, child_res->ptr_); ObEvalCtx::TempAllocGuard tmp_alloc_g(ctx); common::ObArenaAllocator &temp_allocator = tmp_alloc_g.get_allocator(); OZ(get_text_full_data(expr, ctx, &temp_allocator, child_res, in_str)); if (OB_SUCC(ret)) { int warning = 0; uint64_t value = 0; ObEvalCtx::TempAllocGuard alloc_guard(ctx); ret = string_to_set(alloc_guard.get_allocator(), in_str, expr.args_[0]->datum_meta_.cs_type_, str_values, cast_mode, expr, warning, value); SET_RES_ENUM(value); } } return ret; } CAST_ENUMSET_FUNC_NAME(datetime, enum) { EVAL_ARG() { int warning = 0; char buf[OB_CAST_TO_VARCHAR_MAX_LENGTH] = {0}; int64_t len = 0; int64_t in_val = child_res->get_int(); if (OB_FAIL(common_datetime_string(expr.args_[0]->datum_meta_.type_, ObVarcharType, expr.args_[0]->datum_meta_.scale_, false, in_val, ctx, buf, sizeof(buf), len))) { LOG_WARN("common_datetime_string failed", K(ret)); } else { ObString in_str(len, buf); uint64_t value = 0; ObEvalCtx::TempAllocGuard alloc_guard(ctx); ret = string_to_enum(alloc_guard.get_allocator(), in_str, ObCharset::get_system_collation(), str_values, cast_mode, expr, warning, value); SET_RES_ENUM(value); } } return ret; } CAST_ENUMSET_FUNC_NAME(datetime, set) { EVAL_ARG() { int warning = 0; char buf[OB_CAST_TO_VARCHAR_MAX_LENGTH] = {0}; int64_t len = 0; int64_t in_val = child_res->get_int(); if (OB_FAIL(common_datetime_string(expr.args_[0]->datum_meta_.type_, ObVarcharType, expr.args_[0]->datum_meta_.scale_, false, in_val, ctx, buf, sizeof(buf), len))) { LOG_WARN("common_datetime_string failed", K(ret)); } else { ObString in_str(len, buf); uint64_t value = 0; ObEvalCtx::TempAllocGuard alloc_guard(ctx); ret = string_to_set(alloc_guard.get_allocator(), in_str, ObCharset::get_system_collation(), str_values, cast_mode, expr, warning, value); SET_RES_SET(value); } } return ret; } CAST_ENUMSET_FUNC_NAME(date, enum) { EVAL_ARG() { int warning = 0; int32_t in_val = child_res->get_date(); char buf[OB_CAST_TO_VARCHAR_MAX_LENGTH] = {0}; int64_t len = 0; if (OB_FAIL(ObTimeConverter::date_to_str(in_val, buf, sizeof(buf), len))) { LOG_WARN("date_to_str failed", K(ret)); } else { ObString in_str(len, buf); uint64_t value = 0; ObEvalCtx::TempAllocGuard alloc_guard(ctx); ret = string_to_enum(alloc_guard.get_allocator(), in_str, ObCharset::get_system_collation(), str_values, cast_mode, expr, warning, value); SET_RES_ENUM(value); } } return ret; } CAST_ENUMSET_FUNC_NAME(date, set) { EVAL_ARG() { int warning = 0; int32_t in_val = child_res->get_date(); char buf[OB_CAST_TO_VARCHAR_MAX_LENGTH] = {0}; int64_t len = 0; if (OB_FAIL(ObTimeConverter::date_to_str(in_val, buf, sizeof(buf), len))) { LOG_WARN("date_to_str failed", K(ret)); } else { ObString in_str(len, buf); uint64_t value = 0; ObEvalCtx::TempAllocGuard alloc_guard(ctx); ret = string_to_set(alloc_guard.get_allocator(), in_str, ObCharset::get_system_collation(), str_values, cast_mode, expr, warning, value); SET_RES_SET(value); } } return ret; } CAST_ENUMSET_FUNC_NAME(time, enum) { EVAL_ARG() { int warning = 0; int64_t in_val = child_res->get_int(); char buf[OB_CAST_TO_VARCHAR_MAX_LENGTH] = {0}; int64_t len = 0; ObScale in_scale = expr.args_[0]->datum_meta_.scale_; if (OB_FAIL(ObTimeConverter::time_to_str(in_val, in_scale, buf, sizeof(buf), len))) { LOG_WARN("time_to_str failed", K(ret), K(in_val)); } else { ObString in_str(len, buf); uint64_t value = 0; ObEvalCtx::TempAllocGuard alloc_guard(ctx); ret = string_to_enum(alloc_guard.get_allocator(), in_str, ObCharset::get_system_collation(), str_values, cast_mode, expr, warning, value); SET_RES_ENUM(value); } } return ret; } CAST_ENUMSET_FUNC_NAME(time, set) { EVAL_ARG() { int warning = 0; int64_t in_val = child_res->get_int(); char buf[OB_CAST_TO_VARCHAR_MAX_LENGTH] = {0}; int64_t len = 0; ObScale in_scale = expr.args_[0]->datum_meta_.scale_; if (OB_FAIL(ObTimeConverter::time_to_str(in_val, in_scale, buf, sizeof(buf), len))) { LOG_WARN("time_to_str failed", K(ret), K(in_val)); } else { ObString in_str(len, buf); uint64_t value = 0; ObEvalCtx::TempAllocGuard alloc_guard(ctx); ret = string_to_set(alloc_guard.get_allocator(), in_str, ObCharset::get_system_collation(), str_values, cast_mode, expr, warning, value); SET_RES_SET(value); } } return ret; } CAST_ENUMSET_FUNC_NAME(year, enum) { EVAL_ARG() { if (child_res->is_null()) { res_datum.set_null(); } else { int warning = 0; uint8_t in_val = child_res->get_year(); int64_t tmp_int = 0; if (OB_FAIL(ObTimeConverter::year_to_int(in_val, tmp_int))) { LOG_WARN("year_to_int failed", K(ret)); } else { uint64_t val_uint = static_cast(tmp_int); uint64_t value = 0; ret = uint_to_enum(val_uint, str_values, cast_mode, warning, value); SET_RES_ENUM(value); } } } return ret; } CAST_ENUMSET_FUNC_NAME(year, set) { EVAL_ARG() { int warning = 0; uint8_t in_val = child_res->get_year(); int64_t tmp_int = 0; if (OB_FAIL(ObTimeConverter::year_to_int(in_val, tmp_int))) { LOG_WARN("year_to_int failed", K(ret)); } else { uint64_t val_uint = static_cast(tmp_int); uint64_t value = 0; ret = uint_to_set(val_uint, str_values, cast_mode, warning, value); SET_RES_SET(value); } } return ret; } CAST_ENUMSET_FUNC_NAME(bit, enum) { EVAL_ARG() { if (child_res->is_null()) { res_datum.set_null(); } else { int warning = 0; uint64_t val_uint = child_res->get_bit(); uint64_t value = 0; ret = uint_to_enum(val_uint, str_values, cast_mode, warning, value); SET_RES_ENUM(value); } } return ret; } CAST_ENUMSET_FUNC_NAME(bit, set) { EVAL_ARG() { int warning = 0; uint64_t val_uint = child_res->get_bit(); uint64_t value = 0; ret = uint_to_set(val_uint, str_values, cast_mode, warning, value); SET_RES_SET(value); } return ret; } // exclude varchar/char type int anytype_anytype_explicit(const sql::ObExpr &expr, sql::ObEvalCtx &ctx, sql::ObDatum &res_datum) { EVAL_ARG() { int warning = OB_SUCCESS; ObObjType out_type = ObMaxType; ObAccuracy out_acc; // tmp_datum is for datum_accuracy_check(). ObDatum tmp_datum = res_datum; if (OB_ISNULL(expr.inner_functions_) || 1 != expr.inner_func_cnt_ || OB_ISNULL(expr.inner_functions_[0])) { ret = OB_ERR_UNEXPECTED; LOG_WARN("inner_functinos is NULL or inner_func_cnt_ is not valid", K(ret), KP(expr.inner_functions_), K(expr.inner_func_cnt_)); } else if (OB_FAIL(((ObExpr::EvalFunc)(expr.inner_functions_[0]))(expr, ctx, tmp_datum))) { LOG_WARN("inner cast failed", K(ret)); } else if (OB_FAIL(get_accuracy_from_parse_node(expr, ctx, out_acc, out_type))) { LOG_WARN("get accuracy failed", K(ret)); } else if (OB_FAIL(datum_accuracy_check(expr, expr.extra_, ctx, out_acc, expr.obj_meta_.has_lob_header(), tmp_datum, res_datum, warning))) { LOG_WARN("accuracy check failed", K(ret)); } } return ret; } // padding %padding_cnt character, we also need to convert collation type here. // eg: select cast('abc' as nchar(100)) from dual; // the space must be in utf16, because dst_type is nchar int padding_char_for_cast(int64_t padding_cnt, const ObCollationType &padding_cs_type, ObIAllocator &alloc, ObString &padding_res) { int ret = OB_SUCCESS; padding_res.reset(); const ObCharsetType &cs = ObCharset::charset_type_by_coll(padding_cs_type); char padding_char = (CHARSET_BINARY == cs) ? OB_PADDING_BINARY : OB_PADDING_CHAR; int64_t padding_str_size = sizeof(padding_char) * padding_cnt; char *padding_str_ptr = reinterpret_cast(alloc.alloc(padding_str_size)); if (OB_ISNULL(padding_str_ptr)) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("alloc memory failed", K(ret)); } else if (CHARSET_BINARY == cs) { MEMSET(padding_str_ptr, padding_char, padding_str_size); padding_res.assign_ptr(padding_str_ptr, padding_str_size); } else { MEMSET(padding_str_ptr, padding_char, padding_str_size); ObString padding_str(padding_str_size, padding_str_ptr); if (OB_FAIL(ObExprUtil::convert_string_collation(padding_str, ObCharset::get_system_collation(), padding_res, padding_cs_type, alloc))) { LOG_WARN("convert padding str collation faield", K(ret), K(padding_str), K(padding_cs_type)); } } LOG_DEBUG("pad char done", K(ret), K(padding_cnt), K(padding_cs_type), K(padding_res)); return ret; } int anytype_to_varchar_char_explicit(const sql::ObExpr &expr, sql::ObEvalCtx &ctx, sql::ObDatum &res_datum) { int ret = OB_SUCCESS; GET_SESSION() { int warning = OB_SUCCESS; // useless ObAccuracy out_acc; ObObjType out_type = ObMaxType; ObDatum tmp_datum = res_datum; bool is_from_pl = !expr.is_called_in_sql_; if (OB_ISNULL(expr.inner_functions_) || 1 != expr.inner_func_cnt_ || OB_ISNULL(expr.inner_functions_[0])) { ret = OB_ERR_UNEXPECTED; LOG_WARN("inner_functions is NULL or inner_func_cnt_ is not valid", K(ret), KP(expr.inner_functions_), K(expr.inner_func_cnt_)); } else if (OB_FAIL(((ObExpr::EvalFunc)(expr.inner_functions_[0]))(expr, ctx, tmp_datum))) { LOG_WARN("inner cast failed", K(ret)); } else if (tmp_datum.is_null()) { res_datum.set_null(); } else if (OB_FAIL(get_accuracy_from_parse_node(expr, ctx, out_acc, out_type))) { LOG_WARN("get accuracy failed", K(ret)); } else if (OB_FAIL(datum_accuracy_check(expr, expr.extra_, ctx, out_acc, expr.obj_meta_.has_lob_header(), tmp_datum, res_datum, warning))) { if (ob_is_string_type(expr.datum_meta_.type_) && OB_ERR_DATA_TOO_LONG == ret) { ObDatumMeta src_meta; if (ObDatumCast::is_implicit_cast(*expr.args_[0])) { const ObExpr &grand_child = *(expr.args_[0]->args_[0]); if (OB_UNLIKELY(ObDatumCast::is_implicit_cast(grand_child))) { ret = OB_ERR_UNEXPECTED; LOG_WARN("too many cast expr, max is 2", K(ret), K(expr)); } else { src_meta = grand_child.datum_meta_; } } else { src_meta = expr.args_[0]->datum_meta_; } if (OB_LIKELY(OB_ERR_DATA_TOO_LONG == ret)) { if (ob_is_character_type(src_meta.type_, src_meta.cs_type_) && lib::is_oracle_mode()) { ret = OB_SUCCESS; } else if ((ob_is_clob(src_meta.type_, src_meta.cs_type_) || ob_is_clob_locator(src_meta.type_, src_meta.cs_type_) || expr.args_[0]->obj_meta_.is_xml_sql_type()) && lib::is_oracle_mode()) { if (ob_is_nchar(expr.datum_meta_.type_) || ob_is_char(expr.datum_meta_.type_, expr.datum_meta_.cs_type_)) { ret = OB_OPERATE_OVERFLOW; } else { ret = OB_SUCCESS; } } else { ret = OB_ERR_TRUNCATED_WRONG_VALUE; } } } } if (OB_SUCC(ret)) { if (res_datum.is_null()) { // do nothing } else if (-1 == out_acc.get_length()) { // do nothing } else if (0 > out_acc.get_length()) { ret = OB_ERR_TOO_LONG_COLUMN_LENGTH; LOG_WARN("accuracy too long", K(ret), K(out_acc.get_length())); } else { bool has_result = false; if (!lib::is_oracle_mode()) { int64_t max_allowed_packet = 0; if (OB_FAIL(session->get_max_allowed_packet(max_allowed_packet))) { if (OB_ENTRY_NOT_EXIST == ret) { // for compatibility with server before 1470 ret = OB_SUCCESS; max_allowed_packet = OB_MAX_VARCHAR_LENGTH; } else { LOG_WARN("Failed to get max allow packet size", K(ret)); } } else if (out_acc.get_length() > max_allowed_packet && out_acc.get_length() <= INT32_MAX) { res_datum.set_null(); has_result = true; LOG_USER_WARN(OB_ERR_FUNC_RESULT_TOO_LARGE, "cast", static_cast(max_allowed_packet)); } else if (out_acc.get_length() == 0) { res_datum.set_string(NULL, 0); has_result = true; } } if (OB_SUCC(ret) && !has_result) { ObString text(res_datum.len_, res_datum.ptr_); ObCollationType out_cs_type = expr.datum_meta_.cs_type_; bool oracle_char_byte_exceed = false; ObLengthSemantics ls = lib::is_oracle_mode() ? expr.datum_meta_.length_semantics_ : LS_CHAR; int32_t text_length = INT32_MAX; bool is_varbinary_or_binary = (out_type == ObVarcharType && CS_TYPE_BINARY == out_cs_type) || (ObCharType == out_type && CS_TYPE_BINARY == out_cs_type); if (is_varbinary_or_binary) { text_length = text.length(); } else { if (is_oracle_byte_length(lib::is_oracle_mode(), ls)) { text_length = text.length(); } else { text_length = static_cast(ObCharset::strlen_char( expr.datum_meta_.cs_type_, text.ptr(), text.length())); } } if (lib::is_oracle_mode() && ls == LS_CHAR) { if ((ObCharType == out_type || ObNCharType == out_type) && text.length() > (is_from_pl ? OB_MAX_ORACLE_PL_CHAR_LENGTH_BYTE : OB_MAX_ORACLE_CHAR_LENGTH_BYTE)) { oracle_char_byte_exceed = true; } else if ((ObVarcharType == out_type || ObNVarchar2Type == out_type) && text.length() > OB_MAX_ORACLE_VARCHAR_LENGTH) { oracle_char_byte_exceed = true; } } if (out_acc.get_length() < text_length || oracle_char_byte_exceed) { int64_t acc_len = !oracle_char_byte_exceed? out_acc.get_length() : ((ObVarcharType == out_type || ObNVarchar2Type == out_type) ? OB_MAX_ORACLE_VARCHAR_LENGTH: (is_from_pl ? OB_MAX_ORACLE_PL_CHAR_LENGTH_BYTE : OB_MAX_ORACLE_CHAR_LENGTH_BYTE)); int64_t char_len = 0; // UNUSED int64_t size = (ls == LS_BYTE || oracle_char_byte_exceed ? ObCharset::max_bytes_charpos(out_cs_type, text.ptr(), text.length(), acc_len, char_len): ObCharset::charpos(out_cs_type, text.ptr(), text.length(), acc_len)); if (0 == size) { if (lib::is_oracle_mode()) { res_datum.set_null(); } else { res_datum.set_string(NULL, 0); } } else { res_datum.len_ = size; } } else if (out_acc.get_length() == text_length || (ObCharType != out_type && ObNCharType != out_type) || (lib::is_mysql_mode() && ob_is_char(out_type, expr.datum_meta_.cs_type_) && !(SMO_PAD_CHAR_TO_FULL_LENGTH & session->get_sql_mode()))) { // do not padding LOG_DEBUG("no need to padding", K(ret), K(out_acc.get_length()), K(text_length), K(text)); } else if (out_acc.get_length() > text_length) { int64_t padding_cnt = out_acc.get_length() - text_length; ObString padding_res; ObEvalCtx::TempAllocGuard alloc_guard(ctx); ObIAllocator &calc_alloc = alloc_guard.get_allocator(); if (OB_FAIL(padding_char_for_cast(padding_cnt, out_cs_type, calc_alloc, padding_res))) { LOG_WARN("padding char failed", K(ret), K(padding_cnt), K(out_cs_type)); } else { int64_t padding_size = padding_res.length() + text.length(); char *res_ptr = expr.get_str_res_mem(ctx, padding_size); if (OB_ISNULL(res_ptr)) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("allocate memory failed", K(ret)); } else { MEMMOVE(res_ptr, text.ptr(), text.length()); MEMMOVE(res_ptr + text.length(), padding_res.ptr(), padding_res.length()); res_datum.set_string(res_ptr, text.length() + padding_res.length()); } } } else { ret = OB_ERR_UNEXPECTED; LOG_WARN("can never reach", K(ret)); } } } } } return ret; } // master上在accuracy check时没有对interval tc进行check,22x上有,还未 // patch过来,这里函数先留在这里,后面patch过来后会使用该函数 int interval_scale_check(const ObCastMode &cast_mode, const ObAccuracy &accuracy, const ObObjType type, const ObDatum &in_datum, ObDatum &res_datum, int &warning) { int ret = OB_SUCCESS; UNUSED(cast_mode); UNUSED(warning); ObScale expected_scale = accuracy.get_scale(); if (ob_is_interval_ym(type)) { ObIntervalYMValue in_val(in_datum.get_interval_nmonth()); int8_t expected_year_scale = ObIntervalScaleUtil::ob_scale_to_interval_ym_year_scale( static_cast(expected_scale)); int8_t input_year_scale = in_val.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 { res_datum.set_interval_ym(in_datum.get_interval_nmonth()); } } else if (ob_is_interval_ds(type)) { ObIntervalDSValue in_val = in_datum.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, in_val))) { LOG_WARN("fail to round interval ds", K(ret), K(in_val)); } else { int8_t input_day_scale = in_val.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 { res_datum.set_interval_ds(in_val); } } } else { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected in type", K(ret), K(type)); } return ret; } int bit_length_check(const ObCastMode &cast_mode, const ObAccuracy &accuracy, const ObObjType type, const ObDatum &in_datum, ObDatum &res_datum, int &warning) { int ret = OB_SUCCESS; UNUSED(type); uint64_t value = in_datum.get_uint(); 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)); } 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 { res_datum.set_bit(value); } if (OB_FAIL(ret) && CM_IS_WARN_ON_FAIL(cast_mode)) { warning = OB_DATA_OUT_OF_RANGE; ret = OB_SUCCESS; uint64_t max_value = (1ULL< max_accuracy_len)) { ret = OB_OPERATE_OVERFLOW; LOG_WARN("char type length is too long", K(str_len_byte), K(max_accuracy_len)); } else { res_datum.set_datum(in_datum); } return ret; } // check usec scale for ObTimeType, ObDateTimeType int time_usec_scale_check(const ObCastMode &cast_mode, const ObAccuracy &accuracy, const int64_t value) { INIT_SUCC(ret); UNUSED(value); bool need_check_zero_scale = CM_IS_ERROR_ON_SCALE_OVER(cast_mode); // check usec scale for time part if (need_check_zero_scale) { ObScale scale = accuracy.get_scale(); if (OB_UNLIKELY(0 <= scale && scale < MAX_SCALE_FOR_TEMPORAL)) { // get usec part for value int64_t temp_value = value; ObTimeConverter::round_datetime(scale, temp_value); if (temp_value != value) { // round success ret = OB_OPERATE_OVERFLOW; LOG_WARN("Invalid input value.", K(value), K(scale)); } } } return ret; } int time_scale_check(const ObCastMode &cast_mode, const ObAccuracy &accuracy, const ObObjType type, const ObDatum &in_datum, ObDatum &res_datum, int &warning) { int ret = OB_SUCCESS; UNUSED(type); UNUSED(warning); ObScale scale = accuracy.get_scale(); int64_t value = in_datum.get_int(); // First, judge whether it is inserted or updated(CM_IS_COLUMN_CONVERT), and then judge whether the current sqlmode is truncate(CM_IS_TIME_TRUNCATE_FRACTIONAL) bool need_truncate = CM_IS_COLUMN_CONVERT(cast_mode) ? CM_IS_TIME_TRUNCATE_FRACTIONAL(cast_mode) : false; if (OB_FAIL(time_usec_scale_check(cast_mode, accuracy, value))) { LOG_WARN("check usec scale fail.", K(ret), K(value)); } else if (OB_LIKELY(0 <= scale && scale < MAX_SCALE_FOR_TEMPORAL)) { if(need_truncate) { value /= power_of_10[MAX_SCALE_FOR_TEMPORAL - scale]; value *= power_of_10[MAX_SCALE_FOR_TEMPORAL - scale]; } else { ObTimeConverter::round_datetime(scale, value); } res_datum.set_time(value); } else { res_datum.set_datum(in_datum); } return ret; } int otimestamp_scale_check(const ObCastMode &cast_mode, const ObAccuracy &accuracy, const ObObjType type, const ObDatum &in_datum, ObDatum &res_datum, int &warning) { int ret = OB_SUCCESS; UNUSED(cast_mode); UNUSED(warning); ObScale scale = accuracy.get_scale(); ObOTimestampData in_val; 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 in_val; if (OB_FAIL(common_construct_otimestamp(type, in_datum, in_val))) { LOG_WARN("common_construct_otimestamp failed", K(ret)); } else { ObOTimestampData ot_data = ObTimeConverter::round_otimestamp(scale, in_val); if (ObTimeConverter::is_valid_otimestamp(ot_data.time_us_, static_cast(ot_data.time_ctx_.tail_nsec_))) { if (ObTimestampTZType == type) { res_datum.set_otimestamp_tz(ot_data); } else { res_datum.set_otimestamp_tiny(ot_data); } } else { OB_LOG(DEBUG, "invalid otimestamp, set it null ", K(ot_data), K(scale), "orig_date", in_val); res_datum.set_null(); } } } else { res_datum.set_datum(in_datum); } return ret; } int datetime_scale_check(const ObCastMode &cast_mode, const ObAccuracy &accuracy, const ObObjType type, const ObDatum &in_datum, ObDatum &res_datum, int &warning) { int ret = OB_SUCCESS; UNUSED(type); UNUSED(warning); ObScale scale = accuracy.get_scale(); // First, judge whether it is inserted or updated(CM_IS_COLUMN_CONVERT), and then judge whether the current sqlmode is truncate(CM_IS_TIME_TRUNCATE_FRACTIONAL) bool need_truncate = CM_IS_COLUMN_CONVERT(cast_mode) ? CM_IS_TIME_TRUNCATE_FRACTIONAL(cast_mode) : false; 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 { int64_t value = in_datum.get_int(); if (OB_FAIL(time_usec_scale_check(cast_mode, accuracy, value))) { LOG_WARN("check zero scale fail.", K(ret), K(value), K(scale)); } else if (OB_UNLIKELY(0 <= scale && scale < MAX_SCALE_FOR_TEMPORAL)) { int64_t value = in_datum.get_int(); if(need_truncate) { value /= power_of_10[MAX_SCALE_FOR_TEMPORAL - scale]; value *= power_of_10[MAX_SCALE_FOR_TEMPORAL - scale]; } else { ObTimeConverter::round_datetime(scale, value); } if (ObTimeConverter::is_valid_datetime(value)) { res_datum.set_datetime(value); } else { res_datum.set_null(); } } else { res_datum.set_datum(in_datum); } } return ret; } int number_range_check_v2(const ObCastMode &cast_mode, const ObAccuracy &accuracy, const ObObjType type, const ObDatum &in_datum, ObDatum &res_datum, int &warning) { int ret = OB_SUCCESS; int &cast_ret = CM_IS_ERROR_ON_FAIL(cast_mode) ? ret : warning; ObPrecision precision = accuracy.get_precision(); ObScale scale = accuracy.get_scale(); 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; const number::ObNumber in_val(in_datum.get_number()); const static int64_t num_alloc_used_times = 2; // out val alloc will be used twice ObNumStackAllocator out_val_alloc; number::ObNumber out_val; bool is_finish = false; if (ObNumberFloatType == type) { 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, out_val_alloc))) { } else if (OB_FAIL(out_val.round_precision(number_precision))) { } else if (CM_IS_ERROR_ON_SCALE_OVER(cast_mode) && in_val.compare(out_val) != 0) { ret = OB_OPERATE_OVERFLOW; LOG_WARN("input value is out of range.", K(scale), K(in_val)); } else { res_datum.set_number(out_val); is_finish = true; } LOG_DEBUG("finish round_precision", K(in_val), K(number_precision), K(precision)); } else if (PRECISION_UNKNOWN_YET == precision) { res_datum.set_number(in_val); 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) { res_datum.set_number(in_val); is_finish = true; } else if (PRECISION_UNKNOWN_YET == precision && number::ObNumber::MAX_SCALE >= scale && scale >= number::ObNumber::MIN_SCALE) { ObNumStackOnceAlloc tmp_alloc; number::ObNumber num; if (OB_FAIL(num.from(in_val, tmp_alloc))) { } else if (OB_FAIL(num.round(scale))) { } else if (CM_IS_ERROR_ON_SCALE_OVER(cast_mode) && in_val.compare(num) != 0) { ret = OB_OPERATE_OVERFLOW; LOG_WARN("input value is out of range.", K(scale), K(in_val)); } else { res_datum.set_number(num); 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; res_datum.set_number(*min_num_mysql); } is_finish = true; } 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; res_datum.set_number(*max_num_mysql); } is_finish = true; } else { if (OB_FAIL(out_val.from(in_val, out_val_alloc))) { LOG_WARN("out_val.from failed", K(ret), K(in_val)); } else if (OB_FAIL(out_val.round(scale))) { LOG_WARN("out_val.round failed", K(ret), K(scale)); } else if (CM_IS_ERROR_ON_SCALE_OVER(cast_mode) && in_val.compare(out_val) != 0) { ret = OB_OPERATE_OVERFLOW; LOG_WARN("input value is out of range.", K(scale), K(in_val)); } else { res_datum.set_number(out_val); is_finish = true; } } } if (OB_SUCC(ret) && !is_finish) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected situation, res_datum is not set", K(ret)); } LOG_DEBUG("number_range_check_v2 done", K(ret), K(is_finish), K(accuracy), K(in_val), K(out_val), KPC(min_check_num), KPC(max_check_num)); return ret; } template static int float_range_check(const ObCastMode &cast_mode, const ObAccuracy &accuracy, const ObObjType type, const ObDatum &in_datum, ObDatum &res_datum, int &warning) { int ret = OB_SUCCESS; ObObjTypeClass type_class = ob_obj_type_class(type); if (OB_UNLIKELY(ObFloatTC != type_class && ObDoubleTC != type_class)) { ret = OB_INVALID_ARGUMENT; LOG_WARN("obj type is invalid, must be float/double tc", K(ret), K(type), K(type_class)); } else { IN_TYPE in_val = *(reinterpret_cast(in_datum.ptr_)); IN_TYPE out_val = in_val; if (lib::is_oracle_mode() && 0.0 == in_val) { if (ObFloatTC == type_class) { res_datum.set_float(0.0); } else { res_datum.set_double(0.0); } } else if (lib::is_oracle_mode() && isnan(in_val)) { // overwrite -NAN to NAN, OB only store NAN if (ObFloatTC == type_class) { res_datum.set_float(NAN); } else { res_datum.set_double(NAN); } } else { if (CAST_FAIL_CM(real_range_check(accuracy, out_val), cast_mode)) { LOG_WARN("real_range_check failed", K(ret)); } else if (in_val != out_val) { if (ObFloatTC == type_class) { res_datum.set_float(out_val); } else { res_datum.set_double(out_val); } } else { res_datum.set_datum(in_datum); } } } return ret; } int string_length_check(const ObExpr &expr, const ObCastMode &cast_mode, const ObAccuracy &accuracy, const ObObjType type, const ObCollationType cs_type, ObEvalCtx &ctx, const ObDatum &in_datum, ObDatum &res_datum, int &warning) { int ret = OB_SUCCESS; UNUSED(expr); UNUSED(ctx); const ObLength max_accuracy_len = accuracy.get_length(); const int32_t str_len_byte = in_datum.len_; bool is_oracle = lib::is_oracle_mode(); bool is_from_pl = !expr.is_called_in_sql_; ObObjMeta meta; meta.set_type_simple(type); meta.set_collation_type(cs_type); // remember not to change in_datum res_datum.set_datum(in_datum); // 处理异常情况,但str_len_byte大于max_len_char不一定有问题,还需要具体判断 if (max_accuracy_len <= 0 || str_len_byte > max_accuracy_len) { int &cast_ret = (CM_IS_ERROR_ON_FAIL(cast_mode) && !is_oracle) ? ret : warning; const char *str = in_datum.ptr_; int32_t str_len_char = -1; // 在parse时,如果长度大于int32_t最大值, length就会设置为-1 if (max_accuracy_len == -1) { } else if (OB_UNLIKELY(max_accuracy_len <= 0)) { res_datum.set_string(NULL, 0); if (OB_UNLIKELY(0 == max_accuracy_len && str_len_byte > 0)) { cast_ret = OB_ERR_DATA_TOO_LONG; str_len_char = meta.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(max_accuracy_len), K(str_len_char)); } } else { int32_t trunc_len_byte = -1; int32_t trunc_len_char = -1; if (meta.is_varbinary() || meta.is_binary() || meta.is_blob()) { str_len_char = meta.is_blob() ? 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)); } } 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)); } } else if (is_oracle && (meta.is_char() || meta.is_nchar())) { const int32_t str_len_char = static_cast(ObCharset::strlen_char(cs_type, str, str_len_byte)); if (OB_UNLIKELY(str_len_byte > (is_from_pl ? OB_MAX_ORACLE_PL_CHAR_LENGTH_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((is_from_pl ? OB_MAX_ORACLE_PL_CHAR_LENGTH_BYTE : OB_MAX_ORACLE_CHAR_LENGTH_BYTE))); } 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)); } } else {//mysql, oracle varchar(char) // trunc_len_char > max_accuracy_len means an error or warning, without tail ' ' // str_len_char > max_accuracy_len means only warning, even in strict mode. // lengthsp() - returns the length of the given string without trailing spaces. // 所以strlen_byte_no_sp返回的结果是小于等于str的长度 trunc_len_byte = static_cast(ObCharset::strlen_byte_no_sp(cs_type, str, str_len_byte)); trunc_len_char = meta.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)); } 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)); } else { str_len_char = meta.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)) { warning = OB_ERR_DATA_TOO_LONG; LOG_WARN("char type length is too long", K(max_accuracy_len), K(str_len_char)); } } } if (OB_SUCCESS != cast_ret) { LOG_WARN("string accuracy check failed", K(cast_ret), K(ret), K(warning), K(is_oracle), K(meta)); } if (OB_SUCC(ret)) { if (OB_UNLIKELY(OB_ERR_DATA_TOO_LONG == 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 (meta.is_text() || meta.is_json()) { 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) { // 在oracle模式下不清理末尾的空格字符,原因如下: // #bug18529663:例如select cast(' a' as char) from dual; // 执行至此时,trunc_len_byte = 1,意思是截取到' a'的第一个字符' ' // 如果不加判断将会直接执行strlen_byte_no_sp来清理末尾的空格字符, // 执行完毕后由于空格被清理掉,导致trunc_len_byte=0 // trunc_len_byte = 0会导致最终的obchar类型的输出长度为0, // 在oracle模式的比较中将会判其为空,不符号预期. } else if (meta.is_fixed_len_char_type() && !meta.is_binary()) { trunc_len_byte = static_cast(ObCharset::strlen_byte_no_sp(cs_type, str, trunc_len_byte)); } res_datum.len_ = trunc_len_byte; if (is_oracle) { ret = warning; } } else if (OB_SUCC(warning) && is_oracle) { ret = warning; } else { // do nothing } } } } else { // 正常分支 // do nothing } return ret; } int text_length_check(const ObExpr &expr, const ObCastMode &cast_mode, const ObAccuracy &accuracy, const ObObjType type, const ObCollationType cs_type, ObEvalCtx &ctx, bool has_lob_header, const ObDatum &in_datum, ObDatum &res_datum, int &warning) { int ret = OB_SUCCESS; const ObLength max_accuracy_len = accuracy.get_length(); ObDatum tmp_in; if (expr.obj_meta_.is_lob_storage() && has_lob_header) { ObString inrow_data; ObLobLocatorV2 lob(in_datum.get_string(), has_lob_header); if (!lob.is_valid()) { ret = OB_ERR_UNEXPECTED; LOG_WARN("lob locator is invalid", K(ret)); } else if (!lob.is_full_temp_lob() || !lob.is_inrow()) { // do nothing, persist/delta/outrow lob loator not support length check res_datum.set_datum(in_datum); } else if (OB_FAIL(lob.get_inrow_data(inrow_data))) { LOG_WARN("fail to get inrow data", K(ret)); } else if (FALSE_IT(tmp_in.set_string(inrow_data))) { } else if (OB_FAIL(OB_FAIL(string_length_check(expr, cast_mode, accuracy, type, cs_type, ctx, tmp_in, res_datum, warning)))) { LOG_WARN("fail to do string length check", K(ret)); } else { int32_t lob_handle_len = lob.size_ - inrow_data.length(); int32_t new_inrow_byte_len = lob_handle_len + res_datum.len_; res_datum.set_datum(in_datum); res_datum.len_ = new_inrow_byte_len; } } else if (OB_FAIL(string_length_check(expr, cast_mode, accuracy, type, cs_type, ctx, in_datum, res_datum, warning))) { LOG_WARN("fail to do string length check", K(ret)); } return ret; } int rowid_length_check(const ObExpr &expr, const ObCastMode &cast_mode, const ObAccuracy &accuracy, const ObObjType type, const ObCollationType cs_type, ObEvalCtx &ctx, const ObDatum &in_datum, ObDatum &res_datum, int &warning) { int ret = OB_SUCCESS; UNUSED(expr); UNUSED(cast_mode); UNUSED(type); UNUSED(cs_type); UNUSED(ctx); UNUSED(warning); ObURowIDData urowid_data(in_datum.len_, reinterpret_cast(in_datum.ptr_)); if (OB_UNLIKELY(lib::is_mysql_mode())) { ret = OB_NOT_SUPPORTED; LOG_WARN("rowid is not supported in mysql mode", K(ret)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "rowid in mysql mode"); } else if (-1 == accuracy.get_length()) { // select cast('xx' as rowid) from dual; // length will be -1 res_datum.set_datum(in_datum); } else if (urowid_data.rowid_len_ > accuracy.get_length()) { ret = OB_ERR_DATA_TOO_LONG; LOG_WARN("rowid data length is too long", K(urowid_data.rowid_len_), K(accuracy)); } else { res_datum.set_datum(in_datum); } return ret; } int datum_accuracy_check(const ObExpr &expr, const uint64_t cast_mode, ObEvalCtx &ctx, bool has_lob_header, const ObDatum &in_datum, ObDatum &res_datum, int &warning) { ObAccuracy accuracy; accuracy.set_length(expr.max_length_); accuracy.set_scale(expr.datum_meta_.scale_); const ObObjTypeClass &dst_tc = ob_obj_type_class(expr.datum_meta_.type_); if (ObStringTC == dst_tc || ObTextTC == dst_tc || ObJsonTC == dst_tc) { accuracy.set_length_semantics(expr.datum_meta_.length_semantics_); } else { accuracy.set_precision(expr.datum_meta_.precision_); } return datum_accuracy_check(expr, cast_mode, ctx, accuracy, has_lob_header, in_datum, res_datum, warning); } int datum_accuracy_check(const ObExpr &expr, const uint64_t cast_mode, ObEvalCtx &ctx, const ObAccuracy &accuracy, bool has_lob_header, const ObDatum &in_datum, ObDatum &res_datum, int &warning) { int ret = OB_SUCCESS; if (!in_datum.is_null()) { ObObjType type = expr.datum_meta_.type_; ObCollationType cs_type = expr.datum_meta_.cs_type_; switch (ob_obj_type_class(type)) { case ObFloatTC: { ret = float_range_check(cast_mode, accuracy, type, in_datum, res_datum, warning); break; } case ObDoubleTC: { ret = float_range_check(cast_mode, accuracy, type, in_datum, res_datum, warning); break; } case ObNumberTC: { ret = number_range_check_v2(cast_mode, accuracy, type, in_datum, res_datum, warning); break; } case ObDateTimeTC: { ret = datetime_scale_check(cast_mode, accuracy, type, in_datum, res_datum, warning); break; } case ObOTimestampTC: { ret = otimestamp_scale_check(cast_mode, accuracy, type, in_datum, res_datum, warning); break; } case ObTimeTC: { ret = time_scale_check(cast_mode, accuracy, type, in_datum, res_datum, warning); break; } case ObStringTC: { ret = string_length_check(expr, cast_mode, accuracy, type, cs_type, ctx, in_datum, res_datum, warning); break; } case ObRawTC: { ret = raw_length_check(cast_mode, accuracy, type, in_datum, res_datum, warning); break; } case ObTextTC: { ret = text_length_check(expr, cast_mode, accuracy, type, cs_type, ctx, has_lob_header, in_datum, res_datum, warning); break; } case ObBitTC: { ret = bit_length_check(cast_mode, accuracy, type, in_datum, res_datum, warning); break; } case ObIntervalTC: { ret = interval_scale_check(cast_mode, accuracy, type, in_datum, res_datum, warning); break; } case ObRowIDTC: { ret = rowid_length_check(expr, cast_mode, accuracy, type, cs_type, ctx, in_datum, res_datum, warning); break; } default: { res_datum.set_datum(in_datum); break; } } } else { res_datum.set_null(); } return ret; } ObExpr::EvalFunc OB_DATUM_CAST_ORACLE_IMPLICIT[ObMaxTC][ObMaxTC] = { { /*null -> XXX*/ cast_eval_arg,/*null*/ cast_eval_arg,/*int*/ cast_eval_arg,/*uint*/ cast_eval_arg,/*float*/ cast_eval_arg,/*double*/ cast_eval_arg,/*number*/ cast_eval_arg,/*datetime*/ cast_not_expected,/*date*/ cast_not_expected,/*time*/ cast_not_expected,/*year*/ cast_eval_arg,/*string*/ cast_not_expected,/*extend*/ cast_not_expected,/*unknown*/ cast_eval_arg,/*text*/ cast_not_expected,/*bit*/ cast_not_expected,/*enumset*/ cast_not_expected,/*enumsetInner*/ cast_eval_arg,/*otimestamp*/ cast_eval_arg,/*raw*/ cast_eval_arg,/*interval*/ cast_eval_arg,/*rowid*/ cast_eval_arg,/*lob*/ cast_eval_arg,/*json*/ cast_not_support,/*geometry*/ cast_to_udt_not_support,/*udt*/ }, { /*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*/ int_text,/*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*/ cast_inconsistent_types_json,/*json*/ cast_not_support,/*geometry*/ cast_to_udt_not_support,/*udt*/ }, { /*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*/ cast_inconsistent_types_json,/*json*/ cast_not_support,/*geometry*/ cast_to_udt_not_support,/*udt*/ }, { /*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*/ cast_inconsistent_types_json,/*json*/ cast_not_support,/*geometry*/ cast_to_udt_not_support,/*udt*/ }, { /*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*/ cast_inconsistent_types_json,/*json*/ cast_not_support,/*geometry*/ cast_to_udt_not_support,/*udt*/ }, { /*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_text,/*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*/ number_json,/*json*/ cast_not_support,/*geometry*/ cast_to_udt_not_support,/*udt*/ }, { /*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*/ datetime_text,/*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_json,/*json*/ cast_not_support,/*geometry*/ cast_to_udt_not_support,/*udt*/ }, { /*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*/ cast_inconsistent_types_json,/*json*/ cast_not_support,/*geometry*/ cast_to_udt_not_support,/*udt*/ }, { /*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*/ time_json,/*json*/ cast_not_support,/*geometry*/ cast_to_udt_not_support,/*udt*/ }, { /*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*/ cast_inconsistent_types_json,/*json*/ cast_not_support,/*geometry*/ cast_to_udt_not_support,/*udt*/ }, { /*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_text,/*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*/ string_json,/*json*/ cast_not_support,/*geometry*/ cast_to_udt_not_support,/*udt*/ }, { /*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_eval_arg,/*extend*/ cast_not_expected,/*unknown*/ cast_inconsistent_types,/*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*/ cast_inconsistent_types_json,/*json*/ cast_not_support,/*geometry*/ pl_extend_sql_udt,/*udt*/ }, { /*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*/ cast_inconsistent_types_json,/*json*/ cast_not_support,/*geometry*/ cast_to_udt_not_support,/*udt*/ }, { /*text -> XXX*/ cast_not_expected,/*null*/ text_int,/*int*/ text_uint,/*uint*/ text_float,/*float*/ text_double,/*double*/ text_number,/*number*/ text_datetime,/*datetime*/ cast_not_expected,/*date*/ cast_not_expected,/*time*/ cast_not_expected,/*year*/ text_string,/*string*/ cast_not_expected,/*extend*/ cast_not_expected,/*unknown*/ text_text,/*text*/ cast_not_expected,/*bit*/ cast_not_expected,/*enumset*/ cast_not_expected,/*enumset_inner*/ text_otimestamp,/*otimestamp*/ text_raw,/*raw*/ text_interval,/*interval*/ text_rowid,/*rowid*/ text_lob,/*lob*/ string_json,/*json*/ cast_not_support,/*geometry*/ cast_to_udt_not_support,/*udt*/ }, { /*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*/ cast_inconsistent_types_json,/*json*/ cast_not_support,/*geometry*/ cast_to_udt_not_support,/*udt*/ }, { /*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*/ cast_inconsistent_types_json,/*json*/ cast_not_support,/*geometry*/ cast_to_udt_not_support,/*udt*/ }, { /*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*/ cast_inconsistent_types_json,/*json*/ cast_not_support,/*geometry*/ cast_to_udt_not_support,/*udt*/ }, { /*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*/ cast_inconsistent_types_json,/*json*/ cast_not_support,/*geometry*/ cast_to_udt_not_support,/*udt*/ }, { /*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*/ raw_json,/*json*/ cast_not_support,/*geometry*/ cast_to_udt_not_support,/*udt*/ }, { /*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*/ cast_inconsistent_types_json,/*json*/ cast_not_support,/*geometry*/ cast_to_udt_not_support,/*udt*/ }, { /* 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*/ cast_inconsistent_types_json,/*json*/ cast_not_support,/*geometry*/ cast_to_udt_not_support,/*udt*/ }, { /*lob -> XXX*/ cast_not_expected,/*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_expected,/*extend*/ cast_not_expected,/*unknown*/ lob_text,/*text*/ cast_not_expected,/*bit*/ cast_not_expected,/*enumset*/ cast_not_expected,/*enumset_inner*/ lob_otimestamp,/*otimestamp*/ lob_raw,/*raw*/ lob_interval,/*interval*/ lob_rowid,/*rowid*/ lob_lob,/*lob*/ lob_json,/*json*/ cast_not_support,/*geometry*/ cast_to_udt_not_support,/*udt*/ }, { /*json -> XXX*/ cast_not_support,/*null*/ cast_not_support,/*int*/ cast_not_support,/*uint*/ cast_inconsistent_types,/*float*/ cast_inconsistent_types,/*double*/ cast_inconsistent_types,/*number*/ cast_inconsistent_types,/*datetime*/ cast_inconsistent_types,/*date*/ cast_inconsistent_types,/*time*/ cast_not_support,/*year*/ json_string,/*string*/ cast_not_support,/*extend*/ cast_not_support,/*unknown*/ json_text,/*text*/ cast_not_support,/*bit*/ cast_not_support,/*enumset*/ cast_not_support,/*enumset_inner*/ cast_inconsistent_types,/*otimestamp*/ json_raw,/*raw*/ cast_inconsistent_types,/*interval*/ cast_not_support,/*rowid*/ json_lob,/*lob*/ json_json,/*json*/ cast_not_support,/*geometry*/ cast_to_udt_not_support,/*udt*/ }, { /*geometry -> 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_not_support,/*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*/ cast_not_support,/*json*/ cast_not_support,/*geometry*/ cast_not_support,/*udt*/ }, { /*udt -> XXX*/ cast_udt_to_other_not_support,/*null*/ cast_udt_to_other_not_support,/*int*/ cast_udt_to_other_not_support,/*uint*/ cast_udt_to_other_not_support,/*float*/ cast_udt_to_other_not_support,/*double*/ cast_udt_to_other_not_support,/*number*/ cast_udt_to_other_not_support,/*datetime*/ cast_udt_to_other_not_support,/*date*/ cast_udt_to_other_not_support,/*time*/ cast_udt_to_other_not_support,/*year*/ udt_string,/*string*/ sql_udt_pl_extend,/*extend*/ cast_udt_to_other_not_support,/*unknown*/ cast_udt_to_other_not_support,/*text*/ cast_udt_to_other_not_support,/*bit*/ cast_udt_to_other_not_support,/*enumset*/ cast_udt_to_other_not_support,/*enumset_inner*/ cast_udt_to_other_not_support,/*otimestamp*/ cast_udt_to_other_not_support,/*raw*/ cast_udt_to_other_not_support,/*interval*/ cast_udt_to_other_not_support,/*rowid*/ cast_udt_to_other_not_support,/*lob*/ cast_udt_to_other_not_support,/*json*/ cast_udt_to_other_not_support,/*geometry*/ cast_udt_to_other_not_support,/*udt*/ }, }; // 目前代码里面没有使用该矩阵,Oracle模式都是使用impilicit矩阵 // 但是新框架仍然保留,后期如果有需要可以通过cast_mode选择使用该矩阵 ObExpr::EvalFunc OB_DATUM_CAST_ORACLE_EXPLICIT[ObMaxTC][ObMaxTC] = { { /*null -> XXX*/ cast_eval_arg,/*null*/ cast_eval_arg,/*int*/ cast_eval_arg,/*uint*/ cast_eval_arg,/*float*/ cast_eval_arg,/*double*/ cast_eval_arg,/*number*/ cast_eval_arg,/*datetime*/ cast_eval_arg,/*date*/ cast_eval_arg,/*time*/ cast_eval_arg,/*year*/ cast_eval_arg,/*string*/ cast_eval_arg,/*extend*/ cast_eval_arg,/*unknown*/ cast_eval_arg,/*text*/ cast_eval_arg,/*bit*/ cast_eval_arg,/*enumset*/ cast_eval_arg,/*enumsetInner*/ cast_eval_arg,/*otimestamp*/ cast_eval_arg,/*raw*/ cast_eval_arg,/*interval*/ cast_eval_arg,/*rowid*/ cast_eval_arg,/*lob*/ cast_eval_arg,/*json*/ cast_not_support,/*geometry*/ cast_to_udt_not_support,/*udt*/ }, { /*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_text,/*text*/ cast_eval_arg,/*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*/ cast_inconsistent_types,/*json*/ cast_not_support,/*geometry*/ cast_to_udt_not_support,/*udt*/ }, { /*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_text,/*text*/ cast_eval_arg,/*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*/ cast_inconsistent_types,/*json*/ cast_not_support,/*geometry*/ cast_to_udt_not_support,/*udt*/ }, { /*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_text,/*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*/ cast_inconsistent_types,/*json*/ cast_not_support,/*geometry*/ cast_to_udt_not_support,/*udt*/ }, { /*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_text,/*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*/ cast_inconsistent_types,/*json*/ cast_not_support,/*geometry*/ cast_to_udt_not_support,/*udt*/ }, { /*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_text,/*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*/ cast_inconsistent_types,/*json*/ cast_not_support,/*geometry*/ cast_to_udt_not_support,/*udt*/ }, { /*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_text,/*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*/ cast_inconsistent_types,/*json*/ cast_not_support,/*geometry*/ cast_to_udt_not_support,/*udt*/ }, { /*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_support,/*rowid*/ cast_not_expected,/*lob*/ cast_not_expected,/*json*/ cast_not_support,/*geometry*/ cast_to_udt_not_support,/*udt*/ }, { /*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_support,/*rowid*/ cast_not_expected,/*lob*/ cast_not_expected,/*json*/ cast_not_support,/*geometry*/ cast_to_udt_not_support,/*udt*/ }, { /*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_support,/*rowid*/ cast_not_expected,/*lob*/ cast_not_expected,/*json*/ cast_not_support,/*geometry*/ cast_to_udt_not_support,/*udt*/ }, { /*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_text,/*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*/ cast_inconsistent_types,/*json*/ cast_not_support,/*geometry*/ cast_to_udt_not_support,/*udt*/ }, { /*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_eval_arg,/*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*/ cast_not_support,/*json*/ cast_not_support,/*geometry*/ pl_extend_sql_udt,/*udt*/ }, { /*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_eval_arg,/*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*/ cast_not_support,/*json*/ cast_not_support,/*geometry*/ cast_to_udt_not_support,/*udt*/ }, { /*text -> XXX*/ cast_not_support,/*null*/ text_int,/*int*/ text_uint,/*uint*/ text_float,/*float*/ text_double,/*double*/ text_number,/*number*/ text_datetime,/*datetime*/ cast_not_expected,/*date*/ cast_not_expected,/*time*/ cast_not_expected,/*year*/ text_string,/*string*/ cast_not_support,/*extend*/ cast_not_support,/*unknown*/ text_text,/*text*/ text_bit,/*bit*/ cast_not_expected,/*enumset*/ cast_not_expected,/*enumset_inner*/ text_otimestamp,/*otimestamp*/ text_raw,/*raw*/ text_interval,/*interval*/ cast_not_support,/*rowid*/ cast_inconsistent_types,/*lob*/ string_json,/*json*/ cast_not_support,/*geometry*/ cast_to_udt_not_support,/*udt*/ }, { /*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*/ cast_not_expected,/*json*/ cast_not_support,/*geometry*/ cast_to_udt_not_support,/*udt*/ }, { /*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*/ cast_not_expected,/*json*/ cast_not_support,/*geometry*/ cast_to_udt_not_support,/*udt*/ }, { /*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*/ cast_not_expected,/*json*/ cast_not_support,/*geometry*/ cast_to_udt_not_support,/*udt*/ }, { /*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_text,/*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*/ cast_not_support,/*json*/ cast_not_support,/*geometry*/ cast_to_udt_not_support,/*udt*/ }, { /*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*/ cast_not_support,/*json*/ cast_not_support,/*geometry*/ cast_to_udt_not_support,/*udt*/ }, { /*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*/ cast_not_support,/*interval*/ cast_not_support,/*rowid*/ cast_inconsistent_types,/*lob*/ cast_not_support,/*json*/ cast_not_support,/*geometry*/ cast_to_udt_not_support,/*udt*/ }, { /*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*/ cast_not_support,/*json*/ cast_not_support,/*geometry*/ cast_to_udt_not_support,/*udt*/ }, { /*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_text,/*text*/ lob_bit,/*bit*/ cast_not_expected,/*enumset*/ cast_not_expected,/*enumset_inner*/ lob_otimestamp,/*otimestamp*/ lob_raw,/*raw*/ lob_interval,/*interval*/ cast_not_support,/*rowid*/ cast_inconsistent_types,/*lob*/ string_json,/*json*/ cast_not_support,/*geometry*/ cast_to_udt_not_support,/*udt*/ }, { /*json -> 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*/ json_string,/*string*/ cast_not_support,/*extend*/ cast_not_support,/*unknown*/ json_text,/*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*/ json_lob,/*lob*/ json_json,/*json*/ cast_not_support,/*geometry*/ cast_to_udt_not_support,/*udt*/ }, { /*geometry -> 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_not_support,/*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*/ cast_not_support,/*json*/ cast_not_support,/*geometry*/ cast_not_support,/*udt*/ }, { /*udt -> XXX*/ cast_udt_to_other_not_support,/*null*/ cast_udt_to_other_not_support,/*int*/ cast_udt_to_other_not_support,/*uint*/ cast_udt_to_other_not_support,/*float*/ cast_udt_to_other_not_support,/*double*/ cast_udt_to_other_not_support,/*number*/ cast_udt_to_other_not_support,/*datetime*/ cast_udt_to_other_not_support,/*date*/ cast_udt_to_other_not_support,/*time*/ cast_udt_to_other_not_support,/*year*/ udt_string,/*string*/ sql_udt_pl_extend,/*extend*/ cast_udt_to_other_not_support,/*unknown*/ cast_udt_to_other_not_support,/*text*/ cast_udt_to_other_not_support,/*bit*/ cast_udt_to_other_not_support,/*enumset*/ cast_udt_to_other_not_support,/*enumset_inner*/ cast_udt_to_other_not_support,/*otimestamp*/ cast_udt_to_other_not_support,/*raw*/ cast_udt_to_other_not_support,/*interval*/ cast_udt_to_other_not_support,/*rowid*/ cast_udt_to_other_not_support,/*lob*/ cast_udt_to_other_not_support,/*json*/ cast_udt_to_other_not_support,/*geometry*/ cast_udt_to_other_not_support,/*udt*/ }, }; ObExpr::EvalFunc OB_DATUM_CAST_MYSQL_IMPLICIT[ObMaxTC][ObMaxTC] = { { /*null -> XXX*/ cast_eval_arg,/*null*/ cast_eval_arg,/*int*/ cast_eval_arg,/*uint*/ cast_eval_arg,/*float*/ cast_eval_arg,/*double*/ cast_eval_arg,/*number*/ cast_eval_arg,/*datetime*/ cast_eval_arg,/*date*/ cast_eval_arg,/*time*/ cast_eval_arg,/*year*/ cast_eval_arg,/*string*/ cast_eval_arg,/*extend*/ cast_eval_arg,/*unknown*/ cast_eval_arg,/*text*/ cast_eval_arg,/*bit*/ cast_eval_arg,/*enumset*/ cast_eval_arg,/*enumsetInner*/ cast_eval_arg,/*otimestamp*/ cast_inconsistent_types,/*raw*/ cast_not_expected,/*interval*/ cast_not_expected,/*rowid*/ cast_not_expected,/*lob*/ cast_eval_arg,/*json*/ cast_eval_arg,/*geometry*/ cast_not_expected,/*udt, not implemented in mysql mode*/ }, { /*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_text,/*text*/ cast_eval_arg,/*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*/ int_json,/*json*/ int_geometry,/*geometry*/ cast_not_expected,/*udt, not implemented in mysql mode*/ }, { /*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_text,/*text*/ cast_eval_arg,/*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*/ uint_json,/*json*/ uint_geometry,/*geometry*/ cast_not_expected,/*udt, not implemented in mysql mode*/ }, { /*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_text,/*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*/ cast_not_expected,/*lob*/ float_json,/*json*/ float_geometry,/*geometry*/ cast_not_expected,/*udt, not implemented in mysql mode*/ }, { /*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_text,/*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*/ cast_not_expected,/*lob*/ double_json,/*json*/ double_geometry,/*geometry*/ cast_not_expected,/*udt, not implemented in mysql mode*/ }, { /*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_text,/*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*/ cast_not_expected,/*lob*/ number_json,/*json*/ number_geometry,/*geometry*/ cast_not_expected,/*udt, not implemented in mysql mode*/ }, { /*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_text,/*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*/ cast_not_expected,/*lob*/ datetime_json,/*json*/ datetime_geometry,/*geometry*/ cast_not_expected,/*udt, not implemented in mysql mode*/ }, { /*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_eval_arg,/*date*/ date_time,/*time*/ date_year,/*year*/ date_string,/*string*/ cast_not_support,/*extend*/ cast_not_support,/*unknown*/ date_text,/*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*/ cast_not_expected,/*lob*/ date_json,/*json*/ date_geometry,/*geometry*/ cast_not_expected,/*udt, not implemented in mysql mode*/ }, { /*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_eval_arg,/*time*/ cast_not_support,/*year*/ time_string,/*string*/ cast_not_support,/*extend*/ cast_not_support,/*unknown*/ time_text,/*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*/ cast_not_expected,/*lob*/ time_json,/*json*/ time_geometry,/*geometry*/ cast_not_expected,/*udt, not implemented in mysql mode*/ }, { /*year -> XXX*/ cast_not_support,/*null*/ year_int,/*int*/ year_uint,/*uint*/ year_float,/*float*/ year_double,/*double*/ year_number,/*number*/ year_datetime,/*datetime*/ year_date,/*date*/ cast_not_support,/*time*/ cast_eval_arg,/*year*/ year_string,/*string*/ cast_not_support,/*extend*/ cast_not_support,/*unknown*/ year_text,/*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*/ cast_not_expected,/*lob*/ year_json,/*json*/ year_geometry,/*geometry*/ cast_not_expected,/*udt, not implemented in mysql mode*/ }, { /*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_text,/*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*/ cast_not_expected,/*lob*/ string_json,/*json*/ string_geometry,/*geometry*/ cast_not_expected,/*udt, not implemented in mysql mode*/ }, { /*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_eval_arg,/*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_expected,/*lob*/ cast_not_support,/*json*/ cast_not_support,/*geometry*/ cast_not_expected,/*udt, not implemented in mysql mode*/ }, { /*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_eval_arg,/*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_expected,/*lob*/ cast_not_expected,/*json*/ cast_not_expected,/*geometry*/ cast_not_expected,/*udt, not implemented in mysql mode*/ }, { /*text -> XXX*/ cast_not_support,/*null*/ text_int,/*int*/ text_uint,/*uint*/ text_float,/*float*/ text_double,/*double*/ text_number,/*number*/ text_datetime,/*datetime*/ text_date,/*date*/ text_time,/*time*/ text_year,/*year*/ text_string,/*string*/ cast_not_support,/*extend*/ cast_not_support,/*unknown*/ text_text,/*text*/ text_bit,/*bit*/ cast_not_expected,/*enumset*/ cast_not_expected,/*enumset_inner*/ text_otimestamp,/*otimestamp*/ cast_inconsistent_types,/*raw*/ cast_not_expected,/*interval*/ cast_not_expected,/*rowid*/ cast_not_expected,/*lob*/ string_json,/*json*/ string_geometry,/*geometry*/ cast_not_expected,/*udt, not implemented in mysql mode*/ }, { /*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_text,/*text*/ cast_eval_arg,/*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*/ bit_json,/*json*/ bit_geometry,/*geometry*/ cast_not_expected,/*udt, not implemented in mysql mode*/ }, { /*enumset -> 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*/ cast_not_expected,/*json*/ cast_not_expected,/*geometry*/ cast_not_expected,/*udt, not implemented in mysql mode*/ }, { /*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_expected,/*lob*/ cast_not_expected,/*json*/ cast_not_expected,/*geometry*/ cast_not_expected,/*udt, not implemented in mysql mode*/ }, { /*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*/ cast_not_expected,/*json*/ cast_not_expected,/*geometry*/ cast_not_expected,/*udt, not implemented in mysql mode*/ }, { /*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*/ cast_not_expected,/*json*/ cast_not_expected,/*geometry*/ cast_not_expected,/*udt, not implemented in mysql mode*/ }, { /*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*/ cast_not_expected,/*json*/ cast_not_expected,/*geometry*/ cast_not_expected,/*udt, not implemented in mysql mode*/ }, { /*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*/ cast_not_expected,/*json*/ cast_not_expected,/*geometry*/ cast_not_expected,/*udt, not implemented in mysql mode*/ }, { /*lob -> 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*/ cast_not_expected,/*json*/ cast_not_expected,/*geometry*/ cast_not_expected,/*udt, not implemented in mysql mode*/ }, { /*json -> XXX*/ cast_not_support,/*null*/ json_int,/*int*/ json_uint,/*uint*/ json_float,/*float*/ json_double,/*double*/ json_number,/*number*/ json_datetime,/*datetime*/ json_date,/*date*/ json_time,/*time*/ json_year,/*year*/ json_string,/*string*/ cast_not_support,/*extend*/ cast_not_support,/*unknown*/ json_string,/*text*/ json_bit,/*bit*/ cast_not_expected,/*enumset*/ cast_not_expected,/*enumset_inner*/ json_otimestamp,/*otimestamp*/ cast_inconsistent_types,/*raw*/ cast_not_expected,/*interval*/ cast_not_expected,/*rowid*/ cast_not_expected,/*lob*/ json_json,/*json*/ json_geometry,/*geometry*/ cast_not_expected,/*udt, not implemented in mysql mode*/ }, { /*geometry -> XXX*/ cast_not_support,/*null*/ geometry_int,/*int*/ geometry_uint,/*uint*/ geometry_float,/*float*/ geometry_double,/*double*/ geometry_number,/*number*/ geometry_datetime,/*datetime*/ geometry_date,/*date*/ geometry_time,/*time*/ geometry_year,/*year*/ geometry_string,/*string*/ cast_not_support,/*extend*/ cast_not_support,/*unknown*/ geometry_string,/*text*/ geometry_bit,/*bit*/ cast_not_expected,/*enumset*/ cast_not_expected,/*enumset_inner*/ geometry_otimestamp,/*otimestamp*/ cast_inconsistent_types,/*raw*/ cast_not_expected,/*interval*/ cast_not_expected,/*rowid*/ cast_not_expected,/*lob*/ geometry_json,/*json*/ geometry_geometry,/*geometry*/ cast_not_expected,/*udt, not implemented in mysql mode*/ }, { /*udt -> 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*/ cast_not_expected,/*json*/ cast_not_expected,/*geometry*/ cast_not_expected,/*udt, not implemented in mysql mode*/ }, }; ObExpr::EvalEnumSetFunc OB_DATUM_CAST_MYSQL_ENUMSET_IMPLICIT[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*/ text_enum,/*enum*/ text_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*/ }, { /*OTimestamp -> enum_or_set*/ cast_not_support_enum_set,/*enum*/ cast_not_support_enum_set,/*set*/ }, { /*Raw -> enum_or_set*/ cast_not_support_enum_set,/*enum*/ cast_not_support_enum_set,/*set*/ }, { /*Interval -> enum_or_set*/ cast_not_support_enum_set,/*enum*/ cast_not_support_enum_set,/*set*/ }, { /*RowID -> enum_or_set*/ cast_not_support_enum_set,/*enum*/ cast_not_support_enum_set,/*set*/ }, { /*Lob -> enum_or_set*/ cast_not_support_enum_set,/*enum*/ cast_not_support_enum_set,/*set*/ }, { /*Json -> enum_or_set*/ cast_not_support_enum_set,/*enum*/ cast_not_support_enum_set,/*set*/ }, { /*Geometry -> enum_or_set*/ cast_not_support_enum_set,/*enum*/ cast_not_support_enum_set,/*set*/ }, { /*UDT -> enum_or_set*/ cast_not_support_enum_set,/*enum*/ cast_not_support_enum_set,/*set*/ }, }; int string_collation_check(const bool is_strict_mode, const ObCollationType check_cs_type, const ObObjType str_type, ObString &str) { int ret = OB_SUCCESS; if (!ob_is_string_type(str_type)) { // nothing to do } else if (check_cs_type == CS_TYPE_BINARY) { //任何类型都可以直接转成binary // do nothing } else { int64_t well_formed_len = 0; if (OB_FAIL(ObCharset::well_formed_len(check_cs_type, str.ptr(), str.length(), well_formed_len))) { LOG_WARN("invalid string for charset", K(ret), K(is_strict_mode), K(check_cs_type), K(str), K(well_formed_len)); if (lib::is_oracle_mode()) { // invalid character is acceptable in oracle mode ret = OB_SUCCESS; } else if (is_strict_mode) { ret = OB_ERR_INCORRECT_STRING_VALUE; } else { ret = OB_SUCCESS; str.assign_ptr(str.ptr(), static_cast(well_formed_len)); } } else { // if check succeed, do nothing } } return ret; } int ob_datum_to_ob_time_with_date(const ObDatum &datum, const ObObjType type, const ObTimeZoneInfo* tz_info, ObTime& ob_time, const int64_t cur_ts_value, const bool is_dayofmonth, const ObDateSqlMode date_sql_mode, const bool has_lob_header) { int ret = OB_SUCCESS; switch (ob_obj_type_class(type)) { case ObIntTC: // fallthrough. case ObUIntTC: { ret = ObTimeConverter::int_to_ob_time_with_date(datum.get_int(), ob_time, is_dayofmonth, date_sql_mode); break; } case ObOTimestampTC: { if (ObTimestampTZType == type) { ret = ObTimeConverter::otimestamp_to_ob_time(type, datum.get_otimestamp_tz(), tz_info, ob_time); } else { ret = ObTimeConverter::otimestamp_to_ob_time(type, datum.get_otimestamp_tiny(), tz_info, ob_time); } break; } case ObDateTimeTC: { ret = ObTimeConverter::datetime_to_ob_time(datum.get_datetime(), (ObTimestampType == type) ? tz_info : NULL, ob_time); break; } case ObDateTC: { ret = ObTimeConverter::date_to_ob_time(datum.get_date(), ob_time); break; } case ObTimeTC: { int64_t dt_value = 0; if (OB_FAIL(ObTimeConverter::timestamp_to_datetime(cur_ts_value, tz_info, dt_value))) { LOG_WARN("convert timestamp to datetime failed", K(ret)); } else { const int64_t usec_per_day = 3600 * 24 * USECS_PER_SEC; // 将datetime的时间截取,只保留日期,然后转为微秒 int64_t day_usecs = dt_value - dt_value % usec_per_day; ret = ObTimeConverter::datetime_to_ob_time(datum.get_time() + day_usecs, NULL, ob_time); } break; } case ObTextTC: // TODO@hanhui texttc share with the stringtc temporarily case ObStringTC: { ObScale res_scale = -1; ObArenaAllocator lob_allocator(ObModIds::OB_LOB_ACCESS_BUFFER, OB_MALLOC_NORMAL_BLOCK_SIZE, MTL_ID()); ObString str = datum.get_string(); if (OB_FAIL(ObTextStringHelper::read_real_string_data(&lob_allocator, type, CS_TYPE_BINARY, has_lob_header, str))) { LOG_WARN("fail to get real string data", K(ret), K(datum)); } else { ret = ObTimeConverter::str_to_ob_time_with_date(str, ob_time, &res_scale, is_dayofmonth, date_sql_mode); } break; } case ObNumberTC: { int64_t int_part = 0; int64_t dec_part = 0; const number::ObNumber num(datum.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, date_sql_mode); if (OB_SUCC(ret)) { ob_time.parts_[DT_USEC] = (dec_part + 500) / 1000; } } break; } default: { ret = OB_NOT_SUPPORTED; LOG_USER_ERROR(OB_NOT_SUPPORTED, "cast to time with date"); } } LOG_DEBUG("end ob_datum_to_ob_time_with_date", K(type), K(cur_ts_value), K(ob_time), K(ret)); return ret; } int ob_datum_to_ob_time_without_date(const ObDatum &datum, const ObObjType type, const ObTimeZoneInfo *tz_info, ObTime &ob_time, const bool has_lob_header) { int ret = OB_SUCCESS; switch (ob_obj_type_class(type)) { case ObIntTC: // fallthrough. case ObUIntTC: { if (OB_FAIL(ObTimeConverter::int_to_ob_time_without_date(datum.get_int(), ob_time))) { LOG_WARN("int to ob time without date failed", K(ret)); } else { //mysql中intTC转time时,如果hour超过838,那么time应该为null,而不是最大值。 const int64_t time_max_val = TIME_MAX_VAL; // 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: { if (ObTimestampTZType == type) { ret = ObTimeConverter::otimestamp_to_ob_time(type, datum.get_otimestamp_tz(), tz_info, ob_time); } else { ret = ObTimeConverter::otimestamp_to_ob_time(type, datum.get_otimestamp_tiny(), tz_info, ob_time); } break; } case ObDateTimeTC: { ret = ObTimeConverter::datetime_to_ob_time(datum.get_datetime(), (ObTimestampType == type) ? tz_info : NULL, ob_time); break; } case ObDateTC: { ret = ObTimeConverter::date_to_ob_time(datum.get_date(), ob_time); break; } case ObTimeTC: { ret = ObTimeConverter::time_to_ob_time(datum.get_time(), ob_time); break; } case ObTextTC: // TODO@hanhui texttc share with the stringtc temporarily case ObStringTC: { ObArenaAllocator lob_allocator(ObModIds::OB_LOB_ACCESS_BUFFER, OB_MALLOC_NORMAL_BLOCK_SIZE, MTL_ID()); ObString str = datum.get_string(); if (OB_FAIL(ObTextStringHelper::read_real_string_data(&lob_allocator, type, CS_TYPE_BINARY, has_lob_header, str))) { LOG_WARN("fail to get real string data", K(ret), K(datum)); } else { ret = ObTimeConverter::str_to_ob_time_without_date(str, ob_time); if (OB_SUCC(ret)) { int64_t value = ObTimeConverter::ob_time_to_time(ob_time); int64_t tmp_value = value; ObTimeConverter::time_overflow_trunc(value); if (value != tmp_value) { ObTimeConverter::time_to_ob_time(value, ob_time); } } } break; } case ObNumberTC: { int64_t int_part = 0; int64_t dec_part = 0; const number::ObNumber num(datum.get_number()); 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 { if (OB_FAIL(ObTimeConverter::int_to_ob_time_without_date(int_part, ob_time, dec_part))) { LOG_WARN("int to ob time without date failed", K(ret)); } else { if ((!ob_time.parts_[DT_YEAR]) && (!ob_time.parts_[DT_MON]) && (!ob_time.parts_[DT_MDAY])) { //mysql中intTC转time时,如果超过838:59:59,那么time应该为null,而不是最大值。 const int64_t time_max_val = TIME_MAX_VAL; // 838:59:59. int64_t value = ObTimeConverter::ob_time_to_time(ob_time); if(value > time_max_val) { ret = OB_INVALID_DATE_VALUE; } } } } break; } default: { ret = OB_NOT_SUPPORTED; LOG_USER_ERROR(OB_NOT_SUPPORTED, "cast to time without date"); } } LOG_DEBUG("end ob_datum_to_ob_time_without_date", K(type), K(ob_time), K(ret)); return ret; } // 不能进行cast的情况包括: // 1. Oracle模式下, string/text/lob->string/text/lob时, blob不支持转向nonblob // 2. Oracle模式下, string/text/lob->string/text/lob, nonblob转向blob时,如果输入必须是char/varchar/raw // TODO by shaoge // 3. Oracle模式下, 只有string/text->string/text的转换支持blob往其他类型转,其余的不允许 // 4. TODO: lob_outrow的处理还未完善 int ObDatumCast::check_can_cast(const ObObjType in_type, const ObCollationType in_cs_type, const ObObjType out_type, const ObCollationType out_cs_type) { int ret = OB_SUCCESS; ObObjTypeClass in_tc = ob_obj_type_class(in_type); ObObjTypeClass out_tc = ob_obj_type_class(out_type); const bool is_stringtext_tc_to_stringtext_tc = ((ObStringTC == in_tc || ObTextTC == in_tc || ObLobTC == in_tc) && (ObStringTC == out_tc || ObTextTC == out_tc || ObLobTC == out_tc)); const bool is_blob_in = ob_is_blob(in_type, in_cs_type) || ob_is_blob_locator(in_type, in_cs_type); const bool is_blob_out = ob_is_blob(out_type, out_cs_type) || ob_is_blob_locator(out_type, out_cs_type); const bool is_blob_to_nonblob = is_blob_in && (! is_blob_out); const bool is_nonblob_to_blob = (! is_blob_in) && is_blob_out; if (ObNullType == in_type || ObNullType == out_type) { // let null be ok } else if (! lib::is_oracle_mode()) { } else if(is_blob_in && ObJsonTC == out_tc) { } else if ((ob_is_number_tc(in_type) || ob_is_int_tc(in_type) || ob_is_datetime_tc(in_type) || ob_is_clob(in_type, in_cs_type) || ob_is_clob_locator(in_type, in_cs_type)) && is_blob_out) { ret = OB_ERR_INVALID_TYPE_FOR_OP; LOG_WARN("cast number to blob not allowed", K(ret)); } else if ((ob_is_clob(in_type, in_cs_type) || ob_is_clob_locator(in_type, in_cs_type)) && ObRawTC == out_tc) { ret = OB_ERR_INVALID_TYPE_FOR_OP; LOG_WARN("cast clob to raw not allowed", K(ret)); } else if (is_oracle_mode() && ObTinyIntType == in_type && ob_is_text_tc(out_type)) { ret = OB_ERR_INVALID_TYPE_FOR_OP; LOG_WARN("cast boolean to lob not allowed", K(ret)); } else if (is_stringtext_tc_to_stringtext_tc && is_blob_to_nonblob) { ret = OB_NOT_SUPPORTED; LOG_WARN("invalid use of blob type", K(ret), K(out_type)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "blob cast to other type"); } else if (is_stringtext_tc_to_stringtext_tc && is_nonblob_to_blob && !ob_is_raw(in_type) && !ob_is_varchar_char_type(in_type, in_cs_type)) { ret = OB_NOT_SUPPORTED; LOG_WARN("invalid use of blob type", K(ret), K(out_type), K(out_cs_type), K(in_type), K(in_cs_type)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "cast to blob type"); // } else if (ObTextTC == in_tc && is_lob_outrow) { // ret = OB_NOT_SUPPORTED; // LOG_WARN("cannot cast blob to nonblob", K(ret)); // shanting: is_stringtext_tc_to_nonstringtext_tc没有使用,不知道是不是有问题。@shaoge } else if (!is_stringtext_tc_to_stringtext_tc && is_blob_in && ObRawTC != out_tc) { ret = OB_NOT_SUPPORTED; LOG_WARN("cannot cast blob to nonblob", K(ret)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "cast blob to nonblob type"); } return ret; } // string/text -> string/text的特殊情况的描述: // 1. !blob -> blob is ok. (in_type must be varchar/char/raw, varchar/char call hextoraw to cast) // 2. !blob -> !blob is ok (just copy or convert charset) // a. 如果是相同字符集,则调用cast_eval_arg // b. 如果是不同字符集,且输入输出都不是cs_type_binary,则需要进行字符集转换 // c. 如果输入输出有任意一个是cs_type_binary,会调用cast_eval_arg // 3. blob -> blob ok. 直接调用cast_eval_arg // 4. blob -> !blob not ok.choose_cast_func会检测并报错 int ObDatumCast::is_trivial_cast(const ObObjType in_type, const ObCollationType in_cs_type, const ObObjType out_type, const ObCollationType out_cs_type, const ObCastMode &cast_mode, bool &is_trivial_cast) { is_trivial_cast = false; int ret = OB_SUCCESS; ObCharsetType in_cs = ObCharset::charset_type_by_coll(in_cs_type); ObCharsetType out_cs = ObCharset::charset_type_by_coll(out_cs_type); ObObjTypeClass in_tc = ob_obj_type_class(in_type); ObObjTypeClass out_tc = ob_obj_type_class(out_type); const bool is_same_charset = (ob_is_string_type(in_type) && ob_is_string_type(out_type) && (in_cs == out_cs || /** GB18030 and GB18030_2022 have the same code points, * but they have different mapping to unicode. * So, we do not do charset_convert for them in cast*/ (in_cs == CHARSET_GB18030 && out_cs == CHARSET_GB18030_2022) || (in_cs == CHARSET_GB18030_2022 && out_cs == CHARSET_GB18030))); const bool is_clob_to_nonclob = (ob_is_clob(in_type, in_cs_type) && !ob_is_clob(out_type, out_cs_type)); const bool is_nonblob_to_blob = ((false == ob_is_blob(in_type, in_cs_type)) && (true == ob_is_blob(out_type, out_cs_type))); const bool is_blob_to_blob = ((true == ob_is_blob(in_type, in_cs_type)) && (true == ob_is_blob(out_type, out_cs_type))); const bool is_nonblob_to_nonblob = ((false == ob_is_blob(in_type, in_cs_type)) && (false == ob_is_blob(out_type, out_cs_type))); // Notice: large text types has lob locator header, cannot be trivial when cast to tinytext or strings const bool is_stringtext_tc_to_stringtext_tc = ((ObStringTC == in_tc || ObTextTC == in_tc) && (ObStringTC == out_tc || ObTextTC == out_tc)); const bool is_large_text_to_large_text = (ob_is_large_text(in_type) && ob_is_large_text(out_type)); const bool is_small_text_to_small_text = ((ObStringTC == in_tc || ObTinyTextType == in_type) && (ObStringTC == out_tc || ObTinyTextType == out_type)); const bool may_be_trivial_cast = (is_large_text_to_large_text || is_small_text_to_small_text || (is_stringtext_tc_to_stringtext_tc && !ob_enable_lob_locator_v2())); if (ObNullType == in_type) { // cast func of xxx(not_null)-> null is cast_not_expected() or cast_not_support() // cast func of null -> xxx is cast_eval_arg is_trivial_cast = true; } else if (ob_is_raw(in_type) && ob_is_blob(out_type, out_cs_type)) { // if locator v2 enabled, cannot do trivial cast, or should always set to true? // here may be called by get_next_row, not in cg. is_trivial_cast = !ob_enable_lob_locator_v2(); } else if (may_be_trivial_cast && lib::is_oracle_mode()) { // In order to keep physical plan the same with 4.0 if ((is_same_charset && !is_nonblob_to_blob) || (is_blob_to_blob) || (is_nonblob_to_nonblob && (CS_TYPE_BINARY == in_cs_type || CS_TYPE_BINARY == out_cs_type))) { if (!is_clob_to_nonclob) { is_trivial_cast = true; } } } else if (may_be_trivial_cast && !lib::is_oracle_mode()) { if ((is_same_charset || CS_TYPE_BINARY == out_cs_type)) { is_trivial_cast = true; } } else if (!lib::is_oracle_mode() && ((ObIntTC == in_tc && ObBitTC == out_tc) || (ObUIntTC == in_tc && ObBitTC == out_tc) || (ObDateType == in_type && ObDateType == out_type) || (ObYearType == in_type && ObYearType == out_type) || (ObExtendType == in_type && ObExtendType == out_type) || (ObBitType == in_type && ObBitType == out_type) || (ObUnknownType == in_type && ObUnknownType == out_type))) { is_trivial_cast = true; } else if (lib::is_oracle_mode() && ((ObExtendType == in_type && ObExtendType == out_type) || (ObUnknownType == in_type && ObUnknownType == out_type) || (ObIntervalYMType == in_type && ObIntervalYMType == out_type) || (ObIntervalDSType == in_type && ObIntervalDSType == out_type))) { // Oracle模式没有bit/year/date/time类型(Oracle的date类型在OB中用ObDateTimeType表示) is_trivial_cast = true; } else if (ObUIntTC == in_tc && ObIntTC == out_tc && CM_IS_EXTERNAL_CALL(cast_mode) && CM_SKIP_CAST_INT_UINT(cast_mode)) { is_trivial_cast = true; } else { is_trivial_cast = false; } LOG_DEBUG("is_trivial_cast debug", K(ret), K(in_type), K(out_type), K(in_cs_type), K(out_cs_type), K(cast_mode), K(is_trivial_cast), K(lbt())); return ret; } int ObDatumCast::get_implicit_cast_function(const ObObjType in_type, const ObCollationType in_cs_type, const ObObjType out_type, const ObCollationType out_cs_type, const int64_t cast_mode, ObExpr::EvalFunc &eval_func) { int ret = OB_SUCCESS; bool pass_cast = false; if (OB_FAIL(check_can_cast(in_type, in_cs_type, out_type, out_cs_type))) { LOG_WARN("check_can_cast failed", K(ret)); } else if (OB_FAIL(is_trivial_cast(in_type, in_cs_type, out_type, out_cs_type, cast_mode, pass_cast))) { LOG_WARN("is_trivial_cast failed", K(ret), K(in_type), K(out_type)); } else if (pass_cast) { eval_func = cast_eval_arg; } else { ObObjTypeClass in_tc = ob_obj_type_class(in_type); ObObjTypeClass out_tc = ob_obj_type_class(out_type); if (lib::is_oracle_mode()) { eval_func = OB_DATUM_CAST_ORACLE_IMPLICIT[in_tc][out_tc]; } else { eval_func = OB_DATUM_CAST_MYSQL_IMPLICIT[in_tc][out_tc]; } LOG_DEBUG("get_implicit_cast_function ", K(in_tc), K(out_tc), K(in_type), K(out_type)); } return ret; } int ObDatumCast::choose_cast_function(const ObObjType in_type, const ObCollationType in_cs_type, const ObObjType out_type, const ObCollationType out_cs_type, const int64_t cast_mode, ObIAllocator &allocator, ObExpr &rt_expr) { int ret = OB_SUCCESS; bool just_eval_arg = false; if (OB_FAIL(check_can_cast(in_type, in_cs_type, out_type, out_cs_type))) { LOG_WARN("check_can_cast failed", K(ret)); } else if (OB_FAIL(is_trivial_cast(in_type, in_cs_type, out_type, out_cs_type, cast_mode, just_eval_arg))) { LOG_WARN("is_trivial_cast failed", K(ret), K(in_type), K(out_type)); } else if (just_eval_arg && !CM_IS_EXPLICIT_CAST(cast_mode)) { // 即使是相同类型,显式cast也需要进行accuracy check rt_expr.eval_func_ = cast_eval_arg; } else { ObObjTypeClass in_tc = ob_obj_type_class(in_type); ObObjTypeClass out_tc = ob_obj_type_class(out_type); if (CM_IS_EXPLICIT_CAST(cast_mode)) { if (OB_ISNULL(rt_expr.inner_functions_ = reinterpret_cast(allocator.alloc(sizeof(void*))))) { ret = OB_ALLOCATE_MEMORY_FAILED; LOG_WARN("alloc memory failed", K(ret)); } else { rt_expr.inner_func_cnt_ = 1; if (just_eval_arg) { rt_expr.inner_functions_[0] = reinterpret_cast(cast_eval_arg); } else { if (lib::is_oracle_mode()) { rt_expr.inner_functions_[0] = reinterpret_cast(OB_DATUM_CAST_ORACLE_IMPLICIT[in_tc][out_tc]); } else { rt_expr.inner_functions_[0] = reinterpret_cast(OB_DATUM_CAST_MYSQL_IMPLICIT[in_tc][out_tc]); } } if (ob_is_character_type(out_type, out_cs_type) || ob_is_varbinary_or_binary(out_type, out_cs_type)) { rt_expr.eval_func_ = anytype_to_varchar_char_explicit; } else { rt_expr.eval_func_ = anytype_anytype_explicit; } } } else if (lib::is_oracle_mode()) { rt_expr.eval_func_ = OB_DATUM_CAST_ORACLE_IMPLICIT[in_tc][out_tc]; } else { rt_expr.eval_func_ = OB_DATUM_CAST_MYSQL_IMPLICIT[in_tc][out_tc]; } } if (OB_SUCC(ret)) { // TODO:@xiaofeng.lby, need to modify cast expr in batch mode // cast in batch mode will degrade into single row mode now rt_expr.eval_batch_func_ = cast_eval_arg_batch; } LOG_DEBUG("in choose_cast_function", K(ret), K(in_type), K(out_type), K(in_cs_type), K(out_cs_type), K(CM_IS_EXPLICIT_CAST(cast_mode)), K(CM_IS_ZERO_FILL(cast_mode)), K(cast_mode), K(lbt())); return ret; } int ObDatumCast::get_enumset_cast_function(const common::ObObjTypeClass in_tc, const common::ObObjType out_type, ObExpr::EvalEnumSetFunc &eval_func) { int ret = OB_SUCCESS; // in_type可以为NullType, out_type不能为NullType if (OB_UNLIKELY(!(ObNullTC <= in_tc && in_tc < ObMaxTC)) || OB_UNLIKELY(out_type != ObEnumType && out_type != ObSetType)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("expecected intype or outtype", K(ret), K(in_tc), K(out_type)); } else { eval_func = OB_DATUM_CAST_MYSQL_ENUMSET_IMPLICIT[in_tc][out_type == ObSetType]; } LOG_DEBUG("in get_enumset_cast_function", K(ret), K(in_tc), K(out_type)); return ret; } int ObDatumCast::cast_obj(ObEvalCtx &ctx, ObIAllocator &alloc, const ObObjType &dst_type, const ObCollationType &dst_cs_type, const ObObj &src_obj, ObObj &dst_obj) { int ret = OB_SUCCESS; ObCastMode def_cm = CM_NONE; ObSQLSessionInfo *session = ctx.exec_ctx_.get_my_session(); CK(OB_NOT_NULL(session)); if (OB_SUCC(ret)) { ObPhysicalPlanCtx *phy_plan_ctx = ctx.exec_ctx_.get_physical_plan_ctx(); const ObDataTypeCastParams dtc_params = ObBasicSessionInfo::create_dtc_params(session); if (OB_FAIL(ObSQLUtils::get_default_cast_mode(session->get_stmt_type(), session, def_cm))) { LOG_WARN("get_default_cast_mode failed", K(ret)); } else { ObCastCtx cast_ctx(&alloc, &dtc_params, get_cur_time(phy_plan_ctx), def_cm, dst_cs_type, NULL, NULL); if (OB_FAIL(ObObjCaster::to_type(dst_type, cast_ctx, src_obj, dst_obj))) { LOG_WARN("failed to cast object to ", K(ret), K(src_obj), K(dst_type)); } } } return ret; } int ObDatumCaster::init(ObExecContext &ctx) { int ret = OB_SUCCESS; if (!inited_) { void *ctx_mem = NULL; void *expr_mem = NULL; void *extra_mem = NULL; void *expr_args_mem = NULL; void *extra_args_mem = NULL; void *frame_mem = NULL; void *frames_mem = NULL; ObIAllocator &alloc = ctx.get_allocator(); int64_t res_buf_len = ObDatum::get_reserved_size(ObObjDatumMapType::OBJ_DATUM_STRING); const int64_t datum_eval_info_size = sizeof(ObDatum) + sizeof(ObEvalInfo); int64_t frame_size = (datum_eval_info_size + sizeof(ObDynReserveBuf) + res_buf_len) * 2; int64_t frames_size = 0; CK(OB_NOT_NULL(ctx.get_frames())); OX(frames_size = sizeof(char*) * (ctx.get_frame_cnt() + 1)); OV(OB_NOT_NULL(ctx_mem = alloc.alloc(sizeof(ObEvalCtx))), OB_ALLOCATE_MEMORY_FAILED); OV(OB_NOT_NULL(frames_mem = alloc.alloc(frames_size)), OB_ALLOCATE_MEMORY_FAILED); OV(OB_NOT_NULL(frame_mem = alloc.alloc(frame_size)), OB_ALLOCATE_MEMORY_FAILED); OV(OB_NOT_NULL(expr_mem = alloc.alloc(sizeof(ObExpr))), OB_ALLOCATE_MEMORY_FAILED); OV(OB_NOT_NULL(extra_mem = alloc.alloc(sizeof(ObExpr))), OB_ALLOCATE_MEMORY_FAILED); OV(OB_NOT_NULL(expr_args_mem = alloc.alloc(sizeof(ObExpr*))), OB_ALLOCATE_MEMORY_FAILED); OV(OB_NOT_NULL(extra_args_mem = alloc.alloc(sizeof(ObExpr*))), OB_ALLOCATE_MEMORY_FAILED); OX(MEMCPY(frames_mem, ctx.get_frames(), sizeof(char*) * ctx.get_frame_cnt())); if (OB_FAIL(ret)) { } else { // init eval_ctx_ char *frame = reinterpret_cast(frame_mem); MEMSET(frame, 0, frame_size); eval_ctx_ = new(ctx_mem) ObEvalCtx(ctx); eval_ctx_->frames_ = reinterpret_cast(frames_mem); eval_ctx_->frames_[ctx.get_frame_cnt()] = frame; eval_ctx_->max_batch_size_ = 0; eval_ctx_->set_batch_size(1); eval_ctx_->set_batch_idx(0); // init cast_expr_/extra_cast_expr and frame cast_expr_ = new (expr_mem) ObExpr(); cast_expr_->args_ = reinterpret_cast(expr_args_mem); extra_cast_expr_ = new (extra_mem) ObExpr(); extra_cast_expr_->args_ = reinterpret_cast(extra_args_mem); ObExpr *exprs[2] = {cast_expr_, extra_cast_expr_}; int64_t data_off = datum_eval_info_size * 2; const int64_t consume_size = res_buf_len + sizeof(ObDynReserveBuf); for (int64_t i = 0; OB_SUCC(ret) && i < sizeof(exprs) / sizeof(ObExpr*); ++i) { ObExpr *e = exprs[i]; e->type_ = T_FUN_SYS_CAST; e->max_length_ = -1; e->inner_func_cnt_ = 0; e->inner_functions_ = NULL; e->frame_idx_ = ctx.get_frame_cnt(); e->datum_off_ = datum_eval_info_size * i; e->eval_info_off_ = e->datum_off_ + sizeof(ObDatum); e->res_buf_len_ = res_buf_len; data_off += consume_size; e->res_buf_off_ = data_off - e->res_buf_len_; e->dyn_buf_header_offset_ = e->res_buf_off_ - sizeof(ObDynReserveBuf); e->arg_cnt_ = 1; ObDatum *expr_datum = reinterpret_cast(frame + e->datum_off_); expr_datum->ptr_ = frame + e->res_buf_off_; ObDynReserveBuf *drb = reinterpret_cast( frame + e->dyn_buf_header_offset_ + sizeof(ObDynReserveBuf)); drb->len_ = e->res_buf_len_; drb->mem_ = frame + e->res_buf_off_; } } OX(inited_ = true); } return ret; } int ObDatumCaster::to_type(const ObDatumMeta &dst_type, const ObExpr &src_expr, const ObCastMode &cm, ObDatum *&res, int64_t batch_idx) { int ret = OB_SUCCESS; const ObDatumMeta &src_type = src_expr.datum_meta_; const ObCharsetType &src_cs = ObCharset::charset_type_by_coll(src_type.cs_type_); const ObCharsetType &dst_cs = ObCharset::charset_type_by_coll(dst_type.cs_type_); if (OB_UNLIKELY(!inited_) || OB_ISNULL(eval_ctx_) || OB_ISNULL(cast_expr_) || OB_ISNULL(extra_cast_expr_)) { ret = OB_NOT_INIT; LOG_WARN("ObDatumCaster is invalid", K(ret), K(inited_), KP(eval_ctx_), KP(cast_expr_), KP(extra_cast_expr_)); } else if (FALSE_IT(eval_ctx_->batch_idx_ = batch_idx)) { } else if ((ob_is_string_or_lob_type(src_type.type_) && src_type.type_ == dst_type.type_ && src_cs == dst_cs) || (!ob_is_string_or_lob_type(src_type.type_) && src_type.type_ == dst_type.type_)) { LOG_DEBUG("no need to cast, just eval src_expr", K(ret), K(src_expr), K(dst_type)); if (OB_FAIL(src_expr.eval(*eval_ctx_, res))) { LOG_WARN("eval src_expr failed", K(ret)); } } else { bool nonstr_to_str = !ob_is_string_or_lob_type(src_type.type_) && ob_is_string_or_lob_type(dst_type.type_); bool str_to_nonstr = ob_is_string_or_lob_type(src_type.type_) && !ob_is_string_or_lob_type(dst_type.type_); bool need_extra_cast_for_src_type = false; bool need_extra_cast_for_dst_type = false; if (str_to_nonstr) { if (CHARSET_BINARY != src_cs && ObCharset::get_default_charset() != src_cs) { need_extra_cast_for_src_type = true; } } else if (nonstr_to_str) { if (CHARSET_BINARY != dst_cs && ObCharset::get_default_charset() != dst_cs) { need_extra_cast_for_dst_type = true; } } ObDatumMeta extra_dst_type = src_type; if (need_extra_cast_for_src_type) { // non-utf8 -> int/num... extra_dst_type = src_type; extra_dst_type.cs_type_ = ObCharset::get_system_collation(); } else if (need_extra_cast_for_dst_type) { // int/num... -> non-utf8 extra_dst_type = dst_type; extra_dst_type.cs_type_ = ObCharset::get_system_collation(); } if (need_extra_cast_for_src_type || need_extra_cast_for_dst_type) { if (OB_FAIL(setup_cast_expr(extra_dst_type, src_expr, cm, *extra_cast_expr_))) { LOG_WARN("setup_cast_expr failed", K(ret)); } else if (OB_FAIL(setup_cast_expr(dst_type, *extra_cast_expr_, cm, *cast_expr_))) { LOG_WARN("setup_cast_expr failed", K(ret)); } } else { if (OB_FAIL(setup_cast_expr(dst_type, src_expr, cm, *cast_expr_))) { LOG_WARN("setup_cast_expr failed", K(ret)); } } if (OB_SUCC(ret) && OB_FAIL(cast_expr_->eval(*eval_ctx_, res))) { LOG_WARN("eval cast expr failed", K(ret)); } LOG_DEBUG("ObDatumCaster::to_type done", K(ret), K(src_expr), K(dst_type), K(cm), K(need_extra_cast_for_src_type), K(need_extra_cast_for_dst_type), KP(eval_ctx_->frames_)); } return ret; } int ObDatumCaster::to_type(const ObDatumMeta &dst_type, const ObIArray &str_values, const ObExpr &src_expr, const ObCastMode &cm, ObDatum *&res, int64_t batch_idx) { int ret = OB_SUCCESS; const ObDatumMeta &src_type = src_expr.datum_meta_; if (OB_UNLIKELY(!inited_) || OB_ISNULL(cast_expr_) || OB_ISNULL(extra_cast_expr_) || OB_ISNULL(eval_ctx_)) { ret = OB_NOT_INIT; LOG_WARN("ObDatumCaster is invalid", K(ret), K(inited_), KP(eval_ctx_), KP(cast_expr_), KP(extra_cast_expr_)); } else if (OB_UNLIKELY(!ob_is_enumset_tc(dst_type.type_)) || OB_UNLIKELY(ob_is_invalid_obj_type(src_type.type_))) { ret = OB_INVALID_ARGUMENT; LOG_WARN("invalid src_type or dst_type", K(ret), K(src_type), K(dst_type)); } else { // enum -> enum or set -> set will give error(see OB_DATUM_CAST_MYSQL_ENUMSET_IMPLICIT) // we do not check if need cast bool need_extra_cast = false; eval_ctx_->batch_idx_ = batch_idx; const ObCharsetType &src_cs = ObCharset::charset_type_by_coll(src_type.cs_type_); if (ob_is_string_type(src_type.type_) && CHARSET_BINARY != src_cs && ObCharset::get_default_charset() != src_cs) { need_extra_cast = true; } if (need_extra_cast) { // non-utf8 -> enumset ObDatumMeta extra_dst_type = src_type; extra_dst_type.cs_type_ = ObCharset::get_system_collation(); if (OB_FAIL(setup_cast_expr(extra_dst_type, src_expr, cm, *extra_cast_expr_))) { LOG_WARN("setup_cast_expr failed", K(ret)); } else if (OB_FAIL(setup_cast_expr(dst_type, *extra_cast_expr_, cm, *cast_expr_))) { LOG_WARN("setup_cast_expr failed", K(ret)); } } else { if (OB_FAIL(setup_cast_expr(dst_type, src_expr, cm, *cast_expr_))) { LOG_WARN("setup_cast_expr failed", K(ret)); } } if (OB_SUCC(ret)) { if (OB_FAIL(cast_expr_->eval_enumset(*eval_ctx_, str_values, cast_expr_->extra_, res))) { LOG_WARN("eval_enumset failed", K(ret)); } } LOG_DEBUG("ObDatumCaster::to_type done", K(ret), K(src_expr), K(dst_type), K(str_values), KP(eval_ctx_->frames_), K(cm), K(need_extra_cast), K(lbt())); } return ret; } int ObDatumCaster::destroy() { int ret = OB_SUCCESS; if (inited_) { if (OB_ISNULL(cast_expr_) || OB_ISNULL(extra_cast_expr_) || OB_ISNULL(eval_ctx_)) { ret = OB_NOT_INIT; LOG_WARN("ObDatumCaster is invalid", K(ret), K(inited_), KP(eval_ctx_), KP(cast_expr_), KP(extra_cast_expr_)); } else { inited_ = false; ObIAllocator &alloc = eval_ctx_->exec_ctx_.get_allocator(); eval_ctx_->~ObEvalCtx(); // ~ObEvalCtx() is default deallocator, so free frames_ manually. alloc.free(eval_ctx_->frames_); alloc.free(eval_ctx_); alloc.free(cast_expr_); alloc.free(extra_cast_expr_); eval_ctx_ = NULL; cast_expr_ = NULL; extra_cast_expr_ = NULL; } } return ret; } int ObDatumCaster::setup_cast_expr(const ObDatumMeta &dst_type, const ObExpr &src_expr, const ObCastMode cm, ObExpr &cast_expr) { int ret = OB_SUCCESS; const ObDatumMeta &src_type = src_expr.datum_meta_; if (!inited_ || OB_ISNULL(cast_expr.args_) || OB_ISNULL(eval_ctx_)) { ret = OB_NOT_INIT; LOG_WARN("invalid cast expr", K(ret), K(inited_), KP(cast_expr.args_)); } else if (OB_FAIL(ObDatumCast::get_implicit_cast_function(src_type.type_, src_type.cs_type_, dst_type.type_, dst_type.cs_type_, cm, cast_expr.eval_func_))) { LOG_WARN("get_implicit_cast_function failed", K(ret)); } else if (OB_ISNULL(cast_expr.eval_func_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("invalid eval func", K(ret), KP(cast_expr.eval_func_)); } else { cast_expr.datum_meta_ = dst_type; cast_expr.obj_datum_map_ = ObDatum::get_obj_datum_map_type(dst_type.type_); cast_expr.args_[0] = const_cast(&src_expr); cast_expr.extra_ = cm; cast_expr.obj_meta_.set_type(dst_type.type_); cast_expr.obj_meta_.set_collation_type(dst_type.cs_type_); cast_expr.obj_meta_.set_collation_level(CS_LEVEL_INVALID); cast_expr.obj_meta_.set_scale(-1); if (is_lob_storage(dst_type.type_)) { if (is_lob_storage(src_expr.obj_meta_.get_type())) { // if src is lob types from ps (in param store), it may not have lob head, // and run cast_eval_arg, in this case, has no chance to add lob header, unless we modify cast_eval_arg if (src_expr.obj_meta_.has_lob_header()) { cast_expr.obj_meta_.set_has_lob_header(); } } else if (!IS_CLUSTER_VERSION_BEFORE_4_1_0_0) { // other types to lobs cast_expr.obj_meta_.set_has_lob_header(); } } // implicit cast donot use these, so we set it all invalid. cast_expr.parents_ = NULL; cast_expr.parent_cnt_ = 0; cast_expr.basic_funcs_ = NULL; cast_expr.get_eval_info(*eval_ctx_).clear_evaluated_flag(); } return ret; } // register function serialization // function array is two dimension array, need to convert to index stable array first. // ObExpr::EvalFunc OB_DATUM_CAST_ORACLE_IMPLICIT[ObMaxTC][ObMaxTC] = // ObExpr::EvalFunc OB_DATUM_CAST_ORACLE_EXPLICIT[ObMaxTC][ObMaxTC] = // ObExpr::EvalFunc OB_DATUM_CAST_MYSQL_IMPLICIT[ObMaxTC][ObMaxTC] = // ObExpr::EvalEnumSetFunc OB_DATUM_CAST_MYSQL_ENUMSET_IMPLICIT[ObMaxTC][2] = static_assert(ObMaxTC * ObMaxTC == sizeof(OB_DATUM_CAST_ORACLE_IMPLICIT) / sizeof(void *), "unexpected size"); static void *g_ser_datum_cast_oracle_implicit[ObMaxTC * ObMaxTC]; bool g_ser_datum_cast_oracle_implicit_init = ObFuncSerialization::convert_NxN_array( g_ser_datum_cast_oracle_implicit, reinterpret_cast(OB_DATUM_CAST_ORACLE_IMPLICIT), ObMaxTC); REG_SER_FUNC_ARRAY(OB_SFA_DATUM_CAST_ORACLE_IMPLICIT, g_ser_datum_cast_oracle_implicit, ARRAYSIZEOF(g_ser_datum_cast_oracle_implicit)); static_assert(ObMaxTC * ObMaxTC == sizeof(OB_DATUM_CAST_ORACLE_EXPLICIT) / sizeof(void *), "unexpected size"); static void *g_ser_datum_cast_oracle_explicit[ObMaxTC * ObMaxTC]; bool g_ser_datum_cast_oracle_explcit_init = ObFuncSerialization::convert_NxN_array( g_ser_datum_cast_oracle_explicit, reinterpret_cast(OB_DATUM_CAST_ORACLE_EXPLICIT), ObMaxTC); REG_SER_FUNC_ARRAY(OB_SFA_DATUM_CAST_ORACLE_EXPLICIT, g_ser_datum_cast_oracle_explicit, ARRAYSIZEOF(g_ser_datum_cast_oracle_explicit)); static_assert(ObMaxTC * ObMaxTC == sizeof(OB_DATUM_CAST_MYSQL_IMPLICIT) / sizeof(void *), "unexpected size"); static void *g_ser_datum_cast_mysql_implicit[ObMaxTC * ObMaxTC]; bool g_ser_datum_cast_mysql_implicit_init = ObFuncSerialization::convert_NxN_array( g_ser_datum_cast_mysql_implicit, reinterpret_cast(OB_DATUM_CAST_MYSQL_IMPLICIT), ObMaxTC); REG_SER_FUNC_ARRAY(OB_SFA_DATUM_CAST_MYSQL_IMPLICIT, g_ser_datum_cast_mysql_implicit, ARRAYSIZEOF(g_ser_datum_cast_mysql_implicit)); static_assert(ObMaxTC * 2 == sizeof(OB_DATUM_CAST_MYSQL_ENUMSET_IMPLICIT) / sizeof(void *), "unexpected size"); REG_SER_FUNC_ARRAY(OB_SFA_DATUM_CAST_MYSQL_ENUMSET_IMPLICIT, OB_DATUM_CAST_MYSQL_ENUMSET_IMPLICIT, sizeof(OB_DATUM_CAST_MYSQL_ENUMSET_IMPLICIT) / sizeof(void *)); #undef CAST_FAIL #undef EVAL_ARG } // namespace sql } // namespace oceanbase