Files
oceanbase/src/share/object/ob_obj_cast.cpp
2022-02-22 16:04:51 +08:00

11836 lines
445 KiB
C++

/**
* Copyright (c) 2021 OceanBase
* OceanBase CE is licensed under Mulan PubL v2.
* You can use this software according to the terms and conditions of the Mulan PubL v2.
* You may obtain a copy of Mulan PubL v2 at:
* http://license.coscl.org.cn/MulanPubL-2.0
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PubL v2 for more details.
*/
#define USING_LOG_PREFIX COMMON
#include "share/object/ob_obj_cast.h"
#include <math.h>
#include <float.h>
#include "lib/charset/ob_dtoa.h"
#include "lib/string/ob_sql_string.h"
#include "rpc/obmysql/ob_mysql_util.h"
#include "share/ob_worker.h"
#include "share/object/ob_obj_cast_util.h"
#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"
// from sql_parser_base.h
#define DEFAULT_STR_LENGTH -1
namespace oceanbase {
using namespace lib;
using namespace share;
namespace common {
using namespace number;
static const int64_t MAX_DOUBLE_STRICT_PRINT_SIZE = 512;
static int cast_identity(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
UNUSED(expect_type);
UNUSED(params);
UNUSED(cast_mode);
if (&in != &out) {
out = in;
}
return OB_SUCCESS;
}
static int cast_not_support(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
UNUSED(params);
LOG_WARN("not supported obj type convert", K(expect_type), K(in), K(out), K(cast_mode));
return OB_NOT_SUPPORTED;
}
static int cast_not_expected(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
UNUSED(params);
LOG_WARN("not expected obj type convert", K(expect_type), K(in), K(out), K(cast_mode));
return OB_ERR_UNEXPECTED;
}
static int cast_inconsistent_types(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
UNUSED(params);
UNUSED(out);
UNUSED(cast_mode);
LOG_WARN("inconsistent datatypes", "expected", expect_type, "got", in.get_type());
return OB_ERR_INVALID_TYPE_FOR_OP;
}
static int cast_not_support_enum_set(
const ObExpectType& expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out)
{
UNUSED(params);
LOG_WARN("not supported obj type convert", K(expect_type), K(in), K(out));
return OB_NOT_SUPPORTED;
}
static int cast_identity_enum_set(const ObExpectType& expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out)
{
UNUSED(expect_type);
UNUSED(params);
if (&in != &out) {
out = in;
}
return OB_SUCCESS;
}
static int cast_not_expected_enum_set(
const ObExpectType& expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out)
{
UNUSED(params);
LOG_WARN("not expected obj type convert", K(expect_type), K(in), K(out));
return OB_ERR_UNEXPECTED;
}
static int unknown_other(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
return cast_not_support(expect_type, params, in, out, cast_mode);
}
////////////////////////////////////////////////////////////////
// Utility func
// %align_offset is used in mysql mode to align blob to other charset.
static int copy_string(const ObObjCastParams& params, const ObObjType type, const char* str, int64_t len, ObObj& obj,
int64_t align_offset = 0)
{
int ret = OB_SUCCESS;
char* buf = NULL;
if (OB_LIKELY(len > 0 && NULL != str)) {
if (OB_LIKELY(NULL != params.zf_info_) && params.zf_info_->need_zerofill_) {
int64_t str_len = std::max(len, static_cast<int64_t>(params.zf_info_->max_length_));
if (OB_UNLIKELY(NULL == (buf = static_cast<char*>(params.alloc(str_len))))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
} else {
int64_t zf = params.zf_info_->max_length_ - len;
if (zf > 0) {
MEMSET(buf, '0', zf);
MEMCPY(buf + zf, str, len);
len = str_len; // set string length
} else {
MEMCPY(buf, str, len);
}
}
} else {
len += align_offset;
if (OB_UNLIKELY(NULL == (buf = static_cast<char*>(params.alloc(len))))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
} else {
MEMSET(buf, 0, align_offset);
MEMCPY(buf + align_offset, str, len - align_offset);
}
}
}
if (OB_SUCC(ret)) {
if (ob_is_text_tc(type)) {
obj.set_lob_value(type, buf, static_cast<int32_t>(len));
} else if (ob_is_raw(type)) {
obj.set_raw(buf, static_cast<int32_t>(len));
} else {
obj.set_string(type, buf, static_cast<int32_t>(len));
}
}
return ret;
}
static int copy_string(
const ObObjCastParams& params, const ObObjType type, const ObString& str, ObObj& obj, int64_t align_offset = 0)
{
return copy_string(params, type, str.ptr(), str.length(), obj, align_offset);
}
/*
* check err when a string cast to int/uint/double/float according to endptr
*@str input string
*@endptr result pointer to end of converted string
*@len length of str
*@err
* incorrect -> "a232"->int or "a2323.23"->double
* truncated -> "23as" -> int or "as2332.a"->double
* @note
* This is called after one has called strntoull10rnd() or strntod function.
*/
int check_convert_str_err(const char* str, const char* endptr, const int32_t len, const int err)
{
int ret = OB_SUCCESS;
// 1. only one of str and endptr is null, it is invalid input.
if ((OB_ISNULL(str) || OB_ISNULL(endptr)) && str != endptr) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("null pointer(s)", K(ret), KP(str), KP(endptr));
} else if (is_oracle_mode() && 0 != err) {
ret = OB_ERR_CAST_VARCHAR_TO_NUMBER;
} else
// 2. str == endptr include NULL == NULL.
if (OB_UNLIKELY(str == endptr) || OB_UNLIKELY(EDOM == err)) {
ret = OB_ERR_TRUNCATED_WRONG_VALUE_FOR_FIELD; // 1366
} else {
// 3. so here we are sure that both str and endptr are not NULL.
endptr += ObCharset::scan_str(endptr, str + len, OB_SEQ_SPACES);
endptr += ObCharset::scan_str(endptr, str + len, OB_SEQ_INTTAIL);
if (endptr < str + len) {
ret = OB_ERR_DATA_TRUNCATED; // 1265
LOG_DEBUG("check_convert_str_err", K(len), K(str - endptr));
}
}
return ret;
}
static int convert_string_collation(const ObString& in, const ObCollationType in_collation, ObString& out,
const ObCollationType out_collation, ObObjCastParams& params)
{
int ret = OB_SUCCESS;
if (!ObCharset::is_valid_collation(in_collation) || !ObCharset::is_valid_collation(out_collation) ||
ObCharset::charset_type_by_coll(in_collation) == CHARSET_BINARY ||
ObCharset::charset_type_by_coll(out_collation) == CHARSET_BINARY ||
(ObCharset::charset_type_by_coll(in_collation) == ObCharset::charset_type_by_coll(out_collation))) {
out = in;
} else if (in.empty()) {
out.reset();
} else {
char* buf = NULL;
const int32_t CharConvertFactorNum = 4;
int32_t buf_len = in.length() * CharConvertFactorNum;
uint32_t result_len = 0;
if (OB_ISNULL(buf = static_cast<char*>(params.alloc(buf_len)))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_ERROR("alloc memory failed", K(ret));
} else if (OB_FAIL(ObCharset::charset_convert(
in_collation, in.ptr(), in.length(), out_collation, buf, buf_len, result_len))) {
LOG_WARN("charset convert failed", K(ret));
} else {
out.assign_ptr(buf, result_len);
}
}
LOG_DEBUG("convert_string_collation", K(in.length()), K(in_collation), K(out.length()), K(out_collation));
return ret;
}
////////////////////////////////////////////////////////////////
OB_INLINE int get_cast_ret(const ObCastMode cast_mode, int ret, int& warning)
{
// compatibility for old ob
if (OB_UNLIKELY(OB_ERR_UNEXPECTED_TZ_TRANSITION == ret) || OB_UNLIKELY(OB_ERR_UNKNOWN_TIME_ZONE == ret)) {
ret = OB_INVALID_DATE_VALUE;
} else if (OB_SUCCESS != ret &&
// OB_ERR_UNEXPECTED != ret &&
CM_IS_WARN_ON_FAIL(cast_mode)) {
warning = ret;
ret = OB_SUCCESS;
}
return ret;
}
#define CAST_FAIL(stmt) (OB_UNLIKELY((OB_SUCCESS != (ret = get_cast_ret(cast_mode, (stmt), params.warning_)))))
#define CAST_RET(stmt) (ret = get_cast_ret(cast_mode, (stmt), params.warning_))
#define SET_RES_OBJ(res, func_val, obj_type, comma, val, zero_val) \
do { \
if (OB_SUCC(ret)) { \
if (OB_SUCCESS == params.warning_ || OB_ERR_TRUNCATED_WRONG_VALUE == params.warning_ || \
OB_DATA_OUT_OF_RANGE == params.warning_ || OB_ERR_DATA_TRUNCATED == params.warning_ || \
OB_ERR_DOUBLE_TRUNCATED == params.warning_ || OB_ERR_TRUNCATED_WRONG_VALUE_FOR_FIELD == params.warning_) { \
res.set_##func_val(obj_type comma val); \
} else if (CM_IS_ZERO_ON_WARN(cast_mode)) { \
res.set_##func_val(obj_type comma zero_val); \
} else { \
res.set_null(); \
} \
} else { \
res.set_##func_val(obj_type comma val); \
} \
} while (0)
#define COMMA ,
#define SET_RES_INT(res) SET_RES_OBJ(res, int, expect_type, COMMA, value, 0)
#define SET_RES_UINT(res) SET_RES_OBJ(res, uint, expect_type, COMMA, value, 0)
#define SET_RES_FLOAT(res) SET_RES_OBJ(res, float, expect_type, COMMA, value, 0.0)
#define SET_RES_DOUBLE(res) SET_RES_OBJ(res, double, expect_type, COMMA, value, 0.0)
#define SET_RES_NUMBER(res) SET_RES_OBJ(res, number, expect_type, COMMA, value, (value.set_zero(), value))
#define SET_RES_DATETIME(res) SET_RES_OBJ(res, datetime, expect_type, COMMA, value, ObTimeConverter::ZERO_DATETIME)
#define SET_RES_DATE(res) SET_RES_OBJ(res, date, , , value, ObTimeConverter::ZERO_DATE)
#define SET_RES_TIME(res) SET_RES_OBJ(res, time, , , value, ObTimeConverter::ZERO_TIME)
#define SET_RES_YEAR(res) SET_RES_OBJ(res, year, , , value, ObTimeConverter::ZERO_YEAR)
#define SET_RES_BIT(res) SET_RES_OBJ(res, bit, , , value, 0)
#define SET_RES_ENUM(res) SET_RES_OBJ(res, enum, , , value, 0)
#define SET_RES_SET(res) SET_RES_OBJ(res, set, , , value, 0)
#define SET_RES_OTIMESTAMP(res) SET_RES_OBJ(res, otimestamp_value, expect_type, COMMA, value, ObOTimestampData())
#define SET_RES_INTERVAL_YM(res) SET_RES_OBJ(res, interval_ym, , , value, ObIntervalYMValue())
#define SET_RES_INTERVAL_DS(res) SET_RES_OBJ(res, interval_ds, , , value, ObIntervalDSValue())
#define SET_RES_UROWID(res) SET_RES_OBJ(res, urowid, , , value, ObURowIDData());
#define SET_RES_ACCURACY(res_precision, res_scale, res_length) \
if (params.res_accuracy_ != NULL && OB_SUCCESS == ret) { \
params.res_accuracy_->set_scale(res_scale); \
params.res_accuracy_->set_precision(res_precision); \
params.res_accuracy_->set_length(res_length); \
}
#define SET_RES_ACCURACY_STRING(type, res_precision, res_length) \
if (params.res_accuracy_ != NULL && OB_SUCCESS == ret) { \
params.res_accuracy_->set_precision(res_precision); \
params.res_accuracy_->set_length(res_length); \
if (ob_is_text_tc(type)) { \
params.res_accuracy_->set_scale(DEFAULT_SCALE_FOR_TEXT); \
} else { \
params.res_accuracy_->set_scale(DEFAULT_SCALE_FOR_STRING); \
} \
}
////////////////////////////////////////////////////////////////
// range check function templates.
////////////////////////////////////////////////////////////////////////////////////////////////////
ObNumber ObNumberConstValue::MYSQL_MIN[ObNumber::MAX_PRECISION + 1][ObNumber::MAX_SCALE + 1] = {};
ObNumber ObNumberConstValue::MYSQL_MAX[ObNumber::MAX_PRECISION + 1][ObNumber::MAX_SCALE + 1] = {};
ObNumber ObNumberConstValue::MYSQL_CHECK_MIN[ObNumber::MAX_PRECISION + 1][ObNumber::MAX_SCALE + 1] = {};
ObNumber ObNumberConstValue::MYSQL_CHECK_MAX[ObNumber::MAX_PRECISION + 1][ObNumber::MAX_SCALE + 1] = {};
ObNumber ObNumberConstValue::ORACLE_CHECK_MIN[OB_MAX_NUMBER_PRECISION + 1]
[ObNumberConstValue::MAX_ORACLE_SCALE_SIZE + 1] = {};
ObNumber ObNumberConstValue::ORACLE_CHECK_MAX[OB_MAX_NUMBER_PRECISION + 1]
[ObNumberConstValue::MAX_ORACLE_SCALE_SIZE + 1] = {};
int ObNumberConstValue::init(ObIAllocator& allocator, const lib::ObMemAttr& attr)
{
int ret = OB_SUCCESS;
int64_t total_alloc_size = 0;
const int64_t BUFFER_SIZE = 2 * (ObNumber::MAX_SCALE + ObNumber::MAX_PRECISION);
char buf[BUFFER_SIZE];
buf[BUFFER_SIZE - 1] = '\0';
// prepare string like "99.999".
int pos = 0;
buf[pos++] = '-';
{
CompatModeGuard tmp_mode(ObWorker::CompatMode::MYSQL);
for (int16_t precision = OB_MIN_DECIMAL_PRECISION; OB_SUCC(ret) && precision <= ObNumber::MAX_PRECISION;
++precision) {
for (int16_t scale = 0; OB_SUCC(ret) && precision >= scale && scale <= ObNumber::MAX_SCALE; ++scale) {
pos = 1;
MEMSET(buf + pos, 0, BUFFER_SIZE - pos);
if (precision == scale) {
buf[pos++] = '0';
}
MEMSET(buf + pos, '9', precision + 1);
buf[pos + precision + 1] = '5';
buf[pos + precision - scale] = '.';
// make min and max numbers.
ObNumber& min_check_num = MYSQL_CHECK_MIN[precision][scale];
ObNumber& max_check_num = MYSQL_CHECK_MAX[precision][scale];
ObString tmp_string(pos + precision + 1 + 1, buf);
if (OB_FAIL(min_check_num.from(tmp_string.ptr(), tmp_string.length(), allocator, attr))) {
LOG_ERROR("fail to call from", K(precision), K(scale), K(tmp_string), K(pos), K(ret));
} else if (OB_FAIL(max_check_num.from(tmp_string.ptr() + 1, tmp_string.length() - 1, allocator, attr))) {
LOG_ERROR("fail to call from", K(precision), K(scale), K(tmp_string), K(pos), K(ret));
} else {
total_alloc_size += sizeof(uint32_t) * (min_check_num.get_length() + max_check_num.get_length());
LOG_DEBUG("succ to build mysql min max check number",
K(precision),
K(scale),
K(tmp_string),
K(total_alloc_size),
K(min_check_num),
K(max_check_num));
}
if (OB_SUCC(ret)) {
buf[pos + precision + 1] = '0';
// make min and max numbers.
ObNumber& min_num = MYSQL_MIN[precision][scale];
ObNumber& max_num = MYSQL_MAX[precision][scale];
if (OB_FAIL(min_num.from(tmp_string.ptr(), tmp_string.length(), allocator, attr))) {
LOG_ERROR("fail to call from", K(precision), K(scale), K(tmp_string), K(pos), K(ret));
} else if (OB_FAIL(max_num.from(tmp_string.ptr() + 1, tmp_string.length() - 1, allocator, attr))) {
LOG_ERROR("fail to call from", K(precision), K(scale), K(tmp_string), K(pos), K(ret));
} else {
total_alloc_size += sizeof(uint32_t) * (min_num.get_length() + max_num.get_length());
LOG_DEBUG("succ to build mysql min max number",
K(precision),
K(scale),
K(tmp_string),
K(total_alloc_size),
K(min_num),
K(max_num));
}
}
}
}
}
{
CompatModeGuard tmp_mode(ObWorker::CompatMode::ORACLE);
for (int16_t precision = OB_MIN_NUMBER_PRECISION; OB_SUCC(ret) && precision <= OB_MAX_NUMBER_PRECISION;
++precision) {
for (int16_t scale = ObNumber::MIN_SCALE; OB_SUCC(ret) && scale <= ObNumber::MAX_SCALE; ++scale) {
pos = 1;
MEMSET(buf + pos, 0, BUFFER_SIZE - pos);
ObNumber& min_check_num = ORACLE_CHECK_MIN[precision][scale + MAX_ORACLE_SCALE_DELTA];
ObNumber& max_check_num = ORACLE_CHECK_MAX[precision][scale + MAX_ORACLE_SCALE_DELTA];
ObString tmp_string;
if (precision >= scale && scale >= 0) {
/* number(3, 1) => legal range(-99.95, 99.95) */
if (precision == scale) {
buf[pos++] = '0';
}
MEMSET(buf + pos, '9', precision + 1);
buf[pos + precision - scale] = '.';
buf[pos + precision + 1] = '5';
tmp_string.assign_ptr(buf, pos + precision + 1 + 1);
} else if (scale < 0) {
/* number(2, -3) => legal range: (-99500, 99500) */
MEMSET(buf + pos, '9', precision);
buf[pos + precision] = '5';
MEMSET(buf + pos + precision + 1, '0', 0 - scale - 1);
tmp_string.assign_ptr(buf, pos + precision - scale);
} else {
// number(2, 3) => legal range:(-0.0995, 0.0995)
buf[pos++] = '0';
buf[pos++] = '.';
MEMSET(buf + pos, '0', scale - precision);
MEMSET(buf + pos + scale - precision, '9', precision);
buf[pos + scale] = '5';
tmp_string.assign_ptr(buf, pos + scale + 1);
}
// make min and max numbers.
if (OB_FAIL(min_check_num.from(tmp_string.ptr(), tmp_string.length(), allocator, attr))) {
LOG_ERROR("fail to call from", K(precision), K(scale), K(tmp_string), K(ret));
} else if (OB_FAIL(max_check_num.from(tmp_string.ptr() + 1, tmp_string.length() - 1, allocator, attr))) {
LOG_ERROR("fail to call from", K(precision), K(scale), K(tmp_string), K(ret));
} else {
total_alloc_size += sizeof(uint32_t) * (min_check_num.get_length() + max_check_num.get_length());
LOG_DEBUG("succ to build min max number",
K(precision),
K(scale),
K(tmp_string),
K(total_alloc_size),
K(min_check_num),
K(max_check_num));
}
}
}
}
return ret;
}
// Type is float/double
template <typename Type>
int real_range_check_only(const ObAccuracy& accuracy, Type value)
{
int ret = OB_SUCCESS;
const ObPrecision precision = accuracy.get_precision();
const ObScale scale = accuracy.get_scale();
if (OB_LIKELY(precision > 0) && OB_LIKELY(scale >= 0) && OB_LIKELY(precision >= scale)) {
Type integer_part = static_cast<Type>(pow(10.0, static_cast<double>(precision - scale)));
Type decimal_part = static_cast<Type>(pow(10.0, static_cast<double>(scale)));
Type max_value = integer_part - 1 / decimal_part;
Type min_value = -max_value;
if (OB_FAIL(numeric_range_check(value, min_value, max_value, value))) {}
}
return ret;
}
#define BOUND_INFO_START_POS 18
template <typename T>
ObPrecision get_precision_for_integer(T value)
{
static const uint64_t bound_info[] = {
INT64_MAX + 1ULL,
999999999999999999ULL,
99999999999999999ULL,
9999999999999999ULL,
999999999999999ULL,
99999999999999ULL,
9999999999999ULL,
999999999999ULL,
99999999999ULL,
9999999999ULL,
999999999ULL,
99999999ULL,
9999999ULL,
999999ULL,
99999ULL,
9999ULL,
999ULL,
99ULL,
9ULL,
99ULL,
999ULL,
9999ULL,
99999ULL,
999999ULL,
9999999ULL,
99999999ULL,
999999999ULL,
9999999999ULL,
99999999999ULL,
999999999999ULL,
9999999999999ULL,
99999999999999ULL,
999999999999999ULL,
9999999999999999ULL,
99999999999999999ULL,
999999999999999999ULL,
9999999999999999999ULL,
UINT64_MAX,
};
int64_t flag = std::less<T>()(value, 0) ? -1 : 1;
uint64_t abs_value = value * flag;
const uint64_t* iter = bound_info + BOUND_INFO_START_POS;
while (abs_value > *iter) {
iter += flag;
}
// *(iter - 1) < abs <= *iter
return static_cast<ObPrecision>((iter - (bound_info + BOUND_INFO_START_POS)) * flag + 1);
}
int ObHexUtils::unhex(const ObString& text, ObCastCtx& cast_ctx, ObObj& result)
{
int ret = OB_SUCCESS;
ObString str_result;
char* buf = NULL;
const bool need_fill_zero = (1 == text.length() % 2);
const int32_t tmp_length = text.length() / 2 + need_fill_zero;
int32_t alloc_length = (0 == tmp_length ? 1 : tmp_length);
if (OB_ISNULL(cast_ctx.allocator_v2_)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("allocator in cast ctx is NULL", K(ret), K(text));
} else if (OB_ISNULL(buf = static_cast<char*>(cast_ctx.allocator_v2_->alloc(alloc_length)))) {
result.set_null();
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_ERROR("alloc memory failed", K(alloc_length), K(ret));
} else {
int32_t i = 0;
char c1 = 0;
char c2 = 0;
if (text.length() > 0) {
if (need_fill_zero) {
c1 = '0';
c2 = text[0];
i = 0;
} else {
c1 = text[0];
c2 = text[1];
i = 1;
}
}
while (OB_SUCC(ret) && i < text.length()) {
if (isxdigit(c1) && isxdigit(c2)) {
buf[i / 2] = (char)((get_xdigit(c1) << 4) | get_xdigit(c2));
c1 = text[++i];
c2 = text[++i];
} else {
ret = OB_ERR_INVALID_HEX_NUMBER;
LOG_WARN("invalid hex number", K(ret), K(c1), K(c2), K(text));
}
}
if (OB_SUCC(ret)) {
str_result.assign_ptr(buf, tmp_length);
result.set_varchar(str_result);
}
}
return ret;
}
int ObHexUtils::hex(const ObString& text, ObCastCtx& cast_ctx, ObObj& result)
{
int ret = OB_SUCCESS;
ObString str_result;
char* buf = NULL;
const int32_t alloc_length = text.empty() ? 1 : text.length() * 2;
if (OB_ISNULL(cast_ctx.allocator_v2_)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("allocator in cast ctx is NULL", K(ret), K(text));
} else if (OB_ISNULL(buf = static_cast<char*>(cast_ctx.allocator_v2_->alloc(alloc_length)))) {
result.set_null();
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_ERROR("alloc memory failed", K(ret), K(alloc_length));
} else {
static const char* HEXCHARS = "0123456789ABCDEF";
int32_t pos = 0;
for (int32_t i = 0; i < text.length(); ++i) {
buf[pos++] = HEXCHARS[text[i] >> 4 & 0xF];
buf[pos++] = HEXCHARS[text[i] & 0xF];
}
str_result.assign_ptr(buf, pos);
result.set_varchar(str_result);
LOG_DEBUG("succ to hex", K(text), "length", text.length(), K(str_result));
}
return ret;
}
int ObHexUtils::hex_for_mysql(const uint64_t uint_val, common::ObCastCtx& cast_ctx, common::ObObj& result)
{
int ret = OB_SUCCESS;
char* buf = NULL;
const int32_t MAX_INT64_LEN = 20;
if (OB_ISNULL(cast_ctx.allocator_v2_)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("allocator in cast ctx is NULL", K(ret), K(uint_val));
} else if (OB_ISNULL(buf = static_cast<char*>(cast_ctx.allocator_v2_->alloc(MAX_INT64_LEN)))) {
result.set_null();
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_ERROR("alloc memory failed", K(ret));
} else {
int pos = snprintf(buf, MAX_INT64_LEN, "%lX", uint_val);
if (OB_UNLIKELY(pos <= 0) || OB_UNLIKELY(pos >= MAX_INT64_LEN)) {
ret = OB_SIZE_OVERFLOW;
LOG_ERROR("size is overflow", K(ret), K(uint_val));
} else {
ObString str_result(pos, buf);
result.set_varchar(str_result);
}
}
return ret;
}
// https://docs.oracle.com/en/database/oracle/oracle-database/12.2/sqlrf/RAWTOHEX.html
// As a SQL built-in function, RAWTOHEX accepts an argument of any scalar data type other than LONG,
// LONG RAW, CLOB, NCLOB, BLOB, or BFILE. If the argument is of a data type other than RAW,
// then this function converts the argument value, which is represented using some number of data bytes,
// into a RAW value with the same number of data bytes. The data itself is not modified in any way,
// but the data type is recast to a RAW data type.
int ObHexUtils::rawtohex(const ObObj& text, ObCastCtx& cast_ctx, ObObj& result)
{
int ret = OB_SUCCESS;
if (text.is_null()) {
result.set_null();
} else {
ObString str;
ObObj num_obj;
char* splice_num_str = NULL; // for splice Desc and degits_ of number.
ObOTimestampData time_value;
switch (text.get_type()) {
// TODO::this should same as oracle, and support dump func
case ObTinyIntType:
case ObSmallIntType:
case ObInt32Type:
case ObIntType: {
int64_t int_value = text.get_int();
number::ObNumber nmb;
if (OB_FAIL(nmb.from(int_value, cast_ctx))) {
LOG_WARN("fail to int_number", K(ret), K(int_value), "type", text.get_type());
} else {
num_obj.set_number(ObNumberType, nmb);
int32_t alloc_len =
static_cast<int32_t>(sizeof(num_obj.get_number_desc()) + num_obj.get_number_byte_length());
if (OB_ISNULL(cast_ctx.allocator_v2_)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("allocator in cast ctx is NULL", K(ret));
} else if (OB_ISNULL(splice_num_str = static_cast<char*>(cast_ctx.allocator_v2_->alloc(alloc_len)))) {
result.set_null();
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_ERROR("alloc memory failed", K(ret), K(alloc_len));
} else {
MEMCPY(splice_num_str, &(num_obj.get_number_desc()), sizeof(num_obj.get_number_desc()));
MEMCPY(splice_num_str + sizeof(num_obj.get_number_desc()),
num_obj.get_data_ptr(),
num_obj.get_number_byte_length());
str.assign_ptr(static_cast<const char*>(splice_num_str), alloc_len);
}
LOG_DEBUG("succ to int_number", K(ret), K(int_value), "type", num_obj.get_type(), K(nmb), K(str));
}
break;
}
case ObNumberFloatType:
case ObNumberType: {
int32_t alloc_len = static_cast<int32_t>(sizeof(text.get_number_desc()) + text.get_number_byte_length());
if (OB_ISNULL(cast_ctx.allocator_v2_)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("allocator in cast ctx is NULL", K(ret));
} else if (OB_ISNULL(splice_num_str = static_cast<char*>(cast_ctx.allocator_v2_->alloc(alloc_len)))) {
result.set_null();
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_ERROR("alloc memory failed", K(ret), K(alloc_len));
} else {
MEMCPY(splice_num_str, &(text.get_number_desc()), sizeof(text.get_number_desc()));
MEMCPY(splice_num_str + sizeof(text.get_number_desc()), text.get_data_ptr(), text.get_number_byte_length());
str.assign_ptr(static_cast<const char*>(splice_num_str), alloc_len);
}
break;
}
case ObDateTimeType: {
str.assign_ptr(static_cast<const char*>(text.get_data_ptr()), static_cast<int32_t>(sizeof(int64_t)));
break;
}
case ObNVarchar2Type:
case ObNCharType:
case ObVarcharType:
case ObCharType:
case ObLongTextType:
case ObRawType:
case ObJsonType: {
// https://www.techonthenet.com/oracle/functions/rawtohex.php
// NOTE:: when convert string to raw, Oracle use utl_raw.cast_to_raw(), while PL/SQL use hextoraw()
// here we use utl_raw.cast_to_raw(), as we can not distinguish in which SQL
str = text.get_varbinary();
break;
}
case ObTimestampTZType:
case ObTimestampLTZType:
case ObTimestampNanoType: {
time_value = text.get_otimestamp_value();
str.assign_ptr(reinterpret_cast<char*>(&time_value), static_cast<int32_t>(text.get_otimestamp_store_size()));
break;
}
case ObLobType: {
const ObLobLocator* lob_locator = text.get_lob_locator();
if (OB_ISNULL(lob_locator)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("lob_locator is null", K(ret));
} else if (OB_FAIL(lob_locator->get_payload(str))) {
LOG_WARN("get payload from lob_locator failed", K(ret), K(*lob_locator));
}
break;
}
default: {
ret = OB_ERR_INVALID_HEX_NUMBER;
LOG_WARN("invalid hex number", K(ret), K(text), "type", text.get_type());
}
}
if (OB_SUCC(ret)) {
if (OB_FAIL(hex(str, cast_ctx, result))) {
LOG_WARN("fail to convert to hex", K(ret), K(str));
} else {
result.set_default_collation_type();
}
}
}
LOG_DEBUG("succ to rawtohex", "type", text.get_type(), K(text), K(result), K(lbt()));
return ret;
}
int ObHexUtils::hextoraw(const ObObj& text, ObCastCtx& cast_ctx, ObObj& result)
{
int ret = OB_SUCCESS;
if (text.is_null()) {
result.set_null();
} else if (text.is_numeric_type()) {
number::ObNumber nmb_val;
if (OB_FAIL(get_uint(text, cast_ctx, nmb_val))) {
LOG_WARN("fail to get uint64", K(ret), K(text));
} else if (OB_FAIL(uint_to_raw(nmb_val, cast_ctx, result))) {
LOG_WARN("fail to convert to hex", K(ret), K(nmb_val));
}
} else if (text.is_raw()) {
// fast path
if (OB_FAIL(copy_raw(text, cast_ctx, result))) {
LOG_WARN("fail to convert to hex", K(ret), K(text));
}
} else if (text.is_character_type() || text.is_varbinary_or_binary()) {
ObString utf8_string;
if (OB_FAIL(convert_string_collation(
text.get_string(), text.get_collation_type(), utf8_string, ObCharset::get_system_collation(), cast_ctx))) {
LOG_WARN("convert_string_collation", K(ret));
} else if (OB_FAIL(unhex(utf8_string, cast_ctx, result))) {
LOG_WARN("fail to convert to hex", K(ret), K(text));
} else {
result.set_raw(result.get_raw());
}
} else {
ret = OB_ERR_INVALID_HEX_NUMBER;
LOG_WARN("invalid hex number", K(ret), K(text));
}
LOG_DEBUG("succ to hextoraw", "type", text.get_type(), K(text), K(result.get_raw()), K(result), K(lbt()));
return ret;
}
int ObHexUtils::get_uint(const ObObj& obj, ObCastCtx& cast_ctx, number::ObNumber& out)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(!ob_is_accurate_numeric_type(obj.get_type()))) {
ret = OB_ERR_INVALID_HEX_NUMBER;
LOG_WARN("invalid hex number", K(ret), K(obj));
} else if (obj.is_number() || obj.is_unumber()) {
const number::ObNumber& value = obj.get_number();
if (OB_FAIL(out.from(value, cast_ctx))) {
LOG_WARN("deep copy failed", K(ret), K(obj));
} else if (OB_UNLIKELY(!out.is_integer()) || OB_UNLIKELY(out.is_negative())) {
ret = OB_ERR_INVALID_HEX_NUMBER;
LOG_WARN("invalid hex number", K(ret), K(out));
} else if (OB_FAIL(out.round(0))) {
LOG_WARN("round failed", K(ret), K(out));
}
} else {
if (OB_UNLIKELY(obj.get_int() < 0)) {
ret = OB_ERR_INVALID_HEX_NUMBER;
LOG_WARN("invalid hex number", K(ret), K(obj));
} else if (OB_FAIL(out.from(obj.get_int(), cast_ctx))) {
LOG_WARN("deep copy failed", K(ret), K(obj));
}
}
return ret;
}
int ObHexUtils::uint_to_raw(const number::ObNumber& uint_num, ObCastCtx& cast_ctx, ObObj& result)
{
int ret = OB_SUCCESS;
const int64_t oracle_max_avail_len = 40;
char uint_buf[number::ObNumber::MAX_TOTAL_SCALE] = {0};
int64_t uint_pos = 0;
ObString uint_str;
if (OB_FAIL(uint_num.format(uint_buf, number::ObNumber::MAX_TOTAL_SCALE, uint_pos, 0))) {
LOG_WARN("fail to format ", K(ret), K(uint_num));
} else if (uint_pos > oracle_max_avail_len) {
ret = OB_ERR_INVALID_HEX_NUMBER;
LOG_WARN("invalid hex number", K(ret), K(uint_pos), K(oracle_max_avail_len), K(uint_num));
} else {
uint_str.assign_ptr(uint_buf, static_cast<int32_t>(uint_pos));
if (OB_FAIL(unhex(uint_str, cast_ctx, result))) {
LOG_WARN("fail to str_to_raw", K(ret), K(result));
} else {
result.set_raw(result.get_raw());
}
}
return ret;
}
int ObHexUtils::copy_raw(const common::ObObj& obj, common::ObCastCtx& cast_ctx, common::ObObj& result)
{
int ret = OB_SUCCESS;
char* buf = NULL;
const ObString& value = obj.get_raw();
const int32_t alloc_length = value.empty() ? 1 : value.length();
if (OB_ISNULL(cast_ctx.allocator_v2_)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("allocator in cast ctx is NULL", K(ret));
} else if (OB_ISNULL(buf = static_cast<char*>(cast_ctx.allocator_v2_->alloc(alloc_length)))) {
result.set_null();
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_ERROR("alloc memory failed", K(ret), K(alloc_length));
} else {
MEMCPY(buf, value.ptr(), value.length());
result.set_raw(buf, value.length());
}
return ret;
}
static int check_convert_string(const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out)
{
int ret = OB_SUCCESS;
// UNUSED(expect_type);
// UNUSED(params);
// if (lib::is_oracle_mode()) {
// //varchar2 --> raw
// if (in.is_varchar_or_char() && ob_is_varbinary_type(expect_type, params.expect_obj_collation_)) {
// if (OB_FAIL(ObHexUtils::hextoraw(in, params, out))) {
// LOG_WARN("fail to hextoraw", K(ret), K(in));
// }
// //raw --> varchar2
// } else if (in.is_varbinary() && ob_is_varchar_char_type(expect_type, params.expect_obj_collation_)) {
// if (OB_FAIL(ObHexUtils::rawtohex(in, params, out))) {
// LOG_WARN("fail to rawtohex", K(ret), K(in));
// }
// } else {
// //TODO::for lob, for long raw ,
// out = in;
// LOG_DEBUG("do nothing");
// }
// LOG_DEBUG("finish check_convert_string", K(ret), "in_type", in.get_type(), "in_cs_type",
// in.get_collation_type(), K(in), K(expect_type), "expect_cs_type", params.dest_collation_, K(out));
if (lib::is_oracle_mode() && ob_is_blob(expect_type, params.expect_obj_collation_) && !in.is_blob() && !in.is_raw()) {
if (in.is_varchar_or_char()) {
if (OB_FAIL(ObHexUtils::hextoraw(in, params, out))) {
LOG_WARN("fail to hextoraw for blob", K(ret), K(in));
}
} else {
ret = OB_NOT_SUPPORTED;
LOG_ERROR("invalid use of blob type", K(ret), K(in), K(expect_type));
LOG_USER_ERROR(OB_NOT_SUPPORTED, "Cast to blob type");
}
} else {
out = in;
}
return ret;
}
static int check_convert_string(
const ObObjType expect_type, ObObjCastParams& params, const ObString& in_string, ObObj& out)
{
ObObj tmp_obj;
tmp_obj.set_varchar(in_string);
return check_convert_string(expect_type, params, tmp_obj, out);
}
static int check_convert_string(
const ObObjType expect_type, ObObjCastParams& params, const char* in_str, const int64_t len, ObObj& out)
{
ObObj tmp_obj;
tmp_obj.set_varchar(in_str, static_cast<ObString::obstr_size_t>(len));
return check_convert_string(expect_type, params, tmp_obj, out);
}
////////////////////////////////////////////////////////////////
// Int -> XXX
static const double ROUND_DOUBLE = 0.5;
static int int_int(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
ObPrecision res_precision = -1;
if (OB_UNLIKELY(ObIntTC != in.get_type_class() || ObIntTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else {
int64_t value = in.get_int();
if (in.get_type() > expect_type && CAST_FAIL(int_range_check(expect_type, value, value))) {
} else {
out.set_int(expect_type, value);
res_precision = get_precision_for_integer(value);
}
}
SET_RES_ACCURACY(res_precision, DEFAULT_SCALE_FOR_INTEGER, DEFAULT_LENGTH_FOR_NUMERIC);
return ret;
}
static int int_uint(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
ObPrecision res_precision = -1;
if (OB_UNLIKELY(ObIntTC != in.get_type_class() || ObUIntTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (CM_SKIP_CAST_INT_UINT(cast_mode)) {
out = in;
res_precision = get_precision_for_integer(out.get_uint64());
} else {
uint64_t value = static_cast<uint64_t>(in.get_int());
if (CM_NEED_RANGE_CHECK(cast_mode) && CAST_FAIL(uint_range_check(expect_type, in.get_int(), value))) {
} else {
out.set_uint(expect_type, value);
res_precision = get_precision_for_integer(out.get_uint64());
}
}
SET_RES_ACCURACY(res_precision, DEFAULT_SCALE_FOR_INTEGER, DEFAULT_LENGTH_FOR_NUMERIC);
return ret;
}
static int int_float(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(ObIntTC != in.get_type_class() || ObFloatTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else {
double value = static_cast<double>(in.get_int());
if (ObUFloatType == expect_type && CAST_FAIL(numeric_negative_check(value))) {
} else {
out.set_float(expect_type, static_cast<float>(value));
}
}
SET_RES_ACCURACY(PRECISION_UNKNOWN_YET, SCALE_UNKNOWN_YET, LENGTH_UNKNOWN_YET);
return ret;
}
static int int_double(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(ObIntTC != in.get_type_class() || ObDoubleTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else {
double value = static_cast<double>(in.get_int());
if (ObUDoubleType == expect_type && CAST_FAIL(numeric_negative_check(value))) {
} else {
out.set_double(expect_type, value);
}
}
SET_RES_ACCURACY(PRECISION_UNKNOWN_YET, SCALE_UNKNOWN_YET, LENGTH_UNKNOWN_YET);
return ret;
}
static int int_number(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
ObPrecision res_precision = -1;
if (OB_UNLIKELY(ObIntTC != in.get_type_class() || ObNumberTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else {
int64_t value = in.get_int();
number::ObNumber nmb;
if (ObUNumberType == expect_type && CAST_FAIL(numeric_negative_check(value))) {
} else if (OB_FAIL(nmb.from(value, params))) {
} else {
out.set_number(expect_type, nmb);
res_precision = get_precision_for_integer(in.get_int());
}
}
SET_RES_ACCURACY(res_precision, DEFAULT_SCALE_FOR_INTEGER, DEFAULT_LENGTH_FOR_NUMERIC);
return ret;
}
static int int_datetime(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(ObIntTC != in.get_type_class() || ObDateTimeTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else {
ObTimeConvertCtx cvrt_ctx(params.dtc_params_.tz_info_, ObTimestampType == expect_type);
int64_t value = 0;
if (in.get_int() < 0) {
ret = OB_INVALID_DATE_FORMAT;
} else {
ret = ObTimeConverter::int_to_datetime(in.get_int(), 0, cvrt_ctx, value);
}
if (CAST_FAIL(ret)) {
} else {
SET_RES_DATETIME(out);
}
}
SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, MIN_SCALE_FOR_TEMPORAL, DEFAULT_LENGTH_FOR_TEMPORAL);
return ret;
}
static int int_datetime_interval(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(ObIntTC != in.get_type_class()) || OB_UNLIKELY(ObDateTimeTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else {
// oracle treate int as day
int64_t value = in.get_int() * USECS_PER_DAY;
SET_RES_DATETIME(out);
LOG_DEBUG("succ to int_datetime_interval", K(ret), K(in), K(value), K(expect_type));
}
SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, MIN_SCALE_FOR_TEMPORAL, DEFAULT_LENGTH_FOR_TEMPORAL);
return ret;
}
static int int_date(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(ObIntTC != in.get_type_class() || ObDateTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else {
int32_t value = 0;
if (CAST_FAIL(ObTimeConverter::int_to_date(in.get_int(), value))) {
} else {
SET_RES_DATE(out);
}
}
SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, DEFAULT_SCALE_FOR_DATE, DEFAULT_LENGTH_FOR_TEMPORAL);
return ret;
}
static int int_time(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(ObIntTC != in.get_type_class() || ObTimeTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else {
int64_t value = 0;
if (CAST_FAIL(ObTimeConverter::int_to_time(in.get_int(), value))) {
} else {
SET_RES_TIME(out);
}
}
SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, MIN_SCALE_FOR_TEMPORAL, DEFAULT_LENGTH_FOR_TEMPORAL);
return ret;
}
static int int_year(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(ObIntTC != in.get_type_class() || ObYearTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else {
uint8_t value = 0;
if (CAST_FAIL(ObTimeConverter::int_to_year(in.get_int(), value))) {
} else {
SET_RES_YEAR(out);
}
}
SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, DEFAULT_SCALE_FOR_YEAR, DEFAULT_LENGTH_FOR_TEMPORAL);
return ret;
}
static int int_string(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
ObLength res_length = -1;
if (OB_UNLIKELY(ObIntTC != in.get_type_class() ||
(ObStringTC != ob_obj_type_class(expect_type) && ObTextTC != ob_obj_type_class(expect_type)))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else {
ObObj tmp_out;
ObFastFormatInt ffi(in.get_int());
ObString tmp_str;
if (OB_FAIL(convert_string_collation(ObString(ffi.length(), ffi.ptr()),
ObCharset::get_system_collation(),
tmp_str,
params.dest_collation_,
params))) {
LOG_WARN("fail to convert string collation", K(ret));
} else if (OB_FAIL(check_convert_string(expect_type, params, tmp_str.ptr(), tmp_str.length(), tmp_out))) {
LOG_WARN("fail to check_convert_string", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(copy_string(params, expect_type, tmp_out.get_string(), out))) {
} else {
res_length = static_cast<ObLength>(out.get_string_len());
}
}
SET_RES_ACCURACY_STRING(expect_type, DEFAULT_PRECISION_FOR_STRING, res_length);
UNUSED(cast_mode);
return ret;
}
static int int_bit(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
UNUSED(cast_mode);
int ret = OB_SUCCESS;
uint64_t value = static_cast<uint64_t>(in.get_int());
int32_t bit_len = 0;
if (OB_UNLIKELY(ObIntTC != in.get_type_class() || ObBitTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(get_bit_len(value, bit_len))) {
LOG_WARN("fail to get bit len", K(ret), K(value), K(bit_len));
} else {
SET_RES_BIT(out);
SET_RES_ACCURACY(static_cast<ObPrecision>(bit_len), DEFAULT_SCALE_FOR_BIT, DEFAULT_LENGTH_FOR_NUMERIC);
}
return ret;
}
static int uint_enum(const ObExpectType& expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out);
static int int_enum(const ObExpectType& expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(ObEnumType != expect_type.get_type()) || OB_UNLIKELY(ObIntTC != in.get_type_class())) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument", K(expect_type), K(in), K(ret));
} else {
uint64_t value = static_cast<uint64_t>(in.get_int());
ObObj uint_val;
uint_val.set_uint64(value);
if (OB_FAIL(uint_enum(expect_type, params, uint_val, out))) {
LOG_WARN("fail to cast uint to enum", K(expect_type), K(in), K(uint_val), K(out), K(ret));
}
}
return ret;
}
static int uint_set(const ObExpectType& expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out);
static int int_set(const ObExpectType& expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(ObSetType != expect_type.get_type()) || OB_UNLIKELY(ObIntTC != in.get_type_class())) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument", K(expect_type), K(in), K(ret));
} else {
uint64_t value = static_cast<uint64_t>(in.get_int());
ObObj uint_val;
uint_val.set_uint64(value);
if (OB_FAIL(uint_set(expect_type, params, uint_val, out))) {
LOG_WARN("fail to cast uint to enum", K(expect_type), K(in), K(uint_val), K(out), K(ret));
}
}
return ret;
}
static int string_lob(const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out,
const ObCastMode cast_mode, const ObLobLocator* lob_locator);
static int string_lob(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
return string_lob(expect_type, params, in, out, cast_mode, NULL);
}
#define CAST_TO_LOB_METHOD(TYPE, TYPE_CLASS) \
static int TYPE##_lob( \
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) \
{ \
int ret = OB_SUCCESS; \
ObObj tmp_val; \
if (OB_UNLIKELY(TYPE_CLASS != in.get_type_class() || ObLobTC != ob_obj_type_class(expect_type))) { \
ret = OB_ERR_UNEXPECTED; \
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); \
} else if (OB_FAIL(TYPE##_string(ObLongTextType, params, in, tmp_val, cast_mode))) { \
LOG_WARN("fail to cast" #TYPE "to string", K(ret), K(expect_type), K(in), K(tmp_val)); \
} else if (OB_FAIL(string_lob(expect_type, params, tmp_val, out, cast_mode))) { \
LOG_WARN("fail to cast string to lob", K(ret), K(expect_type), K(in), K(tmp_val)); \
} \
return ret; \
}
CAST_TO_LOB_METHOD(int, ObIntTC);
static int int_json(const ObObjType expect_type, ObObjCastParams &params,
const ObObj &in, ObObj &out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
ObLength res_length = -1;
if (CM_IS_COLUMN_CONVERT(cast_mode) && is_mysql_unsupported_json_column_conversion(in.get_type())) {
ret = OB_ERR_INVALID_JSON_TEXT;
LOG_USER_ERROR(OB_ERR_INVALID_JSON_TEXT);
} else if (OB_UNLIKELY(ObIntTC != in.get_type_class() || (ObJsonType != expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_UNLIKELY(params.allocator_v2_ == NULL)) {
ret= OB_ERR_UNEXPECTED;
LOG_ERROR("NULL allocator in json cast function", K(ret), K(in), K(expect_type));
} else {
ObJsonInt j_int(in.get_int());
bool bool_val = (in.get_int() == 1) ? true : false;
ObJsonBoolean j_bool(bool_val);
ObIJsonBase *j_base = &j_int;
if (CM_HAS_BOOLEAN_FLAG(cast_mode)) {
j_base = &j_bool;
}
ObString raw_bin;
if (OB_FAIL(j_base->get_raw_binary(raw_bin, params.allocator_v2_))) {
LOG_WARN("fail to get int json binary", K(ret), K(in), K(expect_type), K(*j_base));
} else {
out.set_json_value(expect_type, raw_bin.ptr(), raw_bin.length());
res_length = static_cast<ObLength>(raw_bin.length());
}
}
SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_STRING, DEFAULT_SCALE_FOR_TEXT, res_length)
return ret;
}
////////////////////////////////////////////////////////////////
// UInt -> XXX
static int uint_int(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
ObPrecision res_precision = -1;
if (OB_UNLIKELY(ObUIntTC != in.get_type_class() || ObIntTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (CM_IS_EXTERNAL_CALL(cast_mode) && CM_SKIP_CAST_INT_UINT(cast_mode)) {
out = in;
res_precision = get_precision_for_integer(out.get_int());
} else {
int64_t value = static_cast<int64_t>(in.get_uint64());
if (CM_NEED_RANGE_CHECK(cast_mode) && CAST_FAIL(int_upper_check(expect_type, in.get_uint64(), value))) {
} else {
out.set_int(expect_type, value);
res_precision = get_precision_for_integer(value);
}
}
SET_RES_ACCURACY(res_precision, DEFAULT_SCALE_FOR_INTEGER, DEFAULT_LENGTH_FOR_NUMERIC);
return ret;
}
static int uint_uint(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
ObPrecision res_precision = -1;
if (OB_UNLIKELY(ObUIntTC != in.get_type_class() || ObUIntTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else {
uint64_t value = in.get_uint64();
if (in.get_type() > expect_type && CAST_FAIL(uint_upper_check(expect_type, value))) {
} else {
out.set_uint(expect_type, value);
res_precision = get_precision_for_integer(value);
}
}
SET_RES_ACCURACY(res_precision, DEFAULT_SCALE_FOR_INTEGER, DEFAULT_LENGTH_FOR_NUMERIC);
return ret;
}
static int uint_float(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(ObUIntTC != in.get_type_class() || ObFloatTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else {
// for compatibility with mysql, we cast uint to double first, then to float.
double value = static_cast<double>(in.get_uint64());
out.set_float(expect_type, static_cast<float>(value));
}
UNUSED(cast_mode);
SET_RES_ACCURACY(PRECISION_UNKNOWN_YET, SCALE_UNKNOWN_YET, LENGTH_UNKNOWN_YET);
return ret;
}
static int uint_double(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(ObUIntTC != in.get_type_class() || ObDoubleTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else {
out.set_double(expect_type, static_cast<double>(in.get_uint64()));
}
UNUSED(cast_mode);
SET_RES_ACCURACY(PRECISION_UNKNOWN_YET, SCALE_UNKNOWN_YET, LENGTH_UNKNOWN_YET);
return ret;
}
static int uint_number(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
number::ObNumber nmb;
ObPrecision res_precision = -1;
if (OB_UNLIKELY(ObUIntTC != in.get_type_class() || ObNumberTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(nmb.from(in.get_uint64(), params))) {
} else {
out.set_number(expect_type, nmb);
res_precision = get_precision_for_integer(in.get_uint64());
}
UNUSED(cast_mode);
SET_RES_ACCURACY(res_precision, DEFAULT_SCALE_FOR_INTEGER, DEFAULT_LENGTH_FOR_NUMERIC);
return ret;
}
static int uint_datetime(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
ObObj int64;
if (OB_UNLIKELY(ObUIntTC != in.get_type_class() || ObDateTimeTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(uint_int(ObIntType, params, in, int64, CM_UNSET_NO_CAST_INT_UINT(cast_mode)))) {
} else if (OB_FAIL(int_datetime(expect_type, params, int64, out, cast_mode))) {
}
// has set the accuracy in prev int_datetime call
return ret;
}
static int uint_date(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
ObObj int64;
if (OB_UNLIKELY(ObUIntTC != in.get_type_class() || ObDateTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(uint_int(ObIntType, params, in, int64, CM_UNSET_NO_CAST_INT_UINT(cast_mode)))) {
} else if (OB_FAIL(int_date(expect_type, params, int64, out, cast_mode))) {
}
SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, DEFAULT_SCALE_FOR_DATE, DEFAULT_LENGTH_FOR_TEMPORAL);
return ret;
}
static int uint_time(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
ObObj int64;
if (OB_UNLIKELY(ObUIntTC != in.get_type_class() || ObTimeTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(uint_int(ObIntType, params, in, int64, CM_UNSET_NO_CAST_INT_UINT(cast_mode)))) {
} else if (OB_FAIL(int_time(expect_type, params, int64, out, cast_mode))) {
}
// accuracy has been set in prev int_time call
return ret;
}
static int uint_year(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
ObObj int64;
if (OB_UNLIKELY(ObUIntTC != in.get_type_class() || ObYearTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(uint_int(ObIntType, params, in, int64, CM_UNSET_NO_CAST_INT_UINT(cast_mode)))) {
} else if (OB_FAIL(int_year(expect_type, params, int64, out, cast_mode))) {
}
SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, DEFAULT_SCALE_FOR_YEAR, DEFAULT_LENGTH_FOR_TEMPORAL);
return ret;
}
static int uint_string(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
ObLength res_length = -1;
if (OB_UNLIKELY(ObUIntTC != in.get_type_class() ||
(ObStringTC != ob_obj_type_class(expect_type) && ObTextTC != ob_obj_type_class(expect_type)))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else {
ObObj tmp_out;
ObFastFormatInt ffi(in.get_uint64());
ObString tmp_str;
if (OB_FAIL(convert_string_collation(ObString(ffi.length(), ffi.ptr()),
ObCharset::get_system_collation(),
tmp_str,
params.dest_collation_,
params))) {
LOG_WARN("fail to convert string collation", K(ret));
} else if (OB_FAIL(check_convert_string(expect_type, params, tmp_str.ptr(), tmp_str.length(), tmp_out))) {
LOG_WARN("fail to check_convert_string", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(copy_string(params, expect_type, tmp_out.get_string(), out))) {
} else {
res_length = static_cast<ObLength>(out.get_string_len());
}
}
UNUSED(cast_mode);
SET_RES_ACCURACY_STRING(expect_type, DEFAULT_PRECISION_FOR_STRING, res_length);
return ret;
}
static int uint_bit(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
UNUSED(cast_mode);
int ret = OB_SUCCESS;
uint64_t value = in.get_uint64();
int32_t bit_len = 0;
if (OB_UNLIKELY(ObUIntTC != in.get_type_class() || ObBitTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(get_bit_len(value, bit_len))) {
LOG_WARN("fail to get bit len", K(ret), K(value), K(bit_len));
} else {
SET_RES_BIT(out);
SET_RES_ACCURACY(static_cast<ObPrecision>(bit_len), DEFAULT_SCALE_FOR_BIT, DEFAULT_LENGTH_FOR_NUMERIC);
}
return ret;
}
static int uint_enum(const ObExpectType& expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out)
{
int ret = OB_SUCCESS;
ObCastMode cast_mode = params.cast_mode_;
const ObIArray<ObString>* type_infos = NULL;
if (OB_UNLIKELY(ObEnumType != expect_type.get_type()) || OB_UNLIKELY(ObUIntTC != in.get_type_class()) ||
OB_ISNULL(type_infos = expect_type.get_type_infos())) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument", K(expect_type), K(in), K(ret));
} else {
uint64_t value = in.get_uint64();
if (OB_UNLIKELY(0 == value || value > type_infos->count())) {
value = 0;
ret = OB_ERR_DATA_TRUNCATED;
LOG_WARN("input value out of range", K(in), K(expect_type), K(ret));
}
if (OB_FAIL(ret) && CM_IS_WARN_ON_FAIL(cast_mode)) {
params.warning_ = OB_ERR_DATA_TRUNCATED;
ret = OB_SUCCESS;
}
LOG_DEBUG("finish uint_enum", K(ret), K(expect_type), K(in), K(out), KPC(type_infos), K(lbt()));
SET_RES_ENUM(out);
}
return ret;
}
static int uint_set(const ObExpectType& expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out)
{
int ret = OB_SUCCESS;
ObCastMode cast_mode = params.cast_mode_;
const ObIArray<ObString>* type_infos = NULL;
int64_t val_cnt = 0;
if (OB_UNLIKELY(ObSetType != expect_type.get_type()) || OB_UNLIKELY(ObUIntTC != in.get_type_class()) ||
OB_ISNULL(type_infos = expect_type.get_type_infos())) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument", K(expect_type), K(in), K(ret));
} else {
uint64_t value = in.get_uint64();
val_cnt = type_infos->count();
if (OB_UNLIKELY(val_cnt <= 0)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpect val_cnt", K(in), K(out), K(expect_type), K(ret));
} else if (val_cnt >= 64) { // do nothing
} else if (val_cnt < 64 && value > ((1ULL << val_cnt) - 1)) {
value = value & ((1ULL << val_cnt) - 1);
ret = OB_ERR_DATA_TRUNCATED;
LOG_WARN("input value out of range", K(in), K(val_cnt), K(ret));
}
if (OB_FAIL(ret) && CM_IS_WARN_ON_FAIL(cast_mode)) {
params.warning_ = OB_ERR_DATA_TRUNCATED;
ret = OB_SUCCESS;
}
LOG_DEBUG("finish uint_set", K(ret), K(expect_type), K(in), K(out), KPC(type_infos), K(lbt()));
SET_RES_SET(out);
}
return ret;
}
CAST_TO_LOB_METHOD(uint, ObUIntTC);
static int uint_json(const ObObjType expect_type, ObObjCastParams &params,
const ObObj &in, ObObj &out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
ObLength res_length = -1;
if (CM_IS_COLUMN_CONVERT(cast_mode) && is_mysql_unsupported_json_column_conversion(in.get_type())) {
ret = OB_ERR_INVALID_JSON_TEXT;
LOG_USER_ERROR(OB_ERR_INVALID_JSON_TEXT);
} else if (OB_UNLIKELY(ObUIntTC != in.get_type_class() || (ObJsonType != expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_UNLIKELY(params.allocator_v2_ == NULL)) {
ret= OB_ERR_UNEXPECTED;
LOG_ERROR("NULL allocator in json cast function", K(ret), K(in), K(expect_type));
} else {
ObJsonUint j_uint(in.get_uint64());
ObIJsonBase *j_base = &j_uint;
ObString raw_bin;
if (OB_FAIL(j_base->get_raw_binary(raw_bin, params.allocator_v2_))) {
LOG_WARN("fail to get uint json binary", K(ret), K(in), K(expect_type), K(*j_base));
} else {
out.set_json_value(expect_type, raw_bin.ptr(), raw_bin.length());
res_length = static_cast<ObLength>(raw_bin.length());
}
}
SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_STRING, DEFAULT_SCALE_FOR_TEXT, res_length)
return ret;
}
////////////////////////////////////////////////////////////////
// Float -> XXX
// directly stacit cast from float to int or uint:
// case 1: float = -99999896450971467776.000000, int64 = -9223372036854775808, uint64 = 9223372036854775808.
// case 2: float = 99999896450971467776.000000, int64 = -9223372036854775808, uint64 = 0.
// case 3: float = -99999904.000000, int64 = -99999904, uint64 = 18446744073609551712.
// case 4: float = 99999904.000000, int64 = 99999904, uint64 = 99999904.
// we can see that if float value is out of range of int or uint value, the casted int or uint
// value can't be used to compare with INT64_MAX and so on, see case 2.
// so we should use float value to determine weither it is in range of int or uint.
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<double>(LLONG_MIN)) {
out = trunc_min_value;
if (in < static_cast<double>(LLONG_MIN)) {
ret = OB_DATA_OUT_OF_RANGE;
}
} else if (in >= static_cast<double>(LLONG_MAX)) {
out = trunc_max_value;
if (in > static_cast<double>(LLONG_MAX)) {
ret = OB_DATA_OUT_OF_RANGE;
}
} else {
out = static_cast<int64_t>(rint(in));
}
return ret;
}
static int float_int(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
int64_t value = 0;
ObPrecision res_precision = -1;
if (OB_UNLIKELY(ObFloatTC != in.get_type_class() || ObIntTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else {
if (CAST_FAIL(common_double_int(
in.get_float(), value, LLONG_MIN, CM_IS_COLUMN_CONVERT(cast_mode) ? LLONG_MAX : LLONG_MIN))) {
LOG_WARN("cast float to int failed", K(ret), K(in), K(value));
} else if (CAST_FAIL(int_range_check(expect_type, value, value))) {
} else {
out.set_int(expect_type, value);
}
if (OB_SUCC(ret)) {
res_precision = get_precision_for_integer(value);
}
}
SET_RES_ACCURACY(res_precision, DEFAULT_SCALE_FOR_INTEGER, DEFAULT_LENGTH_FOR_NUMERIC);
return ret;
}
static int float_uint(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
uint64_t value = 0;
ObPrecision res_precision = -1;
double in_value = static_cast<double>(in.get_float());
bool is_column_convert = CM_IS_COLUMN_CONVERT(cast_mode);
if (OB_UNLIKELY(ObFloatTC != in.get_type_class() || ObUIntTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else {
if (in_value <= static_cast<double>(LLONG_MIN) || in_value >= static_cast<double>(ULLONG_MAX)) {
value = static_cast<uint64_t>(LLONG_MIN);
ret = OB_DATA_OUT_OF_RANGE;
} else {
if (is_column_convert) {
value = static_cast<uint64_t>(rint(in_value));
} else {
value = static_cast<uint64_t>(static_cast<int64_t>(rint(in_value)));
}
if (in_value < 0 && value != 0) {
ret = OB_DATA_OUT_OF_RANGE;
}
}
if (CAST_FAIL(ret)) {
LOG_WARN("cast float to uint failed", K(ret), K(in), K(value));
}
}
if (OB_FAIL(ret)) {
} else if (CM_NEED_RANGE_CHECK(cast_mode) && CAST_FAIL(uint_range_check(expect_type, value, value))) {
} else {
out.set_uint(expect_type, value);
}
if (OB_SUCC(ret)) {
res_precision = get_precision_for_integer(value);
}
SET_RES_ACCURACY(res_precision, DEFAULT_SCALE_FOR_INTEGER, DEFAULT_LENGTH_FOR_NUMERIC);
return ret;
}
static int float_float(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
float value = in.get_float();
if (OB_UNLIKELY(ObFloatTC != in.get_type_class() || ObFloatTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (ObUFloatType == expect_type && CAST_FAIL(numeric_negative_check(value))) {
} else {
out.set_float(expect_type, value);
}
SET_RES_ACCURACY(PRECISION_UNKNOWN_YET, SCALE_UNKNOWN_YET, LENGTH_UNKNOWN_YET);
return ret;
}
static int float_double(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
double value = static_cast<double>(in.get_float());
if (OB_UNLIKELY(ObFloatTC != in.get_type_class() || ObDoubleTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (ObUDoubleType == expect_type && CAST_FAIL(numeric_negative_check(value))) {
} else {
out.set_double(expect_type, value);
}
SET_RES_ACCURACY(PRECISION_UNKNOWN_YET, SCALE_UNKNOWN_YET, LENGTH_UNKNOWN_YET);
return ret;
}
static int float_number(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
float value = in.get_float();
ObPrecision res_precision = -1;
ObScale res_scale = -1;
if (OB_UNLIKELY(ObFloatTC != in.get_type_class() || ObNumberTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (std::isnan(value)) {
ret = OB_INVALID_NUMERIC;
LOG_WARN("float_number failed ", K(ret), K(value));
} else if (std::isinf(value)) {
ret = OB_NUMERIC_OVERFLOW;
LOG_WARN("float_number failed", K(ret), K(value));
} else if (ObUNumberType == expect_type && CAST_FAIL(numeric_negative_check(value))) {
} else {
char buf[MAX_DOUBLE_STRICT_PRINT_SIZE];
MEMSET(buf, 0, MAX_DOUBLE_STRICT_PRINT_SIZE);
int64_t length = 0;
if (lib::is_oracle_mode()) {
length = ob_gcvt_opt(in.get_float(), OB_GCVT_ARG_FLOAT, sizeof(buf) - 1, buf, NULL, TRUE);
} else {
length = ob_gcvt(in.get_float(), OB_GCVT_ARG_DOUBLE, sizeof(buf) - 1, buf, NULL);
}
ObString str(sizeof(buf), static_cast<int32_t>(length), buf);
number::ObNumber nmb;
if (OB_FAIL(nmb.from_sci_opt(str.ptr(), str.length(), params, &res_precision, &res_scale))) {
LOG_WARN("fail to from str to number", K(ret), K(str));
} else {
out.set_number(expect_type, nmb);
}
LOG_DEBUG("finish float to number", K(ret), K(str), K(length), K(in), K(expect_type), K(nmb), K(out), K(lbt()));
}
SET_RES_ACCURACY(res_precision, res_scale, DEFAULT_LENGTH_FOR_NUMERIC);
return ret;
}
static int double_datetime(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode);
static int float_datetime(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
ObObj dbl;
if (OB_UNLIKELY(ObFloatTC != in.get_type_class() || ObDateTimeTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(float_double(ObDoubleType, params, in, dbl, cast_mode))) {
} else if (OB_FAIL(double_datetime(expect_type, params, dbl, out, cast_mode))) {
}
// has set accuracy in prev double_datetime call
return ret;
}
static int double_datetime_interval(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode);
static int float_datetime_interval(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
ObObj dbl;
if (OB_UNLIKELY(ObFloatTC != in.get_type_class() || ObDateTimeTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(float_double(ObDoubleType, params, in, dbl, cast_mode))) {
} else if (OB_FAIL(double_datetime_interval(expect_type, params, dbl, out, cast_mode))) {
}
return ret;
}
static int double_date(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode);
static int float_date(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
ObObj dbl;
if (OB_UNLIKELY(ObFloatTC != in.get_type_class() || ObDateTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(float_double(ObDoubleType, params, in, dbl, cast_mode))) {
} else if (OB_FAIL(double_date(expect_type, params, dbl, out, cast_mode))) {
}
// has set accuracy in prev double_date call
return ret;
}
static int double_time(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode);
static int float_time(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
ObObj dbl;
if (OB_UNLIKELY(ObFloatTC != in.get_type_class() || ObTimeTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(float_double(ObDoubleType, params, in, dbl, cast_mode))) {
} else if (OB_FAIL(double_time(expect_type, params, dbl, out, cast_mode))) {
}
// has set accuracy in prev double_time call
return ret;
}
static int float_string(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
char buf[OB_CAST_TO_VARCHAR_MAX_LENGTH] = {0};
ObScale scale = in.get_scale();
int64_t length = 0;
ObLength res_length = -1;
if (OB_UNLIKELY(ObFloatTC != in.get_type_class() ||
(ObStringTC != ob_obj_type_class(expect_type) && ObTextTC != ob_obj_type_class(expect_type)))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else {
if (0 <= scale) {
length = ob_fcvt(in.get_float(), scale, sizeof(buf) - 1, buf, NULL);
} else {
length = ob_gcvt_opt(in.get_float(), OB_GCVT_ARG_FLOAT, sizeof(buf) - 1, buf, NULL, lib::is_oracle_mode());
}
ObString str(sizeof(buf), static_cast<int32_t>(length), buf);
LOG_DEBUG("finish float_string", K(ret), K(in), K(expect_type), K(str));
ObObj tmp_out;
ObString tmp_str;
if (OB_FAIL(convert_string_collation(
str, ObCharset::get_system_collation(), tmp_str, params.dest_collation_, params))) {
LOG_WARN("fail to convert string collation", K(ret));
} else if (OB_FAIL(check_convert_string(expect_type, params, tmp_str.ptr(), tmp_str.length(), tmp_out))) {
LOG_WARN("fail to check_convert_string", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(copy_string(params, expect_type, tmp_out.get_string(), out))) {
} else {
res_length = static_cast<ObLength>(out.get_string_len());
}
}
UNUSED(cast_mode);
SET_RES_ACCURACY_STRING(expect_type, DEFAULT_PRECISION_FOR_STRING, res_length);
return ret;
}
static int float_bit(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
UNUSED(cast_mode);
int ret = OB_SUCCESS;
uint64_t value = static_cast<uint64_t>(in.get_float());
int32_t bit_len = 0;
if (OB_UNLIKELY(ObFloatTC != in.get_type_class() || ObBitTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(get_bit_len(value, bit_len))) {
LOG_WARN("fail to get bit len", K(ret), K(value), K(bit_len));
} else {
SET_RES_BIT(out);
SET_RES_ACCURACY(static_cast<ObPrecision>(bit_len), DEFAULT_SCALE_FOR_BIT, DEFAULT_LENGTH_FOR_NUMERIC);
}
return ret;
}
static int float_enum(const ObExpectType& expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(ObEnumType != expect_type.get_type()) || OB_UNLIKELY(ObFloatTC != in.get_type_class())) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument", K(expect_type), K(in), K(ret));
} else {
int64_t value = static_cast<int64_t>(in.get_float());
ObObj int_val(value);
if (OB_FAIL(int_enum(expect_type, params, int_val, out))) {
LOG_WARN("fail to cast int to enum", K(expect_type), K(in), K(int_val), K(out), K(ret));
}
}
return ret;
}
static int float_set(const ObExpectType& expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(ObSetType != expect_type.get_type()) || OB_UNLIKELY(ObFloatTC != in.get_type_class())) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument", K(expect_type), K(in), K(ret));
} else {
int64_t value = static_cast<int64_t>(in.get_float());
ObObj int_val(value);
if (OB_FAIL(int_set(expect_type, params, int_val, out))) {
LOG_WARN("fail to cast int to enum", K(expect_type), K(in), K(int_val), K(out), K(ret));
}
}
return ret;
}
CAST_TO_LOB_METHOD(float, ObFloatTC);
static int float_json(const ObObjType expect_type, ObObjCastParams &params,
const ObObj &in, ObObj &out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
ObLength res_length = -1;
if (CM_IS_COLUMN_CONVERT(cast_mode) && is_mysql_unsupported_json_column_conversion(in.get_type())) {
ret = OB_ERR_INVALID_JSON_TEXT;
LOG_USER_ERROR(OB_ERR_INVALID_JSON_TEXT);
} else if (OB_UNLIKELY(ObFloatTC != in.get_type_class() || (ObJsonType != expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_UNLIKELY(params.allocator_v2_ == NULL)) {
ret= OB_ERR_UNEXPECTED;
LOG_ERROR("NULL allocator in json cast function", K(ret), K(in), K(expect_type));
} else {
ObJsonDouble j_double(in.get_float());
ObIJsonBase *j_base = &j_double;
ObString raw_bin;
if (OB_FAIL(j_base->get_raw_binary(raw_bin, params.allocator_v2_))) {
LOG_WARN("fail to get float json binary", K(ret), K(in), K(expect_type), K(*j_base));
} else {
out.set_json_value(expect_type, raw_bin.ptr(), raw_bin.length());
res_length = static_cast<ObLength>(raw_bin.length());
}
}
SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_STRING, DEFAULT_SCALE_FOR_TEXT, res_length)
return ret;
}
////////////////////////////////////////////////////////////////
// Double -> XXX
static int double_int(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
int64_t value = 0;
ObPrecision res_precision = -1;
if (OB_UNLIKELY(ObDoubleTC != in.get_type_class() || ObIntTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else {
if (CAST_FAIL(common_double_int(in.get_double(), value, LLONG_MIN, LLONG_MAX))) {
LOG_WARN("common double to in failed", K(ret), K(in), K(cast_mode));
} else if (CAST_FAIL(int_range_check(expect_type, value, value))) {
LOG_WARN("int range check failed", K(ret), K(value));
} else {
out.set_int(expect_type, value);
}
if (OB_SUCC(ret)) {
res_precision = get_precision_for_integer(value);
}
}
SET_RES_ACCURACY(res_precision, DEFAULT_SCALE_FOR_INTEGER, DEFAULT_LENGTH_FOR_NUMERIC);
return ret;
}
static int double_uint(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
uint64_t value = 0;
ObPrecision res_precision = -1;
double in_value = in.get_double();
bool is_column_convert = CM_IS_COLUMN_CONVERT(cast_mode);
if (OB_UNLIKELY(ObDoubleTC != in.get_type_class() || ObUIntTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else {
if (in_value <= static_cast<double>(LLONG_MIN)) {
value = static_cast<uint64_t>(LLONG_MIN);
ret = OB_DATA_OUT_OF_RANGE;
} else if (in_value >= static_cast<double>(ULLONG_MAX)) {
value = static_cast<uint64_t>(LLONG_MAX);
ret = OB_DATA_OUT_OF_RANGE;
} else {
if (is_column_convert) {
value = static_cast<uint64_t>(rint(in_value));
} else if (in_value >= static_cast<double>(LLONG_MAX)) {
value = static_cast<uint64_t>(LLONG_MAX);
} else {
value = static_cast<uint64_t>(static_cast<int64_t>(rint(in_value)));
}
if (in_value < 0 && value != 0) {
ret = OB_DATA_OUT_OF_RANGE;
}
}
if (CAST_FAIL(ret)) {
LOG_WARN("cast float to uint failed", K(ret), K(in), K(value));
}
}
if (OB_FAIL(ret)) {
} else if (CM_NEED_RANGE_CHECK(cast_mode) && CAST_FAIL(uint_range_check(expect_type, value, value))) {
} else {
out.set_uint(expect_type, value);
}
if (OB_SUCC(ret)) {
res_precision = get_precision_for_integer(value);
}
SET_RES_ACCURACY(res_precision, DEFAULT_SCALE_FOR_INTEGER, DEFAULT_LENGTH_FOR_NUMERIC);
return ret;
}
static int double_float(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
float value = static_cast<float>(in.get_double());
if (OB_UNLIKELY(ObDoubleTC != in.get_type_class() || ObFloatTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (CAST_FAIL(real_range_check(expect_type, in.get_double(), value))) {
} else {
out.set_float(expect_type, value);
LOG_DEBUG("succ to double_float", K(ret), K(in), K(value), K(out));
}
SET_RES_ACCURACY(PRECISION_UNKNOWN_YET, SCALE_UNKNOWN_YET, LENGTH_UNKNOWN_YET);
return ret;
}
static int double_double(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
double value = in.get_double();
if (OB_UNLIKELY(ObDoubleTC != in.get_type_class() || ObDoubleTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (ObUDoubleType == expect_type && CAST_FAIL(numeric_negative_check(value))) {
} else {
out.set_double(expect_type, value);
}
SET_RES_ACCURACY(PRECISION_UNKNOWN_YET, SCALE_UNKNOWN_YET, LENGTH_UNKNOWN_YET);
return ret;
}
static int double_number(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
double value = in.get_double();
ObPrecision res_precision = -1;
ObScale res_scale = -1;
if (OB_UNLIKELY(ObDoubleTC != in.get_type_class() || ObNumberTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (std::isnan(value) && lib::is_oracle_mode()) {
ret = OB_INVALID_NUMERIC;
LOG_WARN("float_number failed ", K(ret), K(value));
} else if (std::isinf(value) && lib::is_oracle_mode()) {
ret = OB_NUMERIC_OVERFLOW;
LOG_WARN("float_number failed", K(ret), K(value));
} else if (ObUNumberType == expect_type && CAST_FAIL(numeric_negative_check(value))) {
} else {
char buf[MAX_DOUBLE_STRICT_PRINT_SIZE];
MEMSET(buf, 0, MAX_DOUBLE_STRICT_PRINT_SIZE);
int64_t length =
ob_gcvt_opt(in.get_double(), OB_GCVT_ARG_DOUBLE, sizeof(buf) - 1, buf, NULL, lib::is_oracle_mode());
ObString str(sizeof(buf), static_cast<int32_t>(length), buf);
number::ObNumber nmb;
if (OB_FAIL(nmb.from_sci_opt(str.ptr(), str.length(), params, &res_precision, &res_scale))) {
} else {
out.set_number(expect_type, nmb);
}
LOG_DEBUG("finish double to number", K(ret), K(str), K(length), K(in), K(expect_type), K(nmb), K(out), K(lbt()));
}
SET_RES_ACCURACY(res_precision, res_scale, DEFAULT_LENGTH_FOR_NUMERIC);
return ret;
}
static int number_datetime(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode);
static int double_datetime(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
// double to datetime must cast to number first, then cast string to datetime.
// because double 20151016153421.8 may actually 20151016153421.801 in memory,
// so we will get '2015-10-16 15:34:21.801' instead of '2015-10-16 15:34:21.8'.
// this problem can be resolved by cast double to number.
int ret = OB_SUCCESS;
ObScale res_scale = -1;
int64_t value = 0;
ObTimeConvertCtx cvrt_ctx(params.dtc_params_.tz_info_, ObTimestampType == expect_type);
ObObj tmp_num_obj;
if (OB_UNLIKELY(ObDoubleTC != in.get_type_class() || ObDateTimeTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(double_number(ObNumberType, params, in, tmp_num_obj, cast_mode))) {
LOG_WARN("cast double to number failed", K(ret), K(cast_mode));
if (CM_IS_WARN_ON_FAIL(cast_mode)) {
ret = OB_SUCCESS;
if (CM_IS_ZERO_ON_WARN(cast_mode)) {
out.set_datetime(expect_type, ObTimeConverter::ZERO_DATETIME);
} else {
out.set_null();
}
} else {
ret = OB_INVALID_DATE_VALUE;
}
} else if (CAST_FAIL(number_datetime(expect_type, params, tmp_num_obj, out, cast_mode))) {
LOG_WARN("number to datetime failed", K(ret));
}
return ret;
}
static int double_datetime_interval(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
ObScale res_scale = -1;
if (OB_UNLIKELY(ObDoubleTC != in.get_type_class()) || OB_UNLIKELY(ObDateTimeTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else {
const int64_t value = static_cast<int64_t>(in.get_double() * static_cast<double>(USECS_PER_DAY));
LOG_DEBUG("succ to double_datetime_interval", K(ret), K(in), K(value), K(expect_type));
SET_RES_DATETIME(out);
}
SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, res_scale, DEFAULT_LENGTH_FOR_TEMPORAL);
return ret;
}
static int double_date(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
// TODO In datediff,mysql does truncate NOT round
// So,we have to revise double 2 int which act as round (right now) to truncation
int ret = OB_SUCCESS;
ObObj int64;
if (OB_UNLIKELY(ObDoubleTC != in.get_type_class() || ObDateTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(double_int(ObIntType, params, in, int64, cast_mode))) {
} else if (OB_FAIL(int_date(expect_type, params, int64, out, cast_mode))) {
}
SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, DEFAULT_SCALE_FOR_DATE, DEFAULT_LENGTH_FOR_TEMPORAL);
return ret;
}
static int double_time(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
// double to time must cast to string first, then cast string to time.
// see comment in double_datetime.
int ret = OB_SUCCESS;
ObScale res_scale = -1;
if (OB_UNLIKELY(ObDoubleTC != in.get_type_class() || ObTimeTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else {
int64_t value = 0;
char buf[MAX_DOUBLE_PRINT_SIZE];
MEMSET(buf, 0, MAX_DOUBLE_PRINT_SIZE);
int64_t length = ob_gcvt(in.get_double(), OB_GCVT_ARG_DOUBLE, sizeof(buf) - 1, buf, NULL);
ObString str(sizeof(buf), static_cast<int32_t>(length), buf);
if (CAST_FAIL(ObTimeConverter::str_to_time(str, value, &res_scale))) {
} else {
SET_RES_TIME(out);
}
}
SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, res_scale, DEFAULT_LENGTH_FOR_TEMPORAL);
return ret;
}
static int double_year(const ObObjType expect_type, ObObjCastParams &params,
const ObObj &in, ObObj &out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(ObDoubleTC != in.get_type_class()
|| ObYearTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type",
K(ret), K(in), K(expect_type));
} else {
uint8_t value = 0;
double in_val = in.get_double();
in_val = in_val < 0 ? INT_MIN : in_val + 0.5;
uint64_t intvalue = static_cast<uint64_t>(in_val);
if (CAST_FAIL(ObTimeConverter::int_to_year(intvalue, value))) {
} else {
SET_RES_YEAR(out);
}
}
SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, DEFAULT_SCALE_FOR_YEAR, DEFAULT_LENGTH_FOR_TEMPORAL);
return ret;
}
static int double_string(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
ObLength res_length = -1;
if (OB_UNLIKELY(ObDoubleTC != in.get_type_class() ||
(ObStringTC != ob_obj_type_class(expect_type) && ObTextTC != ob_obj_type_class(expect_type)))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else {
char buf[OB_CAST_TO_VARCHAR_MAX_LENGTH] = {0};
ObScale scale = in.get_scale();
int64_t length = 0;
if (0 <= scale) {
length = ob_fcvt(in.get_double(), scale, sizeof(buf) - 1, buf, NULL);
} else {
length = ob_gcvt_opt(in.get_double(), OB_GCVT_ARG_DOUBLE, sizeof(buf) - 1, buf, NULL, lib::is_oracle_mode());
}
ObString str(sizeof(buf), static_cast<int32_t>(length), buf);
LOG_DEBUG("finish double_string", K(ret), K(in), K(expect_type), K(str));
ObObj tmp_out;
ObString tmp_str;
if (OB_FAIL(convert_string_collation(
str, ObCharset::get_system_collation(), tmp_str, params.dest_collation_, params))) {
LOG_WARN("fail to convert string collation", K(ret));
} else if (OB_FAIL(check_convert_string(expect_type, params, tmp_str, tmp_out))) {
LOG_WARN("fail to check_convert_string", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(copy_string(params, expect_type, tmp_out.get_string(), out))) {
} else {
res_length = static_cast<ObLength>(out.get_string_len());
}
}
SET_RES_ACCURACY_STRING(expect_type, DEFAULT_PRECISION_FOR_STRING, res_length);
UNUSED(cast_mode);
return ret;
}
static int double_bit(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
UNUSED(cast_mode);
int ret = OB_SUCCESS;
uint64_t value = static_cast<uint64_t>(in.get_double());
int32_t bit_len = 0;
if (OB_UNLIKELY(ObDoubleTC != in.get_type_class() || ObBitTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(get_bit_len(value, bit_len))) {
LOG_WARN("fail to get bit len", K(ret), K(value), K(bit_len));
} else {
SET_RES_BIT(out);
SET_RES_ACCURACY(static_cast<ObPrecision>(bit_len), DEFAULT_SCALE_FOR_BIT, DEFAULT_LENGTH_FOR_NUMERIC);
}
return ret;
}
static int double_enum(const ObExpectType& expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(ObEnumType != expect_type.get_type()) || OB_UNLIKELY(ObDoubleTC != in.get_type_class())) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument", K(expect_type), K(in), K(ret));
} else {
int64_t value = static_cast<int64_t>(in.get_double());
ObObj int_val(value);
if (OB_FAIL(int_enum(expect_type, params, int_val, out))) {
LOG_WARN("fail to cast int to enum", K(expect_type), K(in), K(int_val), K(out), K(ret));
}
}
return ret;
}
static int double_set(const ObExpectType& expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(ObSetType != expect_type.get_type()) || OB_UNLIKELY(ObDoubleTC != in.get_type_class())) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument", K(expect_type), K(in), K(ret));
} else {
int64_t value = static_cast<int64_t>(in.get_double());
ObObj int_val(value);
if (OB_FAIL(int_set(expect_type, params, int_val, out))) {
LOG_WARN("fail to cast int to enum", K(expect_type), K(in), K(int_val), K(out), K(ret));
}
}
return ret;
}
CAST_TO_LOB_METHOD(double, ObDoubleTC);
static int double_json(const ObObjType expect_type, ObObjCastParams &params,
const ObObj &in, ObObj &out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
ObLength res_length = -1;
if (CM_IS_COLUMN_CONVERT(cast_mode) && is_mysql_unsupported_json_column_conversion(in.get_type())) {
ret = OB_ERR_INVALID_JSON_TEXT;
LOG_USER_ERROR(OB_ERR_INVALID_JSON_TEXT);
} else if (OB_UNLIKELY(ObDoubleTC != in.get_type_class() || (ObJsonType != expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_UNLIKELY(params.allocator_v2_ == NULL)) {
ret= OB_ERR_UNEXPECTED;
LOG_ERROR("NULL allocator in json cast function", K(ret), K(in), K(expect_type));
} else {
ObJsonDouble j_double(in.get_double());
ObIJsonBase *j_base = &j_double;
ObString raw_bin;
if (OB_FAIL(j_base->get_raw_binary(raw_bin, params.allocator_v2_))) {
LOG_WARN("fail to get double json binary", K(ret), K(in), K(expect_type), K(*j_base));
} else {
out.set_json_value(expect_type, raw_bin.ptr(), raw_bin.length());
res_length = static_cast<ObLength>(raw_bin.length());
}
}
SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_STRING, DEFAULT_SCALE_FOR_TEXT, res_length)
return ret;
}
////////////////////////////////////////////////////////////////
// Number -> XXX
static int string_int(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode);
static int number_int(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
ObPrecision res_precision = -1;
if (OB_UNLIKELY(ObNumberTC != in.get_type_class() || ObIntTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else {
const number::ObNumber& nmb = in.get_number();
const char* value = nmb.format();
if (OB_ISNULL(value)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("null pointer", K(ret), K(value));
} else {
ObObj from;
from.set_varchar(value, static_cast<ObString::obstr_size_t>(strlen(value)));
ret = string_int(expect_type, params, from, out, CM_UNSET_STRING_INTEGER_TRUNC(cast_mode));
}
}
if (OB_SUCC(ret)) {
res_precision = get_precision_for_integer(out.get_int());
}
SET_RES_ACCURACY(res_precision, DEFAULT_SCALE_FOR_INTEGER, DEFAULT_LENGTH_FOR_NUMERIC);
return ret;
}
static int string_uint(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode);
static int number_uint(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
ObPrecision res_precision = -1;
if (OB_UNLIKELY(ObNumberTC != in.get_type_class() || ObUIntTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else {
const number::ObNumber& nmb = in.get_number();
const char* value = nmb.format();
if (OB_ISNULL(value)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("null pointer", K(ret), K(value));
} else {
ObObj from;
from.set_varchar(value, static_cast<ObString::obstr_size_t>(strlen(value)));
ret = string_uint(expect_type, params, from, out, CM_UNSET_STRING_INTEGER_TRUNC(cast_mode));
}
}
if (OB_SUCC(ret)) {
res_precision = get_precision_for_integer(out.get_uint64());
}
SET_RES_ACCURACY(res_precision, DEFAULT_SCALE_FOR_INTEGER, DEFAULT_LENGTH_FOR_NUMERIC);
return ret;
}
static int string_float(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode);
static int number_float(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(ObNumberTC != in.get_type_class() || ObFloatTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else {
const char* value = in.get_number().format();
if (OB_ISNULL(value)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("null pointer", K(ret), K(value));
} else {
ObObj from;
from.set_varchar(value, static_cast<ObString::obstr_size_t>(strlen(value)));
ret = string_float(expect_type, params, from, out, cast_mode);
}
}
SET_RES_ACCURACY(PRECISION_UNKNOWN_YET, SCALE_UNKNOWN_YET, LENGTH_UNKNOWN_YET);
return ret;
}
static int string_double(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode);
static int number_double(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(ObNumberTC != in.get_type_class() || ObDoubleTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else {
const char* value = in.get_number().format();
if (OB_ISNULL(value)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("null pointer", K(ret), K(value));
} else {
ObObj from;
from.set_varchar(value, static_cast<ObString::obstr_size_t>(strlen(value)));
ret = string_double(expect_type, params, from, out, cast_mode);
}
}
SET_RES_ACCURACY(PRECISION_UNKNOWN_YET, SCALE_UNKNOWN_YET, LENGTH_UNKNOWN_YET);
return ret;
}
static int number_number(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(ObNumberTC != in.get_type_class() || ObNumberTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else {
const number::ObNumber& nmb = in.get_number();
number::ObNumber value;
if (OB_FAIL(value.from(nmb, params))) {
} else if (ObUNumberType == expect_type && CAST_FAIL(numeric_negative_check(value))) {
} else {
out.set_number(expect_type, value);
}
}
// todo maybe we can do some dirty work to get better result.
// for now, just set it to unknown....
SET_RES_ACCURACY(PRECISION_UNKNOWN_YET, NUMBER_SCALE_UNKNOWN_YET, LENGTH_UNKNOWN_YET);
return ret;
}
static int string_datetime(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode);
static int number_datetime(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
const int64_t three_digit_min = 100;
const int64_t eight_digit_max = 99999999;
if (OB_UNLIKELY(ObNumberTC != in.get_type_class() || ObDateTimeTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else {
ObTimeConvertCtx cvrt_ctx(params.dtc_params_.tz_info_, ObTimestampType == expect_type);
int64_t value = 0;
int64_t int_part = 0;
int64_t dec_part = 0;
if (in.get_number().is_negative()) {
ret = OB_INVALID_DATE_FORMAT;
LOG_WARN("invalid date format", K(ret), K(in), K(cast_mode));
} else if (!in.get_number().is_int_parts_valid_int64(int_part,dec_part)) {
ret = OB_INVALID_DATE_FORMAT;
LOG_WARN("invalid date format", K(ret), K(in), K(cast_mode));
} else if (OB_UNLIKELY(dec_part != 0
&& ((0 == int_part && ObTimestampType == expect_type)
|| (int_part >= three_digit_min && int_part <= eight_digit_max)))) {
if (CM_IS_COLUMN_CONVERT(cast_mode) && !CM_IS_WARN_ON_FAIL(cast_mode)) {
ret = OB_INVALID_DATE_VALUE;
LOG_WARN("invalid date value", K(ret));
} else {
dec_part = 0;
}
}
if (OB_SUCC(ret)) {
ret = ObTimeConverter::int_to_datetime(int_part, dec_part, cvrt_ctx, value);
LOG_DEBUG("succ to number_datetime", K(ret), K(in), K(value), K(expect_type), K(int_part), K(dec_part));
}
if (CAST_FAIL(ret)) {
} else {
SET_RES_DATETIME(out);
}
}
SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, MIN_SCALE_FOR_TEMPORAL, DEFAULT_LENGTH_FOR_TEMPORAL);
return ret;
}
static int number_datetime_interval(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(ObNumberTC != in.get_type_class()) || OB_UNLIKELY(ObDateTimeTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else {
int64_t int_part = 0;
int64_t dec_part = 0;
if (!in.get_number().is_int_parts_valid_int64(int_part, dec_part)) {
ret = OB_INVALID_DATE_FORMAT;
LOG_WARN("invalid date format", K(ret), K(in), K(cast_mode));
} else {
const int64_t value =
static_cast<int64_t>(int_part * USECS_PER_DAY) +
(in.is_negative_number() ? -1 : 1) *
static_cast<int64_t>(static_cast<double>(dec_part) / NSECS_PER_SEC * static_cast<double>(USECS_PER_DAY));
LOG_DEBUG("succ to number_datetime_interval", K(ret), K(in), K(value), K(expect_type), K(int_part), K(dec_part));
SET_RES_DATETIME(out);
}
}
SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, MIN_SCALE_FOR_TEMPORAL, DEFAULT_LENGTH_FOR_TEMPORAL);
return ret;
}
static int string_date(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode);
static int number_date(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
ObObj int64;
int32_t value = 0;
if (OB_UNLIKELY(ObNumberTC != in.get_type_class() || ObDateTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type",
K(ret), K(in), K(expect_type));
} else {
int64_t int_part = 0;
int64_t dec_part = 0;
const number::ObNumber nmb = in.get_number();
if (nmb.is_negative()) {
ret = OB_INVALID_DATE_VALUE;
LOG_WARN("invalid date value", K(ret), K(nmb));
} else if (!nmb.is_int_parts_valid_int64(int_part, dec_part)) {
ret = OB_INVALID_DATE_VALUE;
LOG_WARN("invalid date format", K(ret), K(nmb));
} else {
ret = ObTimeConverter::int_to_date(int_part, value);
if (OB_SUCC(ret) && OB_UNLIKELY(dec_part > 0)) {
if (CM_IS_COLUMN_CONVERT(cast_mode) && !CM_IS_WARN_ON_FAIL(cast_mode)) {
ret = OB_INVALID_DATE_VALUE;
LOG_WARN("invalid date value with decimal part", K(ret));
}
}
}
if (CAST_FAIL(ret)) {
} else {
SET_RES_DATE(out);
}
}
return ret;
}
static int string_time(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode);
static int number_time(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(ObNumberTC != in.get_type_class() || ObTimeTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else {
const char* value = in.get_number().format();
if (OB_ISNULL(value)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("null pointer", K(ret), K(value));
} else {
ObObj from;
from.set_varchar(value, static_cast<ObString::obstr_size_t>(strlen(value)));
ret = string_time(expect_type, params, from, out, cast_mode);
}
}
// has set accuracy in prev string_time call
return ret;
}
static int string_year(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode);
static int number_year(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(ObNumberTC != in.get_type_class() || ObYearTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else {
const char* value = in.get_number().format();
if (OB_ISNULL(value)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("null pointer", K(ret), K(value));
} else if (in.get_number().is_negative()) {
uint8_t value = 0;
if (CAST_FAIL(ObTimeConverter::int_to_year(INT_MIN, value))) {
}
} else {
ObObj from;
from.set_varchar(value, static_cast<ObString::obstr_size_t>(strlen(value)));
ret = string_year(expect_type, params, from, out, cast_mode);
}
}
SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, DEFAULT_SCALE_FOR_YEAR, DEFAULT_LENGTH_FOR_TEMPORAL);
return ret;
}
static int number_string(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
char buf[OB_CAST_TO_VARCHAR_MAX_LENGTH] = {0};
int64_t len = 0;
ObLength res_length = -1;
if (OB_UNLIKELY(ObNumberTC != in.get_type_class() ||
(ObStringTC != ob_obj_type_class(expect_type) && ObTextTC != ob_obj_type_class(expect_type)))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (is_oracle_mode() && ob_is_blob(expect_type, params.dest_collation_)) {
ret = OB_ERR_INVALID_TYPE_FOR_OP;
LOG_WARN("cast number to blob not allowed", K(ret));
} else {
if (lib::is_oracle_mode() && params.format_number_with_limit_) {
if (OB_FAIL(in.get_number().format_with_oracle_limit(buf, sizeof(buf), len, in.get_scale()))) {
LOG_WARN("fail to format", K(ret), K(in.get_number()));
}
} else {
if (OB_FAIL(in.get_number().format(buf, sizeof(buf), len, in.get_scale()))) {
LOG_WARN("fail to format", K(ret), K(in.get_number()));
}
}
if (OB_SUCC(ret)) {
ObString tmp_str;
ObObj tmp_out;
if (OB_FAIL(convert_string_collation(
ObString(len, buf), ObCharset::get_system_collation(), tmp_str, params.dest_collation_, params))) {
LOG_WARN("fail to convert string collation", K(ret));
} else if (OB_FAIL(check_convert_string(expect_type, params, tmp_str, tmp_out))) {
LOG_WARN("fail to check_convert_string", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(copy_string(params, expect_type, tmp_out.get_string(), out))) {
} else {
res_length = static_cast<ObLength>(out.get_string_len());
}
}
}
UNUSED(cast_mode);
SET_RES_ACCURACY_STRING(expect_type, DEFAULT_PRECISION_FOR_STRING, res_length);
return ret;
}
static int number_bit(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
ObObj tmp_val;
if (OB_UNLIKELY(ObNumberTC != in.get_type_class() || ObBitTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(number_uint(ObUInt64Type, params, in, tmp_val, cast_mode))) {
LOG_WARN("fail to cast number to uint", K(ret), K(expect_type), K(in), K(tmp_val));
} else if (OB_FAIL(uint_bit(expect_type, params, tmp_val, out, cast_mode))) {
LOG_WARN("fail to cast uint to bit", K(ret), K(expect_type), K(out), K(tmp_val));
}
return ret;
}
static int number_enum(const ObExpectType& expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out)
{
int ret = OB_SUCCESS;
ObObj double_val;
ObCastMode cast_mode = params.cast_mode_;
if (OB_UNLIKELY(ObEnumType != expect_type.get_type()) || OB_UNLIKELY(ObNumberTC != in.get_type_class())) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument", K(expect_type), K(in), K(ret));
} else if (OB_FAIL(number_double(ObDoubleType, params, in, double_val, cast_mode))) {
LOG_WARN("fail to cast number to double", K(in), K(double_val), K(ret));
} else if (OB_FAIL(double_enum(expect_type, params, double_val, out))) {
LOG_WARN("fail to cast double to enum", K(expect_type), K(out), K(double_val), K(ret));
}
return ret;
}
static int number_set(const ObExpectType& expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out)
{
int ret = OB_SUCCESS;
ObObj double_val;
ObCastMode cast_mode = params.cast_mode_;
if (OB_UNLIKELY(ObSetType != expect_type.get_type()) || OB_UNLIKELY(ObNumberTC != in.get_type_class())) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument", K(expect_type), K(in), K(ret));
} else if (OB_FAIL(number_double(ObDoubleType, params, in, double_val, cast_mode))) {
LOG_WARN("fail to cast number to double", K(in), K(double_val), K(ret));
} else if (OB_FAIL(double_set(expect_type, params, double_val, out))) {
LOG_WARN("fail to cast double to enum", K(expect_type), K(out), K(double_val), K(ret));
}
return ret;
}
CAST_TO_LOB_METHOD(number, ObNumberTC);
static int number_json(const ObObjType expect_type, ObObjCastParams &params,
const ObObj &in, ObObj &out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
ObLength res_length = -1;
if (CM_IS_COLUMN_CONVERT(cast_mode) && is_mysql_unsupported_json_column_conversion(in.get_type())) {
ret = OB_ERR_INVALID_JSON_TEXT;
LOG_USER_ERROR(OB_ERR_INVALID_JSON_TEXT);
} else if (OB_UNLIKELY(ObNumberTC != in.get_type_class() || (ObJsonType != expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_UNLIKELY(params.allocator_v2_ == NULL)) {
ret= OB_ERR_UNEXPECTED;
LOG_ERROR("NULL allocator in json cast function", K(ret), K(in), K(expect_type));
} else {
const number::ObNumber nmb(in.get_number());
ObJsonDecimal j_dec(nmb, -1, in.get_scale());
ObIJsonBase *j_base = &j_dec;
ObString raw_bin;
if (OB_FAIL(j_base->get_raw_binary(raw_bin, params.allocator_v2_))) {
LOG_WARN("fail to get decimal json binary", K(ret), K(in), K(expect_type), K(*j_base));
} else {
out.set_json_value(expect_type, raw_bin.ptr(), raw_bin.length());
res_length = static_cast<ObLength>(raw_bin.length());
}
}
SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_STRING, DEFAULT_SCALE_FOR_TEXT, res_length)
return ret;
}
////////////////////////////////////////////////////////////
// Datetime -> XXX
static int datetime_int(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
ObPrecision res_precision = -1;
if (OB_UNLIKELY(ObDateTimeTC != in.get_type_class() || ObIntTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else {
const ObTimeZoneInfo* tz_info = (ObTimestampType == in.get_type()) ? params.dtc_params_.tz_info_ : NULL;
int64_t value = 0;
if (OB_FAIL(ObTimeConverter::datetime_to_int(in.get_datetime(), tz_info, value))) {
} else if (expect_type < ObIntType && CAST_FAIL(int_range_check(expect_type, value, value))) {
} else {
out.set_int(expect_type, value);
res_precision = get_precision_for_integer(value);
}
}
SET_RES_ACCURACY(res_precision, DEFAULT_SCALE_FOR_INTEGER, DEFAULT_LENGTH_FOR_NUMERIC);
return ret;
}
static int datetime_uint(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
ObPrecision res_precision = -1;
if (OB_UNLIKELY(ObDateTimeTC != in.get_type_class() || ObUIntTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else {
const ObTimeZoneInfo* tz_info = (ObTimestampType == in.get_type()) ? params.dtc_params_.tz_info_ : NULL;
int64_t int64 = 0;
if (OB_FAIL(ObTimeConverter::datetime_to_int(in.get_datetime(), tz_info, int64))) {
} else {
uint64_t value = static_cast<uint64_t>(int64);
if (expect_type < ObUInt64Type && CAST_FAIL(uint_range_check(expect_type, int64, value))) {
} else {
out.set_uint(expect_type, value);
res_precision = get_precision_for_integer(value);
}
}
}
SET_RES_ACCURACY(res_precision, DEFAULT_SCALE_FOR_INTEGER, DEFAULT_LENGTH_FOR_NUMERIC);
return ret;
}
static int datetime_float(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(ObDateTimeTC != in.get_type_class() || ObFloatTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else {
const ObTimeZoneInfo* tz_info = (ObTimestampType == in.get_type()) ? params.dtc_params_.tz_info_ : NULL;
double value = 0.0;
if (OB_FAIL(ObTimeConverter::datetime_to_double(in.get_datetime(), tz_info, value))) {
} else {
// if datetime_to_double return OB_SUCCESS, double value must be in (0, INT64_MAX),
// so we can static_cast to float without range check.
out.set_float(expect_type, static_cast<float>(value));
}
}
SET_RES_ACCURACY(PRECISION_UNKNOWN_YET, SCALE_UNKNOWN_YET, LENGTH_UNKNOWN_YET);
UNUSED(cast_mode);
return ret;
}
static int datetime_double(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(ObDateTimeTC != in.get_type_class() || ObDoubleTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else {
const ObTimeZoneInfo* tz_info = (ObTimestampType == in.get_type()) ? params.dtc_params_.tz_info_ : NULL;
double value = 0.0;
if (OB_FAIL(ObTimeConverter::datetime_to_double(in.get_datetime(), tz_info, value))) {
} else {
out.set_double(expect_type, value);
}
}
SET_RES_ACCURACY(PRECISION_UNKNOWN_YET, SCALE_UNKNOWN_YET, LENGTH_UNKNOWN_YET);
UNUSED(cast_mode);
return ret;
}
static int datetime_number(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
ObPrecision res_precision = -1;
ObScale res_scale = -1;
if (OB_UNLIKELY(ObDateTimeTC != in.get_type_class() || ObNumberTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else {
const ObTimeZoneInfo* tz_info = (ObTimestampType == in.get_type()) ? params.dtc_params_.tz_info_ : NULL;
ObString nls_format;
char buf[OB_CAST_TO_VARCHAR_MAX_LENGTH] = {0};
int64_t len = 0;
number::ObNumber value;
if (OB_FAIL(ObTimeConverter::datetime_to_str(
in.get_datetime(), tz_info, nls_format, in.get_scale(), buf, sizeof(buf), len, false))) {
LOG_WARN("failed to convert datetime to string", K(ret));
} else if (CAST_FAIL(value.from(buf, len, params, &res_precision, &res_scale))) {
LOG_WARN("failed to convert string to number", K(ret));
} else {
out.set_number(expect_type, value);
}
}
SET_RES_ACCURACY(res_precision, res_scale, DEFAULT_LENGTH_FOR_NUMERIC);
return ret;
}
static int datetime_datetime(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(ObDateTimeTC != in.get_type_class() || ObDateTimeTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else {
int64_t value = in.get_datetime();
if (ObDateTimeType == in.get_type() && ObTimestampType == expect_type) {
ret = ObTimeConverter::datetime_to_timestamp(in.get_datetime(), params.dtc_params_.tz_info_, value);
ret = OB_ERR_UNEXPECTED_TZ_TRANSITION == ret ? OB_INVALID_DATE_VALUE : ret;
} else if (ObTimestampType == in.get_type() && ObDateTimeType == expect_type) {
ret = ObTimeConverter::timestamp_to_datetime(in.get_datetime(), params.dtc_params_.tz_info_, value);
}
if (OB_FAIL(ret)) {
} else {
out.set_datetime(expect_type, value);
}
}
SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, in.get_scale(), DEFAULT_LENGTH_FOR_TEMPORAL);
UNUSED(cast_mode);
return ret;
}
static int datetime_date(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(ObDateTimeTC != in.get_type_class() || ObDateTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else {
const ObTimeZoneInfo* tz_info = (ObTimestampType == in.get_type()) ? params.dtc_params_.tz_info_ : NULL;
int32_t value = 0;
if (OB_FAIL(ObTimeConverter::datetime_to_date(in.get_datetime(), tz_info, value))) {
} else {
out.set_date(value);
}
}
SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, DEFAULT_SCALE_FOR_DATE, DEFAULT_LENGTH_FOR_TEMPORAL);
UNUSED(cast_mode);
return ret;
}
static int datetime_time(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(ObDateTimeTC != in.get_type_class() || ObTimeTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else {
const ObTimeZoneInfo* tz_info = (ObTimestampType == in.get_type()) ? params.dtc_params_.tz_info_ : NULL;
int64_t value = 0;
if (OB_FAIL(ObTimeConverter::datetime_to_time(in.get_datetime(), tz_info, value))) {
} else {
out.set_time(value);
}
}
SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, in.get_scale(), DEFAULT_LENGTH_FOR_TEMPORAL);
UNUSED(cast_mode);
return ret;
}
static int datetime_year(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(ObDateTimeTC != in.get_type_class() || ObYearTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else {
const ObTimeZoneInfo* tz_info = (ObTimestampType == in.get_type()) ? params.dtc_params_.tz_info_ : NULL;
uint8_t value = 0;
if (CAST_FAIL(ObTimeConverter::datetime_to_year(in.get_datetime(), tz_info, value))) {
} else {
SET_RES_YEAR(out);
}
}
SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, DEFAULT_SCALE_FOR_YEAR, DEFAULT_LENGTH_FOR_TEMPORAL);
UNUSED(cast_mode);
return ret;
}
static int datetime_string(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
ObLength res_length = -1;
if (OB_UNLIKELY(ObDateTimeTC != in.get_type_class() ||
(ObStringTC != ob_obj_type_class(expect_type) && ObTextTC != ob_obj_type_class(expect_type)))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else {
const ObTimeZoneInfo* tz_info = (ObTimestampType == in.get_type()) ? params.dtc_params_.tz_info_ : NULL;
ObString nls_format;
if (lib::is_oracle_mode() && !params.dtc_params_.force_use_standard_format_) {
nls_format = params.dtc_params_.get_nls_format(ObDateTimeType);
}
char buf[OB_CAST_TO_VARCHAR_MAX_LENGTH] = {0};
int64_t len = 0;
if (OB_FAIL(ObTimeConverter::datetime_to_str(
in.get_datetime(), tz_info, nls_format, in.get_scale(), buf, sizeof(buf), len))) {
LOG_WARN("failed to convert datetime to string", K(ret));
} else {
out.set_type(expect_type);
ObString tmp_str;
ObObj tmp_out;
if (OB_FAIL(convert_string_collation(
ObString(len, buf), ObCharset::get_system_collation(), tmp_str, params.dest_collation_, params))) {
LOG_WARN("fail to convert string collation", K(ret));
} else if (OB_FAIL(check_convert_string(expect_type, params, tmp_str, tmp_out))) {
LOG_WARN("fail to check_convert_string", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(copy_string(params, expect_type, tmp_out.get_string(), out))) {
} else {
res_length = static_cast<ObLength>(out.get_string_len());
}
}
}
SET_RES_ACCURACY_STRING(expect_type, DEFAULT_PRECISION_FOR_STRING, res_length);
UNUSED(cast_mode);
return ret;
}
static int string_bit(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode);
static int datetime_bit(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
ObObj tmp_val;
if (OB_UNLIKELY(ObDateTimeTC != in.get_type_class() || ObBitTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(datetime_string(ObVarcharType, params, in, tmp_val, cast_mode))) {
LOG_WARN("fail to cast datetime to string", K(ret), K(expect_type), K(in), K(tmp_val));
} else if (OB_FAIL(string_bit(expect_type, params, tmp_val, out, cast_mode))) {
LOG_WARN("fail to cast string to bit", K(ret), K(expect_type), K(in), K(tmp_val));
}
return ret;
}
static int string_enum(const ObExpectType& expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out);
static int datetime_enum(const ObExpectType& expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out)
{
int ret = OB_SUCCESS;
ObObj str_val;
ObCastMode cast_mode = params.cast_mode_;
if (OB_UNLIKELY(ObEnumType != expect_type.get_type()) || OB_UNLIKELY(ObDateTimeTC != in.get_type_class())) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument", K(expect_type), K(in), K(ret));
} else if (OB_FAIL(datetime_string(ObVarcharType, params, in, str_val, cast_mode))) {
LOG_WARN("fail to cast number to double", K(in), K(str_val), K(ret));
} else if (OB_FAIL(string_enum(expect_type, params, str_val, out))) {
LOG_WARN("fail to cast double to enum", K(expect_type), K(out), K(str_val), K(ret));
}
return ret;
}
static int string_set(const ObExpectType& expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out);
static int datetime_set(const ObExpectType& expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out)
{
int ret = OB_SUCCESS;
ObObj str_val;
ObCastMode cast_mode = params.cast_mode_;
if (OB_UNLIKELY(ObSetType != expect_type.get_type()) || OB_UNLIKELY(ObDateTimeTC != in.get_type_class())) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument", K(expect_type), K(in), K(ret));
} else if (OB_FAIL(datetime_string(ObVarcharType, params, in, str_val, cast_mode))) {
LOG_WARN("fail to cast number to double", K(in), K(str_val), K(ret));
} else if (OB_FAIL(string_set(expect_type, params, str_val, out))) {
LOG_WARN("fail to cast double to enum", K(expect_type), K(out), K(str_val), K(ret));
}
return ret;
}
static int datetime_otimestamp(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(ObDateTimeTC != in.get_type_class()) ||
OB_UNLIKELY(ObOTimestampTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else {
int64_t dt_value = 0;
if (ObTimestampType == in.get_type()) {
int64_t utc_value = in.get_timestamp();
if (OB_FAIL(ObTimeConverter::timestamp_to_datetime(utc_value, params.dtc_params_.tz_info_, dt_value))) {
LOG_WARN("failed to convert timestamp to datetime", K(ret));
}
} else {
dt_value = in.get_datetime();
}
if (OB_SUCC(ret)) {
int64_t odate_value = 0;
ObOTimestampData value;
ObTimeConverter::datetime_to_odate(dt_value, odate_value);
if (OB_FAIL(ObTimeConverter::odate_to_otimestamp(odate_value, params.dtc_params_.tz_info_, expect_type, value))) {
LOG_WARN("fail to timestamp_to_timestamp_tz", K(ret), K(in), K(expect_type));
} else {
SET_RES_OTIMESTAMP(out);
}
}
}
SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, in.get_scale(), DEFAULT_LENGTH_FOR_TEMPORAL);
UNUSED(cast_mode);
return ret;
}
CAST_TO_LOB_METHOD(datetime, ObDateTimeTC);
static int datetime_json(const ObObjType expect_type, ObObjCastParams &params,
const ObObj &in, ObObj &out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
ObLength res_length = -1;
if (CM_IS_COLUMN_CONVERT(cast_mode) && is_mysql_unsupported_json_column_conversion(in.get_type())) {
ret = OB_ERR_INVALID_JSON_TEXT;
LOG_USER_ERROR(OB_ERR_INVALID_JSON_TEXT);
} else if (OB_UNLIKELY(ObDateTimeTC != in.get_type_class() || (ObJsonType != expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_UNLIKELY(params.allocator_v2_ == NULL)) {
ret= OB_ERR_UNEXPECTED;
LOG_ERROR("NULL allocator in json cast function", K(ret), K(in), K(expect_type));
} else {
int64_t in_val = in.get_datetime();
ObTime ob_time(DT_TYPE_DATETIME);
const ObTimeZoneInfo *tz_info = (ObTimestampType == in.get_type()) ?
params.dtc_params_.tz_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));
} else {
ObJsonNodeType j_type = (ObTimestampType == in.get_type())
? ObJsonNodeType::J_TIMESTAMP
: ObJsonNodeType::J_DATETIME;
ObJsonDatetime j_datetime(j_type, ob_time);
ObIJsonBase *j_base = &j_datetime;
ObString raw_bin;
if (OB_FAIL(j_base->get_raw_binary(raw_bin, params.allocator_v2_))) {
LOG_WARN("fail to get datetime json binary", K(ret), K(in), K(expect_type), K(*j_base));
} else {
out.set_json_value(expect_type, raw_bin.ptr(), raw_bin.length());
res_length = static_cast<ObLength>(raw_bin.length());
}
}
}
SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_STRING, DEFAULT_SCALE_FOR_TEXT, res_length)
return ret;
}
////////////////////////////////////////////////////////////
// Date -> XXX
static int date_int(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
int64_t value = 0;
ObPrecision res_precision = -1;
if (OB_UNLIKELY(ObDateTC != in.get_type_class() || ObIntTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(ObTimeConverter::date_to_int(in.get_date(), value))) {
} else if (expect_type < ObInt32Type && CAST_FAIL(int_range_check(expect_type, value, value))) {
} else {
out.set_int(expect_type, value);
res_precision = get_precision_for_integer(value);
}
SET_RES_ACCURACY(res_precision, DEFAULT_SCALE_FOR_INTEGER, DEFAULT_LENGTH_FOR_NUMERIC);
return ret;
}
static int date_uint(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
ObPrecision res_precision = -1;
int64_t int64 = 0;
uint64_t value = 0;
if (OB_UNLIKELY(ObDateTC != in.get_type_class() || ObUIntTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(ObTimeConverter::date_to_int(in.get_date(), int64))) {
} else {
value = static_cast<uint64_t>(int64);
if (expect_type < ObUInt32Type && CAST_FAIL(uint_range_check(expect_type, int64, value))) {
} else {
out.set_uint(expect_type, value);
res_precision = get_precision_for_integer(value);
}
}
SET_RES_ACCURACY(res_precision, DEFAULT_SCALE_FOR_INTEGER, DEFAULT_LENGTH_FOR_NUMERIC);
return ret;
}
static int date_float(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
int64_t value = 0;
if (OB_UNLIKELY(ObDateTC != in.get_type_class() || ObFloatTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(ObTimeConverter::date_to_int(in.get_date(), value))) {
} else {
out.set_float(expect_type, static_cast<float>(value));
}
SET_RES_ACCURACY(PRECISION_UNKNOWN_YET, SCALE_UNKNOWN_YET, LENGTH_UNKNOWN_YET);
UNUSED(cast_mode);
return ret;
}
static int date_double(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
int64_t value = 0;
if (OB_UNLIKELY(ObDateTC != in.get_type_class() || ObDoubleTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(ObTimeConverter::date_to_int(in.get_date(), value))) {
} else {
out.set_double(expect_type, static_cast<double>(value));
}
SET_RES_ACCURACY(PRECISION_UNKNOWN_YET, SCALE_UNKNOWN_YET, LENGTH_UNKNOWN_YET);
UNUSED(cast_mode);
return ret;
}
static int date_number(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
ObObj obj_int;
if (OB_UNLIKELY(ObDateTC != in.get_type_class() || ObNumberTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(date_int(ObIntType, params, in, obj_int, cast_mode))) {
} else if (OB_FAIL(int_number(expect_type, params, obj_int, out, cast_mode))) {
}
// has set accuracy in prev int_number
return ret;
}
static int date_datetime(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(ObDateTC != in.get_type_class() || ObDateTimeTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else {
ObTimeConvertCtx cvrt_ctx(params.dtc_params_.tz_info_, ObTimestampType == expect_type);
int64_t value = 0;
if (OB_FAIL(ObTimeConverter::date_to_datetime(in.get_date(), cvrt_ctx, value))) {
} else {
out.set_datetime(expect_type, value);
}
}
SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, MIN_SCALE_FOR_TEMPORAL, DEFAULT_LENGTH_FOR_TEMPORAL);
UNUSED(cast_mode);
return ret;
}
static int date_time(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(ObDateTC != in.get_type_class() || ObTimeTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else {
out.set_time(ObTimeConverter::ZERO_TIME);
}
SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, MIN_SCALE_FOR_TEMPORAL, DEFAULT_LENGTH_FOR_TEMPORAL);
UNUSED(cast_mode);
return OB_SUCCESS;
}
static int date_year(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
uint8_t value = 0;
if (OB_UNLIKELY(ObDateTC != in.get_type_class() || ObYearTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (CAST_FAIL(ObTimeConverter::date_to_year(in.get_date(), value))) {
} else {
SET_RES_YEAR(out);
}
SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, DEFAULT_SCALE_FOR_YEAR, DEFAULT_LENGTH_FOR_TEMPORAL);
UNUSED(cast_mode);
return ret;
}
static int date_string(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
char buf[OB_CAST_TO_VARCHAR_MAX_LENGTH] = {0};
int64_t len = 0;
ObLength res_length = -1;
if (OB_UNLIKELY(ObDateTC != in.get_type_class() ||
(ObStringTC != ob_obj_type_class(expect_type) && ObTextTC != ob_obj_type_class(expect_type)))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(ObTimeConverter::date_to_str(in.get_date(), buf, sizeof(buf), len))) {
} else {
out.set_type(expect_type);
ret = copy_string(params, expect_type, buf, len, out);
if (OB_SUCC(ret)) {
res_length = static_cast<ObLength>(out.get_string_len());
}
}
SET_RES_ACCURACY_STRING(expect_type, DEFAULT_PRECISION_FOR_STRING, res_length);
UNUSED(cast_mode);
return ret;
}
static int date_bit(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
ObObj tmp_val;
if (OB_UNLIKELY(ObDateTC != in.get_type_class() || ObBitTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(date_string(ObVarcharType, params, in, tmp_val, cast_mode))) {
LOG_WARN("fail to cast datetime to string", K(ret), K(expect_type), K(in), K(tmp_val));
} else if (OB_FAIL(string_bit(expect_type, params, tmp_val, out, cast_mode))) {
LOG_WARN("fail to cast string to bit", K(ret), K(expect_type), K(in), K(tmp_val));
}
return ret;
}
static int date_enum(const ObExpectType& expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out)
{
int ret = OB_SUCCESS;
ObObj str_val;
ObCastMode cast_mode = params.cast_mode_;
if (OB_UNLIKELY(ObEnumType != expect_type.get_type()) || OB_UNLIKELY(ObDateTC != in.get_type_class())) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument", K(expect_type), K(in), K(ret));
} else if (OB_FAIL(date_string(ObVarcharType, params, in, str_val, cast_mode))) {
LOG_WARN("fail to cast number to double", K(in), K(str_val), K(ret));
} else if (OB_FAIL(string_enum(expect_type, params, str_val, out))) {
LOG_WARN("fail to cast double to enum", K(expect_type), K(out), K(str_val), K(ret));
}
return ret;
}
static int date_set(const ObExpectType& expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out)
{
int ret = OB_SUCCESS;
ObObj str_val;
ObCastMode cast_mode = params.cast_mode_;
if (OB_UNLIKELY(ObSetType != expect_type.get_type()) || OB_UNLIKELY(ObDateTC != in.get_type_class())) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument", K(expect_type), K(in), K(ret));
} else if (OB_FAIL(date_string(ObVarcharType, params, in, str_val, cast_mode))) {
LOG_WARN("fail to cast number to double", K(in), K(str_val), K(ret));
} else if (OB_FAIL(string_set(expect_type, params, str_val, out))) {
LOG_WARN("fail to cast double to enum", K(expect_type), K(out), K(str_val), K(ret));
}
return ret;
}
CAST_TO_LOB_METHOD(date, ObDateTC);
static int date_json(const ObObjType expect_type, ObObjCastParams &params,
const ObObj &in, ObObj &out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
ObLength res_length = -1;
if (CM_IS_COLUMN_CONVERT(cast_mode) && is_mysql_unsupported_json_column_conversion(in.get_type())) {
ret = OB_ERR_INVALID_JSON_TEXT;
LOG_USER_ERROR(OB_ERR_INVALID_JSON_TEXT);
} else if (OB_UNLIKELY(ObDateTC != in.get_type_class() || (ObJsonType != expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_UNLIKELY(params.allocator_v2_ == NULL)) {
ret= OB_ERR_UNEXPECTED;
LOG_ERROR("NULL allocator in json cast function", K(ret), K(in), K(expect_type));
} else {
int32_t in_val = in.get_date();
ObTime ob_time(DT_TYPE_DATE);
if (OB_FAIL(ObTimeConverter::date_to_ob_time(in_val, ob_time))) {
LOG_WARN("fail to create datetime from int failed", K(ret), K(in));
} else {
ObJsonDatetime j_date(ObJsonNodeType::J_DATE, ob_time);
ObIJsonBase *j_base = &j_date;
ObString raw_bin;
if (OB_FAIL(j_base->get_raw_binary(raw_bin, params.allocator_v2_))) {
LOG_WARN("fail to get date json binary", K(ret), K(in), K(expect_type), K(*j_base));
} else {
out.set_json_value(expect_type, raw_bin.ptr(), raw_bin.length());
res_length = static_cast<ObLength>(raw_bin.length());
}
}
}
SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_STRING, DEFAULT_SCALE_FOR_TEXT, res_length)
return ret;
}
////////////////////////////////////////////////////////////
// Time -> XXX
static int time_int(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
int64_t value = 0;
ObPrecision res_precision = -1;
if (OB_UNLIKELY(ObTimeTC != in.get_type_class() || ObIntTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(ObTimeConverter::time_to_int(in.get_time(), value))) {
} else if (expect_type < ObInt32Type && CAST_FAIL(int_range_check(expect_type, value, value))) {
} else {
out.set_int(expect_type, value);
res_precision = get_precision_for_integer(value);
}
SET_RES_ACCURACY(res_precision, DEFAULT_SCALE_FOR_INTEGER, DEFAULT_LENGTH_FOR_NUMERIC);
return ret;
}
static int time_uint(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
int64_t int64 = 0;
uint64_t value = 0;
ObPrecision res_precision = -1;
if (OB_UNLIKELY(ObTimeTC != in.get_type_class() || ObUIntTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(ObTimeConverter::time_to_int(in.get_time(), int64))) {
} else {
value = static_cast<uint64_t>(int64);
if (CM_NEED_RANGE_CHECK(cast_mode) && CAST_FAIL(uint_range_check(expect_type, int64, value))) {
} else {
out.set_uint(expect_type, value);
res_precision = get_precision_for_integer(value);
}
}
SET_RES_ACCURACY(res_precision, DEFAULT_SCALE_FOR_INTEGER, DEFAULT_LENGTH_FOR_NUMERIC);
return ret;
}
static int time_float(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
double value = 0.0;
if (OB_UNLIKELY(ObTimeTC != in.get_type_class() || ObFloatTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(ObTimeConverter::time_to_double(in.get_time(), value))) {
} else if (ObUFloatType == expect_type && CAST_FAIL(numeric_negative_check(value))) {
} else {
// if time_to_double return OB_SUCCESS, double value must be in (INT64_MIN, INT64_MAX),
// so we can static_cast to float without range check.
out.set_float(expect_type, static_cast<float>(value));
}
SET_RES_ACCURACY(PRECISION_UNKNOWN_YET, SCALE_UNKNOWN_YET, LENGTH_UNKNOWN_YET);
return ret;
}
static int time_double(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
double value = 0.0;
if (OB_UNLIKELY(ObTimeTC != in.get_type_class() || ObDoubleTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(ObTimeConverter::time_to_double(in.get_time(), value))) {
} else if (ObUDoubleType == expect_type && CAST_FAIL(numeric_negative_check(value))) {
} else {
out.set_double(expect_type, value);
}
SET_RES_ACCURACY(PRECISION_UNKNOWN_YET, SCALE_UNKNOWN_YET, LENGTH_UNKNOWN_YET);
UNUSED(cast_mode);
return ret;
}
static int time_number(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
char buf[OB_CAST_TO_VARCHAR_MAX_LENGTH] = {0};
int64_t len = 0;
number::ObNumber value;
ObPrecision res_precision = -1;
ObScale res_scale = -1;
if (OB_UNLIKELY(ObTimeTC != in.get_type_class() || ObNumberTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(ObTimeConverter::time_to_str(in.get_time(), in.get_scale(), buf, sizeof(buf), len, false))) {
} else if (CAST_FAIL(value.from(buf, len, params, &res_precision, &res_scale))) {
} else {
out.set_number(expect_type, value);
}
SET_RES_ACCURACY(res_precision, res_scale, DEFAULT_LENGTH_FOR_NUMERIC);
return ret;
}
static int time_datetime(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
const ObTimeZoneInfo* tz_info = params.dtc_params_.tz_info_;
int64_t value = 0;
if (OB_UNLIKELY(ObTimeTC != in.get_type_class() || ObDateTimeTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(ObTimeConverter::time_to_datetime(in.get_time(), params.cur_time_, tz_info, value, expect_type))) {
} else {
out.set_datetime(expect_type, value);
}
SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, in.get_scale(), DEFAULT_LENGTH_FOR_TEMPORAL);
UNUSED(cast_mode);
return ret;
}
static int time_date(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
const ObTimeZoneInfo* tz_info = params.dtc_params_.tz_info_;
int32_t value = 0;
if (OB_UNLIKELY(ObTimeTC != in.get_type_class() || ObDateTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type",
K(ret), K(in), K(expect_type));
} else if (OB_FAIL(ObTimeConverter::datetime_to_date(params.cur_time_, tz_info, value))) {
LOG_WARN("datetime_to_date failed", K(ret), K(params.cur_time_));
} else {
out.set_date(value);
}
SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, DEFAULT_SCALE_FOR_DATE, DEFAULT_LENGTH_FOR_TEMPORAL);
UNUSED(cast_mode);
return ret;
}
static int time_string(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
char buf[OB_CAST_TO_VARCHAR_MAX_LENGTH] = {0};
int64_t len = 0;
ObLength res_length = -1;
if (OB_UNLIKELY(ObTimeTC != in.get_type_class() ||
(ObStringTC != ob_obj_type_class(expect_type) && ObTextTC != ob_obj_type_class(expect_type)))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(ObTimeConverter::time_to_str(in.get_time(), in.get_scale(), buf, sizeof(buf), len))) {
} else {
out.set_type(expect_type);
ret = copy_string(params, expect_type, buf, len, out);
if (OB_SUCC(ret)) {
res_length = static_cast<ObLength>(out.get_string_len());
}
}
SET_RES_ACCURACY_STRING(expect_type, DEFAULT_PRECISION_FOR_STRING, res_length);
UNUSED(cast_mode);
return ret;
}
static int time_bit(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
ObObj tmp_val;
if (OB_UNLIKELY(ObTimeTC != in.get_type_class() || ObBitTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(time_string(ObVarcharType, params, in, tmp_val, cast_mode))) {
LOG_WARN("fail to cast datetime to string", K(ret), K(expect_type), K(in), K(tmp_val));
} else if (OB_FAIL(string_bit(expect_type, params, tmp_val, out, cast_mode))) {
LOG_WARN("fail to cast string to bit", K(ret), K(expect_type), K(in), K(tmp_val));
}
return ret;
}
static int time_enum(const ObExpectType& expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out)
{
int ret = OB_SUCCESS;
ObObj str_val;
ObCastMode cast_mode = params.cast_mode_;
if (OB_UNLIKELY(ObEnumType != expect_type.get_type()) || OB_UNLIKELY(ObTimeTC != in.get_type_class())) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument", K(expect_type), K(in), K(ret));
} else if (OB_FAIL(time_string(ObVarcharType, params, in, str_val, cast_mode))) {
LOG_WARN("fail to cast number to double", K(in), K(str_val), K(ret));
} else if (OB_FAIL(string_enum(expect_type, params, str_val, out))) {
LOG_WARN("fail to cast double to enum", K(expect_type), K(out), K(str_val), K(ret));
}
return ret;
}
static int time_set(const ObExpectType& expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out)
{
int ret = OB_SUCCESS;
ObObj str_val;
ObCastMode cast_mode = params.cast_mode_;
if (OB_UNLIKELY(ObSetType != expect_type.get_type()) || OB_UNLIKELY(ObTimeTC != in.get_type_class())) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument", K(expect_type), K(in), K(ret));
} else if (OB_FAIL(time_string(ObVarcharType, params, in, str_val, cast_mode))) {
LOG_WARN("fail to cast number to double", K(in), K(str_val), K(ret));
} else if (OB_FAIL(string_set(expect_type, params, str_val, out))) {
LOG_WARN("fail to cast double to enum", K(expect_type), K(out), K(str_val), K(ret));
}
return ret;
}
CAST_TO_LOB_METHOD(time, ObTimeTC);
static int time_json(const ObObjType expect_type, ObObjCastParams &params,
const ObObj &in, ObObj &out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
ObLength res_length = -1;
if (CM_IS_COLUMN_CONVERT(cast_mode) && is_mysql_unsupported_json_column_conversion(in.get_type())) {
ret = OB_ERR_INVALID_JSON_TEXT;
LOG_USER_ERROR(OB_ERR_INVALID_JSON_TEXT);
} else if (OB_UNLIKELY(ObTimeTC != in.get_type_class() || (ObJsonType != expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_UNLIKELY(params.allocator_v2_ == NULL)) {
ret= OB_ERR_UNEXPECTED;
LOG_ERROR("NULL allocator in json cast function", K(ret), K(in), K(expect_type));
} else {
int64_t in_val = in.get_int();
ObTime ob_time(DT_TYPE_TIME);
if (OB_FAIL(ObTimeConverter::time_to_ob_time(in_val, ob_time))) {
LOG_WARN("fail to create datetime from int failed", K(ret), K(in));
} else {
ObJsonDatetime j_time(ObJsonNodeType::J_TIME, ob_time);
ObIJsonBase *j_base = &j_time;
ObString raw_bin;
if (OB_FAIL(j_base->get_raw_binary(raw_bin, params.allocator_v2_))) {
LOG_WARN("fail to get time json binary", K(ret), K(in), K(expect_type), K(*j_base));
} else {
out.set_json_value(expect_type, raw_bin.ptr(), raw_bin.length());
res_length = static_cast<ObLength>(raw_bin.length());
}
}
}
SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_STRING, DEFAULT_SCALE_FOR_TEXT, res_length)
return ret;
}
////////////////////////////////////////////////////////////
// Year -> XXX
static int year_int(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
int64_t value = 0;
ObPrecision res_precision = -1;
if (OB_UNLIKELY(ObYearTC != in.get_type_class() || ObIntTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(ObTimeConverter::year_to_int(in.get_year(), value))) {
} else if (expect_type < ObSmallIntType && CAST_FAIL(int_range_check(expect_type, value, value))) {
} else {
out.set_int(expect_type, value);
res_precision = get_precision_for_integer(value);
}
SET_RES_ACCURACY(res_precision, DEFAULT_SCALE_FOR_INTEGER, DEFAULT_LENGTH_FOR_NUMERIC);
return ret;
}
static int year_uint(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
int64_t int64 = 0;
uint64_t value = 0;
ObPrecision res_precision = -1;
if (OB_UNLIKELY(ObYearTC != in.get_type_class() || ObUIntTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(ObTimeConverter::year_to_int(in.get_year(), int64))) {
} else {
value = static_cast<uint64_t>(int64);
if (expect_type < ObUSmallIntType && CAST_FAIL(uint_range_check(expect_type, int64, value))) {
} else {
out.set_uint(expect_type, value);
res_precision = get_precision_for_integer(value);
}
}
SET_RES_ACCURACY(res_precision, DEFAULT_SCALE_FOR_INTEGER, DEFAULT_LENGTH_FOR_NUMERIC);
return ret;
}
static int year_float(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
int64_t value = 0;
if (OB_UNLIKELY(ObYearTC != in.get_type_class() || ObFloatTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(ObTimeConverter::year_to_int(in.get_year(), value))) {
} else {
out.set_float(expect_type, static_cast<float>(value));
}
SET_RES_ACCURACY(PRECISION_UNKNOWN_YET, SCALE_UNKNOWN_YET, LENGTH_UNKNOWN_YET);
UNUSED(cast_mode);
return ret;
}
static int year_double(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
int64_t value = 0;
if (OB_UNLIKELY(ObYearTC != in.get_type_class() || ObDoubleTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(ObTimeConverter::year_to_int(in.get_year(), value))) {
} else {
out.set_double(expect_type, static_cast<double>(value));
}
SET_RES_ACCURACY(PRECISION_UNKNOWN_YET, SCALE_UNKNOWN_YET, LENGTH_UNKNOWN_YET);
UNUSED(cast_mode);
return ret;
}
static int year_number(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
ObObj obj_int;
if (OB_UNLIKELY(ObYearTC != in.get_type_class() || ObNumberTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(year_int(ObIntType, params, in, obj_int, cast_mode))) {
} else if (OB_FAIL(int_number(expect_type, params, obj_int, out, cast_mode))) {
}
// has set accuracy in prev int_number
return ret;
}
static int year_date(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
int64_t in_value = 0;
if (OB_UNLIKELY(ObYearTC != in.get_type_class() || ObDateTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type",
K(ret), K(in), K(expect_type));
} else if (OB_FAIL(ObTimeConverter::year_to_int(in.get_year(), in_value))) {
} else {
int32_t value = 0;
if (CAST_FAIL(ObTimeConverter::int_to_date(in_value, value))) {
} else {
SET_RES_DATE(out);
}
}
SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, DEFAULT_SCALE_FOR_DATE, DEFAULT_LENGTH_FOR_TEMPORAL);
return ret;
}
static int year_string(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
char buf[OB_CAST_TO_VARCHAR_MAX_LENGTH] = {0};
int64_t len = 0;
ObLength res_length = -1;
if (OB_UNLIKELY(ObYearTC != in.get_type_class() ||
(ObStringTC != ob_obj_type_class(expect_type) && ObTextTC != ob_obj_type_class(expect_type)))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(ObTimeConverter::year_to_str(in.get_year(), buf, sizeof(buf), len))) {
} else {
out.set_type(expect_type);
ret = copy_string(params, expect_type, buf, len, out);
if (OB_SUCC(ret)) {
res_length = static_cast<ObLength>(out.get_string_len());
}
}
SET_RES_ACCURACY_STRING(expect_type, DEFAULT_PRECISION_FOR_STRING, res_length);
UNUSED(cast_mode);
return ret;
}
static int year_bit(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
ObObj tmp_val;
if (OB_UNLIKELY(ObYearTC != in.get_type_class() || ObBitTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(year_int(ObIntType, params, in, tmp_val, cast_mode))) {
LOG_WARN("fail to cast datetime to int", K(ret), K(expect_type), K(in), K(tmp_val));
} else if (OB_FAIL(int_bit(expect_type, params, tmp_val, out, cast_mode))) {
LOG_WARN("fail to cast int to bit", K(ret), K(expect_type), K(in), K(tmp_val));
}
return ret;
}
static int year_enum(const ObExpectType& expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out)
{
int ret = OB_SUCCESS;
ObObj uint_val;
ObCastMode cast_mode = params.cast_mode_;
if (OB_UNLIKELY(ObEnumType != expect_type.get_type()) || OB_UNLIKELY(ObYearTC != in.get_type_class())) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument", K(expect_type), K(in), K(ret));
} else if (OB_FAIL(year_uint(ObUInt64Type, params, in, uint_val, cast_mode))) {
LOG_WARN("fail to cast number to double", K(in), K(uint_val), K(ret));
} else if (OB_FAIL(uint_enum(expect_type, params, uint_val, out))) {
LOG_WARN("fail to cast double to enum", K(expect_type), K(out), K(uint_val), K(ret));
}
return ret;
}
static int year_set(const ObExpectType& expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out)
{
int ret = OB_SUCCESS;
ObObj uint_val;
ObCastMode cast_mode = params.cast_mode_;
if (OB_UNLIKELY(ObSetType != expect_type.get_type()) || OB_UNLIKELY(ObYearTC != in.get_type_class())) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument", K(expect_type), K(in), K(ret));
} else if (OB_FAIL(year_uint(ObUInt64Type, params, in, uint_val, cast_mode))) {
LOG_WARN("fail to cast number to double", K(in), K(uint_val), K(ret));
} else if (OB_FAIL(uint_set(expect_type, params, uint_val, out))) {
LOG_WARN("fail to cast double to enum", K(expect_type), K(out), K(uint_val), K(ret));
}
return ret;
}
CAST_TO_LOB_METHOD(year, ObYearTC);
static int year_json(const ObObjType expect_type, ObObjCastParams &params,
const ObObj &in, ObObj &out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
ObLength res_length = -1;
int64_t full_year = 0;
if (CM_IS_COLUMN_CONVERT(cast_mode) && is_mysql_unsupported_json_column_conversion(in.get_type())) {
ret = OB_ERR_INVALID_JSON_TEXT;
LOG_USER_ERROR(OB_ERR_INVALID_JSON_TEXT);
} else if (OB_UNLIKELY(ObYearTC != in.get_type_class() || (ObJsonType != expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_UNLIKELY(params.allocator_v2_ == NULL)) {
ret= OB_ERR_UNEXPECTED;
LOG_ERROR("NULL allocator in json cast function", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(ObTimeConverter::year_to_int(in.get_year(), full_year))) {
LOG_WARN("convert year to int failed in year to json convert", K(ret), K(in.get_year()));
} else {
ObJsonInt j_year(full_year);
ObIJsonBase *j_base = &j_year;
ObString raw_bin;
if (OB_FAIL(j_base->get_raw_binary(raw_bin, params.allocator_v2_))) {
LOG_WARN("fail to get year json binary", K(ret), K(in), K(expect_type), K(*j_base));
} else {
out.set_json_value(expect_type, raw_bin.ptr(), raw_bin.length());
res_length = static_cast<ObLength>(raw_bin.length());
}
}
SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_STRING, DEFAULT_SCALE_FOR_TEXT, res_length)
return ret;
}
////////////////////////////////////////////////////////////
// String -> XXX
int common_string_unsigned_integer(const ObCastMode& cast_mode, const ObObjType& in_type, const ObString& in_str,
const bool is_str_integer_cast, uint64_t& out_val)
{
int ret = OB_SUCCESS;
if (ObHexStringType == in_type) {
out_val = hex_to_uint64(in_str);
} else {
int err = 0;
char* endptr = NULL;
if (is_str_integer_cast && CM_IS_STRING_INTEGER_TRUNC(cast_mode)) {
out_val = ObCharset::strntoull(in_str.ptr(), in_str.length(), 10, &endptr, &err);
if (ERANGE == err && (INT64_MIN == out_val || INT64_MAX == out_val)) {
ret = OB_DATA_OUT_OF_RANGE;
} else if (endptr == in_str.ptr() || endptr != in_str.ptr() + in_str.length()) {
ret = OB_ERR_TRUNCATED_WRONG_VALUE;
if (CM_IS_WARN_ON_FAIL(cast_mode)) {
ObString tmp_msg("INTEGER");
LOG_USER_WARN(OB_ERR_TRUNCATED_WRONG_VALUE, tmp_msg.length(), tmp_msg.ptr(), in_str.length(), in_str.ptr());
}
}
} else {
out_val = ObCharset::strntoullrnd(in_str.ptr(), in_str.length(), true, &endptr, &err);
if (ERANGE == err && (0 == out_val || UINT64_MAX == out_val)) {
ret = OB_DATA_OUT_OF_RANGE;
} else {
ret = check_convert_str_err(in_str.ptr(), endptr, in_str.length(), err);
}
}
}
return ret;
}
int common_string_integer(const ObCastMode& cast_mode, const ObObjType& in_type, const ObString& in_str,
const bool is_str_integer_cast, int64_t& out_val)
{
int ret = OB_SUCCESS;
if (ObHexStringType == in_type) {
out_val = static_cast<int64_t>(hex_to_uint64(in_str));
} else {
int err = 0;
char* endptr = NULL;
if (is_str_integer_cast && CM_IS_STRING_INTEGER_TRUNC(cast_mode)) {
out_val = ObCharset::strntoll(in_str.ptr(), in_str.length(), 10, &endptr, &err);
if (ERANGE == err && (INT64_MIN == out_val || INT64_MAX == out_val)) {
ret = OB_DATA_OUT_OF_RANGE;
} else if (endptr == in_str.ptr() || endptr != in_str.ptr() + in_str.length()) {
ret = OB_ERR_TRUNCATED_WRONG_VALUE;
if (CM_IS_WARN_ON_FAIL(cast_mode)) {
ObString tmp_msg("INTEGER");
LOG_USER_WARN(OB_ERR_TRUNCATED_WRONG_VALUE, tmp_msg.length(), tmp_msg.ptr(), in_str.length(), in_str.ptr());
}
}
} else {
out_val = static_cast<int64_t>(ObCharset::strntoullrnd(in_str.ptr(), in_str.length(), false, &endptr, &err));
if (ERANGE == err && (INT64_MIN == out_val || INT64_MAX == out_val)) {
ret = OB_DATA_OUT_OF_RANGE;
} else {
ret = check_convert_str_err(in_str.ptr(), endptr, in_str.length(), err);
}
}
}
return ret;
}
static int string_int(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
ObPrecision res_precision = -1;
if (OB_UNLIKELY((ObStringTC != in.get_type_class() && ObTextTC != in.get_type_class()) ||
ObIntTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (lib::is_oracle_mode() && in.is_blob()) {
ret = OB_NOT_SUPPORTED;
LOG_ERROR("invalid use of blob type", K(ret), K(in), K(expect_type));
LOG_USER_ERROR(OB_NOT_SUPPORTED, "Cast to blob type");
} else {
const ObString& str = in.get_string();
int64_t value = 0;
const bool is_str_int_cast = true;
if (CAST_FAIL(common_string_integer(cast_mode, in.get_type(), str, is_str_int_cast, value))) {
} else if (expect_type < ObIntType && CAST_FAIL(int_range_check(expect_type, value, value))) {
} else {
SET_RES_INT(out);
}
}
if (OB_SUCC(ret)) {
res_precision = get_precision_for_integer(out.get_int());
}
SET_RES_ACCURACY(res_precision, DEFAULT_SCALE_FOR_INTEGER, DEFAULT_LENGTH_FOR_NUMERIC);
return ret;
}
static int string_uint(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
ObPrecision res_precision = -1;
if (OB_UNLIKELY((ObStringTC != in.get_type_class() && ObTextTC != in.get_type_class()) ||
ObUIntTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (lib::is_oracle_mode() && in.is_blob()) {
ret = OB_NOT_SUPPORTED;
LOG_ERROR("invalid use of blob type", K(ret), K(in), K(expect_type));
LOG_USER_ERROR(OB_NOT_SUPPORTED, "Cast to blob type");
} else {
const ObString& str = in.get_string();
uint64_t value = 0;
const bool is_str_int_cast = true;
if (CAST_FAIL(common_string_unsigned_integer(cast_mode, in.get_type(), str, is_str_int_cast, value))) {
} else if (expect_type < ObUInt64Type && CM_NEED_RANGE_CHECK(cast_mode) &&
CAST_FAIL(uint_upper_check(expect_type, value))) {
} else {
SET_RES_UINT(out);
}
}
if (OB_SUCC(ret)) {
res_precision = get_precision_for_integer(out.get_uint64());
}
SET_RES_ACCURACY(res_precision, DEFAULT_SCALE_FOR_INTEGER, DEFAULT_LENGTH_FOR_NUMERIC);
return ret;
}
static int string_float(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
ObObj dbl;
if (OB_UNLIKELY((ObStringTC != in.get_type_class() && ObTextTC != in.get_type_class()) ||
ObFloatTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (lib::is_oracle_mode() && in.is_blob()) {
ret = OB_NOT_SUPPORTED;
LOG_ERROR("invalid use of blob type", K(ret), K(in), K(expect_type));
LOG_USER_ERROR(OB_NOT_SUPPORTED, "Cast to blob type");
} else if (OB_FAIL(string_double(ObDoubleType, params, in, dbl, cast_mode))) {
} else if (OB_FAIL(double_float(expect_type, params, dbl, out, cast_mode))) {
}
// has set accuracy in prev double_float call
return ret;
}
static int string_double(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY((ObStringTC != in.get_type_class() && ObTextTC != in.get_type_class()) ||
ObDoubleTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (lib::is_oracle_mode() && in.is_blob()) {
ret = OB_NOT_SUPPORTED;
LOG_ERROR("invalid use of blob type", K(ret), K(in), K(expect_type));
LOG_USER_ERROR(OB_NOT_SUPPORTED, "Cast to blob type");
} else {
double value = 0.0;
if (ObHexStringType == in.get_type()) {
value = static_cast<double>(hex_to_uint64(in.get_string()));
} else {
int err = 0;
char* endptr = NULL;
ObString str_utf8;
if (OB_FAIL(convert_string_collation(
in.get_string(), in.get_collation_type(), str_utf8, ObCharset::get_system_collation(), params))) {
LOG_WARN("convert_string_collation", K(ret), K(str_utf8), K(in.get_string()));
} else {
value = ObCharset::strntod(str_utf8.ptr(), str_utf8.length(), &endptr, &err);
if (EOVERFLOW == err && (-DBL_MAX == value || DBL_MAX == value)) {
ret = OB_DATA_OUT_OF_RANGE;
} else {
ObString trimed_str = str_utf8.trim();
if (lib::is_mysql_mode() && 0 == trimed_str.length()) {
if (!CM_IS_COLUMN_CONVERT(cast_mode)) {
// skip
} else {
ret = OB_ERR_DOUBLE_TRUNCATED;
LOG_WARN("convert string to double failed", K(ret), K(str_utf8));
}
} else if (OB_SUCCESS != (ret = check_convert_str_err(str_utf8.ptr(), endptr, str_utf8.length(), err))) {
LOG_WARN("failed to check_convert_str_err", K(ret), K(str_utf8), K(value), K(err));
ret = OB_ERR_DOUBLE_TRUNCATED;
if (CM_IS_WARN_ON_FAIL(cast_mode)) {
LOG_USER_WARN(OB_ERR_DOUBLE_TRUNCATED, str_utf8.length(), str_utf8.ptr());
}
}
}
}
}
if (CAST_FAIL(ret)) {
} else if (ObUDoubleType == expect_type && CAST_FAIL(numeric_negative_check(value))) {
} else {
SET_RES_DOUBLE(out);
}
}
SET_RES_ACCURACY(PRECISION_UNKNOWN_YET, SCALE_UNKNOWN_YET, LENGTH_UNKNOWN_YET);
return ret;
}
static int string_number(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
ObPrecision res_precision = PRECISION_UNKNOWN_YET;
ObScale res_scale = NUMBER_SCALE_UNKNOWN_YET;
ObString utf8_string;
if (OB_ISNULL(params.allocator_v2_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("invalid allocator", K(ret));
} else if (OB_UNLIKELY((ObStringTC != in.get_type_class() && ObTextTC != in.get_type_class()) ||
ObNumberTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (lib::is_oracle_mode() && in.is_blob()) {
ret = OB_NOT_SUPPORTED;
LOG_ERROR("invalid use of blob type", K(ret), K(in), K(expect_type));
LOG_USER_ERROR(OB_NOT_SUPPORTED, "Cast to blob type");
} else {
number::ObNumber value;
if (ObHexStringType == in.get_type()) {
ret = value.from(hex_to_uint64(in.get_string()), params);
} else if (OB_UNLIKELY(0 == in.get_string().length())) {
value.set_zero();
ret = OB_ERR_TRUNCATED_WRONG_VALUE_FOR_FIELD;
} else if (OB_FAIL(convert_string_collation(
in.get_string(), in.get_collation_type(), utf8_string, ObCharset::get_system_collation(), params))) {
LOG_WARN("convert_string_collation", K(ret));
} else {
const ObString& str = utf8_string;
ret = value.from_sci_opt(str.ptr(), str.length(), params, &res_precision, &res_scale);
// select cast('1e500' as decimal); -> max_val
// select cast('-1e500' as decimal); -> min_val
if (ret == OB_NUMERIC_OVERFLOW) {
int64_t i = 0;
while (i < str.length() && isspace(str[i])) {
++i;
}
bool is_neg = (str[i] == '-');
int tmp_ret = OB_SUCCESS;
const ObAccuracy& def_acc = ObAccuracy::DDL_DEFAULT_ACCURACY2[0][expect_type];
const ObPrecision prec = def_acc.get_precision();
const ObScale scale = def_acc.get_scale();
const ObNumber* bound_num = NULL;
if (is_neg) {
bound_num = &(ObNumberConstValue::MYSQL_MIN[prec][scale]);
} else {
bound_num = &(ObNumberConstValue::MYSQL_MAX[prec][scale]);
}
if (OB_ISNULL(bound_num)) {
tmp_ret = OB_ERR_UNEXPECTED;
LOG_WARN("bound_num is NULL", K(tmp_ret), K(ret), K(is_neg));
} else if (OB_SUCCESS != (tmp_ret = value.from(*bound_num, *params.allocator_v2_))) {
LOG_WARN("copy min number failed", K(ret), K(tmp_ret), KPC(bound_num));
}
}
}
if (CAST_FAIL(ret)) {
} else if (ObUNumberType == expect_type && CAST_FAIL(numeric_negative_check(value))) {
} else {
out.set_number(expect_type, value);
}
}
SET_RES_ACCURACY(res_precision, res_scale, DEFAULT_LENGTH_FOR_NUMERIC);
return ret;
}
static int string_datetime(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
ObScale res_scale = -1;
ObString utf8_string;
if (OB_UNLIKELY((ObStringTC != in.get_type_class() && ObTextTC != in.get_type_class()) ||
ObDateTimeTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (lib::is_oracle_mode() && in.is_blob()) {
ret = OB_NOT_SUPPORTED;
LOG_ERROR("invalid use of blob type", K(ret), K(in), K(expect_type));
LOG_USER_ERROR(OB_NOT_SUPPORTED, "Cast to blob type");
} else if (OB_FAIL(convert_string_collation(
in.get_string(), in.get_collation_type(), utf8_string, ObCharset::get_system_collation(), params))) {
LOG_WARN("convert_string_collation", K(ret));
} else {
int64_t value = 0;
ObTimeConvertCtx cvrt_ctx(params.dtc_params_.tz_info_, ObTimestampType == expect_type);
if (lib::is_oracle_mode()) {
cvrt_ctx.oracle_nls_format_ = params.dtc_params_.get_nls_format(ObDateTimeType);
CAST_RET(ObTimeConverter::str_to_date_oracle(utf8_string, cvrt_ctx, value));
} else {
CAST_RET(ObTimeConverter::str_to_datetime(utf8_string, cvrt_ctx, value, &res_scale));
}
// check zero date for scale over mode
if (CM_IS_ERROR_ON_SCALE_OVER(cast_mode) &&
(value == ObTimeConverter::ZERO_DATE ||
value == ObTimeConverter::ZERO_DATETIME)) {
ret = OB_INVALID_DATE_VALUE;
LOG_USER_ERROR(OB_INVALID_DATE_VALUE, utf8_string.length(), utf8_string.ptr(), "");
}
if (OB_SUCC(ret)) {
SET_RES_DATETIME(out);
}
}
SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, res_scale, DEFAULT_LENGTH_FOR_TEMPORAL);
return ret;
}
static int string_date(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
int32_t value = 0;
if (OB_UNLIKELY((ObStringTC != in.get_type_class() && ObTextTC != in.get_type_class()) ||
ObDateTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (lib::is_oracle_mode() && in.is_blob()) {
ret = OB_NOT_SUPPORTED;
LOG_ERROR("invalid use of blob type", K(ret), K(in), K(expect_type));
LOG_USER_ERROR(OB_NOT_SUPPORTED, "Cast to blob type");
} else if (CAST_FAIL(ObTimeConverter::str_to_date(in.get_string(), value))) {
} else if (CM_IS_ERROR_ON_SCALE_OVER(cast_mode) && value == ObTimeConverter::ZERO_DATE) {
// check zero date for scale over mode
ret = OB_INVALID_DATE_VALUE;
LOG_USER_ERROR(OB_INVALID_DATE_VALUE, in.get_string().length(), in.get_string().ptr(), "");
} else {
SET_RES_DATE(out);
}
SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, DEFAULT_SCALE_FOR_DATE, DEFAULT_LENGTH_FOR_TEMPORAL);
return ret;
}
static int string_time(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
int64_t value = 0;
ObScale res_scale = -1;
if (OB_UNLIKELY((ObStringTC != in.get_type_class() && ObTextTC != in.get_type_class()) ||
ObTimeTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (lib::is_oracle_mode() && in.is_blob()) {
ret = OB_NOT_SUPPORTED;
LOG_ERROR("invalid use of blob type", K(ret), K(in), K(expect_type));
LOG_USER_ERROR(OB_NOT_SUPPORTED, "Cast to blob type");
} else if (CAST_FAIL(ObTimeConverter::str_to_time(in.get_string(), value, &res_scale))) {
} else {
SET_RES_TIME(out);
}
SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, res_scale, DEFAULT_LENGTH_FOR_TEMPORAL);
return ret;
}
static int string_year(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
ObObj int64;
if (OB_UNLIKELY((ObStringTC != in.get_type_class() && ObTextTC != in.get_type_class()) ||
ObYearTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (lib::is_oracle_mode() && in.is_blob()) {
ret = OB_NOT_SUPPORTED;
LOG_ERROR("invalid use of blob type", K(ret), K(in), K(expect_type));
LOG_USER_ERROR(OB_NOT_SUPPORTED, "Cast to blob type");
} else if (OB_FAIL(string_int(
ObIntType, params, in, int64, CM_UNSET_STRING_INTEGER_TRUNC(CM_SET_WARN_ON_FAIL(cast_mode))))) {
} else if (0 == int64.get_int()) {
const uint8_t base_year = 100;
uint8_t value = 4 == in.get_string().length() ? ObTimeConverter::ZERO_YEAR : base_year;
SET_RES_YEAR(out);
} else if (CAST_FAIL(int_year(ObYearType, params, int64, out, cast_mode))) {
} else if (CAST_FAIL(params.warning_)) {
}
SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, DEFAULT_SCALE_FOR_YEAR, DEFAULT_LENGTH_FOR_TEMPORAL);
return ret;
}
static int string_string(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
ObLength res_length = -1;
ObObj tmp_out;
if (OB_UNLIKELY(
(ObStringTC != in.get_type_class() && ObTextTC != in.get_type_class()) ||
OB_UNLIKELY(ObStringTC != ob_obj_type_class(expect_type) && ObTextTC != ob_obj_type_class(expect_type)))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (lib::is_oracle_mode() && !(in.is_blob() && ob_is_blob(expect_type, params.expect_obj_collation_)) &&
(in.is_blob())) {
ret = OB_NOT_SUPPORTED;
LOG_WARN("invalid cast of blob type", K(ret), K(in), K(out.get_meta()), K(expect_type), K(cast_mode));
LOG_USER_ERROR(OB_NOT_SUPPORTED, "cast to blob type");
} else if (ObTextTC == in.get_type_class() && in.is_lob_outrow()) {
ret = OB_NOT_SUPPORTED;
LOG_WARN("invalid cast of out row lob obj", K(ret), K(in), K(out.get_meta()), K(expect_type), K(cast_mode));
} else if (lib::is_oracle_mode() && in.is_clob() && (0 == in.get_string().length()) &&
!ob_is_clob(expect_type, params.expect_obj_collation_)) {
out.set_null();
} else {
ObString str;
in.get_string(str);
if (0 != str.length() && CS_TYPE_BINARY != in.get_collation_type() && CS_TYPE_BINARY != params.dest_collation_ &&
(ObCharset::charset_type_by_coll(in.get_collation_type()) !=
ObCharset::charset_type_by_coll(params.dest_collation_))) {
char* buf = NULL;
// gbk and utf16 is fixed 2 btyes, utf8mb4 is 1 to 4 bytes,
// so the factor should be 2.
const int32_t CharConvertFactorNum = 2;
int32_t buf_len = str.length() * CharConvertFactorNum;
uint32_t result_len = 0;
if (OB_UNLIKELY(NULL == (buf = static_cast<char*>(params.alloc(buf_len))))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_ERROR("alloc memory failed", K(ret));
} else if (OB_FAIL(ObCharset::charset_convert(in.get_collation_type(),
str.ptr(),
str.length(),
params.dest_collation_,
buf,
buf_len,
result_len))) {
LOG_WARN("charset convert failed",
K(ret),
K(in.get_collation_type()),
K(params.dest_collation_),
K(params.is_ignore_));
if (params.is_ignore_) {
ObString question_mark = ObCharsetUtils::get_const_str(params.dest_collation_, '?');
int32_t str_offset = 0;
int64_t buf_offset = 0;
while (str_offset < str.length() && buf_offset + question_mark.length() <= buf_len) {
int64_t offset =
ObCharset::charpos(in.get_collation_type(), str.ptr() + str_offset, str.length() - str_offset, 1);
ret = ObCharset::charset_convert(in.get_collation_type(),
str.ptr() + str_offset,
offset,
params.dest_collation_,
buf + buf_offset,
buf_len - buf_offset,
result_len);
str_offset += offset;
if (OB_SUCCESS == ret) {
buf_offset += result_len;
} else {
MEMCPY(buf + buf_offset, question_mark.ptr(), question_mark.length());
buf_offset += question_mark.length();
}
}
if (str_offset < str.length()) {
ret = OB_SIZE_OVERFLOW;
LOG_WARN("size overflow", K(ret), K(str), KPHEX(str.ptr(), str.length()));
} else {
result_len = buf_offset;
ret = OB_SUCCESS;
LOG_WARN("charset convert failed", K(ret), K(in.get_collation_type()), K(params.dest_collation_));
}
}
}
LOG_DEBUG("convert result", K(str), "result", ObHexEscapeSqlStr(ObString(result_len, buf)));
if (OB_SUCC(ret)) {
if (ObTextTC == ob_obj_type_class(expect_type)) {
out.set_lob_value(expect_type, buf, static_cast<int32_t>(result_len));
} else {
out.set_string(expect_type, buf, static_cast<int32_t>(result_len));
}
if (CS_TYPE_INVALID != in.get_collation_type()) {
out.set_collation_type(params.dest_collation_);
}
}
} else {
// When convert blob to other charset, need to align to mbminlen of destination charset
// by add '\0' prefix in mysql mode. (see mysql String::copy)
int64_t align_offset = 0;
const ObCharsetInfo* cs = NULL;
if (CS_TYPE_BINARY == in.get_collation_type() && is_mysql_mode() &&
NULL != (cs = ObCharset::get_charset(params.dest_collation_))) {
if (cs->mbminlen > 0 && in.get_string_len() % cs->mbminlen != 0) {
align_offset = cs->mbminlen - in.get_string_len() % cs->mbminlen;
}
}
if (OB_FAIL(check_convert_string(expect_type, params, in, tmp_out))) {
LOG_WARN("failed to check_and_convert_string", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(copy_string(params, expect_type, tmp_out.get_string(), out, align_offset))) {
} else {
if (CS_TYPE_INVALID != tmp_out.get_collation_type()) {
out.set_collation_type(tmp_out.get_collation_type());
}
if (ObTextTC == ob_obj_type_class(expect_type)) {
out.set_lob_inrow();
}
}
}
}
if (OB_SUCC(ret)) {
res_length = static_cast<ObLength>(out.get_string_len());
}
SET_RES_ACCURACY_STRING(expect_type, DEFAULT_PRECISION_FOR_STRING, res_length);
UNUSED(cast_mode);
return ret;
}
static int string_bit(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
uint64_t value = 0;
if (OB_UNLIKELY((ObStringTC != in.get_type_class() && ObTextTC != in.get_type_class()) ||
ObBitTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (lib::is_oracle_mode() && in.is_blob()) {
ret = OB_NOT_SUPPORTED;
LOG_ERROR("invalid use of blob type", K(ret), K(in), K(expect_type));
LOG_USER_ERROR(OB_NOT_SUPPORTED, "Cast to blob type");
} else {
int32_t bit_len = 0;
const ObString& str = in.get_string();
if (OB_FAIL(get_bit_len(str, bit_len))) {
LOG_WARN("fail to get bit length", K(ret), K(str));
} else if (OB_UNLIKELY(bit_len <= 0)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("bit length is less than or equal to zero", K(ret), K(str), K(bit_len));
} else {
if (ObHexStringType == in.get_type() && str.empty()) {
value = 0;
ret = OB_ERR_TRUNCATED_WRONG_VALUE_FOR_FIELD;
LOG_WARN("hex string is empty, can't cast to bit", K(ret), K(in));
} else if (OB_UNLIKELY(bit_len > OB_MAX_BIT_LENGTH)) {
value = UINT64_MAX;
ret = OB_ERR_DATA_TOO_LONG;
LOG_WARN("bit type length is too long", K(ret), K(str), K(OB_MAX_BIT_LENGTH), K(bit_len));
} else {
value = hex_to_uint64(str);
}
if (OB_FAIL(ret) && CM_IS_WARN_ON_FAIL(cast_mode)) {
params.warning_ = OB_DATA_OUT_OF_RANGE;
ret = OB_SUCCESS;
}
if (OB_SUCC(ret)) {
SET_RES_BIT(out);
SET_RES_ACCURACY(static_cast<ObPrecision>(bit_len), DEFAULT_SCALE_FOR_BIT, DEFAULT_LENGTH_FOR_NUMERIC);
}
}
}
return ret;
}
static int string_enum(const ObExpectType& expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out)
{
int ret = OB_SUCCESS;
ObCastMode cast_mode = params.cast_mode_;
const ObIArray<ObString>* type_infos = NULL;
const ObCollationType in_cs_type = ObCharset::is_valid_collation(in.get_collation_type())
? in.get_collation_type()
: ObCharset::get_system_collation();
ObCollationType cs_type = expect_type.get_collation_type();
int32_t pos = 0;
uint64_t value = 0;
int32_t no_sp_len = 0;
ObString no_sp_val;
ObString in_str;
if (OB_UNLIKELY(ObEnumType != expect_type.get_type()) ||
OB_UNLIKELY(ObStringTC != in.get_type_class() && ObTextTC != in.get_type_class()) ||
OB_ISNULL(type_infos = expect_type.get_type_infos())) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument", K(expect_type), K(in), K(ret));
} else if (lib::is_oracle_mode() && in.is_blob()) {
ret = OB_NOT_SUPPORTED;
LOG_ERROR("invalid use of blob type", K(ret), K(in), K(expect_type));
LOG_USER_ERROR(OB_NOT_SUPPORTED, "Cast to blob type");
} else if (OB_FAIL(ObCharset::charset_convert(*params.allocator_v2_, in.get_string(), in_cs_type, cs_type, in_str))) {
LOG_WARN("convert charset failed", K(ret), K(in), K(cs_type));
} else {
no_sp_len = static_cast<int32_t>(ObCharset::strlen_byte_no_sp(cs_type, in_str.ptr(), in_str.length()));
no_sp_val.assign_ptr(in_str.ptr(), static_cast<ObString::obstr_size_t>(no_sp_len));
if (OB_FAIL(find_type(*type_infos, cs_type, no_sp_val, pos))) {
LOG_WARN("fail to find type", KPC(type_infos), K(cs_type), K(no_sp_val), K(in_str), K(pos), K(ret));
} else if (OB_UNLIKELY(pos < 0)) {
if (!in_str.is_numeric()) {
ret = OB_ERR_DATA_TRUNCATED;
} else {
int err = 0;
int64_t val_cnt = type_infos->count();
value = ObCharset::strntoull(in_str.ptr(), in_str.length(), 10, &err);
if (err != 0 || value > val_cnt) {
value = 0;
ret = OB_ERR_DATA_TRUNCATED;
LOG_WARN("input value out of range", K(in), K(val_cnt), K(ret), K(err));
}
}
if (OB_FAIL(ret) && CM_IS_WARN_ON_FAIL(cast_mode)) {
params.warning_ = OB_ERR_DATA_TRUNCATED;
ret = OB_SUCCESS;
}
} else {
value = pos + 1; // enum start from 1
}
LOG_DEBUG("finish string_enum", K(ret), K(expect_type), K(in), K(out), KPC(type_infos), K(lbt()));
SET_RES_ENUM(out);
}
return ret;
}
static int string_set(const ObExpectType& expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out)
{
int ret = OB_SUCCESS;
ObCastMode cast_mode = params.cast_mode_;
const ObIArray<ObString>* type_infos = NULL;
const ObCollationType in_cs_type = ObCharset::is_valid_collation(in.get_collation_type())
? in.get_collation_type()
: ObCharset::get_system_collation();
ObCollationType cs_type = expect_type.get_collation_type();
const ObString& sep = ObCharsetUtils::get_const_str(cs_type, ',');
int32_t pos = 0;
uint64_t value = 0;
ObString in_str;
ObString val_str;
bool is_last_value = false;
if (OB_UNLIKELY(ObSetType != expect_type.get_type()) ||
OB_UNLIKELY(ObStringTC != in.get_type_class() && ObTextTC != in.get_type_class()) ||
OB_ISNULL(type_infos = expect_type.get_type_infos()) || !ObCharset::is_valid_collation(cs_type)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument", K(expect_type), K(in), K(cs_type), K(ret));
} else if (lib::is_oracle_mode() && in.is_blob()) {
ret = OB_NOT_SUPPORTED;
LOG_ERROR("invalid use of blob type", K(ret), K(in), K(expect_type));
LOG_USER_ERROR(OB_NOT_SUPPORTED, "Cast to blob type");
} else if (in.get_string().empty()) {
value = 0;
} else if (OB_FAIL(ObCharset::charset_convert(*params.allocator_v2_, in.get_string(), in_cs_type, cs_type, in_str))) {
} else {
const char* remain = in_str.ptr();
int64_t remain_len = ObCharset::strlen_byte_no_sp(cs_type, in_str.ptr(), in_str.length());
do {
pos = 0;
const char* sep_loc = NULL;
if (NULL == (sep_loc = static_cast<const char*>(memmem(remain, remain_len, sep.ptr(), sep.length())))) {
is_last_value = true;
val_str.assign_ptr(remain, remain_len);
if (OB_FAIL(find_type(*type_infos, cs_type, val_str, pos))) {
LOG_WARN("fail to find type", KPC(type_infos), K(cs_type), K(val_str), K(in_str), K(pos), K(ret));
}
} else {
val_str.assign_ptr(remain, sep_loc - remain);
remain_len = remain_len - (sep_loc - remain + sep.length());
remain = sep_loc + sep.length();
if (OB_FAIL(find_type(*type_infos, cs_type, val_str, pos))) {
LOG_WARN("fail to find type", KPC(type_infos), K(cs_type), K(val_str), K(in_str), K(pos), K(ret));
}
}
if (OB_FAIL(ret)) {
} else if (pos < 0) { // not found
if (CM_IS_WARN_ON_FAIL(cast_mode)) {
params.warning_ = OB_ERR_DATA_TRUNCATED;
LOG_INFO(
"input value out of range, and set out value zero", K(pos), K(in), K(val_str), K(in_str), K(expect_type));
} else {
ret = OB_ERR_DATA_TRUNCATED;
LOG_WARN("data truncate", K(pos), K(in), K(val_str), K(in_str), K(expect_type), K(ret));
}
} else {
pos %= 64; // value_count can more than 64 if has duplicated values in mysql.
value |= (1ULL << pos);
}
} while (OB_SUCC(ret) && !is_last_value);
// Bug30666903: check implicit cast logic to handle number cases
if (in_str.is_numeric() &&
(OB_ERR_DATA_TRUNCATED == ret || (params.warning_ == OB_ERR_DATA_TRUNCATED && CM_IS_WARN_ON_FAIL(cast_mode)))) {
int err = 0;
value = ObCharset::strntoull(in_str.ptr(), in_str.length(), 10, &err);
if (err == 0) {
ret = OB_SUCCESS;
uint32_t val_cnt = type_infos->count();
if (OB_UNLIKELY(val_cnt <= 0)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpect val_cnt", K(in), K(out), K(expect_type), K(ret));
} else if (val_cnt >= 64) { // do nothing
} else if (val_cnt < 64 && value > ((1ULL << val_cnt) - 1)) {
value = 0;
ret = OB_ERR_DATA_TRUNCATED;
LOG_WARN("input value out of range", K(in), K(val_cnt), K(ret));
}
if (OB_FAIL(ret) && CM_IS_WARN_ON_FAIL(cast_mode)) {
params.warning_ = OB_ERR_DATA_TRUNCATED;
ret = OB_SUCCESS;
}
} else {
value = 0;
}
}
}
LOG_DEBUG("finish string_set", K(ret), K(expect_type), K(in), K(out), KPC(type_infos), K(lbt()));
SET_RES_SET(out);
return ret;
}
static int string_otimestamp(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
UNUSED(cast_mode);
int ret = OB_SUCCESS;
ObScale res_scale = -1;
ObString utf8_string;
if (OB_UNLIKELY(ObStringTC != in.get_type_class() && ObTextTC != in.get_type_class()) ||
OB_UNLIKELY(ObOTimestampTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (lib::is_oracle_mode() && in.is_blob()) {
ret = OB_NOT_SUPPORTED;
LOG_ERROR("invalid use of blob type", K(ret), K(in), K(expect_type));
LOG_USER_ERROR(OB_NOT_SUPPORTED, "Cast to blob type");
} else if (OB_FAIL(convert_string_collation(
in.get_string(), in.get_collation_type(), utf8_string, ObCharset::get_system_collation(), params))) {
LOG_WARN("convert_string_collation", K(ret));
} else {
ObOTimestampData value;
ObTimeConvertCtx cvrt_ctx(params.dtc_params_.tz_info_, true);
cvrt_ctx.oracle_nls_format_ = params.dtc_params_.get_nls_format(expect_type);
if (CAST_FAIL(ObTimeConverter::str_to_otimestamp(utf8_string, cvrt_ctx, expect_type, value, res_scale))) {
} else {
SET_RES_OTIMESTAMP(out);
}
}
SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, res_scale, DEFAULT_LENGTH_FOR_TEMPORAL);
return ret;
}
static int string_raw(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
UNUSED(cast_mode);
int ret = OB_SUCCESS;
ObLength res_length = -1;
if (OB_UNLIKELY(ObStringTC != in.get_type_class()) || OB_UNLIKELY(ObRawTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(ObHexUtils::hextoraw(in, params, out))) {
LOG_WARN("fail to hextoraw", K(ret), K(in), K(expect_type));
} else {
res_length = static_cast<ObLength>(out.get_string_len());
}
SET_RES_ACCURACY_STRING(expect_type, DEFAULT_PRECISION_FOR_STRING, res_length);
return ret;
}
static int string_interval(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
UNUSED(cast_mode);
int ret = OB_SUCCESS;
ObScale res_scale = -1;
ObLength res_length = -1;
ObPrecision res_precision = -1;
ObString utf8_string;
if (OB_UNLIKELY(!in.is_string_type()) || OB_UNLIKELY(ObIntervalTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(convert_string_collation(
in.get_string(), in.get_collation_type(), utf8_string, ObCharset::get_system_collation(), params))) {
LOG_WARN("convert_string_collation", K(ret));
} else if (ObIntervalYMType == expect_type) {
ObIntervalYMValue value;
// don't know the scale, use the max scale and return the real scale
res_scale = ObAccuracy::MAX_ACCURACY2[ORACLE_MODE][ObIntervalYMType].get_scale();
if (CAST_FAIL(ObTimeConverter::str_to_interval_ym(utf8_string, value, res_scale))) {
} else {
SET_RES_INTERVAL_YM(out);
out.set_scale(res_scale);
}
} else {
ObIntervalDSValue value;
// don't know the scale, use the max scale and return the real scale
res_scale = ObAccuracy::MAX_ACCURACY2[ORACLE_MODE][ObIntervalDSType].get_scale();
if (CAST_FAIL(ObTimeConverter::str_to_interval_ds(utf8_string, value, res_scale))) {
} else {
SET_RES_INTERVAL_DS(out);
out.set_scale(res_scale);
}
}
SET_RES_ACCURACY(res_precision, res_scale, res_length);
return ret;
}
static int string_rowid(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(ob_obj_type_class(expect_type) != ObRowIDTC) || OB_UNLIKELY(in.get_type_class() != ObStringTC)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected arguments", K(expect_type), K(in));
} else if (ObURowIDType != expect_type) {
ret = OB_NOT_SUPPORTED;
LOG_WARN("only support urowid for now", K(ret), K(expect_type));
} else {
ObURowIDData value;
if (OB_FAIL(ObURowIDData::decode2urowid(in.get_string_ptr(), in.get_string_len(), *params.allocator_v2_, value))) {
LOG_WARN("failed to decode to urowid", K(ret));
} else {
SET_RES_UROWID(out);
}
}
return ret;
}
static int string_lob(const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out,
const ObCastMode cast_mode, const ObLobLocator* lob_locator)
{
int ret = OB_SUCCESS;
ObObj tmp_out;
if (!share::is_oracle_mode()) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("Unexpected tenant mode", K(ret));
} else if (OB_UNLIKELY((ObStringTC != in.get_type_class() && ObTextTC != in.get_type_class()) ||
OB_UNLIKELY(!ob_is_lob_locator(expect_type)))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(string_string(ObLongTextType, params, in, tmp_out, cast_mode))) {
LOG_WARN("fail to cast string to longtext", K(ret), K(in));
} else if (tmp_out.is_null()) {
out.set_null();
} else {
ObString str;
char* buf = nullptr;
ObLobLocator* result = nullptr;
if (OB_FAIL(tmp_out.get_string(str))) {
STORAGE_LOG(WARN, "Failed to get string from obj", K(ret), K(tmp_out));
}
const int64_t buf_len =
sizeof(ObLobLocator) + (NULL == lob_locator ? 0 : lob_locator->payload_offset_) + str.length();
if (OB_FAIL(ret)) {
} else if (OB_ISNULL(buf = static_cast<char*>(params.alloc(buf_len)))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("Failed to allocate memory for lob locator", K(ret), K(str));
} else if (FALSE_IT(result = reinterpret_cast<ObLobLocator*>(buf))) {
} else if (NULL == lob_locator) {
if (OB_FAIL(result->init(str))) {
STORAGE_LOG(WARN, "Failed to init lob locator", K(ret), K(str), KPC(result));
}
} else if (NULL != lob_locator) {
ObString rowid;
if (lob_locator->is_inline_mode()) { // inline mode
if (OB_FAIL(lob_locator->get_rowid(rowid))) {
LOG_WARN("get rowid failed", K(ret));
} else if (OB_FAIL(result->init(lob_locator->table_id_,
lob_locator->column_id_,
lob_locator->snapshot_version_,
lob_locator->flags_,
rowid,
str))) {
STORAGE_LOG(WARN, "Failed to init lob locator", K(ret), K(str), KPC(result));
}
} else { // compat mode
if (OB_FAIL(result->init(str))) {
STORAGE_LOG(WARN, "Failed to init lob locator", K(ret), K(str), KPC(result));
}
}
}
if (OB_SUCC(ret)) {
out = tmp_out;
out.set_lob_locator(*result);
}
}
return ret;
}
static int string_json(const ObObjType expect_type, ObObjCastParams &params,
const ObObj &in, ObObj &out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
ObObj tmp_val;
int64_t res_length = -1;
bool need_charset_convert = ((CS_TYPE_BINARY != in.get_collation_type()) &&
(ObCharset::charset_type_by_coll(in.get_collation_type()) !=
ObCharset::charset_type_by_coll(params.dest_collation_)));
if (lib::is_mysql_mode() && (params.dest_collation_ != CS_TYPE_UTF8MB4_BIN)) {
ret = OB_ERR_INVALID_JSON_CHARSET;
LOG_WARN("fail to cast string to json invalid outtype", K(ret), K(params.dest_collation_));
} else if (CM_IS_COLUMN_CONVERT(cast_mode) && is_mysql_unsupported_json_column_conversion(in.get_type())) {
ret = OB_ERR_INVALID_JSON_TEXT;
LOG_USER_ERROR(OB_ERR_INVALID_JSON_TEXT);
} else if (OB_UNLIKELY(ObStringTC != in.get_type_class() && ObTextTC != in.get_type_class())
|| OB_UNLIKELY(ObJsonType != expect_type)) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (need_charset_convert && OB_FAIL(string_string(ObLongTextType, params, in, tmp_val, cast_mode))) {
LOG_WARN("fail to cast string to string", K(ret), K(expect_type), K(in), K(params.dest_collation_), K(tmp_val));
} else if(OB_UNLIKELY(params.allocator_v2_ == NULL)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("invalid allocator in string to json cast", K(ret), K(params.allocator_v2_));
} else {
ObIJsonBase *j_base = NULL;
ObString j_text = (need_charset_convert ? tmp_val.get_string() : in.get_string());
ObJsonOpaque j_opaque(j_text, in.get_type());
ObJsonString j_string(j_text.ptr(), j_text.length());
ObJsonNull j_null;
ObJsonNode *j_tree = NULL;
if (expect_type == ObJsonType && j_text.length() == 0 && cast_mode == 0) { // add column json null
j_base = &j_null;
} else if (CS_TYPE_BINARY == in.get_collation_type()) {
j_base = &j_opaque;
} else if (CM_IS_IMPLICIT_CAST(cast_mode) && !CM_IS_COLUMN_CONVERT(cast_mode)
&& !CM_IS_JSON_VALUE(cast_mode) && ob_is_string_type(in.get_type())) {
// consistent with mysql: TINYTEXT, TEXT, MEDIUMTEXT, and LONGTEXT. We want to treat them like strings
ret = OB_SUCCESS;
j_base = &j_string;
} else if (OB_FAIL(ObJsonParser::get_tree(params.allocator_v2_, j_text, j_tree))) {
if (CM_IS_IMPLICIT_CAST(cast_mode) && !CM_IS_COLUMN_CONVERT(cast_mode)) {
ret = OB_SUCCESS;
j_base = &j_string;
} else {
LOG_WARN("fail to parse string as json", K(ret), K(expect_type), K(in), K(tmp_val));
if (CM_IS_COLUMN_CONVERT(cast_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)) {
ObString raw_bin;
if (OB_FAIL(j_base->get_raw_binary(raw_bin, params.allocator_v2_))) {
LOG_WARN("fail to get string json binary", K(ret), K(in), K(*j_base));
} else {
res_length = raw_bin.length();
out.set_json_value(expect_type, raw_bin.ptr(), res_length);
}
}
}
SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_STRING, DEFAULT_SCALE_FOR_TEXT, res_length);
return ret;
}
////////////////////////////////////////////////////////////
// bit -> XXX
static int bit_int(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
ObPrecision res_precision = -1;
int64_t value = 0;
if (OB_UNLIKELY(ObBitTC != in.get_type_class() || ObIntTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("invalid argument", K(in), K(expect_type), K(ret));
} else {
value = static_cast<int64_t>(in.get_bit());
if (expect_type < ObIntType && CM_NEED_RANGE_CHECK(cast_mode) &&
CAST_FAIL(int_range_check(expect_type, value, value))) {
} else {
SET_RES_INT(out);
res_precision = get_precision_for_integer(out.get_int());
SET_RES_ACCURACY(res_precision, DEFAULT_SCALE_FOR_INTEGER, DEFAULT_LENGTH_FOR_NUMERIC);
}
}
return ret;
}
static int bit_json(const ObObjType expect_type, ObObjCastParams &params,
const ObObj &in, ObObj &out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
UNUSED(cast_mode);
if (OB_UNLIKELY((ObBitTC != in.get_type_class()
|| (ObJsonTC != ob_obj_type_class(expect_type))))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else {
ObIAllocator *allocator = params.allocator_v2_;
uint64_t value = in.get_bit();
ObScale scale = in.get_scale();
const int32_t BUF_LEN = (OB_MAX_BIT_LENGTH + 7) / 8;
char buf[BUF_LEN] = {0};
int64_t pos = 0;
if (OB_FAIL(bit_to_char_array(value, scale, buf, BUF_LEN, pos))) {
LOG_WARN("fail to store val", KP(buf), K(BUF_LEN), K(value), K(pos));
} else if (OB_ISNULL(allocator)) {
ret= OB_ERR_UNEXPECTED;
LOG_ERROR("NULL allocator in json cast function", K(ret), K(in), K(expect_type));
} else {
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, params.allocator_v2_))) {
LOG_WARN("fail to get int json binary", K(ret), K(in), K(expect_type), K(*j_base));
} else if (OB_FAIL(copy_string(params, expect_type, raw_bin.ptr(), raw_bin.length(), out))) {
LOG_WARN("fail to copy string", K(ret), K(expect_type), K(raw_bin));
} else {
ObLength res_length = static_cast<ObLength>(out.get_string_len());
SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_STRING, DEFAULT_SCALE_FOR_STRING, res_length);
}
}
}
return ret;
}
static int bit_uint(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
ObPrecision res_precision = -1;
uint64_t value = 0;
if (OB_UNLIKELY(ObBitTC != in.get_type_class() || ObUIntTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("invalid argument", K(in), K(expect_type), K(ret));
} else {
value = static_cast<uint64_t>(in.get_bit());
if (expect_type < ObUInt64Type && CM_NEED_RANGE_CHECK(cast_mode) &&
CAST_FAIL(uint_upper_check(expect_type, value))) {
} else {
SET_RES_UINT(out);
res_precision = get_precision_for_integer(out.get_uint64());
SET_RES_ACCURACY(res_precision, DEFAULT_SCALE_FOR_INTEGER, DEFAULT_LENGTH_FOR_NUMERIC);
}
}
return ret;
}
static int bit_double(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode);
static int bit_float(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
ObObj dbl;
if (OB_UNLIKELY((ObBitTC != in.get_type_class() || ObFloatTC != ob_obj_type_class(expect_type)))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(bit_double(ObDoubleType, params, in, dbl, cast_mode))) {
} else if (OB_FAIL(double_float(expect_type, params, dbl, out, cast_mode))) {
}
// has set accuracy in prev double_float call
return ret;
}
static int bit_double(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
UNUSED(cast_mode);
int ret = OB_SUCCESS;
double value = 0.0;
if (OB_UNLIKELY((ObBitTC != in.get_type_class() || ObDoubleTC != ob_obj_type_class(expect_type)))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else {
value = static_cast<double>(in.get_bit());
SET_RES_DOUBLE(out);
SET_RES_ACCURACY(PRECISION_UNKNOWN_YET, SCALE_UNKNOWN_YET, LENGTH_UNKNOWN_YET);
}
return ret;
}
static int bit_number(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
UNUSED(cast_mode);
int ret = OB_SUCCESS;
number::ObNumber nmb;
ObPrecision res_precision = -1;
if (OB_UNLIKELY(ObBitTC != in.get_type_class() || ObNumberTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(nmb.from(in.get_bit(), params))) {
LOG_WARN("fail to make number", K(ret), K(in));
} else {
out.set_number(expect_type, nmb);
res_precision = get_precision_for_integer(in.get_bit());
SET_RES_ACCURACY(res_precision, DEFAULT_SCALE_FOR_INTEGER, DEFAULT_LENGTH_FOR_NUMERIC);
}
return ret;
}
static int bit_datetime(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
uint64_t bit_value = in.get_bit();
int64_t value = 0;
ObScale res_scale = -1;
if (OB_UNLIKELY((ObBitTC != in.get_type_class() || ObDateTimeTC != ob_obj_type_class(expect_type)))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (CM_IS_COLUMN_CONVERT(cast_mode)) {
// if cast mode is column convert, using bit as int64 to do cast.
ObTimeConvertCtx cvrt_ctx(params.dtc_params_.tz_info_, ObTimestampType == expect_type);
if (CAST_FAIL(ObTimeConverter::int_to_datetime(bit_value, 0, cvrt_ctx, value))) {
LOG_WARN("int_to_datetime failed", K(ret), K(bit_value));
}
} else {
// using bit as char array to do cast.
ObScale scale = in.get_scale();
const int32_t BUF_LEN = (OB_MAX_BIT_LENGTH + 7) / 8;
int64_t pos = 0;
char buf[BUF_LEN];
MEMSET(buf, 0, BUF_LEN);
if (OB_FAIL(bit_to_char_array(bit_value, scale, buf, BUF_LEN, pos))) {
LOG_WARN("fail to store val", KP(buf), K(BUF_LEN), K(bit_value), K(pos));
} else {
ObString str(pos, buf);
ObTimeConvertCtx cvrt_ctx(params.dtc_params_.tz_info_, ObTimestampType == expect_type);
if (CAST_FAIL(ObTimeConverter::str_to_datetime(str, cvrt_ctx, value, &res_scale))) {
LOG_WARN("int_to_datetime failed", K(ret), K(bit_value), K(str));
}
}
}
if (OB_SUCC(ret)) {
SET_RES_DATETIME(out);
SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, res_scale, DEFAULT_LENGTH_FOR_TEMPORAL);
}
return ret;
}
static int bit_date(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
uint64_t bit_value = in.get_bit();
int32_t value = 0;
ObScale res_scale = -1;
if (OB_UNLIKELY((ObBitTC != in.get_type_class() || ObDateTC != ob_obj_type_class(expect_type)))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (CM_IS_COLUMN_CONVERT(cast_mode)) {
// if cast mode is column convert, using bit as int64 to do cast.
if (CAST_FAIL(ObTimeConverter::int_to_date(bit_value, value))) {
LOG_WARN("int_to_date failed", K(ret), K(bit_value));
}
} else {
// using bit as char array to do cast.
ObScale scale = in.get_scale();
const int32_t BUF_LEN = (OB_MAX_BIT_LENGTH + 7) / 8;
int64_t pos = 0;
char buf[BUF_LEN];
MEMSET(buf, 0, BUF_LEN);
if (OB_FAIL(bit_to_char_array(bit_value, scale, buf, BUF_LEN, pos))) {
LOG_WARN("fail to store val", KP(buf), K(BUF_LEN), K(bit_value), K(pos));
} else {
ObString str(pos, buf);
if (CAST_FAIL(ObTimeConverter::str_to_date(str, value))) {
LOG_WARN("str_to_date failed", K(ret), K(bit_value), K(str));
}
}
}
if (OB_SUCC(ret)) {
SET_RES_DATE(out);
SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, res_scale, DEFAULT_LENGTH_FOR_TEMPORAL);
}
return ret;
}
static int bit_time(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
uint64_t bit_value = in.get_bit();
int64_t value = 0;
ObScale res_scale = -1;
if (OB_UNLIKELY((ObBitTC != in.get_type_class() || ObTimeTC != ob_obj_type_class(expect_type)))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (CM_IS_COLUMN_CONVERT(cast_mode)) {
// if cast mode is column convert, using bit as int64 to do cast.
if (CAST_FAIL(ObTimeConverter::int_to_time(bit_value, value))) {
LOG_WARN("int_to_time failed", K(ret), K(bit_value));
}
} else {
// using bit as char array to do cast.
ObScale scale = in.get_scale();
const int32_t BUF_LEN = (OB_MAX_BIT_LENGTH + 7) / 8;
int64_t pos = 0;
char buf[BUF_LEN];
MEMSET(buf, 0, BUF_LEN);
if (OB_FAIL(bit_to_char_array(bit_value, scale, buf, BUF_LEN, pos))) {
LOG_WARN("fail to store val", KP(buf), K(BUF_LEN), K(bit_value), K(pos));
} else {
ObString str(pos, buf);
if (CAST_FAIL(ObTimeConverter::str_to_time(str, value, &res_scale))) {
LOG_WARN("str_to_date failed", K(ret), K(bit_value), K(str));
}
}
}
if (OB_SUCC(ret)) {
SET_RES_TIME(out);
SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, res_scale, DEFAULT_LENGTH_FOR_TEMPORAL);
}
return ret;
}
static int bit_year(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
uint64_t bit_value = in.get_bit();
uint8_t value = 0;
ObScale res_scale = -1;
if (OB_UNLIKELY((ObBitTC != in.get_type_class() || ObYearTC != ob_obj_type_class(expect_type)))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (CAST_FAIL(ObTimeConverter::int_to_year(bit_value, value))) {
LOG_WARN("int_to_year faile", K(ret), K(bit_value));
} else {
SET_RES_YEAR(out);
SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, res_scale, DEFAULT_LENGTH_FOR_TEMPORAL);
}
return ret;
}
static int bit_string(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
uint64_t value = in.get_bit();
ObLength res_length = -1;
if (OB_UNLIKELY((ObBitTC != in.get_type_class() ||
(ObStringTC != ob_obj_type_class(expect_type) && ObTextTC != ob_obj_type_class(expect_type))))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (CM_IS_COLUMN_CONVERT(cast_mode)) {
// if cast mode is column convert, using bit as int64 to do cast.
ObFastFormatInt ffi(value);
ObString tmp_str;
if (OB_FAIL(convert_string_collation(ObString(ffi.length(), ffi.ptr()),
ObCharset::get_system_collation(),
tmp_str,
params.dest_collation_,
params))) {
LOG_WARN("fail to convert string collation", K(ret));
} else if (OB_FAIL(copy_string(params, expect_type, tmp_str.ptr(), tmp_str.length(), out))) {
LOG_WARN("fail to copy string", KP(tmp_str.ptr()), K(tmp_str.length()), K(value), K(out), K(expect_type));
}
} else {
// using bit as char array to do cast.
ObScale scale = in.get_scale();
const int32_t BUF_LEN = (OB_MAX_BIT_LENGTH + 7) / 8;
int64_t pos = 0;
char tmp_buf[BUF_LEN];
MEMSET(tmp_buf, 0, BUF_LEN);
if (OB_FAIL(bit_to_char_array(value, scale, tmp_buf, BUF_LEN, pos))) {
LOG_WARN("fail to store val", KP(tmp_buf), K(BUF_LEN), K(value), K(pos));
} else if (OB_FAIL(copy_string(params, expect_type, tmp_buf, pos, out))) {
LOG_WARN("fail to copy string", KP(tmp_buf), K(pos), K(value), K(out), K(expect_type));
}
}
if (OB_SUCC(ret)) {
res_length = static_cast<ObLength>(out.get_string_len());
SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_STRING, DEFAULT_SCALE_FOR_STRING, res_length);
}
return ret;
}
static int bit_bit(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
UNUSED(cast_mode);
int ret = OB_SUCCESS;
uint64_t value = in.get_bit();
int32_t bit_len = 0;
if (OB_UNLIKELY(ObBitTC != in.get_type_class() || ObBitTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(get_bit_len(value, bit_len))) {
LOG_WARN("fail to get bit len", K(ret), K(value), K(bit_len));
} else {
SET_RES_BIT(out);
SET_RES_ACCURACY(static_cast<ObPrecision>(bit_len), DEFAULT_SCALE_FOR_BIT, DEFAULT_LENGTH_FOR_NUMERIC);
}
return ret;
}
static int bit_enum(const ObExpectType& expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(ObEnumType != expect_type.get_type()) || OB_UNLIKELY(ObBitTC != in.get_type_class())) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument", K(expect_type), K(in), K(ret));
} else {
uint64_t value = in.get_bit();
ObObj uint_val;
uint_val.set_uint64(value);
if (OB_FAIL(uint_enum(expect_type, params, uint_val, out))) {
LOG_WARN("fail to cast int to enum", K(expect_type), K(in), K(uint_val), K(out), K(ret));
}
}
return ret;
}
static int bit_set(const ObExpectType& expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(ObSetType != expect_type.get_type()) || OB_UNLIKELY(ObBitTC != in.get_type_class())) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid argument", K(expect_type), K(in), K(ret));
} else {
uint64_t value = in.get_bit();
ObObj uint_val;
uint_val.set_uint64(value);
if (OB_FAIL(uint_set(expect_type, params, uint_val, out))) {
LOG_WARN("fail to cast int to enum", K(expect_type), K(in), K(uint_val), K(out), K(ret));
}
}
return ret;
}
CAST_TO_LOB_METHOD(bit, ObBitTC);
ObCastEnumOrSetFunc OB_CAST_ENUM_OR_SET[ObMaxTC][2] = {
{
/*null -> enum_or_set*/
cast_identity_enum_set, /*enum*/
cast_identity_enum_set, /*set*/
},
{
/*int -> enum_or_set*/
int_enum, /*enum*/
int_set, /*set*/
},
{
/*uint -> enum_or_set*/
uint_enum, /*enum*/
uint_set, /*set*/
},
{
/*float -> enum_or_set*/
float_enum, /*enum*/
float_set, /*set*/
},
{
/*double -> enum_or_set*/
double_enum, /*enum*/
double_set, /*set*/
},
{
/*number -> enum_or_set*/
number_enum, /*enum*/
number_set, /*set*/
},
{
/*datetime -> enum_or_set*/
datetime_enum, /*enum*/
datetime_set, /*set*/
},
{
/*date -> enum_or_set*/
date_enum, /*enum*/
date_set, /*set*/
},
{
/*time -> enum_or_set*/
time_enum, /*enum*/
time_set, /*set*/
},
{
/*year -> enum_or_set*/
year_enum, /*enum*/
year_set, /*set*/
},
{
/*string -> enum_or_set*/
string_enum, /*enum*/
string_set, /*set*/
},
{
/*extend -> enum_or_set*/
cast_not_support_enum_set, /*enum*/
cast_not_support_enum_set, /*set*/
},
{
/*unknow -> enum_or_set*/
cast_not_support_enum_set, /*enum*/
cast_not_support_enum_set, /*set*/
},
{
/*text -> enum_or_set*/
string_enum, /*enum*/
string_set, /*set*/
},
{
/*bit -> enum_or_set*/
bit_enum, /*enum*/
bit_set, /*set*/
},
{
/*enumset tc -> enum_or_set*/
cast_not_expected_enum_set, /*enum*/
cast_not_expected_enum_set, /*set*/
},
{
/*enumset_inner tc -> enum_or_set*/
cast_not_expected_enum_set, /*enum*/
cast_not_expected_enum_set, /*set*/
},
{
/*text -> enum_or_set*/
cast_not_support_enum_set, /*enum*/
cast_not_support_enum_set, /*set*/
},
};
////////////////////////////////////////////////////////////
// enum -> XXX
static int enumset_int(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
// we regard enum as uint64 when int_value is needed
int ret = OB_SUCCESS;
if (OB_UNLIKELY(ObEnumSetTC != in.get_type_class() || ObIntTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else {
ObObj uint64_in;
uint64_in.set_uint64(in.get_uint64());
ret = uint_int(expect_type, params, uint64_in, out, cast_mode);
}
return ret;
}
static int enumset_uint(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
ObPrecision res_precision = -1;
if (OB_UNLIKELY(ObEnumSetTC != in.get_type_class() || ObUIntTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else {
uint64_t value = in.get_uint64();
if (CAST_FAIL(uint_upper_check(expect_type, value))) {
} else {
out.set_uint(expect_type, value);
res_precision = get_precision_for_integer(value);
}
}
SET_RES_ACCURACY(res_precision, DEFAULT_SCALE_FOR_INTEGER, DEFAULT_LENGTH_FOR_NUMERIC);
return ret;
}
static int enumset_float(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(ObEnumSetTC != in.get_type_class() || ObFloatTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else {
out.set_float(expect_type, static_cast<float>(in.get_uint64()));
}
UNUSED(cast_mode);
SET_RES_ACCURACY(PRECISION_UNKNOWN_YET, SCALE_UNKNOWN_YET, LENGTH_UNKNOWN_YET);
return ret;
}
static int enumset_double(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(ObEnumSetTC != in.get_type_class() || ObDoubleTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else {
out.set_double(expect_type, static_cast<double>(in.get_uint64()));
}
UNUSED(cast_mode);
SET_RES_ACCURACY(PRECISION_UNKNOWN_YET, SCALE_UNKNOWN_YET, LENGTH_UNKNOWN_YET);
return ret;
}
static int enumset_number(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
number::ObNumber nmb;
ObPrecision res_precision = -1;
if (OB_UNLIKELY(ObEnumSetTC != in.get_type_class() || ObNumberTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(nmb.from(in.get_uint64(), params))) {
LOG_ERROR("failed to from number", K(ret), K(in), K(expect_type));
} else {
out.set_number(expect_type, nmb);
res_precision = get_precision_for_integer(in.get_uint64());
}
UNUSED(cast_mode);
SET_RES_ACCURACY(res_precision, DEFAULT_SCALE_FOR_INTEGER, DEFAULT_LENGTH_FOR_NUMERIC);
return ret;
}
static int enumset_year(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
ObObj int64;
if (OB_UNLIKELY(ObEnumSetTC != in.get_type_class() || ObYearTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(enumset_int(ObIntType, params, in, int64, CM_UNSET_NO_CAST_INT_UINT(cast_mode)))) {
} else if (OB_FAIL(int_year(expect_type, params, int64, out, cast_mode))) {
}
SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, DEFAULT_SCALE_FOR_YEAR, DEFAULT_LENGTH_FOR_TEMPORAL);
return ret;
}
static int enumset_bit(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
UNUSED(cast_mode);
int ret = OB_SUCCESS;
uint64_t value = in.get_uint64();
int32_t bit_len = 0;
if (OB_UNLIKELY(ObEnumSetTC != in.get_type_class() || ObBitTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(get_bit_len(value, bit_len))) {
LOG_WARN("fail to get bit len", K(ret), K(value), K(bit_len));
} else {
SET_RES_BIT(out);
SET_RES_ACCURACY(static_cast<ObPrecision>(bit_len), DEFAULT_SCALE_FOR_BIT, DEFAULT_LENGTH_FOR_NUMERIC);
}
return ret;
}
static int get_uint64_from_enumset_inner(const ObObj& in, ObObj& out)
{
int ret = OB_SUCCESS;
ObEnumSetInnerValue inner_value;
if (OB_UNLIKELY(ObEnumSetInnerTC != in.get_type_class())) {
LOG_ERROR("invalid input type", K(ret), K(in));
} else if (OB_FAIL(in.get_enumset_inner_value(inner_value))) {
LOG_WARN("failed to get_enumset_inner_value", K(in), K(ret));
} else {
out.set_uint64(inner_value.numberic_value_);
}
return ret;
}
static int get_string_from_enumset_inner(const ObObj& in, ObObj& out)
{
int ret = OB_SUCCESS;
ObEnumSetInnerValue inner_value;
if (OB_UNLIKELY(ObEnumSetInnerTC != in.get_type_class())) {
LOG_ERROR("invalid input type", K(ret), K(in));
} else if (OB_FAIL(in.get_enumset_inner_value(inner_value))) {
LOG_WARN("failed to get_enumset_inner_value", K(in), K(ret));
} else {
out.set_varchar(inner_value.string_value_);
out.set_collation_type(in.get_collation_type());
out.set_collation_level(in.get_collation_level());
}
return ret;
}
/* used for case when or in , comment temporary */
// static int enumset_inner_int(const ObObjType expect_type, ObObjCastParams &params,
// const ObObj &in, ObObj &out, const ObCastMode cast_mode)
//{
// //we regard enum as uint16 when int_value is needed
// int ret = OB_SUCCESS;
// ObObj uint64;
// if (OB_UNLIKELY(ObEnumSetInnerTC != in.get_type_class()
// || ObIntTC != ob_obj_type_class(expect_type))) {
// ret = OB_ERR_UNEXPECTED;
// LOG_ERROR("invalid input type",
// K(ret), K(in), K(expect_type));
// } else if (OB_FAIL(get_uint64_from_enumset_inner(in, uint64))) {
// LOG_WARN("failed to get_uint64_from_enumset_inner", K(in), K(ret));
// } else if (OB_FAIL(uint_int(expect_type, params, uint64, out, cast_mode))) {
// LOG_WARN("failed to cast uint to int", K(in), K(uint64), K(ret));
// } else {/*do nothing*/}
// return ret;
//}
//
// static int enumset_inner_uint(const ObObjType expect_type, ObObjCastParams &params,
// const ObObj &in, ObObj &out, const ObCastMode cast_mode)
//{
// //we regard enum as uint16 when int_value is needed
// int ret = OB_SUCCESS;
// ObObj uint64;
// if (OB_UNLIKELY(ObEnumSetInnerTC != in.get_type_class()
// || ObUIntTC != ob_obj_type_class(expect_type))) {
// ret = OB_ERR_UNEXPECTED;
// LOG_ERROR("invalid input type",
// K(ret), K(in), K(expect_type));
// } else if (OB_FAIL(get_uint64_from_enumset_inner(in, uint64))) {
// LOG_WARN("failed to get_uint64_from_enumset_inner", K(in), K(ret));
// } else if (OB_FAIL(uint_uint(expect_type, params, uint64, out, cast_mode))) {
// LOG_WARN("failed to cast uint to uint", K(in), K(uint64), K(ret));
// } else {/*do nothing*/}
// return ret;
//}
//
// static int enumset_inner_float(const ObObjType expect_type, ObObjCastParams &params,
// const ObObj &in, ObObj &out, const ObCastMode cast_mode)
//{
// //we regard enum as uint16 when int_value is needed
// int ret = OB_SUCCESS;
// ObObj uint64;
// if (OB_UNLIKELY(ObEnumSetInnerTC != in.get_type_class()
// || ObFloatTC != ob_obj_type_class(expect_type))) {
// ret = OB_ERR_UNEXPECTED;
// LOG_ERROR("invalid input type",
// K(ret), K(in), K(expect_type));
// } else if (OB_FAIL(get_uint64_from_enumset_inner(in, uint64))) {
// LOG_WARN("failed to get_uint64_from_enumset_inner", K(in), K(ret));
// } else if (OB_FAIL(uint_float(expect_type, params, uint64, out, cast_mode))) {
// LOG_WARN("failed to cast uint to float", K(in), K(uint64), K(ret));
// } else {/*do nothing*/}
// return ret;
//}
//
// static int enumset_inner_double(const ObObjType expect_type, ObObjCastParams &params,
// const ObObj &in, ObObj &out, const ObCastMode cast_mode)
//{
// //we regard enum as uint16 when int_value is needed
// int ret = OB_SUCCESS;
// ObObj uint64;
// if (OB_UNLIKELY(ObEnumSetInnerTC != in.get_type_class()
// || ObDoubleTC != ob_obj_type_class(expect_type))) {
// ret = OB_ERR_UNEXPECTED;
// LOG_ERROR("invalid input type",
// K(ret), K(in), K(expect_type));
// } else if (OB_FAIL(get_uint64_from_enumset_inner(in, uint64))) {
// LOG_WARN("failed to get_uint64_from_enumset_inner", K(in), K(ret));
// } else if (OB_FAIL(uint_double(expect_type, params, uint64, out, cast_mode))) {
// LOG_WARN("failed to cast uint to double", K(in), K(uint64), K(ret));
// } else {/*do nothing*/}
// return ret;
//}
//
// static int enumset_inner_number(const ObObjType expect_type, ObObjCastParams &params,
// const ObObj &in, ObObj &out, const ObCastMode cast_mode)
//{
// //we regard enum as uint16 when int_value is needed
// int ret = OB_SUCCESS;
// ObObj uint64;
// if (OB_UNLIKELY(ObEnumSetInnerTC != in.get_type_class()
// || ObNumberTC != ob_obj_type_class(expect_type))) {
// ret = OB_ERR_UNEXPECTED;
// LOG_ERROR("invalid input type", K(in), K(expect_type), K(ret));
// } else if (OB_FAIL(get_uint64_from_enumset_inner(in, uint64))) {
// LOG_WARN("failed to get_uint64_from_enumset_inner", K(in), K(ret));
// } else if (OB_FAIL(uint_number(expect_type, params, uint64, out, cast_mode))) {
// LOG_WARN("failed to cast uint to number", K(in), K(uint64), K(ret));
// } else {/*do nothing*/}
// return ret;
//}
static int enumset_inner_int(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
// we regard enum as uint16 when int_value is needed
int ret = OB_SUCCESS;
ObObj uint64;
if (OB_UNLIKELY(ObEnumSetInnerTC != in.get_type_class() || ObIntTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(get_uint64_from_enumset_inner(in, uint64))) {
LOG_WARN("failed to get_uint64_from_enumset_inner", K(in), K(ret));
} else if (OB_FAIL(uint_int(expect_type, params, uint64, out, cast_mode))) {
LOG_WARN("failed to cast uint to int", K(in), K(uint64), K(ret));
} else { /*do nothing*/
}
return ret;
}
static int enumset_inner_uint(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
// we regard enum as uint16 when int_value is needed
int ret = OB_SUCCESS;
ObObj uint64;
if (OB_UNLIKELY(ObEnumSetInnerTC != in.get_type_class() || ObUIntTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(get_uint64_from_enumset_inner(in, uint64))) {
LOG_WARN("failed to get_uint64_from_enumset_inner", K(in), K(ret));
} else if (OB_FAIL(uint_uint(expect_type, params, uint64, out, cast_mode))) {
LOG_WARN("failed to cast uint to uint", K(in), K(uint64), K(ret));
} else { /*do nothing*/
}
return ret;
}
static int enumset_inner_float(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
// we regard enum as uint16 when int_value is needed
int ret = OB_SUCCESS;
ObObj uint64;
if (OB_UNLIKELY(ObEnumSetInnerTC != in.get_type_class() || ObFloatTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(get_uint64_from_enumset_inner(in, uint64))) {
LOG_WARN("failed to get_uint64_from_enumset_inner", K(in), K(ret));
} else if (OB_FAIL(uint_float(expect_type, params, uint64, out, cast_mode))) {
LOG_WARN("failed to cast uint to float", K(in), K(uint64), K(ret));
} else { /*do nothing*/
}
return ret;
}
static int enumset_inner_double(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
// we regard enum as uint16 when int_value is needed
int ret = OB_SUCCESS;
ObObj uint64;
if (OB_UNLIKELY(ObEnumSetInnerTC != in.get_type_class() || ObDoubleTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(get_uint64_from_enumset_inner(in, uint64))) {
LOG_WARN("failed to get_uint64_from_enumset_inner", K(in), K(ret));
} else if (OB_FAIL(uint_double(expect_type, params, uint64, out, cast_mode))) {
LOG_WARN("failed to cast uint to double", K(in), K(uint64), K(ret));
} else { /*do nothing*/
}
return ret;
}
static int enumset_inner_number(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
// we regard enum as uint16 when int_value is needed
int ret = OB_SUCCESS;
ObObj uint64;
if (OB_UNLIKELY(ObEnumSetInnerTC != in.get_type_class() || ObNumberTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(in), K(expect_type), K(ret));
} else if (OB_FAIL(get_uint64_from_enumset_inner(in, uint64))) {
LOG_WARN("failed to get_uint64_from_enumset_inner", K(in), K(ret));
} else if (OB_FAIL(uint_number(expect_type, params, uint64, out, cast_mode))) {
LOG_WARN("failed to cast uint to number", K(in), K(uint64), K(ret));
} else { /*do nothing*/
}
return ret;
}
static int enumset_inner_year(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
// we regard enum as uint64 when int_value is needed
int ret = OB_SUCCESS;
ObObj uint64;
if (OB_UNLIKELY(ObEnumSetInnerTC != in.get_type_class() || ObYearTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(get_uint64_from_enumset_inner(in, uint64))) {
LOG_WARN("failed to get_uint64_from_enumset_inner", K(in), K(ret));
} else if (OB_FAIL(uint_year(expect_type, params, uint64, out, cast_mode))) {
LOG_WARN("failed to cast uint to year", K(in), K(uint64), K(ret));
} else { /*do nothing*/
}
return ret;
}
static int enumset_inner_bit(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
// we regard enum as uint16 when int_value is needed
int ret = OB_SUCCESS;
ObObj uint64;
if (OB_UNLIKELY(ObEnumSetInnerTC != in.get_type_class() || ObBitTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(get_uint64_from_enumset_inner(in, uint64))) {
LOG_WARN("failed to get_uint64_from_enumset_inner", K(in), K(ret));
} else if (OB_FAIL(uint_bit(expect_type, params, uint64, out, cast_mode))) {
LOG_WARN("failed to cast uint to year", K(in), K(uint64), K(ret));
} else { /*do nothing*/
}
return ret;
}
static int enumset_inner_datetime(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
// we regard enum as uint16 when int_value is needed
int ret = OB_SUCCESS;
ObObj str_value;
if (OB_UNLIKELY(ObEnumSetInnerTC != in.get_type_class() || ObDateTimeTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(get_string_from_enumset_inner(in, str_value))) {
LOG_WARN("failed to get_string_from_enumset_inner", K(in), K(ret));
} else if (OB_FAIL(string_datetime(expect_type, params, str_value, out, cast_mode))) {
LOG_WARN("failed to cast string to datetime", K(in), K(str_value), K(ret));
} else { /*do nothing*/
}
return ret;
}
static int enumset_inner_date(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
// we regard enum as uint16 when int_value is needed
int ret = OB_SUCCESS;
ObObj str_value;
if (OB_UNLIKELY(ObEnumSetInnerTC != in.get_type_class() || ObDateTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(get_string_from_enumset_inner(in, str_value))) {
LOG_WARN("failed to get_string_from_enumset_inner", K(in), K(ret));
} else if (OB_FAIL(string_date(expect_type, params, str_value, out, cast_mode))) {
LOG_WARN("failed to cast string to date", K(in), K(str_value), K(ret));
} else { /*do nothing*/
}
return ret;
}
static int enumset_inner_time(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
// we regard enum as uint16 when int_value is needed
int ret = OB_SUCCESS;
ObObj str_value;
if (OB_UNLIKELY(ObEnumSetInnerTC != in.get_type_class() || ObTimeTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(get_string_from_enumset_inner(in, str_value))) {
LOG_WARN("failed to get_string_from_enumset_inner", K(in), K(ret));
} else if (OB_FAIL(string_time(expect_type, params, str_value, out, cast_mode))) {
LOG_WARN("failed to cast string to time", K(in), K(str_value), K(ret));
} else { /*do nothing*/
}
return ret;
}
static int enumset_inner_string(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
// we regard enum as uint16 when int_value is needed
int ret = OB_SUCCESS;
ObObj str_value;
if (OB_UNLIKELY(ObEnumSetInnerTC != in.get_type_class() || ObStringTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(get_string_from_enumset_inner(in, str_value))) {
LOG_WARN("failed to get_string_from_enumset_inner", K(in), K(ret));
} else if (OB_FAIL(string_string(expect_type, params, str_value, out, cast_mode))) {
LOG_WARN("failed to cast string to string", K(in), K(str_value), K(ret));
} else { /*do nothing*/
}
return ret;
}
////////////////////////////////////////////////////////////
// OTimestamp -> XXX
static int otimestamp_datetime(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
int64_t usec = 0;
if (OB_UNLIKELY(ObOTimestampTC != in.get_type_class()) ||
OB_UNLIKELY(ObDateTimeTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(ObTimeConverter::otimestamp_to_odate(
in.get_type(), in.get_otimestamp_value(), params.dtc_params_.tz_info_, usec))) {
LOG_WARN("fail to timestamp_tz_to_timestamp", K(ret), K(in), K(expect_type));
} else {
ObTimeConverter::trunc_datetime(OB_MAX_DATE_PRECISION, usec);
out.set_datetime(expect_type, usec);
out.set_scale(OB_MAX_DATE_PRECISION);
}
SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, in.get_scale(), DEFAULT_LENGTH_FOR_TEMPORAL);
UNUSED(cast_mode);
return ret;
}
static int otimestamp_string(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
ObLength res_length = -1;
if (OB_UNLIKELY(ObOTimestampTC != in.get_type_class()) ||
OB_UNLIKELY(ObStringTC != ob_obj_type_class(expect_type) && ObTextTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else {
char buf[OB_CAST_TO_VARCHAR_MAX_LENGTH] = {0};
int64_t len = 0;
if (OB_FAIL(ObTimeConverter::otimestamp_to_str(in.get_otimestamp_value(),
params.dtc_params_,
in.get_scale(),
in.get_type(),
buf,
OB_CAST_TO_VARCHAR_MAX_LENGTH,
len))) {
LOG_WARN("failed to convert otimestamp to string", K(ret));
} else {
ObString tmp_str;
ObObj tmp_out;
if (OB_FAIL(convert_string_collation(
ObString(len, buf), ObCharset::get_system_collation(), tmp_str, params.dest_collation_, params))) {
LOG_WARN("fail to convert string collation", K(ret));
} else if (OB_FAIL(check_convert_string(expect_type, params, tmp_str, tmp_out))) {
LOG_WARN("fail to check_convert_string", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(copy_string(params, expect_type, tmp_out.get_string(), out))) {
LOG_WARN("failed to copy_string", K(ret), K(expect_type), K(len));
} else {
out.set_type(expect_type);
res_length = static_cast<ObLength>(out.get_string_len());
}
}
}
SET_RES_ACCURACY_STRING(expect_type, DEFAULT_PRECISION_FOR_STRING, res_length);
UNUSED(cast_mode);
return ret;
}
static int otimestamp_otimestamp(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
ObOTimestampData value;
if (OB_UNLIKELY(ObOTimestampTC != in.get_type_class()) ||
OB_UNLIKELY(ObOTimestampTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (ObTimestampNanoType == in.get_type()) {
if (OB_FAIL(ObTimeConverter::odate_to_otimestamp(
in.get_otimestamp_value().time_us_, params.dtc_params_.tz_info_, expect_type, value))) {
LOG_WARN("fail to odate_to_otimestamp", K(ret), K(expect_type));
} else {
value.time_ctx_.tail_nsec_ = in.get_otimestamp_value().time_ctx_.tail_nsec_;
}
} else if (ObTimestampNanoType == expect_type) {
if (OB_FAIL(ObTimeConverter::otimestamp_to_odate(
in.get_type(), in.get_otimestamp_value(), params.dtc_params_.tz_info_, *(int64_t*)&value.time_us_))) {
LOG_WARN("fail to otimestamp_to_odate", K(ret), K(expect_type));
} else {
value.time_ctx_.tail_nsec_ = in.get_otimestamp_value().time_ctx_.tail_nsec_;
}
} else {
if (OB_FAIL(ObTimeConverter::otimestamp_to_otimestamp(
in.get_type(), in.get_otimestamp_value(), params.dtc_params_.tz_info_, expect_type, value))) {
LOG_WARN("fail to otimestamp_to_otimestamp", K(ret), K(expect_type));
}
}
if (OB_SUCC(ret)) {
SET_RES_OTIMESTAMP(out);
}
SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, in.get_scale(), DEFAULT_LENGTH_FOR_TEMPORAL);
UNUSED(cast_mode);
return ret;
}
////////////////////////////////////////////////////////////
// Interval -> XXX
static int interval_string(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
char buf[OB_CAST_TO_VARCHAR_MAX_LENGTH] = {0};
int64_t len = 0;
ObLength res_length = -1;
bool is_explicit_cast = CM_IS_EXPLICIT_CAST(cast_mode);
if (OB_UNLIKELY(!ob_is_string_type(expect_type) || ObIntervalTC != in.get_type_class())) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else {
ret = in.is_interval_ym()
? ObTimeConverter::interval_ym_to_str(
in.get_interval_ym(), in.get_scale(), buf, OB_CAST_TO_VARCHAR_MAX_LENGTH, len, is_explicit_cast)
: ObTimeConverter::interval_ds_to_str(
in.get_interval_ds(), in.get_scale(), buf, OB_CAST_TO_VARCHAR_MAX_LENGTH, len, is_explicit_cast);
if (OB_FAIL(ret)) {
LOG_WARN("failed to convert interval to str");
} else {
ObString tmp_str;
ObObj tmp_out;
if (OB_FAIL(convert_string_collation(
ObString(len, buf), ObCharset::get_system_collation(), tmp_str, params.dest_collation_, params))) {
LOG_WARN("fail to convert string collation", K(ret));
} else if (OB_FAIL(check_convert_string(expect_type, params, tmp_str, tmp_out))) {
LOG_WARN("fail to check_convert_string", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(copy_string(params, expect_type, tmp_out.get_string(), out))) {
LOG_WARN("failed to copy_string", K(ret), K(expect_type), K(len));
} else {
out.set_type(expect_type);
res_length = static_cast<ObLength>(out.get_string_len());
}
}
}
SET_RES_ACCURACY_STRING(expect_type, DEFAULT_PRECISION_FOR_STRING, res_length);
UNUSED(cast_mode);
return ret;
}
static int interval_interval(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(ObIntervalTC != ob_obj_type_class(expect_type) || ObIntervalTC != in.get_type_class())) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_UNLIKELY(expect_type != in.get_type())) {
ret = cast_inconsistent_types(expect_type, params, in, out, cast_mode);
} else {
if (&in != &out) {
out = in;
}
}
return ret;
}
////////////////////////////////////////////////////////////
// Raw -> XXX
// lob is excluded.
static int raw_string(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
UNUSED(cast_mode);
int ret = OB_SUCCESS;
ObLength res_length = -1;
ObString tmp_str;
ObObj tmp_obj;
if (OB_UNLIKELY((ObRawTC != in.get_type_class()) || OB_UNLIKELY(ObStringTC != ob_obj_type_class(expect_type)))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(ObHexUtils::rawtohex(in, params, tmp_obj))) {
LOG_WARN("fail to rawtohex", K(ret), K(in), K(expect_type));
} else {
if (!ObCharset::is_cs_nonascii(params.dest_collation_)) {
out.set_string(expect_type, tmp_obj.get_string_ptr(), tmp_obj.get_string_len());
out.set_collation_type(params.dest_collation_);
res_length = static_cast<ObLength>(out.get_string_len());
} else {
if (OB_FAIL(convert_string_collation(
tmp_obj.get_string(), ObCharset::get_system_collation(), tmp_str, params.dest_collation_, params))) {
LOG_WARN("failed to convert string collation", K(ret));
} else {
out.set_string(expect_type, tmp_str.ptr(), tmp_str.length());
out.set_collation_type(params.dest_collation_);
res_length = static_cast<ObLength>(out.get_string_len());
}
}
}
SET_RES_ACCURACY_STRING(expect_type, DEFAULT_PRECISION_FOR_STRING, res_length);
return ret;
}
static int raw_longtext(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
UNUSED(cast_mode);
int ret = OB_SUCCESS;
ObLength res_length = -1;
ObString tmp_str;
ObObj tmp_obj;
if (OB_UNLIKELY((ObRawTC != in.get_type_class()) || OB_UNLIKELY(!ob_is_text_tc(expect_type)))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (ob_is_clob(expect_type, params.expect_obj_collation_)) {
// raw to clob
if (OB_FAIL(ObHexUtils::rawtohex(in, params, tmp_obj))) {
LOG_WARN("fail to rawtohex", K(ret), K(in), K(expect_type));
} else {
if (!ObCharset::is_cs_nonascii(params.expect_obj_collation_)) {
out.set_varchar_value(tmp_obj.get_string_ptr(), tmp_obj.get_string_len());
out.set_collation_type(params.expect_obj_collation_);
} else {
if (OB_FAIL(convert_string_collation(tmp_obj.get_string(),
ObCharset::get_system_collation(),
tmp_str,
params.expect_obj_collation_,
params))) {
LOG_WARN("failed to convert string collation", K(ret));
} else {
out.set_varchar_value(tmp_str.ptr(), tmp_str.length());
out.set_collation_type(params.expect_obj_collation_);
}
}
}
} else if (ob_is_blob(expect_type, params.expect_obj_collation_)) {
// raw to blob
if (OB_FAIL(copy_string(params, expect_type, in.get_string(), out))) {
LOG_WARN("failed to copy string", K(ret), K(in), K(expect_type));
}
}
if (OB_SUCC(ret)) {
out.set_type(expect_type);
out.set_lob_inrow();
out.set_collation_type(params.expect_obj_collation_);
out.set_collation_level(CS_LEVEL_IMPLICIT);
res_length = static_cast<ObLength>(out.get_string_len());
}
SET_RES_ACCURACY_STRING(expect_type, DEFAULT_PRECISION_FOR_STRING, res_length);
return ret;
}
static int raw_lob(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
ObObj tmp_val;
if (OB_UNLIKELY((ObRawTC != in.get_type_class()) || OB_UNLIKELY(ObLobTC != ob_obj_type_class(expect_type)))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(raw_longtext(ObLongTextType, params, in, tmp_val, cast_mode))) {
LOG_WARN("fail to cast raw to longtext", K(ret), K(expect_type), K(in), K(tmp_val));
} else if (OB_FAIL(string_lob(expect_type, params, tmp_val, out, cast_mode))) {
LOG_WARN("fail to cast string to lob", K(ret), K(expect_type), K(in), K(tmp_val));
}
return ret;
}
static int raw_raw(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
UNUSED(cast_mode);
int ret = OB_SUCCESS;
ObLength res_length = -1;
ObObj tmp_out;
if (OB_UNLIKELY((ObRawTC != in.get_type_class()) || OB_UNLIKELY(ObRawTC != ob_obj_type_class(expect_type)))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(check_convert_string(expect_type, params, in, tmp_out))) {
LOG_WARN("failed to check_and_convert_string", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(copy_string(params, expect_type, tmp_out.get_string(), out))) {
LOG_WARN("failed to copy string", K(ret), K(in), K(expect_type));
} else {
out.set_type(expect_type);
res_length = static_cast<ObLength>(out.get_string_len());
}
SET_RES_ACCURACY_STRING(expect_type, DEFAULT_PRECISION_FOR_STRING, res_length);
return ret;
}
////////////////////////////////////////////////////////////
// rowid -> XXX
static int rowid_string(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
UNUSED(cast_mode);
int ret = OB_SUCCESS;
ObLength res_length = -1;
if (OB_UNLIKELY(ObRowIDTC != in.get_type_class()) || OB_UNLIKELY(ObStringTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("invalid input type", K(ret), K(in), K(expect_type));
} else if (!in.is_urowid()) {
ret = OB_NOT_SUPPORTED;
LOG_WARN("not support rowid for now", K(ret));
} else {
int64_t pos = 0;
char* base64_buf = NULL;
int64_t base64_buf_len = in.get_urowid().needed_base64_buffer_size();
if (OB_ISNULL(base64_buf = (char*)(params.alloc(base64_buf_len)))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("failed to allocate memory", K(ret));
} else if (OB_FAIL(in.get_urowid().get_base64_str(base64_buf, base64_buf_len, pos))) {
LOG_WARN("failed to get base64 string", K(ret));
} else {
ObString tmp_str;
ObObj tmp_out;
if (OB_FAIL(convert_string_collation(ObString(base64_buf_len, base64_buf),
ObCharset::get_system_collation(),
tmp_str,
params.dest_collation_,
params))) {
LOG_WARN("failed to convert string collation", K(ret));
} else if (OB_FAIL(check_convert_string(expect_type, params, tmp_str, tmp_out))) {
LOG_WARN("failed to check convert string", K(ret));
} else if (OB_FAIL(copy_string(params, expect_type, tmp_out.get_string(), out))) {
LOG_WARN("failed to copy_string", K(ret), K(expect_type));
} else {
out.set_type(expect_type);
res_length = static_cast<ObLength>(out.get_string_len());
}
}
}
SET_RES_ACCURACY_STRING(expect_type, DEFAULT_PRECISION_FOR_STRING, res_length);
return ret;
}
static int rowid_rowid(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(ObRowIDTC != in.get_type_class()) || OB_UNLIKELY(ObRowIDTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_UNLIKELY(ObURowIDType != expect_type || ObURowIDType != in.get_type())) {
ret = OB_NOT_SUPPORTED;
LOG_WARN("only support urowid type for now", K(ret));
} else {
UNUSED(params);
UNUSED(cast_mode);
if (&in != &out) {
out = in;
}
}
return ret;
}
////////////////////////////////////////////////////////////
// Lob -> XXX
#define CAST_LOB_TO_OTHER_TYPE(TYPE, TYPE_CLASS) \
static int lob_##TYPE( \
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode) \
{ \
int ret = OB_SUCCESS; \
if (OB_UNLIKELY(ObLobTC != in.get_type_class() || TYPE_CLASS != ob_obj_type_class(expect_type))) { \
ret = OB_ERR_UNEXPECTED; \
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type)); \
} else if (lib::is_oracle_mode() && in.is_blob_locator()) { \
ret = OB_NOT_SUPPORTED; \
LOG_ERROR("invalid use of blob type", K(ret), K(in), K(expect_type)); \
LOG_USER_ERROR(OB_NOT_SUPPORTED, "Blob cast to other type"); \
} else { \
ObString str; \
if (OB_FAIL(in.get_string(str))) { \
STORAGE_LOG(WARN, "Failed to get payload from lob locator", K(ret), K(in)); \
} else { \
ObObj tmp_obj; \
tmp_obj.set_varchar(str); \
tmp_obj.set_collation_type(in.get_collation_type()); \
if (OB_FAIL(string_##TYPE(expect_type, params, tmp_obj, out, cast_mode))) { \
LOG_WARN("string to " #TYPE "failed", K(ret), K(tmp_obj)); \
} \
} \
} \
return ret; \
}
CAST_LOB_TO_OTHER_TYPE(int, ObIntTC);
CAST_LOB_TO_OTHER_TYPE(uint, ObUIntTC);
CAST_LOB_TO_OTHER_TYPE(double, ObDoubleTC);
CAST_LOB_TO_OTHER_TYPE(float, ObFloatTC);
CAST_LOB_TO_OTHER_TYPE(number, ObNumberTC);
CAST_LOB_TO_OTHER_TYPE(datetime, ObDateTimeTC);
CAST_LOB_TO_OTHER_TYPE(date, ObDateTC);
CAST_LOB_TO_OTHER_TYPE(time, ObTimeTC);
CAST_LOB_TO_OTHER_TYPE(year, ObYearTC);
CAST_LOB_TO_OTHER_TYPE(bit, ObBitTC);
CAST_LOB_TO_OTHER_TYPE(otimestamp, ObOTimestampTC);
CAST_LOB_TO_OTHER_TYPE(interval, ObIntervalTC);
CAST_LOB_TO_OTHER_TYPE(rowid, ObRowIDTC);
static int lob_string(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
ObObj tmp_out;
ObString in_str;
if (OB_UNLIKELY(ObLobTC != in.get_type_class() || OB_UNLIKELY(ObStringTC != ob_obj_type_class(expect_type) &&
ObTextTC != ob_obj_type_class(expect_type)))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(in.get_string(in_str))) {
LOG_WARN("get string failed", K(ret));
} else {
ObObj tmp_in = in;
tmp_in.set_string(ObLongTextType, in_str);
if (OB_FAIL(string_string(expect_type, params, tmp_in, out, cast_mode))) {
LOG_WARN("cast string to string failed", K(ret));
}
}
return ret;
}
static int lob_lob(
const ObObjType expect_type, ObObjCastParams& params, const ObObj& in, ObObj& out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(ObLobTC != in.get_type_class() || ObLobTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (in.get_collation_type() == params.expect_obj_collation_) {
out = in;
} else if (lib::is_oracle_mode() && in.is_blob_locator()) {
ret = OB_NOT_SUPPORTED;
LOG_ERROR("invalid use of blob type", K(ret), K(in), K(expect_type));
LOG_USER_ERROR(OB_NOT_SUPPORTED, "Blob cast to other type");
} else if (lib::is_oracle_mode() && in.is_clob_locator() && CS_TYPE_BINARY == params.expect_obj_collation_) {
ret = OB_NOT_SUPPORTED;
LOG_WARN("Can't convert collation type of clob to binary",
K(ret),
K(in),
K(expect_type),
K(params.expect_obj_collation_));
LOG_USER_ERROR(OB_NOT_SUPPORTED, "Convert collation type of clob to binary");
} else {
ObString str;
if (OB_FAIL(in.get_string(str))) {
STORAGE_LOG(WARN, "Failed to get payload from lob locator", K(ret), K(in));
} else {
ObObj tmp_obj;
tmp_obj.set_varchar(str);
tmp_obj.set_collation_type(in.get_collation_type());
if (OB_FAIL(string_lob(expect_type, params, tmp_obj, out, cast_mode, in.get_lob_locator()))) {
LOG_WARN("string to rowid failed", K(ret), K(tmp_obj));
}
}
}
return ret;
}
static int lob_json(const ObObjType expect_type, ObObjCastParams &params,
const ObObj &in, ObObj &out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
ObObj tmp_out;
ObString in_str;
if (OB_UNLIKELY(ObLobTC != in.get_type_class() || ObJsonType != expect_type)) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(in.get_string(in_str))) {
LOG_WARN("get string failed", K(ret));
} else {
ObObj tmp_in = in;
tmp_in.set_string(ObLongTextType, in_str);
if (OB_FAIL(string_json(expect_type, params, tmp_in, out, cast_mode))) {
LOG_WARN("cast string to string failed", K(ret));
}
}
return ret;
}
////////////////////////////////////////////////////////////
// json -> XXX
static int json_int(const ObObjType expect_type, ObObjCastParams &params,
const ObObj &in, ObObj &out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
ObPrecision res_precision = -1;
// ToDo convert json to other none string type is also not allowed.
if (OB_UNLIKELY(ObJsonType != in.get_type() || ObIntTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if(OB_UNLIKELY(params.allocator_v2_ == NULL)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("invalid allocator in json cast to other type", K(ret), K(params.allocator_v2_));
} else {
int64_t value = 0;
ObString j_bin_str = in.get_string();
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(value))) {
LOG_WARN("fail to cast json to other type", K(ret), K(j_bin_str), K(expect_type));
ret = OB_ERR_INVALID_JSON_VALUE_FOR_CAST;
LOG_USER_ERROR(OB_ERR_INVALID_JSON_VALUE_FOR_CAST);
} else if (expect_type < ObIntType && CAST_FAIL(int_range_check(expect_type, value, value))) {
LOG_WARN("range check failed", K(ret), K(expect_type), K(value));
} else {
SET_RES_INT(out);
res_precision = get_precision_for_integer(value);
}
}
SET_RES_ACCURACY(res_precision, DEFAULT_SCALE_FOR_INTEGER, DEFAULT_LENGTH_FOR_NUMERIC);
return ret;
}
static int json_uint(const ObObjType expect_type, ObObjCastParams &params,
const ObObj &in, ObObj &out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
ObPrecision res_precision = -1;
// ToDo convert json to other none string type is also not allowed.
if (OB_UNLIKELY(ObJsonType != in.get_type() || ObUIntTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if(OB_UNLIKELY(params.allocator_v2_ == NULL)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("invalid allocator in json cast to other type", K(ret), K(params.allocator_v2_));
} else {
uint64_t value = 0;
ObString j_bin_str = in.get_string();
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(value))) {
LOG_WARN("fail to cast json to other type", K(ret), K(j_bin_str), K(expect_type));
ret = OB_ERR_INVALID_JSON_VALUE_FOR_CAST;
LOG_USER_ERROR(OB_ERR_INVALID_JSON_VALUE_FOR_CAST);
} else if (CAST_FAIL(uint_upper_check(expect_type, value))) {
LOG_WARN("range check failed", K(ret), K(expect_type), K(value));
} else {
SET_RES_UINT(out);
res_precision = get_precision_for_integer(value);
}
}
SET_RES_ACCURACY(res_precision, DEFAULT_SCALE_FOR_INTEGER, DEFAULT_LENGTH_FOR_NUMERIC);
return ret;
}
static int json_double(const ObObjType expect_type, ObObjCastParams &params,
const ObObj &in, ObObj &out, const ObCastMode cast_mode);
static int json_float(const ObObjType expect_type, ObObjCastParams &params,
const ObObj &in, ObObj &out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(ObJsonType != in.get_type() || ObFloatTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else {
ObObj obj_double;
if (OB_FAIL(json_double(ObDoubleType, params, in, obj_double, cast_mode))) {
LOG_WARN("json to double convert failed in json to float convert",
K(ret), K(cast_mode));
} else if (OB_FAIL(double_float(expect_type, params, obj_double, out, cast_mode))) {
LOG_WARN("double to float convert failed in json to float convert",
K(ret), K(obj_double), K(cast_mode));
}
}
return ret;
}
static int json_double(const ObObjType expect_type, ObObjCastParams &params,
const ObObj &in, ObObj &out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
ObPrecision res_precision = -1;
// ToDo convert json to other none string type is also not allowed.
if (OB_UNLIKELY(ObJsonType != in.get_type() || ObDoubleTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if(OB_UNLIKELY(params.allocator_v2_ == NULL)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("invalid allocator in json cast to other type", K(ret), K(params.allocator_v2_));
} else {
double value = 0.0;
ObString j_bin_str = in.get_string();
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(value))) {
LOG_WARN("fail to cast json to other type", K(ret), K(j_bin_str), K(expect_type));
ret = OB_ERR_INVALID_JSON_VALUE_FOR_CAST;
LOG_USER_ERROR(OB_ERR_INVALID_JSON_VALUE_FOR_CAST);
} else if (ObUDoubleType == expect_type && CAST_FAIL(numeric_negative_check(value))) {
LOG_WARN("numeric_negative_check failed", K(ret), K(expect_type), K(value));
} else {
SET_RES_DOUBLE(out);
res_precision = get_precision_for_integer(value);
}
}
SET_RES_ACCURACY(PRECISION_UNKNOWN_YET, SCALE_UNKNOWN_YET, LENGTH_UNKNOWN_YET);
return ret;
}
static int json_number(const ObObjType expect_type, ObObjCastParams &params,
const ObObj &in, ObObj &out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
// ToDo convert json to other none string type is also not allowed.
if (OB_UNLIKELY(ObJsonType != in.get_type() || ObNumberTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if(OB_UNLIKELY(params.allocator_v2_ == NULL)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("invalid allocator in json cast to other type", K(ret), K(params.allocator_v2_));
} else {
number::ObNumber value;
ObString j_bin_str = in.get_string();
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(params.allocator_v2_, value))) {
LOG_WARN("fail to cast json to other type", K(ret), K(j_bin_str), K(expect_type));
ret = OB_ERR_INVALID_JSON_VALUE_FOR_CAST;
LOG_USER_ERROR(OB_ERR_INVALID_JSON_VALUE_FOR_CAST);
} else if (ObUNumberType == expect_type && CAST_FAIL(numeric_negative_check(value))) {
LOG_WARN("numeric_negative_check failed", K(ret), K(expect_type), K(value));
} else {
SET_RES_NUMBER(out);
}
}
SET_RES_ACCURACY(PRECISION_UNKNOWN_YET, SCALE_UNKNOWN_YET, LENGTH_UNKNOWN_YET);
return ret;
}
static int json_datetime(const ObObjType expect_type, ObObjCastParams &params,
const ObObj &in, ObObj &out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
// ToDo convert json to other none string type is also not allowed.
if (OB_UNLIKELY(ObJsonType != in.get_type() || ObDateTimeTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if(OB_UNLIKELY(params.allocator_v2_ == NULL)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("invalid allocator in json cast to other type", K(ret), K(params.allocator_v2_));
} else {
int64_t value;
ObString j_bin_str = in.get_string();
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(value))) {
LOG_WARN("fail to cast json to other type", K(ret), K(j_bin_str), K(expect_type));
ret = OB_ERR_INVALID_JSON_VALUE_FOR_CAST;
LOG_USER_ERROR(OB_ERR_INVALID_JSON_VALUE_FOR_CAST);
} else {
SET_RES_DATETIME(out);
}
}
SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, MIN_SCALE_FOR_TEMPORAL, DEFAULT_LENGTH_FOR_TEMPORAL);
return ret;
}
static int json_date(const ObObjType expect_type, ObObjCastParams &params,
const ObObj &in, ObObj &out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
// ToDo convert json to other none string type is also not allowed.
if (OB_UNLIKELY(ObJsonType != in.get_type() || ObDateTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if(OB_UNLIKELY(params.allocator_v2_ == NULL)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("invalid allocator in json cast to other type", K(ret), K(params.allocator_v2_));
} else {
int32_t value;
ObString j_bin_str = in.get_string();
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(value))) {
LOG_WARN("fail to cast json to other type", K(ret), K(j_bin_str), K(expect_type));
ret = OB_ERR_INVALID_JSON_VALUE_FOR_CAST;
LOG_USER_ERROR(OB_ERR_INVALID_JSON_VALUE_FOR_CAST);
} else {
SET_RES_DATE(out);
}
}
SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, DEFAULT_SCALE_FOR_DATE, DEFAULT_LENGTH_FOR_TEMPORAL);
return ret;
}
static int json_time(const ObObjType expect_type, ObObjCastParams &params,
const ObObj &in, ObObj &out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
// ToDo convert json to other none string type is also not allowed.
if (OB_UNLIKELY(ObJsonType != in.get_type() || ObTimeTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if(OB_UNLIKELY(params.allocator_v2_ == NULL)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("invalid allocator in json cast to other type", K(ret), K(params.allocator_v2_));
} else {
int64_t value;
ObString j_bin_str = in.get_string();
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(value))) {
LOG_WARN("fail to cast json to other type", K(ret), K(j_bin_str), K(expect_type));
ret = OB_ERR_INVALID_JSON_VALUE_FOR_CAST;
LOG_USER_ERROR(OB_ERR_INVALID_JSON_VALUE_FOR_CAST);
} else {
SET_RES_TIME(out);
}
}
SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, MIN_SCALE_FOR_TEMPORAL, DEFAULT_LENGTH_FOR_TEMPORAL);
return ret;
}
static int json_year(const ObObjType expect_type, ObObjCastParams &params,
const ObObj &in, ObObj &out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
// ToDo convert json to other none string type is also not allowed.
if (OB_UNLIKELY(ObJsonType != in.get_type() || ObYearTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if(OB_UNLIKELY(params.allocator_v2_ == NULL)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("invalid allocator in json cast to other type", K(ret), K(params.allocator_v2_));
} else {
uint8_t value = 0;
int64_t int_value = 0;
ObString j_bin_str = in.get_string();
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_value, false, true))) {
LOG_WARN("fail to cast json to other type", K(ret), K(j_bin_str), K(expect_type));
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_value, value))){
LOG_WARN("fail to cast json int to year type", K(ret), K(int_value), K(expect_type));
} else {
if (lib::is_mysql_mode() && (params.warning_ == OB_DATA_OUT_OF_RANGE)) {
out.set_null(); // not change the behavior of int_year
} else {
SET_RES_YEAR(out);
}
}
}
SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_TEMPORAL, DEFAULT_SCALE_FOR_YEAR, DEFAULT_LENGTH_FOR_TEMPORAL);
return ret;
}
static int json_string(const ObObjType expect_type, ObObjCastParams &params,
const ObObj &in, ObObj &out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
// ToDo convert json to other none string type is also not allowed.
if (OB_UNLIKELY(ObJsonType != in.get_type() ||
OB_UNLIKELY(ObStringTC != ob_obj_type_class(expect_type) && ObTextTC != ob_obj_type_class(expect_type)))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (in.is_json_outrow()) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("invalid cast of out row json obj", K(ret), K(in), K(out.get_meta()), K(expect_type), K(cast_mode));
} else if(OB_UNLIKELY(params.allocator_v2_ == NULL)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("invalid allocator in json cast to other type", K(ret), K(params.allocator_v2_));
} else {
ObJsonBuffer j_buf(params.allocator_v2_);
ObString j_bin_str = in.get_string();
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->print(j_buf, true))) {
LOG_WARN("fail to cast json to other type", K(ret), K(j_bin_str), K(expect_type));
ret = OB_ERR_INVALID_JSON_VALUE_FOR_CAST;
LOG_USER_ERROR(OB_ERR_INVALID_JSON_VALUE_FOR_CAST);
} else {
// get in cs type
bool need_charset_convert = ((CS_TYPE_BINARY == params.dest_collation_) ||
(ObCharset::charset_type_by_coll(in.get_collation_type()) !=
ObCharset::charset_type_by_coll(params.dest_collation_)));
ObString temp_str_val(j_buf.length(), j_buf.ptr());
/* this function maybe called in json generated column
* and the generated column may has limitaion constrain the string length */
uint64_t accuracy_max_len = 0;
if (params.res_accuracy_ && params.res_accuracy_->get_length()) {
accuracy_max_len = params.res_accuracy_->get_length();
}
if (!need_charset_convert) {
if (accuracy_max_len > 0 && accuracy_max_len < j_buf.length()) {
temp_str_val.assign_ptr(j_buf.ptr(), accuracy_max_len);
}
ret = copy_string(params, expect_type, temp_str_val, out);
} else {
ObObj tmp_obj;
tmp_obj.set_collation_type(in.get_collation_type());
tmp_obj.set_collation_level(in.get_collation_level());
tmp_obj.set_string(ObLongTextType, temp_str_val);
ret = string_string(expect_type, params, tmp_obj, out, cast_mode);
if (accuracy_max_len && accuracy_max_len < out.get_string().length()) {
ObString tmp_str = out.get_string();
out.set_string(expect_type, tmp_str.ptr(), accuracy_max_len);
}
}
}
}
return ret;
}
static int json_bit(const ObObjType expect_type, ObObjCastParams &params,
const ObObj &in, ObObj &out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
uint64_t value;
int32_t bit_len = 0;
if (OB_UNLIKELY(ObJsonType != in.get_type()
|| ObBitTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else {
ObString j_bin_str = in.get_string();
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_bit(value))) {
ret = OB_ERR_INVALID_JSON_VALUE_FOR_CAST;
LOG_USER_ERROR(OB_ERR_INVALID_JSON_VALUE_FOR_CAST);
} else if (OB_FAIL(get_bit_len(value, bit_len))) {
LOG_WARN("fail to get bit len", K(ret), K(value), K(bit_len));
} else {
SET_RES_BIT(out);
SET_RES_ACCURACY(static_cast<ObPrecision>(bit_len), DEFAULT_SCALE_FOR_BIT, DEFAULT_LENGTH_FOR_NUMERIC);
}
}
UNUSED(params);
UNUSED(cast_mode);
return ret;
}
static int json_otimestamp(const ObObjType expect_type, ObObjCastParams &params,
const ObObj &in, ObObj &out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
ObObj datetime_obj;
if (OB_UNLIKELY(ObJsonType != in.get_type()) || OB_UNLIKELY(ObOTimestampTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else if (OB_FAIL(json_datetime(ObDateTimeType, params, in, datetime_obj, cast_mode))) {
LOG_WARN("json to datatime convert failed in json to otimestamp convert",
K(ret), K(cast_mode));
} else if (OB_FAIL(datetime_otimestamp(expect_type, params, datetime_obj, out, cast_mode))) {
LOG_WARN("datatime to otimestamp convert failed in json to otimestamp convert",
K(ret), K(datetime_obj), K(cast_mode));
}
return ret;
}
static int json_lob(const ObObjType expect_type, ObObjCastParams &params,
const ObObj &in, ObObj &out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
if (!share::is_oracle_mode()) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("Unexpected tenant mode", K(ret));
} else {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("only support mysql json type currently", K(ret));
}
UNUSED(expect_type);
UNUSED(params);
UNUSED(in);
UNUSED(out);
UNUSED(cast_mode);
return ret;
}
static int json_json(const ObObjType expect_type, ObObjCastParams &params,
const ObObj &in, ObObj &out, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
if (OB_UNLIKELY(ObJsonType != in.get_type()) || OB_UNLIKELY(ObJsonTC != ob_obj_type_class(expect_type))) {
ret = OB_ERR_UNEXPECTED;
LOG_ERROR("invalid input type", K(ret), K(in), K(expect_type));
} else {
ObString str = in.get_string();
out.set_json_value(expect_type, str.ptr(), str.length());
ObLength res_length = static_cast<ObLength>(out.get_string_len());
SET_RES_ACCURACY(DEFAULT_SCALE_FOR_TEXT, DEFAULT_PRECISION_FOR_STRING, res_length);
}
UNUSED(cast_mode);
return ret;
}
ObObjCastFunc OB_OBJ_CAST[ObMaxTC][ObMaxTC] = {
{
/*null -> XXX*/
cast_identity, /*null*/
cast_identity, /*int*/
cast_identity, /*uint*/
cast_identity, /*float*/
cast_identity, /*double*/
cast_identity, /*number*/
cast_identity, /*datetime*/
cast_identity, /*date*/
cast_identity, /*time*/
cast_identity, /*year*/
cast_identity, /*string*/
cast_identity, /*extend*/
cast_identity, /*unknown*/
cast_identity, /*text*/
cast_identity, /*bit*/
cast_identity, /*enumset*/
cast_identity, /*enumsetInner*/
cast_identity, /*otimestamp*/
cast_inconsistent_types, /*raw*/
cast_not_expected, /*interval*/
cast_not_expected, /*rowid*/
cast_identity, /*lob*/
cast_identity, /*json*/
},
{
/*int -> XXX*/
cast_not_support, /*null*/
int_int, /*int*/
int_uint, /*uint*/
int_float, /*float*/
int_double, /*double*/
int_number, /*number*/
int_datetime, /*datetime*/
int_date, /*date*/
int_time, /*time*/
int_year, /*year*/
int_string, /*string*/
cast_not_support, /*extend*/
cast_not_support, /*unknown*/
int_string, /*text*/
int_bit, /*bit*/
cast_not_expected, /*enumset*/
cast_not_expected, /*enumset_inner*/
cast_not_support, /*otimestamp*/
cast_inconsistent_types, /*raw*/
cast_not_expected, /*interval*/
cast_not_expected, /*rowid*/
int_lob, /*lob*/
int_json, /*json*/
},
{
/*uint -> XXX*/
cast_not_support, /*null*/
uint_int, /*int*/
uint_uint, /*uint*/
uint_float, /*float*/
uint_double, /*double*/
uint_number, /*number*/
uint_datetime, /*datetime*/
uint_date, /*date*/
uint_time, /*time*/
uint_year, /*year*/
uint_string, /*string*/
cast_not_support, /*extend*/
cast_not_support, /*unknown*/
uint_string, /*text*/
uint_bit, /*bit*/
cast_not_expected, /*enumset*/
cast_not_expected, /*enumset_inner*/
cast_not_support, /*otimestamp*/
cast_inconsistent_types, /*raw*/
cast_not_expected, /*interval*/
cast_not_expected, /*rowid*/
uint_lob, /*lob*/
uint_json, /*json*/
},
{
/*float -> XXX*/
cast_not_support, /*null*/
float_int, /*int*/
float_uint, /*uint*/
float_float, /*float*/
float_double, /*double*/
float_number, /*number*/
float_datetime, /*datetime*/
float_date, /*date*/
float_time, /*time*/
cast_not_support, /*year*/
float_string, /*string*/
cast_not_support, /*extend*/
cast_not_support, /*unknown*/
float_string, /*text*/
float_bit, /*bit*/
cast_not_expected, /*enumset*/
cast_not_expected, /*enumset_inner*/
cast_not_support, /*otimestamp*/
cast_inconsistent_types, /*raw*/
cast_not_expected, /*interval*/
cast_not_expected, /*rowid*/
float_lob, /*lob*/
float_json, /*json*/
},
{
/*double -> XXX*/
cast_not_support, /*null*/
double_int, /*int*/
double_uint, /*uint*/
double_float, /*float*/
double_double, /*double*/
double_number, /*number*/
double_datetime, /*datetime*/
double_date, /*date*/
double_time, /*time*/
double_year, /*year*/
double_string, /*string*/
cast_not_support, /*extend*/
cast_not_support, /*unknown*/
double_string, /*text*/
double_bit, /*bit*/
cast_not_expected, /*enumset*/
cast_not_expected, /*enumset_inner*/
cast_not_support, /*otimestamp*/
cast_inconsistent_types, /*raw*/
cast_not_expected, /*interval*/
cast_not_expected, /*rowid*/
double_lob, /*lob*/
double_json, /*json*/
},
{
/*number -> XXX*/
cast_not_support, /*null*/
number_int, /*int*/
number_uint, /*uint*/
number_float, /*float*/
number_double, /*double*/
number_number, /*number*/
number_datetime, /*datetime*/
number_date, /*date*/
number_time, /*time*/
number_year, /*year*/
number_string, /*string*/
cast_not_support, /*extend*/
cast_not_support, /*unknown*/
number_string, /*text*/
number_bit, /*bit*/
cast_not_expected, /*enumset*/
cast_not_expected, /*enumset_inner*/
cast_not_support, /*otimestamp*/
cast_inconsistent_types, /*raw*/
cast_not_expected, /*interval*/
cast_not_expected, /*rowid*/
number_lob, /*lob*/
number_json, /*lob*/
},
{
/*datetime -> XXX*/
cast_not_support, /*null*/
datetime_int, /*int*/
datetime_uint, /*uint*/
datetime_float, /*float*/
datetime_double, /*double*/
datetime_number, /*number*/
datetime_datetime, /*datetime*/
datetime_date, /*date*/
datetime_time, /*time*/
datetime_year, /*year*/
datetime_string, /*string*/
cast_not_support, /*extend*/
cast_not_support, /*unknown*/
datetime_string, /*text*/
datetime_bit, /*bit*/
cast_not_expected, /*enumset*/
cast_not_expected, /*enumset_inner*/
datetime_otimestamp, /*otimestamp*/
cast_inconsistent_types, /*raw*/
cast_not_expected, /*interval*/
cast_not_expected, /*rowid*/
datetime_lob, /*lob*/
datetime_json, /*json*/
},
{
/*date -> XXX*/
cast_not_support, /*null*/
date_int, /*int*/
date_uint, /*uint*/
date_float, /*float*/
date_double, /*double*/
date_number, /*number*/
date_datetime, /*datetime*/
cast_identity, /*date*/
date_time, /*time*/
date_year, /*year*/
date_string, /*string*/
cast_not_support, /*extend*/
cast_not_support, /*unknown*/
date_string, /*text*/
date_bit, /*bit*/
cast_not_expected, /*enumset*/
cast_not_expected, /*enumset_inner*/
cast_not_support, /*otimestamp*/
cast_inconsistent_types, /*raw*/
cast_not_expected, /*interval*/
cast_not_expected, /*rowid*/
date_lob, /*lob*/
date_json, /*json*/
},
{
/*time -> XXX*/
cast_not_support, /*null*/
time_int, /*int*/
time_uint, /*uint*/
time_float, /*float*/
time_double, /*double*/
time_number, /*number*/
time_datetime, /*datetime*/
time_date, /*date*/
cast_identity, /*time*/
cast_not_support, /*year*/
time_string, /*string*/
cast_not_support, /*extend*/
cast_not_support, /*unknown*/
time_string, /*text*/
time_bit, /*bit*/
cast_not_expected, /*enumset*/
cast_not_expected, /*enumset_inner*/
cast_not_support, /*otimestamp*/
cast_inconsistent_types, /*raw*/
cast_not_expected, /*interval*/
cast_not_expected, /*rowid*/
time_lob, /*lob*/
time_json, /*json*/
},
{
/*year -> XXX*/
cast_not_support, /*null*/
year_int, /*int*/
year_uint, /*uint*/
year_float, /*float*/
year_double, /*double*/
year_number, /*number*/
cast_not_support, /*datetime*/
year_date, /*date*/
cast_not_support, /*time*/
cast_identity, /*year*/
year_string, /*string*/
cast_not_support, /*extend*/
cast_not_support, /*unknown*/
year_string, /*text*/
year_bit, /*bit*/
cast_not_expected, /*enumset*/
cast_not_expected, /*enumset_inner*/
cast_not_support, /*otimestamp*/
cast_inconsistent_types, /*raw*/
cast_not_expected, /*interval*/
cast_not_expected, /*rowid*/
year_lob, /*lob*/
year_json, /*json*/
},
{
/*string -> XXX*/
cast_not_support, /*null*/
string_int, /*int*/
string_uint, /*uint*/
string_float, /*float*/
string_double, /*double*/
string_number, /*number*/
string_datetime, /*datetime*/
string_date, /*date*/
string_time, /*time*/
string_year, /*year*/
string_string, /*string*/
cast_not_support, /*extend*/
cast_not_support, /*unknown*/
string_string, /*text*/
string_bit, /*bit*/
cast_not_expected, /*enumset*/
cast_not_expected, /*enumset_inner*/
string_otimestamp, /*otimestamp*/
cast_inconsistent_types, /*raw*/
cast_not_expected, /*interval*/
cast_not_expected, /*rowid*/
string_lob, /*lob*/
string_json, /*json*/
},
{
/*extend -> XXX*/
cast_not_support, /*null*/
cast_not_support, /*int*/
cast_not_support, /*uint*/
cast_not_support, /*float*/
cast_not_support, /*double*/
cast_not_support, /*number*/
cast_not_support, /*datetime*/
cast_not_support, /*date*/
cast_not_support, /*time*/
cast_not_support, /*year*/
cast_not_support, /*string*/
cast_identity, /*extend*/
cast_not_support, /*unknown*/
cast_not_support, /*text*/
cast_not_support, /*bit*/
cast_not_support, /*enumset*/
cast_not_support, /*enumset_inner*/
cast_not_support, /*otimestamp*/
cast_inconsistent_types, /*raw*/
cast_not_expected, /*interval*/
cast_not_expected, /*rowid*/
cast_not_support, /*lob*/
cast_not_support, /*json*/
},
{
/*unknown -> XXX*/
unknown_other, /*null*/
unknown_other, /*int*/
unknown_other, /*uint*/
unknown_other, /*float*/
unknown_other, /*double*/
unknown_other, /*number*/
unknown_other, /*datetime*/
unknown_other, /*date*/
unknown_other, /*time*/
unknown_other, /*year*/
unknown_other, /*string*/
unknown_other, /*extend*/
cast_identity, /*unknown*/
cast_not_support, /*text*/
unknown_other, /*bit*/
unknown_other, /*enumset*/
unknown_other, /*enumsetInner*/
unknown_other, /*otimestamp*/
cast_inconsistent_types, /*raw*/
cast_not_expected, /*interval*/
cast_not_expected, /*rowid*/
cast_not_support, /*lob*/
cast_not_support, /*json*/
},
{
/*text -> XXX*/
cast_not_support, /*null*/
string_int, /*int*/
string_uint, /*uint*/
string_float, /*float*/
string_double, /*double*/
string_number, /*number*/
string_datetime, /*datetime*/
string_date, /*date*/
string_time, /*time*/
string_year, /*year*/
string_string, /*string*/
cast_not_support, /*extend*/
cast_not_support, /*unknown*/
string_string, /*text*/
string_bit, /*bit*/
cast_not_expected, /*enumset*/
cast_not_expected, /*enumset_inner*/
string_otimestamp, /*otimestamp*/
cast_inconsistent_types, /*raw*/
cast_not_expected, /*interval*/
cast_not_expected, /*rowid*/
string_lob, /*lob*/
string_json, /*json*/
},
{
/*bit -> XXX*/
cast_not_support, /*null*/
bit_int, /*int*/
bit_uint, /*uint*/
bit_float, /*float*/
bit_double, /*double*/
bit_number, /*number*/
bit_datetime, /*datetime*/
bit_date, /*date*/
bit_time, /*time*/
bit_year, /*year*/
bit_string, /*string*/
cast_not_support, /*extend*/
cast_not_support, /*unknown*/
bit_string, /*text*/
bit_bit, /*bit*/
cast_not_expected, /*enumset*/
cast_not_expected, /*enumset_inner*/
cast_not_support, /*otimestamp*/
cast_inconsistent_types, /*raw*/
cast_not_expected, /*interval*/
cast_not_expected, /*rowid*/
bit_lob, /*lob*/
bit_json, /*lob*/
},
{
/*enum -> XXX*/
cast_not_support, /*null*/
enumset_int, /*int*/
enumset_uint, /*uint*/
enumset_float, /*float*/
enumset_double, /*double*/
enumset_number, /*number*/
cast_not_expected, /*datetime*/
cast_not_expected, /*date*/
cast_not_expected, /*time*/
enumset_year, /*year*/
cast_not_expected, /*string*/
cast_not_support, /*extend*/
cast_not_support, /*unknown*/
cast_not_expected, /*text*/
enumset_bit, /*bit*/
cast_not_expected, /*enumset*/
cast_not_expected, /*enumset_inner*/
cast_not_support, /*otimestamp*/
cast_inconsistent_types, /*raw*/
cast_not_expected, /*interval*/
cast_not_expected, /*rowid*/
cast_not_expected, /*lob*/
cast_not_expected, /*json*/
},
{
/*enumset_inner -> XXX*/
cast_not_support, /*null*/
enumset_inner_int, /*int*/
enumset_inner_uint, /*uint*/
enumset_inner_float, /*float*/
enumset_inner_double, /*double*/
enumset_inner_number, /*number*/
enumset_inner_datetime, /*datetime*/
enumset_inner_date, /*date*/
enumset_inner_time, /*time*/
enumset_inner_year, /*year*/
enumset_inner_string, /*string*/
cast_not_support, /*extend*/
cast_not_support, /*unknown*/
cast_not_support, /*text*/
enumset_inner_bit, /*bit*/
cast_not_expected, /*enumset*/
cast_not_expected, /*enumset_inner*/
cast_not_expected, /*otimestamp*/
cast_inconsistent_types, /*raw*/
cast_not_expected, /*interval*/
cast_not_expected, /*rowid*/
cast_not_support, /*lob*/
cast_not_support, /*json*/
},
{
/*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*/
},
{
/*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*/
},
{
/*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*/
},
{
/*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*/
},
{
/*lob -> XXX*/
cast_not_support, /*null*/
lob_int, /*int*/
lob_uint, /*uint*/
lob_float, /*float*/
lob_double, /*double*/
lob_number, /*number*/
lob_datetime, /*datetime*/
lob_date, /*date*/
lob_time, /*time*/
lob_year, /*year*/
lob_string, /*string*/
cast_not_support, /*extend*/
cast_not_support, /*unknown*/
lob_string, /*text*/
lob_bit, /*bit*/
cast_not_expected, /*enumset*/
cast_not_expected, /*enumset_inner*/
lob_otimestamp, /*otimestamp*/
cast_inconsistent_types, /*raw*/
cast_not_expected, /*interval*/
cast_not_expected, /*rowid*/
lob_lob, /*lob*/
lob_json, /*json*/
},
{
/*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*/
json_lob, /*lob*/
json_json, /*json*/
},
};
ObObjCastFunc OBJ_CAST_ORACLE_EXPLICIT[ObMaxTC][ObMaxTC] = {
{
/*null -> XXX*/
cast_identity, /*null*/
cast_identity, /*int*/
cast_identity, /*uint*/
cast_identity, /*float*/
cast_identity, /*double*/
cast_identity, /*number*/
cast_identity, /*datetime*/
cast_identity, /*date*/
cast_identity, /*time*/
cast_identity, /*year*/
cast_identity, /*string*/
cast_identity, /*extend*/
cast_identity, /*unknown*/
cast_identity, /*text*/
cast_identity, /*bit*/
cast_identity, /*enumset*/
cast_identity, /*enumsetInner*/
cast_identity, /*otimestamp*/
cast_identity, /*raw*/
cast_identity, /*interval*/
cast_identity, /*rowid*/
cast_identity, /*lob*/
cast_identity, /*json*/
},
{
/*int -> XXX*/
cast_not_support, /*null*/
int_int, /*int*/
int_uint, /*uint*/
int_float, /*float*/
int_double, /*double*/
int_number, /*number*/
cast_not_support, /*datetime*/
cast_not_support, /*date*/
cast_not_support, /*time*/
cast_not_support, /*year*/
int_string, /*string*/
cast_not_support, /*extend*/
cast_not_support, /*unknown*/
int_string, /*text*/
int_bit, /*bit*/
cast_not_expected, /*enumset*/
cast_not_expected, /*enumset_inner*/
cast_not_support, /*otimestamp*/
cast_not_support, /*raw*/
cast_not_support, /*interval*/
cast_not_support, /*rowid*/
cast_inconsistent_types, /*lob*/
cast_not_support, /*json not support oracle yet*/
},
{
/*uint -> XXX*/
cast_not_support, /*null*/
uint_int, /*int*/
uint_uint, /*uint*/
uint_float, /*float*/
uint_double, /*double*/
uint_number, /*number*/
cast_not_support, /*datetime*/
cast_not_support, /*date*/
cast_not_support, /*time*/
cast_not_support, /*year*/
uint_string, /*string*/
cast_not_support, /*extend*/
cast_not_support, /*unknown*/
uint_string, /*text*/
uint_bit, /*bit*/
cast_not_expected, /*enumset*/
cast_not_expected, /*enumset_inner*/
cast_not_support, /*otimestamp*/
cast_not_support, /*raw*/
cast_not_support, /*interval*/
cast_not_support, /*rowid*/
cast_inconsistent_types, /*lob*/
cast_not_support, /*json not support oracle yet*/
},
{
/*float -> XXX*/
cast_not_support, /*null*/
float_int, /*int*/
float_uint, /*uint*/
float_float, /*float*/
float_double, /*double*/
float_number, /*number*/
cast_not_support, /*datetime*/
cast_not_support, /*date*/
cast_not_support, /*time*/
cast_not_support, /*year*/
float_string, /*string*/
cast_not_support, /*extend*/
cast_not_support, /*unknown*/
float_string, /*text*/
float_bit, /*bit*/
cast_not_expected, /*enumset*/
cast_not_expected, /*enumset_inner*/
cast_not_support, /*otimestamp*/
cast_not_support, /*raw*/
cast_not_support, /*interval*/
cast_not_support, /*rowid*/
cast_inconsistent_types, /*lob*/
cast_not_support, /*json not support oracle yet*/
},
{
/*double -> XXX*/
cast_not_support, /*null*/
double_int, /*int*/
double_uint, /*uint*/
double_float, /*float*/
double_double, /*double*/
double_number, /*number*/
cast_not_support, /*datetime*/
cast_not_expected, /*date*/
cast_not_support, /*time*/
cast_not_support, /*year*/
double_string, /*string*/
cast_not_support, /*extend*/
cast_not_support, /*unknown*/
double_string, /*text*/
double_bit, /*bit*/
cast_not_expected, /*enumset*/
cast_not_expected, /*enumset_inner*/
cast_not_support, /*otimestamp*/
cast_not_support, /*raw*/
cast_not_support, /*interval*/
cast_not_support, /*rowid*/
cast_inconsistent_types, /*lob*/
cast_not_support, /*json not support oracle yet*/
},
{
/*number -> XXX*/
cast_not_support, /*null*/
number_int, /*int*/
number_uint, /*uint*/
number_float, /*float*/
number_double, /*double*/
number_number, /*number*/
cast_not_support, /*datetime*/
cast_not_support, /*date*/
cast_not_support, /*time*/
cast_not_support, /*year*/
number_string, /*string*/
cast_not_support, /*extend*/
cast_not_support, /*unknown*/
number_string, /*text*/
number_bit, /*bit*/
cast_not_expected, /*enumset*/
cast_not_expected, /*enumset_inner*/
cast_not_support, /*otimestamp*/
cast_not_support, /*raw*/
cast_not_support, /*interval*/
cast_not_support, /*rowid*/
cast_inconsistent_types, /*lob*/
cast_not_support, /*json not support oracle yet*/
},
{
/*datetime -> XXX*/
cast_not_support, /*null*/
cast_not_support, /*int*/
cast_not_support, /*uint*/
cast_not_support, /*float*/
cast_not_support, /*double*/
cast_not_support, /*number*/
datetime_datetime, /*datetime*/
cast_not_support, /*date*/
cast_not_support, /*time*/
cast_not_support, /*year*/
datetime_string, /*string*/
cast_not_support, /*extend*/
cast_not_support, /*unknown*/
datetime_string, /*text*/
datetime_bit, /*bit*/
cast_not_expected, /*enumset*/
cast_not_expected, /*enumset_inner*/
datetime_otimestamp, /*otimestamp*/
cast_not_support, /*raw*/
cast_not_support, /*interval*/
cast_not_support, /*rowid*/
cast_inconsistent_types, /*lob*/
cast_not_support, /*json not support oracle yet*/
},
{
/*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_not_support, /*json not support oracle yet*/
},
{
/*time -> XXX*/
cast_not_support, /*null*/
cast_not_expected, /*int*/
cast_not_expected, /*uint*/
cast_not_expected, /*float*/
cast_not_expected, /*double*/
cast_not_expected, /*number*/
cast_not_expected, /*datetime*/
cast_not_expected, /*date*/
cast_not_expected, /*time*/
cast_not_expected, /*year*/
cast_not_expected, /*string*/
cast_not_expected, /*extend*/
cast_not_expected, /*unknown*/
cast_not_expected, /*text*/
cast_not_expected, /*bit*/
cast_not_expected, /*enumset*/
cast_not_expected, /*enumset_inner*/
cast_not_expected, /*otimestamp*/
cast_not_expected, /*raw*/
cast_not_expected, /*interval*/
cast_not_expected, /*rowid*/
cast_not_expected, /*lob*/
cast_not_support, /*json not support oracle yet*/
},
{
/*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_not_support, /*json not support oracle yet*/
},
{
/*string -> XXX*/
cast_not_support, /*null*/
string_int, /*int*/
string_uint, /*uint*/
string_float, /*float*/
string_double, /*double*/
string_number, /*number*/
string_datetime, /*datetime*/
cast_not_expected, /*date*/
cast_not_expected, /*time*/
cast_not_expected, /*year*/
string_string, /*string*/
cast_not_support, /*extend*/
cast_not_support, /*unknown*/
string_string, /*text*/
string_bit, /*bit*/
cast_not_expected, /*enumset*/
cast_not_expected, /*enumset_inner*/
string_otimestamp, /*otimestamp*/
string_raw, /*raw*/
string_interval, /*interval*/
string_rowid, /*rowid*/
cast_inconsistent_types, /*lob*/
cast_not_support, /*json not support oracle yet*/
},
{
/*extend -> XXX*/
cast_not_support, /*null*/
cast_not_support, /*int*/
cast_not_support, /*uint*/
cast_not_support, /*float*/
cast_not_support, /*double*/
cast_not_support, /*number*/
cast_not_support, /*datetime*/
cast_not_support, /*date*/
cast_not_support, /*time*/
cast_not_support, /*year*/
cast_not_support, /*string*/
cast_identity, /*extend*/
cast_not_support, /*unknown*/
cast_not_support, /*text*/
cast_not_support, /*bit*/
cast_not_support, /*enumset*/
cast_not_support, /*enumset_inner*/
cast_not_support, /*otimestamp*/
cast_not_support, /*raw*/
cast_not_support, /*interval*/
cast_not_support, /*rowid*/
cast_not_support, /*lob*/
cast_not_support, /*json not support oracle yet*/
},
{
/*unknown -> XXX*/
unknown_other, /*null*/
unknown_other, /*int*/
unknown_other, /*uint*/
unknown_other, /*float*/
unknown_other, /*double*/
unknown_other, /*number*/
unknown_other, /*datetime*/
unknown_other, /*date*/
unknown_other, /*time*/
unknown_other, /*year*/
unknown_other, /*string*/
unknown_other, /*extend*/
cast_identity, /*unknown*/
cast_not_support, /*text*/
unknown_other, /*bit*/
unknown_other, /*enumset*/
unknown_other, /*enumsetInner*/
unknown_other, /*otimestamp*/
unknown_other, /*raw*/
unknown_other, /*interval*/
unknown_other, /*rowid*/
cast_not_support, /*lob*/
cast_not_support, /*json not support oracle yet*/
},
{
/*text -> XXX*/
cast_not_support, /*null*/
string_int, /*int*/
string_uint, /*uint*/
string_float, /*float*/
string_double, /*double*/
string_number, /*number*/
string_datetime, /*datetime*/
cast_not_expected, /*date*/
cast_not_expected, /*time*/
cast_not_expected, /*year*/
string_string, /*string*/
cast_not_support, /*extend*/
cast_not_support, /*unknown*/
string_string, /*text*/
string_bit, /*bit*/
cast_not_expected, /*enumset*/
cast_not_expected, /*enumset_inner*/
string_otimestamp, /*otimestamp*/
cast_not_support, /*raw*/
string_interval, /*interval*/
cast_not_support, /*rowid*/
cast_inconsistent_types, /*lob*/
cast_not_support, /*json not support oracle yet*/
},
{
/*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_support, /*json not support oracle yet*/
},
{
/*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_support, /*json not support oracle yet*/
},
{
/*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_support, /*json not support oracle yet*/
},
{
/*otimestamp -> XXX*/
cast_not_support, /*null*/
cast_not_support, /*int*/
cast_not_support, /*uint*/
cast_not_support, /*float*/
cast_not_support, /*double*/
cast_not_support, /*number*/
otimestamp_datetime, /*datetime*/
cast_not_expected, /*date*/
cast_not_expected, /*time*/
cast_not_expected, /*year*/
otimestamp_string, /*string*/
cast_not_support, /*extend*/
cast_not_support, /*unknown*/
otimestamp_string, /*text*/
cast_not_support, /*bit*/
cast_not_expected, /*enumset*/
cast_not_expected, /*enumset_inner*/
otimestamp_otimestamp, /*otimestamp*/
cast_not_support, /*raw*/
cast_not_support, /*interval*/
cast_not_support, /*rowid*/
cast_inconsistent_types, /*lob*/
cast_not_support, /*json not support oracle yet*/
},
{
/*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 not support oracle yet*/
},
{
/*interval -> XXX*/
cast_not_expected, /*null*/
cast_not_expected, /*int*/
cast_not_expected, /*uint*/
cast_not_expected, /*float*/
cast_not_expected, /*double*/
cast_not_expected, /*number*/
cast_not_expected, /*datetime*/
cast_not_expected, /*date*/
cast_not_expected, /*time*/
cast_not_expected, /*year*/
interval_string, /*string*/
cast_not_expected, /*extend*/
cast_not_expected, /*unknown*/
cast_not_expected, /*text*/
cast_not_expected, /*bit*/
cast_not_expected, /*enumset*/
cast_not_expected, /*enumset_inner*/
cast_not_expected, /*otimestamp*/
cast_not_expected, /*raw*/
interval_interval, /*interval*/
cast_not_support, /*rowid*/
cast_inconsistent_types, /*lob*/
cast_not_support, /*json not support oracle yet*/
},
{
/*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 not support oracle yet*/
},
{
/*lob -> XXX*/
cast_not_support, /*null*/
lob_int, /*int*/
lob_uint, /*uint*/
lob_float, /*float*/
lob_double, /*double*/
lob_number, /*number*/
lob_datetime, /*datetime*/
cast_not_expected, /*date*/
cast_not_expected, /*time*/
cast_not_expected, /*year*/
lob_string, /*string*/
cast_not_support, /*extend*/
cast_not_support, /*unknown*/
lob_string, /*text*/
lob_bit, /*bit*/
cast_not_expected, /*enumset*/
cast_not_expected, /*enumset_inner*/
lob_otimestamp, /*otimestamp*/
cast_not_support, /*raw*/
lob_interval, /*interval*/
cast_not_support, /*rowid*/
cast_inconsistent_types, /*lob*/
cast_not_support, /*json not support oracle yet*/
},
{
/*json -> XXX, not support oracle currently*/
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*/
},
};
/*
* 1. I think not_support() means something we will support in future, and cast_not_expected() means
* something wrong, so there is no not_support() appears in OBJ_CAST_ORACLE_IMPLICIT now.
* 2. int and uint are needed in inner operation, for example, some system variable is uint,
* like auto_increment_increment, which will be cast to uint in load_default_sys_variable().
* so this matrix allows cast from or to int / uint.
* 3. we can't use ObObjOType as index of this matrix, because int / uint too.
*/
ObObjCastFunc OBJ_CAST_ORACLE_IMPLICIT[ObMaxTC][ObMaxTC] = {
{
/*null -> XXX*/
cast_identity, /*null*/
cast_identity, /*int*/
cast_identity, /*uint*/
cast_identity, /*float*/
cast_identity, /*double*/
cast_identity, /*number*/
cast_identity, /*datetime*/
cast_not_expected, /*date*/
cast_not_expected, /*time*/
cast_not_expected, /*year*/
cast_identity, /*string*/
cast_not_expected, /*extend*/
cast_not_expected, /*unknown*/
cast_identity, /*text*/
cast_not_expected, /*bit*/
cast_not_expected, /*enumset*/
cast_not_expected, /*enumsetInner*/
cast_identity, /*otimestamp*/
cast_identity, /*raw*/
cast_identity, /*interval*/
cast_identity, /*rowid*/
cast_identity, /*lob*/
cast_identity, /*json*/
},
{
/*int -> XXX*/
cast_not_expected, /*null*/
int_int, /*int*/
int_uint, /*uint*/
int_float, /*float*/
int_double, /*double*/
int_number, /*number*/
cast_inconsistent_types, /*datetime*/
cast_not_expected, /*date*/
cast_not_expected, /*time*/
cast_not_expected, /*year*/
int_string, /*string*/
cast_not_expected, /*extend*/
cast_not_expected, /*unknown*/
cast_inconsistent_types, /*text*/
cast_not_expected, /*bit*/
cast_not_expected, /*enumset*/
cast_not_expected, /*enumset_inner*/
cast_inconsistent_types, /*otimestamp*/
cast_inconsistent_types, /*raw*/
cast_inconsistent_types, /*interval*/
cast_inconsistent_types, /*rowid*/
cast_inconsistent_types, /*lob*/
cast_inconsistent_types, /*json*/
},
{
/*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*/
},
{
/*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*/
},
{
/*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*/
},
{
/*number -> XXX*/
cast_not_expected, /*null*/
number_int, /*int*/
number_uint, /*uint*/
number_float, /*float*/
number_double, /*double*/
number_number, /*number*/
cast_inconsistent_types, /*datetime*/
cast_not_expected, /*date*/
cast_not_expected, /*time*/
cast_not_expected, /*year*/
number_string, /*string*/
cast_not_expected, /*extend*/
cast_not_expected, /*unknown*/
number_string, /*text*/
cast_not_expected, /*bit*/
cast_not_expected, /*enumset*/
cast_not_expected, /*enumset_inner*/
cast_inconsistent_types, /*otimestamp*/
cast_inconsistent_types, /*raw*/
cast_inconsistent_types, /*interval*/
cast_inconsistent_types, /*rowid*/
number_lob, /*lob*/
cast_inconsistent_types, /*json*/
},
{
/*datetime -> XXX*/
cast_not_expected, /*null*/
cast_inconsistent_types, /*int*/
cast_inconsistent_types, /*uint*/
cast_inconsistent_types, /*float*/
cast_inconsistent_types, /*double*/
cast_inconsistent_types, /*number*/
datetime_datetime, /*datetime*/
cast_not_expected, /*date*/
cast_not_expected, /*time*/
cast_not_expected, /*year*/
datetime_string, /*string*/
cast_not_expected, /*extend*/
cast_not_expected, /*unknown*/
cast_inconsistent_types, /*text*/
cast_not_expected, /*bit*/
cast_not_expected, /*enumset*/
cast_not_expected, /*enumset_inner*/
datetime_otimestamp, /*otimestamp*/
cast_inconsistent_types, /*raw*/
cast_inconsistent_types, /*interval*/
cast_inconsistent_types, /*rowid*/
cast_inconsistent_types, /*lob*/
cast_inconsistent_types, /*json*/
},
{
/*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_not_expected, /*json*/
},
{
/*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*/
cast_not_expected, /*json*/
},
{
/*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_not_expected, /*json*/
},
{
/*string -> XXX*/
cast_not_expected, /*null*/
string_int, /*int*/
string_uint, /*uint*/
string_float, /*float*/
string_double, /*double*/
string_number, /*number*/
string_datetime, /*datetime*/
cast_not_expected, /*date*/
cast_not_expected, /*time*/
cast_not_expected, /*year*/
string_string, /*string*/
cast_not_expected, /*extend*/
cast_not_expected, /*unknown*/
string_string, /*text*/
cast_not_expected, /*bit*/
cast_not_expected, /*enumset*/
cast_not_expected, /*enumset_inner*/
string_otimestamp, /*otimestamp*/
string_raw, /*raw*/
string_interval, /*interval*/
string_rowid, /*rowid*/
string_lob, /*lob*/
cast_inconsistent_types,/*json*/
},
{
/*extend -> XXX*/
cast_not_expected, /*null*/
cast_not_expected, /*int*/
cast_not_expected, /*uint*/
cast_not_expected, /*float*/
cast_not_expected, /*double*/
cast_not_expected, /*number*/
cast_not_expected, /*datetime*/
cast_not_expected, /*date*/
cast_not_expected, /*time*/
cast_not_expected, /*year*/
cast_not_expected, /*string*/
cast_identity, /*extend*/
cast_not_expected, /*unknown*/
cast_not_expected, /*text*/
cast_not_expected, /*bit*/
cast_not_expected, /*enumset*/
cast_not_expected, /*enumset_inner*/
cast_not_expected, /*otimestamp*/
cast_not_expected, /*raw*/
cast_not_expected, /*interval*/
cast_not_expected, /*rowid*/
cast_not_expected, /*lob*/
cast_not_expected, /*json*/
},
{
/*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_not_expected, /*json*/
},
{
/*text -> XXX*/
cast_not_expected, /*null*/
string_int, /*int*/
string_uint, /*uint*/
string_float, /*float*/
string_double, /*double*/
cast_not_support, /*number*/
string_datetime, /*datetime*/
cast_not_expected, /*date*/
cast_not_expected, /*time*/
cast_not_expected, /*year*/
string_string, /*string*/
cast_not_expected, /*extend*/
cast_not_expected, /*unknown*/
string_string, /*text*/
cast_not_expected, /*bit*/
cast_not_expected, /*enumset*/
cast_not_expected, /*enumset_inner*/
string_otimestamp, /*otimestamp*/
cast_inconsistent_types, /*raw*/
string_interval, /*interval*/
string_rowid, /*rowid*/
string_lob, /*lob*/
cast_inconsistent_types, /*json*/
},
{
/*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*/
},
{
/*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*/
},
{
/*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*/
},
{
/*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*/
},
{
/*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*/
cast_inconsistent_types, /*json*/
},
{
/*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*/
},
{
/* 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*/
},
{
/*lob -> XXX*/
cast_not_expected, /*null*/
lob_int, /*int*/
lob_uint, /*uint*/
lob_float, /*float*/
lob_double, /*double*/
cast_not_support, /*number*/
lob_datetime, /*datetime*/
cast_not_expected, /*date*/
cast_not_expected, /*time*/
cast_not_expected, /*year*/
lob_string, /*string*/
cast_not_expected, /*extend*/
cast_not_expected, /*unknown*/
lob_string, /*text*/
cast_not_expected, /*bit*/
cast_not_expected, /*enumset*/
cast_not_expected, /*enumset_inner*/
lob_otimestamp, /*otimestamp*/
cast_inconsistent_types, /*raw*/
lob_interval, /*interval*/
lob_rowid, /*rowid*/
lob_lob, /*lob*/
cast_inconsistent_types, /*json*/
},
{
/*json -> XXX, not support oracle currently*/
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*/
},
};
////////////////////////////////////////////////////////////////
bool cast_supported(const ObObjType orig_type, const ObCollationType orig_cs_type, const ObObjType expect_type,
const ObCollationType expect_cs_type)
{
bool bret = false;
bool clob_in = ob_is_clob(orig_type, orig_cs_type) || ob_is_clob_locator(orig_type, orig_cs_type);
bool blob_out = ob_is_blob(expect_type, expect_cs_type) || ob_is_blob_locator(expect_type, expect_cs_type);
if (OB_UNLIKELY(ob_is_invalid_obj_type(orig_type) || ob_is_invalid_obj_type(expect_type))) {
LOG_WARN("invalid cast type", K(orig_type), K(expect_type));
// number can be casted to clob, but can not casted to blob,
// OB_OBJ_CAST and OBJ_CAST_ORACLE_IMPLICIT can not support this rule.
} else if (is_oracle_mode() && (clob_in || ob_is_number_tc(orig_type)) && blob_out) {
bret = false;
} else {
ObObjTypeClass orig_tc = ob_obj_type_class(orig_type);
ObObjTypeClass expect_tc = ob_obj_type_class(expect_type);
if (ObIntervalTC == orig_tc && ObIntervalTC == expect_tc && orig_type != expect_type) {
bret = false;
LOG_WARN("cast between intervalYM and intervalDS not allowed", K(bret), K(orig_type), K(expect_type));
} else {
ObObjCastFunc cast_func =
lib::is_oracle_mode() ? OBJ_CAST_ORACLE_IMPLICIT[orig_tc][expect_tc] : OB_OBJ_CAST[orig_tc][expect_tc];
bret = (cast_func != cast_not_support && cast_func != cast_inconsistent_types);
}
}
return bret;
}
int float_range_check(ObObjCastParams& params, const ObAccuracy& accuracy, const ObObj& obj, ObObj& buf_obj,
const ObObj*& res_obj, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
float value = obj.get_float();
res_obj = &obj;
if (lib::is_oracle_mode() && 0.0 == value) {
value = 0.0;
buf_obj.set_float(obj.get_type(), value);
res_obj = &buf_obj;
} else {
if (CAST_FAIL(real_range_check(accuracy, value))) {
} else if (obj.get_float() != value) {
buf_obj.set_float(obj.get_type(), value);
res_obj = &buf_obj;
}
}
return ret;
}
int double_check_precision(ObObjCastParams& params, const ObAccuracy& accuracy, const ObObj& obj, ObObj& buf_obj,
const ObObj*& res_obj, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
double value = obj.get_double();
res_obj = &obj;
if (lib::is_oracle_mode() && 0.0 == value) {
value = 0.0;
buf_obj.set_double(obj.get_type(), value);
res_obj = &buf_obj;
} else if (CAST_FAIL(real_range_check(accuracy, value))) {
} else if (obj.get_double() != value) {
buf_obj.set_double(obj.get_type(), value);
res_obj = &buf_obj;
}
return ret;
}
int number_range_check(ObObjCastParams& params, const ObAccuracy& accuracy, const ObObj& obj, ObObj& buf_obj,
const ObObj*& res_obj, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
res_obj = NULL;
static const int64_t BUFFER_SIZE = 2 * (number::ObNumber::MAX_SCALE + number::ObNumber::MAX_PRECISION);
if (OB_ISNULL(params.allocator_v2_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("invalid allocator", K(ret), K(params.allocator_v2_), K(obj));
} else {
int& cast_ret = CM_IS_ERROR_ON_FAIL(cast_mode) ? ret : params.warning_;
ObPrecision precision = accuracy.get_precision();
ObScale scale = accuracy.get_scale();
ObIAllocator& allocator = *params.allocator_v2_;
res_obj = &obj;
if (OB_UNLIKELY(precision < scale)) {
ret = OB_ERR_M_BIGGER_THAN_D;
} else if (number::ObNumber::MAX_PRECISION >= precision && number::ObNumber::MAX_SCALE >= scale && precision >= 0 &&
scale >= 0) {
// prepare string like "99.999".
char buf[BUFFER_SIZE] = {0};
int pos = 0;
buf[pos++] = '-';
if (precision == scale) {
buf[pos++] = '0';
}
MEMSET(buf + pos, '9', precision + 1);
buf[pos + precision - scale] = '.';
// make min and max numbers.
number::ObNumber min_num;
number::ObNumber max_num;
number::ObNumber in_val = obj.get_number();
number::ObNumber out_val;
if (OB_FAIL(min_num.from(buf, allocator))) {
} else if (OB_FAIL(max_num.from(buf + 1, allocator))) {
} else if (in_val < min_num) {
cast_ret = OB_DATA_OUT_OF_RANGE;
buf_obj.set_number(obj.get_type(), min_num);
} else if (in_val > max_num) {
cast_ret = OB_DATA_OUT_OF_RANGE;
buf_obj.set_number(obj.get_type(), max_num);
} else if (OB_FAIL(out_val.from(in_val, allocator))) {
} else if (OB_FAIL(out_val.round(scale))) {
} else {
buf_obj.set_number(obj.get_type(), out_val);
}
res_obj = &buf_obj;
} else {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid arguments", K(ret), K(precision), K(scale));
}
}
return ret;
}
int number_range_check_for_oracle(ObObjCastParams& params, const ObAccuracy& accuracy, const ObObj& obj, ObObj& buf_obj,
const ObObj*& res_obj, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
res_obj = NULL;
static const int64_t BUFFER_SIZE = 2 * (number::ObNumber::MAX_SCALE + number::ObNumber::MAX_PRECISION);
if (OB_ISNULL(params.allocator_v2_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("invalid allocator", K(ret), K(params.allocator_v2_), K(obj));
} else {
int& cast_ret = CM_IS_ERROR_ON_FAIL(cast_mode) ? ret : params.warning_;
ObPrecision precision = accuracy.get_precision();
ObScale scale = accuracy.get_scale();
ObIAllocator& allocator = *params.allocator_v2_;
res_obj = &obj;
if (number::ObNumber::MAX_PRECISION >= precision && number::ObNumber::MAX_SCALE >= scale && precision >= 1 &&
scale >= number::ObNumber::MIN_SCALE) {
// make min and max numbers.
number::ObNumber min_num;
number::ObNumber max_num;
number::ObNumber in_val = obj.get_number();
bool trunc_max_zero = false;
bool trunc_min_zero = false;
// prepare string like "99.999".
char buf[BUFFER_SIZE] = {0};
int pos = 0;
buf[pos++] = '-';
if (precision >= scale && scale >= 0) {
/* number(3, 1) => legal range(-99.95, 99.95) */
if (precision == scale) {
buf[pos++] = '0';
}
MEMSET(buf + pos, '9', precision + 1);
buf[pos + precision - scale] = '.';
buf[pos + precision + 1] = '5';
if (OB_FAIL(min_num.from(buf, allocator))) {
} else if (OB_FAIL(max_num.from(buf + 1, allocator))) {
}
} else {
if (scale < 0) {
/* number(2, -3) => legal range: (-99500, 99500) */
MEMSET(buf + pos, '9', precision);
buf[pos + precision] = '5';
MEMSET(buf + pos + precision + 1, '0', 0 - scale - 1);
if (OB_FAIL(min_num.from(buf, allocator))) {
} else if (OB_FAIL(max_num.from(buf + 1, allocator))) {
}
} else {
// number(2, 3) => legal range:[0, 0.0995) && (-0.00995, 0]
buf[pos++] = '0';
buf[pos++] = '.';
MEMSET(buf + pos, '0', scale - precision);
MEMSET(buf + pos + scale - precision, '9', precision);
buf[pos + scale] = '5';
if (in_val.is_negative()) {
trunc_max_zero = true;
if (OB_FAIL(min_num.from(buf, allocator))) {
LOG_DEBUG("fail to get num from ", K(buf));
} else {
MEMSET(buf + pos + scale - precision, '0', precision);
if (OB_FAIL(max_num.from(buf, allocator))) {
LOG_DEBUG("fail to get num from ", K(buf));
}
}
} else {
trunc_min_zero = true;
if (OB_FAIL(max_num.from(buf + 1, allocator))) {
LOG_DEBUG("fail to get num from ", K(buf + 1));
} else {
MEMSET(buf + pos + scale - precision, '0', precision);
if (OB_FAIL(min_num.from(buf + 1, allocator))) {
LOG_DEBUG("fail to get num from ", K(buf + 1));
}
}
}
}
}
LOG_DEBUG("BUF", KP(buf), K(precision), K(scale), K(min_num), K(max_num), K(trunc_min_zero), K(trunc_max_zero));
number::ObNumber out_val;
if (OB_SUCC(ret)) {
if (in_val <= min_num) {
if (trunc_min_zero) {
min_num.set_zero();
LOG_DEBUG("set min zero");
} else {
cast_ret = OB_DATA_OUT_OF_RANGE;
}
buf_obj.set_number(obj.get_type(), min_num);
} else if (in_val >= max_num) {
if (trunc_max_zero) {
max_num.set_zero();
} else {
cast_ret = OB_DATA_OUT_OF_RANGE;
}
buf_obj.set_number(obj.get_type(), max_num);
} else if (OB_FAIL(out_val.from(in_val, allocator))) {
} else if (OB_FAIL(out_val.round(scale))) {
} else {
buf_obj.set_number(obj.get_type(), out_val);
}
}
res_obj = &buf_obj;
} else if (ORA_NUMBER_SCALE_UNKNOWN_YET == scale && PRECISION_UNKNOWN_YET == precision) {
buf_obj.set_number(obj.get_type(), obj.get_number());
res_obj = &buf_obj;
LOG_DEBUG("unknown scale and precision", K(obj.get_scale()), K(obj), K(buf_obj));
} else {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid arguments", K(ret), K(precision), K(scale));
}
}
return ret;
}
int number_range_check_v2(ObObjCastParams& params, const ObAccuracy& accuracy, const ObObj& obj, ObObj& buf_obj,
const ObObj*& res_obj, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
res_obj = NULL;
if (OB_ISNULL(params.allocator_v2_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("invalid allocator", K(ret), K(params.allocator_v2_), K(obj));
} else {
int& cast_ret = CM_IS_ERROR_ON_FAIL(cast_mode) ? ret : params.warning_;
ObPrecision precision = accuracy.get_precision();
ObScale scale = accuracy.get_scale();
ObIAllocator& allocator = *params.allocator_v2_;
res_obj = &obj;
const number::ObNumber& in_val = obj.get_number();
const number::ObNumber* min_check_num = NULL;
const number::ObNumber* max_check_num = NULL;
const number::ObNumber* min_num_mysql = NULL;
const number::ObNumber* max_num_mysql = NULL;
number::ObNumber out_val;
bool is_finish = false;
if (obj.is_number_float()) {
if (OB_MIN_NUMBER_FLOAT_PRECISION <= precision && precision <= OB_MAX_NUMBER_FLOAT_PRECISION) {
const int64_t number_precision = static_cast<int64_t>(floor(precision * OB_PRECISION_BINARY_TO_DECIMAL_FACTOR));
if (OB_FAIL(out_val.from(in_val, allocator))) {
} else if (OB_FAIL(out_val.round_precision(number_precision))) {
} else 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 {
buf_obj.set_number(obj.get_type(), out_val);
res_obj = &buf_obj;
is_finish = true;
}
LOG_DEBUG("finish round_precision", K(in_val), K(number_precision), K(precision), K(buf_obj));
} else if (PRECISION_UNKNOWN_YET == precision) {
buf_obj.set_number(obj.get_type(), in_val);
res_obj = &buf_obj;
is_finish = true;
} else {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid arguments", K(ret), K(precision), K(scale));
}
} else if (lib::is_oracle_mode()) {
if (OB_MAX_NUMBER_PRECISION >= precision && precision >= OB_MIN_NUMBER_PRECISION &&
number::ObNumber::MAX_SCALE >= scale && scale >= number::ObNumber::MIN_SCALE) {
min_check_num =
&(ObNumberConstValue::ORACLE_CHECK_MIN[precision][scale + ObNumberConstValue::MAX_ORACLE_SCALE_DELTA]);
max_check_num =
&(ObNumberConstValue::ORACLE_CHECK_MAX[precision][scale + ObNumberConstValue::MAX_ORACLE_SCALE_DELTA]);
} else if (ORA_NUMBER_SCALE_UNKNOWN_YET == scale && PRECISION_UNKNOWN_YET == precision) {
buf_obj.set_number(obj.get_type(), in_val);
res_obj = &buf_obj;
is_finish = true;
} else if (PRECISION_UNKNOWN_YET == precision && number::ObNumber::MAX_SCALE >= scale &&
scale >= number::ObNumber::MIN_SCALE) {
number::ObNumber num;
if (OB_FAIL(num.from(obj.get_number(), allocator))) {
} else if (OB_FAIL(num.round(scale))) {
} else if (CM_IS_ERROR_ON_SCALE_OVER(cast_mode) &&
obj.get_number().compare(num) != 0) {
ret = OB_OPERATE_OVERFLOW;
LOG_WARN("input value is out of range.", K(scale), K(in_val));
} else {
buf_obj.set_number(obj.get_type(), num);
res_obj = &buf_obj;
is_finish = true;
}
} else {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid arguments", K(ret), K(precision), K(scale));
}
} else {
if (OB_UNLIKELY(precision < scale)) {
ret = OB_ERR_M_BIGGER_THAN_D;
} else if (number::ObNumber::MAX_PRECISION >= precision && precision >= OB_MIN_DECIMAL_PRECISION &&
number::ObNumber::MAX_SCALE >= scale && scale >= 0) {
min_check_num = &(ObNumberConstValue::MYSQL_CHECK_MIN[precision][scale]);
max_check_num = &(ObNumberConstValue::MYSQL_CHECK_MAX[precision][scale]);
min_num_mysql = &(ObNumberConstValue::MYSQL_MIN[precision][scale]);
max_num_mysql = &(ObNumberConstValue::MYSQL_MAX[precision][scale]);
} else {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid arguments", K(ret), K(precision), K(scale));
}
}
if (OB_SUCC(ret) && !is_finish) {
if (OB_ISNULL(min_check_num) || OB_ISNULL(max_check_num) ||
(!lib::is_oracle_mode() && (OB_ISNULL(min_num_mysql) || OB_ISNULL(max_num_mysql)))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("min_num or max_num is null", K(ret), KPC(min_check_num), KPC(max_check_num));
} else if (in_val <= *min_check_num) {
if (lib::is_oracle_mode()) {
cast_ret = OB_ERR_VALUE_LARGER_THAN_ALLOWED;
} else {
cast_ret = OB_DATA_OUT_OF_RANGE;
buf_obj.set_number(obj.get_type(), *min_num_mysql);
}
} else if (in_val >= *max_check_num) {
if (lib::is_oracle_mode()) {
cast_ret = OB_ERR_VALUE_LARGER_THAN_ALLOWED;
} else {
cast_ret = OB_DATA_OUT_OF_RANGE;
buf_obj.set_number(obj.get_type(), *max_num_mysql);
}
// need round
} else {
if (OB_FAIL(out_val.from(in_val, allocator))) {
} else if (OB_FAIL(out_val.round(scale))) {
} else 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 {
buf_obj.set_number(obj.get_type(), out_val);
}
}
}
LOG_DEBUG("succ to number_range_check_v2",
K(ret),
K(cast_ret),
K(is_finish),
K(precision),
K(scale),
KPC(min_check_num),
KPC(max_check_num),
KPC(min_num_mysql),
KPC(max_num_mysql),
K(in_val),
K(obj),
K(buf_obj));
res_obj = &buf_obj;
}
return ret;
}
int number_range_check_only(const ObAccuracy& accuracy, const ObObj& obj)
{
int ret = OB_SUCCESS;
UNUSED(obj);
ObPrecision precision = accuracy.get_precision();
ObScale scale = accuracy.get_scale();
if (OB_UNLIKELY(precision < scale)) {
ret = OB_ERR_M_BIGGER_THAN_D;
} else if (number::ObNumber::MAX_PRECISION >= precision && number::ObNumber::MAX_SCALE >= scale && precision >= 0 &&
scale >= 0) {
ret = OB_NOT_SUPPORTED;
LOG_WARN("number range check not supported", K(ret));
} else {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid arguments", K(ret), K(precision), K(scale));
}
return ret;
}
// 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);
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 datetime_scale_check(ObObjCastParams& params, const ObAccuracy& accuracy, const ObObj& obj, ObObj& buf_obj,
const ObObj*& res_obj, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
res_obj = NULL;
ObScale scale = accuracy.get_scale();
if (OB_UNLIKELY(scale > MAX_SCALE_FOR_TEMPORAL)) {
ret = OB_ERR_TOO_BIG_PRECISION;
LOG_USER_ERROR(OB_ERR_TOO_BIG_PRECISION, scale, "CAST", static_cast<int64_t>(MAX_SCALE_FOR_TEMPORAL));
} else {
int64_t value = obj.get_datetime();
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)) {
ObTimeConverter::round_datetime(scale, value);
if (ObTimeConverter::is_valid_datetime(value)) {
buf_obj.set_datetime(obj.get_type(), value);
} else {
buf_obj.set_null();
}
res_obj = &buf_obj;
} else {
res_obj = &obj;
}
}
UNUSED(params);
return ret;
}
int otimestamp_scale_check(ObObjCastParams& params, const ObAccuracy& accuracy, const ObObj& obj, ObObj& buf_obj,
const ObObj*& res_obj, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
res_obj = NULL;
ObScale scale = accuracy.get_scale();
if (OB_UNLIKELY(scale > MAX_SCALE_FOR_ORACLE_TEMPORAL)) {
ret = OB_ERR_TOO_BIG_PRECISION;
LOG_USER_ERROR(OB_ERR_TOO_BIG_PRECISION, scale, "CAST", static_cast<int64_t>(MAX_SCALE_FOR_ORACLE_TEMPORAL));
} else if (OB_UNLIKELY(0 <= scale && scale < MAX_SCALE_FOR_ORACLE_TEMPORAL)) {
ObOTimestampData ot_data = ObTimeConverter::round_otimestamp(scale, obj.get_otimestamp_value());
if (ObTimeConverter::is_valid_otimestamp(ot_data.time_us_, static_cast<int32_t>(ot_data.time_ctx_.tail_nsec_))) {
buf_obj.set_otimestamp_value(obj.get_type(), ot_data);
buf_obj.set_scale(scale);
} else {
OB_LOG(DEBUG, "invalid otimestamp, set it null ", K(ot_data), K(scale), "orig_date", obj.get_otimestamp_value());
buf_obj.set_null();
}
res_obj = &buf_obj;
} else {
res_obj = &obj;
}
UNUSED(params);
UNUSED(cast_mode);
return ret;
}
int interval_scale_check(ObObjCastParams& params, const ObAccuracy& accuracy, const ObObj& obj, ObObj& buf_obj,
const ObObj*& res_obj, const ObCastMode cast_mode)
{
UNUSED(cast_mode);
UNUSED(params);
int ret = OB_SUCCESS;
res_obj = NULL;
ObScale expected_scale = accuracy.get_scale();
buf_obj = obj;
if (obj.is_interval_ym()) {
int8_t expected_year_scale =
ObIntervalScaleUtil::ob_scale_to_interval_ym_year_scale(static_cast<int8_t>(expected_scale));
int8_t input_year_scale = obj.get_interval_ym().calc_leading_scale();
if (OB_UNLIKELY(expected_year_scale < input_year_scale)) {
ret = OB_ERR_THE_LEADING_PRECISION_OF_THE_INTERVAL_IS_TOO_SMALL;
LOG_WARN("interval obj scale check", K(ret), K(expected_year_scale), K(input_year_scale));
}
} else if (obj.is_interval_ds()) {
ObIntervalDSValue value = obj.get_interval_ds();
int8_t expected_day_scale =
ObIntervalScaleUtil::ob_scale_to_interval_ds_day_scale(static_cast<int8_t>(expected_scale));
int8_t expected_fs_scale =
ObIntervalScaleUtil::ob_scale_to_interval_ds_second_scale(static_cast<int8_t>(expected_scale));
if (OB_FAIL(ObTimeConverter::round_interval_ds(expected_fs_scale, value))) {
LOG_WARN("fail to round interval ds", K(ret), K(value));
} else {
int8_t input_day_scale = value.calc_leading_scale();
if (OB_UNLIKELY(expected_day_scale < input_day_scale)) {
ret = OB_ERR_THE_LEADING_PRECISION_OF_THE_INTERVAL_IS_TOO_SMALL;
LOG_WARN("interval obj scale check", K(ret), K(expected_day_scale), K(input_day_scale));
} else {
buf_obj.set_interval_ds(value);
}
}
} else {
ret = OB_ERR_UNEXPECTED;
}
if (OB_SUCC(ret)) {
buf_obj.set_scale(expected_scale);
res_obj = &buf_obj;
}
return ret;
}
int datetime_scale_check_only(const ObAccuracy& accuracy, const ObObj& obj)
{
int ret = OB_SUCCESS;
ObScale scale = accuracy.get_scale();
if (OB_UNLIKELY(scale > MAX_SCALE_FOR_TEMPORAL)) {
ret = OB_ERR_TOO_BIG_PRECISION;
LOG_USER_ERROR(OB_ERR_TOO_BIG_PRECISION, scale, "CAST", static_cast<int64_t>(MAX_SCALE_FOR_TEMPORAL));
} else if (OB_UNLIKELY(0 <= scale && scale < MAX_SCALE_FOR_TEMPORAL)) {
int64_t value = obj.get_datetime();
if (!ObTimeConverter::is_valid_datetime(value)) {
ret = OB_INVALID_DATA;
LOG_WARN("invalid datetime value", K(ret), K(value));
}
}
return ret;
}
int time_scale_check(ObObjCastParams& params, const ObAccuracy& accuracy, const ObObj& obj, ObObj& buf_obj,
const ObObj*& res_obj, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
res_obj = NULL;
ObScale scale = accuracy.get_scale();
int64_t value = obj.get_time();
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)) {
ObTimeConverter::round_datetime(scale, value);
buf_obj.set_time(value);
res_obj = &buf_obj;
} else {
res_obj = &obj;
}
UNUSED(params);
return ret;
}
int time_scale_check_only(const ObAccuracy& accuracy, const ObObj& obj)
{
int ret = OB_SUCCESS;
UNUSED(accuracy);
UNUSED(obj);
return ret;
}
int get_bit_len(const ObString& str, int32_t& bit_len)
{
int ret = OB_SUCCESS;
if (str.empty()) {
bit_len = 1;
} else {
const char* ptr = str.ptr();
uint32_t uneven_value = reinterpret_cast<const unsigned char&>(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<int32_t>(sizeof(unsigned int) * 8 - __builtin_clz(uneven_value));
bit_len = uneven_len + 8 * (len - 1);
}
}
return ret;
}
int get_bit_len(uint64_t value, int32_t& bit_len)
{
int ret = OB_SUCCESS;
if (0 == value) {
bit_len = 1;
} else {
bit_len = static_cast<int32_t>(sizeof(unsigned long long) * 8 - __builtin_clzll(value));
}
return ret;
}
int string_length_check(ObObjCastParams& params, const ObAccuracy& accuracy, const ObCollationType cs_type,
const ObObj& obj, ObObj& buf_obj, const ObObj*& res_obj, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
const ObLength max_accuracy_len = accuracy.get_length();
const int32_t str_len_byte = obj.get_string_len();
bool is_oracle = is_oracle_mode();
if (max_accuracy_len <= 0 || str_len_byte > max_accuracy_len) {
int& cast_ret = (CM_IS_ERROR_ON_FAIL(cast_mode) && !is_oracle) ? ret : params.warning_;
const char* str = obj.get_string_ptr();
int32_t str_len_char = -1;
if (max_accuracy_len == DEFAULT_STR_LENGTH) {
res_obj = &obj;
} else if (OB_UNLIKELY(max_accuracy_len <= 0)) {
buf_obj.set_string(obj.get_type(), NULL, 0);
buf_obj.set_collation_level(obj.get_collation_level());
buf_obj.set_collation_type(obj.get_collation_type());
res_obj = &buf_obj;
if (OB_UNLIKELY(0 == max_accuracy_len && str_len_byte > 0)) {
cast_ret = OB_ERR_DATA_TOO_LONG;
str_len_char =
obj.is_lob() ? str_len_byte : static_cast<int32_t>(ObCharset::strlen_char(cs_type, str, str_len_byte));
OB_LOG(WARN, "char type length is too long", K(obj), K(max_accuracy_len), K(str_len_char));
}
} else {
int32_t trunc_len_byte = -1;
int32_t trunc_len_char = -1;
if (obj.is_varbinary() || obj.is_binary() || obj.is_blob()) {
str_len_char =
obj.is_lob() ? str_len_byte : static_cast<int32_t>(ObCharset::strlen_char(cs_type, str, str_len_byte));
if (OB_UNLIKELY(str_len_char > max_accuracy_len)) {
cast_ret = OB_ERR_DATA_TOO_LONG;
LOG_WARN("binary type length is too long", K(max_accuracy_len), K(str_len_char), K(obj));
}
} else if (is_oracle_byte_length(is_oracle, accuracy.get_length_semantics())) {
const ObLength max_len_byte = accuracy.get_length();
if (OB_UNLIKELY(str_len_byte > max_len_byte)) {
cast_ret = OB_ERR_DATA_TOO_LONG;
LOG_WARN("char type length is too long", K(str_len_byte), K(max_len_byte), K(obj));
}
} else if (is_oracle && obj.is_fixed_len_char_type()) {
const int32_t str_len_char = static_cast<int32_t>(ObCharset::strlen_char(cs_type, str, str_len_byte));
if (OB_UNLIKELY(str_len_byte > OB_MAX_ORACLE_CHAR_LENGTH_BYTE)) {
cast_ret = OB_ERR_DATA_TOO_LONG;
LOG_WARN("char byte length is too long", K(str_len_byte), K(OB_MAX_ORACLE_CHAR_LENGTH_BYTE), K(obj));
} else if (OB_UNLIKELY(str_len_char > max_accuracy_len)) {
cast_ret = OB_ERR_DATA_TOO_LONG;
LOG_WARN("char char length is too long", K(str_len_char), K(max_accuracy_len), K(obj));
}
} else { // mysql, oracle varchar(char)
// trunc_len_char > max_accuracy_len means an error or warning, without tail ' ', otherwise
// str_len_char > max_accuracy_len means only warning, even in strict mode.
// lengthsp() - returns the length of the given string without trailing spaces.
trunc_len_byte = static_cast<int32_t>(ObCharset::strlen_byte_no_sp(cs_type, str, str_len_byte));
trunc_len_char =
obj.is_lob() ? trunc_len_byte : static_cast<int32_t>(ObCharset::strlen_char(cs_type, str, trunc_len_byte));
if (is_oracle && OB_UNLIKELY(str_len_byte > OB_MAX_ORACLE_VARCHAR_LENGTH)) {
cast_ret = OB_ERR_DATA_TOO_LONG;
LOG_WARN("varchar2 byte length is too long", K(str_len_byte), K(OB_MAX_ORACLE_VARCHAR_LENGTH), K(obj));
} else if (OB_UNLIKELY(trunc_len_char > max_accuracy_len)) {
cast_ret = OB_ERR_DATA_TOO_LONG;
LOG_WARN("char type length is too long", K(max_accuracy_len), K(trunc_len_char), K(obj));
} else {
str_len_char =
obj.is_lob() ? str_len_byte : static_cast<int32_t>(ObCharset::strlen_char(cs_type, str, str_len_byte));
if (OB_UNLIKELY(str_len_char > max_accuracy_len)) {
params.warning_ = OB_ERR_DATA_TOO_LONG;
LOG_WARN("char type length is too long", K(max_accuracy_len), K(str_len_char), K(obj));
}
}
}
if (OB_SUCC(ret)) {
if (OB_UNLIKELY(OB_ERR_DATA_TOO_LONG == params.warning_)) {
// when warning, always trunc to max_accuracy_len first.
// besides, if char (not binary), trunc to trunc_len_char again, trim tail ' ' after first trunc.
// the reason of two-trunc for char (not binary):
// insert 'ab ! ' to char(3), we get an 'ab' in column, not 'ab ':
// first trunc: 'ab ! ' to 'ab ',
// second trunc: 'ab ' to 'ab'.
if (obj.is_text() || obj.is_json()) {
int64_t char_len = 0;
trunc_len_byte = static_cast<int32_t>(
ObCharset::max_bytes_charpos(cs_type, str, str_len_byte, max_accuracy_len, char_len));
} else {
trunc_len_byte = static_cast<int32_t>(ObCharset::charpos(cs_type, str, str_len_byte, max_accuracy_len));
}
if (is_oracle) {
// select cast(' a' as char) from dual
// the query above return ' ' in oracle.
} else if (obj.is_fixed_len_char_type() && !obj.is_binary()) {
trunc_len_byte = static_cast<int32_t>(ObCharset::strlen_byte_no_sp(cs_type, str, trunc_len_byte));
}
if (OB_FAIL(copy_string(params, obj.get_type(), str, trunc_len_byte, buf_obj))) {
} else {
buf_obj.set_collation_level(obj.get_collation_level());
buf_obj.set_collation_type(obj.get_collation_type());
res_obj = &buf_obj;
}
if (is_oracle) {
ret = params.warning_;
}
} else if (OB_SUCC(params.warning_) && is_oracle) {
ret = params.warning_;
} else {
res_obj = &obj;
}
}
}
} else {
res_obj = &obj;
}
return ret;
}
// no truncate
int string_length_check_only(const ObAccuracy& accuracy, const ObCollationType cs_type, const ObObj& obj)
{
int ret = OB_SUCCESS;
const ObLength max_len_char = accuracy.get_length();
const char* str = obj.get_string_ptr();
const int32_t str_len_byte = obj.get_string_len();
const int32_t str_len_char = static_cast<int32_t>(ObCharset::strlen_char(cs_type, str, str_len_byte));
if (OB_UNLIKELY(max_len_char <= 0)) {
if (OB_UNLIKELY(0 == max_len_char && str_len_byte > 0)) {
ret = OB_ERR_DATA_TOO_LONG;
OB_LOG(WARN, "char type length is too long", K(obj), K(max_len_char), K(str_len_char));
}
} else if (OB_UNLIKELY(str_len_char > max_len_char)) {
ret = OB_ERR_DATA_TOO_LONG;
LOG_WARN("string length is too long", K(max_len_char), K(str_len_char), K(obj));
}
return ret;
}
int raw_length_check(ObObjCastParams& params, const ObAccuracy& accuracy, const ObCollationType cs_type,
const ObObj& obj, ObObj& buf_obj, const ObObj*& res_obj, const ObCastMode cast_mode)
{
UNUSED(params);
UNUSED(cs_type);
UNUSED(buf_obj);
UNUSED(cast_mode);
int ret = OB_SUCCESS;
const ObLength max_accuracy_len = accuracy.get_length();
const int32_t str_len_byte = obj.get_string_len();
if (OB_UNLIKELY(max_accuracy_len >= 0 && str_len_byte > max_accuracy_len)) {
ret = OB_ERR_DATA_TOO_LONG;
LOG_WARN("char type length is too long", K(ret), K(str_len_byte), K(max_accuracy_len), K(obj));
} else {
res_obj = &obj;
}
return ret;
}
int bit_length_check(ObObjCastParams& params, const ObAccuracy& accuracy, const ObObj& obj, ObObj& buf_obj,
const ObObj*& res_obj, const ObCastMode cast_mode)
{
int ret = OB_SUCCESS;
res_obj = NULL;
uint64_t value = obj.get_bit();
int32_t bit_len = 0;
int32_t dst_bit_len = accuracy.get_precision();
if (OB_FAIL(get_bit_len(value, bit_len))) {
LOG_WARN("fail to get_bit_length", K(ret), K(value), K(bit_len));
} else if (OB_UNLIKELY(bit_len <= 0)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("bit length is negative", K(ret), K(value), K(bit_len), K(obj));
} else {
if (OB_UNLIKELY(bit_len > dst_bit_len)) {
ret = OB_ERR_DATA_TOO_LONG;
LOG_WARN("bit type length is too long", K(ret), K(bit_len), K(dst_bit_len), K(value));
} else {
buf_obj.set_bit(value);
}
if (OB_FAIL(ret) && CM_IS_WARN_ON_FAIL(cast_mode)) {
params.warning_ = OB_DATA_OUT_OF_RANGE;
ret = OB_SUCCESS;
uint64_t max_value = (1ULL << dst_bit_len) - 1;
buf_obj.set_bit(max_value);
}
if (OB_SUCC(ret)) {
res_obj = &buf_obj;
}
}
return ret;
}
int bit_length_check_only(const ObAccuracy& accuracy, const ObObj& obj)
{
int ret = OB_SUCCESS;
uint64_t value = obj.get_bit();
int32_t bit_len = 0;
int32_t dst_bit_len = accuracy.get_precision();
if (OB_FAIL(get_bit_len(value, bit_len))) {
LOG_WARN("fail to get_bit_length", K(ret), K(value), K(bit_len));
} else if (OB_UNLIKELY(bit_len <= 0)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("bit length is negative", K(ret), K(value), K(bit_len), K(obj));
} else {
if (OB_UNLIKELY(bit_len > dst_bit_len)) {
ret = OB_ERR_DATA_TOO_LONG;
LOG_WARN("bit type length is too long", K(ret), K(bit_len), K(dst_bit_len), K(value));
}
}
return ret;
}
int obj_collation_check(const bool is_strict_mode, const ObCollationType cs_type, ObObj& obj)
{
int ret = OB_SUCCESS;
if (!ob_is_string_type(obj.get_type()) && !ob_is_lob_locator(obj.get_type())) {
// nothing to do
} else if (cs_type == CS_TYPE_BINARY) {
obj.set_collation_type(cs_type);
} else {
ObString str;
int64_t well_formed_len = 0;
if (ob_is_lob_locator(obj.get_type())) {
if (OB_FAIL(obj.get_string(str))) {
LOG_WARN("Failed to get payload from lob locator", K(ret), K(obj));
}
} else {
if (OB_FAIL(obj.get_string(str))) {
LOG_WARN("Failed to get payload from string", K(ret), K(obj));
}
}
if (OB_FAIL(ret)) {
} else if (OB_FAIL(ObCharset::well_formed_len(cs_type, str.ptr(), str.length(), well_formed_len))) {
LOG_WARN(
"invalid string for charset", K(ret), K(cs_type), K(str), K(well_formed_len), KPHEX(str.ptr(), str.length()));
if (is_strict_mode) {
ret = OB_ERR_INCORRECT_STRING_VALUE;
// LOG_USER_ERROR(ret, str.length(), str.ptr());
} else {
ret = OB_SUCCESS;
obj.set_collation_type(cs_type);
str.assign_ptr(str.ptr(), static_cast<ObString::obstr_size_t>(well_formed_len));
if (ob_is_lob_locator(obj.get_type())) {
if (OB_ISNULL(obj.get_lob_locator())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("Unepected null lob locator", K(ret), K(obj));
} else {
(const_cast<ObLobLocator*>(obj.get_lob_locator()))->payload_size_ = str.length();
}
} else {
obj.set_string(obj.get_type(), str.ptr(), str.length());
}
LOG_WARN("invalid string for charset", K(ret), K(cs_type), K(str), K(well_formed_len), K(str.length()));
}
} else {
obj.set_collation_type(cs_type);
}
}
return ret;
}
int urwoid_length_check_only(const ObAccuracy& accuracy, const ObObj& obj)
{
int ret = OB_SUCCESS;
ObURowIDData urowid_data = obj.get_urowid();
if (OB_UNLIKELY(urowid_data.rowid_len_ <= 0)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("invalid urowid data length", K(ret), K(urowid_data.rowid_len_));
} else if (OB_UNLIKELY(urowid_data.rowid_len_ > accuracy.get_precision())) {
ret = OB_ERR_DATA_TOO_LONG;
LOG_WARN("urowid data length us too long", K(ret), K(accuracy.get_precision()), K(urowid_data.rowid_len_));
}
return ret;
}
int obj_accuracy_check(ObCastCtx& cast_ctx, const ObAccuracy& accuracy, const ObCollationType cs_type, const ObObj& obj,
ObObj& buf_obj, const ObObj*& res_obj)
{
int ret = OB_SUCCESS;
LOG_DEBUG("obj_accuracy_check before", K(obj), K(accuracy), K(cs_type));
switch (obj.get_type_class()) {
case ObFloatTC: {
ret = float_range_check(cast_ctx, accuracy, obj, buf_obj, res_obj, cast_ctx.cast_mode_);
break;
}
case ObDoubleTC: {
ret = double_check_precision(cast_ctx, accuracy, obj, buf_obj, res_obj, cast_ctx.cast_mode_);
break;
}
case ObNumberTC: {
ret = number_range_check_v2(cast_ctx, accuracy, obj, buf_obj, res_obj, cast_ctx.cast_mode_);
break;
}
case ObDateTimeTC: {
ret = datetime_scale_check(cast_ctx, accuracy, obj, buf_obj, res_obj, cast_ctx.cast_mode_);
break;
}
case ObOTimestampTC: {
ret = otimestamp_scale_check(cast_ctx, accuracy, obj, buf_obj, res_obj, cast_ctx.cast_mode_);
break;
}
case ObTimeTC: {
ret = time_scale_check(cast_ctx, accuracy, obj, buf_obj, res_obj, cast_ctx.cast_mode_);
break;
}
case ObStringTC: {
ret = string_length_check(cast_ctx, accuracy, cs_type, obj, buf_obj, res_obj, cast_ctx.cast_mode_);
break;
}
case ObRawTC: {
ret = raw_length_check(cast_ctx, accuracy, cs_type, obj, buf_obj, res_obj, cast_ctx.cast_mode_);
break;
}
case ObTextTC: {
// TODO texttc share with stringtc temporarily
ret = string_length_check(cast_ctx, accuracy, cs_type, obj, buf_obj, res_obj, cast_ctx.cast_mode_);
break;
}
case ObBitTC: {
ret = bit_length_check(cast_ctx, accuracy, obj, buf_obj, res_obj, cast_ctx.cast_mode_);
break;
}
case ObIntervalTC: {
ret = interval_scale_check(cast_ctx, accuracy, obj, buf_obj, res_obj, cast_ctx.cast_mode_);
break;
}
case ObRowIDTC: {
ret = string_length_check(cast_ctx, accuracy, cs_type, obj, buf_obj, res_obj, cast_ctx.cast_mode_);
break;
}
case ObJsonTC: {
// ToDo: json length check
break;
}
case ObLobTC: {
// TODO:shanting lob length check
}
default: {
// LOG_WARN("unexpected type class to check", K(obj));
break;
}
}
return ret;
}
int ob_obj_accuracy_check_only(const ObAccuracy& accuracy, const ObCollationType cs_type, const ObObj& obj)
{
int ret = OB_SUCCESS;
switch (obj.get_type_class()) {
case ObFloatTC: {
switch (obj.get_type()) {
case ObFloatType:
ret = real_range_check_only(accuracy, obj.get_float());
break;
case ObUFloatType: {
double value = obj.get_ufloat();
ret = numeric_negative_check(value);
if (OB_SUCC(ret)) {
ret = real_range_check_only(accuracy, obj.get_ufloat());
}
break;
}
default:
break;
}
break;
}
case ObDoubleTC: {
switch (obj.get_type()) {
case ObDoubleType:
ret = real_range_check_only(accuracy, obj.get_double());
break;
case ObUDoubleType: {
double value = obj.get_udouble();
ret = numeric_negative_check(value);
if (OB_SUCC(ret)) {
ret = real_range_check_only(accuracy, obj.get_udouble());
}
break;
}
default:
break;
}
break;
}
case ObNumberTC:
ret = number_range_check_only(accuracy, obj);
break;
case ObDateTimeTC:
ret = datetime_scale_check_only(accuracy, obj);
break;
case ObTimeTC:
ret = time_scale_check_only(accuracy, obj);
break;
case ObStringTC:
ret = string_length_check_only(accuracy, cs_type, obj);
break;
case ObTextTC:
ret = string_length_check_only(accuracy, cs_type, obj);
break;
case ObBitTC:
ret = bit_length_check_only(accuracy, obj);
break;
case ObIntTC: {
int64_t value = obj.get_int();
ret = int_range_check(obj.get_type(), value, value);
} break;
case ObUIntTC: {
uint64_t value = obj.get_uint64();
ret = uint_upper_check(obj.get_type(), value);
} break;
default:
break;
}
return ret;
}
int ob_obj_to_ob_time_with_date(
const ObObj& obj, const ObTimeZoneInfo* tz_info, ObTime& ob_time, const int64_t cur_ts_value, bool is_dayofmonth /*false*/)
{
int ret = OB_SUCCESS;
switch (obj.get_type_class()) {
case ObIntTC:
// fallthrough.
case ObUIntTC: {
ret = ObTimeConverter::int_to_ob_time_with_date(obj.get_int(), ob_time, is_dayofmonth);
break;
}
case ObOTimestampTC: {
ret = ObTimeConverter::otimestamp_to_ob_time(obj.get_type(), obj.get_otimestamp_value(), tz_info, ob_time);
break;
}
case ObDateTimeTC: {
ret = ObTimeConverter::datetime_to_ob_time(
obj.get_datetime(), (ObTimestampType == obj.get_type()) ? tz_info : NULL, ob_time);
break;
}
case ObDateTC: {
ret = ObTimeConverter::date_to_ob_time(obj.get_date(), ob_time);
break;
}
case ObTimeTC: {
int64_t datetime_val = 0;
if (OB_FAIL(
ObTimeConverter::time_to_datetime(obj.get_time(), cur_ts_value, NULL, datetime_val, ObDateTimeType))) {
LOG_WARN("time_to_datetime failed", K(ret), K(obj), K(cur_ts_value));
} else if (OB_FAIL(ObTimeConverter::datetime_to_ob_time(datetime_val, NULL, ob_time))) {
LOG_WARN("datetime to time failed", K(ret));
}
break;
ret = ObTimeConverter::time_to_ob_time(obj.get_time(), ob_time);
break;
}
case ObTextTC: // TODO texttc share with the stringtc temporarily
case ObStringTC: {
ret = ObTimeConverter::str_to_ob_time_with_date(obj.get_string(), ob_time, NULL, is_dayofmonth);
break;
}
case ObLobTC: {
ObString payload;
if (OB_FAIL(obj.get_string(payload))) {
STORAGE_LOG(WARN, "Failed to get payload from lob locator", K(ret), K(obj));
} else {
ret = ObTimeConverter::str_to_ob_time_with_date(payload, ob_time, NULL, is_dayofmonth);
}
break;
}
case ObNumberTC: {
int64_t int_part = 0;
int64_t dec_part = 0;
const number::ObNumber num = obj.get_number();
if (num.is_negative()) {
ret = OB_INVALID_DATE_FORMAT;
LOG_WARN("invalid date format", K(ret), K(num));
} else if (!num.is_int_parts_valid_int64(int_part, dec_part)) {
ret = OB_INVALID_DATE_FORMAT;
LOG_WARN("invalid date format", K(ret), K(num));
} else {
ret = ObTimeConverter::int_to_ob_time_with_date(int_part, ob_time, is_dayofmonth);
}
break;
}
default: {
ret = OB_NOT_SUPPORTED;
}
}
return ret;
}
int ob_obj_to_ob_time_without_date(const ObObj& obj, const ObTimeZoneInfo* tz_info, ObTime& ob_time)
{
int ret = OB_SUCCESS;
switch (obj.get_type_class()) {
case ObIntTC:
// fallthrough.
case ObUIntTC: {
if (OB_FAIL(ObTimeConverter::int_to_ob_time_without_date(obj.get_int(), ob_time))) {
LOG_WARN("int to ob time without date failed", K(ret));
} else {
const int64_t time_max_val = 3020399 * 1000000LL; // 838:59:59 .
int64_t value = ObTimeConverter::ob_time_to_time(ob_time);
if (value > time_max_val) {
ret = OB_INVALID_DATE_VALUE;
}
}
break;
}
case ObOTimestampTC: {
ret = ObTimeConverter::otimestamp_to_ob_time(obj.get_type(), obj.get_otimestamp_value(), tz_info, ob_time);
break;
}
case ObDateTimeTC: {
ret = ObTimeConverter::datetime_to_ob_time(
obj.get_datetime(), (ObTimestampType == obj.get_type()) ? tz_info : NULL, ob_time);
break;
}
case ObDateTC: {
ret = ObTimeConverter::date_to_ob_time(obj.get_date(), ob_time);
break;
}
case ObTimeTC: {
ret = ObTimeConverter::time_to_ob_time(obj.get_time(), ob_time);
break;
}
case ObTextTC: // TODO texttc share with the stringtc temporarily
case ObStringTC: {
ret = ObTimeConverter::str_to_ob_time_without_date(obj.get_string(), ob_time);
break;
}
case ObLobTC: {
ObString payload;
if (OB_FAIL(obj.get_string(payload))) {
STORAGE_LOG(WARN, "Failed to get payload from lob locator", K(ret), K(obj));
} else {
ret = ObTimeConverter::str_to_ob_time_without_date(payload, ob_time);
}
break;
}
case ObNumberTC: {
const char *num_format = obj.get_number().format();
if (OB_ISNULL(num_format)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("number format value is null", K(ret));
} else {
ObString num_str(num_format);
ret = ObTimeConverter::str_to_ob_time_without_date(num_str, ob_time);
}
break;
}
default: {
ret = OB_NOT_SUPPORTED;
}
}
return ret;
}
int ObObjCaster::to_type(
const ObObjType expect_type, ObCastCtx& cast_ctx, const ObObj& in_obj, ObObj& buf_obj, const ObObj*& res_obj)
{
int ret = OB_SUCCESS;
res_obj = NULL;
cast_ctx.warning_ = OB_SUCCESS;
ObObjType in_type = in_obj.get_type();
bool is_string = ob_is_string_type(in_type) || ob_is_lob_locator(in_type);
if (OB_UNLIKELY((expect_type == in_type && (!is_string)) || ObNullType == in_type)) {
buf_obj = in_obj;
res_obj = &buf_obj;
} else if (in_obj.get_collation_type() == cast_ctx.dest_collation_ &&
(ObVarcharType == in_type || ObCharType == in_type || ob_is_nstring_type(in_type)) &&
(ObVarcharType == expect_type || ObCharType == expect_type || ob_is_nstring_type(expect_type)) &&
NULL == cast_ctx.zf_info_ && NULL == cast_ctx.res_accuracy_) {
// fast path for char/varchar string_string cast.
buf_obj = in_obj;
const_cast<ObObjMeta&>(buf_obj.get_meta()).set_type_simple(expect_type);
res_obj = &buf_obj;
} else if (OB_FAIL(to_type(expect_type,
(is_string && share::is_mysql_mode()) ? in_obj.get_collation_type() : cast_ctx.dest_collation_,
cast_ctx,
in_obj,
buf_obj))) {
LOG_WARN("failed to cast obj", K(ret), K(in_obj), K(expect_type), K(cast_ctx.cast_mode_));
} else {
res_obj = &buf_obj;
}
return ret;
}
int ObObjCaster::to_datetime(
const ObObjType expect_type, ObCastCtx& cast_ctx, const ObObj& in_obj, ObObj& buf_obj, const ObObj*& res_obj)
{
int ret = OB_SUCCESS;
if (ObDateTimeType == in_obj.get_type()) {
res_obj = &in_obj;
} else {
cast_ctx.warning_ = OB_SUCCESS;
switch (in_obj.get_type_class()) {
case ObIntTC: {
ret = int_datetime_interval(expect_type, cast_ctx, in_obj, buf_obj, cast_ctx.cast_mode_);
break;
}
case ObFloatTC: {
ret = float_datetime_interval(expect_type, cast_ctx, in_obj, buf_obj, cast_ctx.cast_mode_);
break;
}
case ObDoubleTC: {
ret = double_datetime_interval(expect_type, cast_ctx, in_obj, buf_obj, cast_ctx.cast_mode_);
break;
}
case ObNumberTC: {
ret = number_datetime_interval(expect_type, cast_ctx, in_obj, buf_obj, cast_ctx.cast_mode_);
break;
}
case ObOTimestampTC: {
ret = otimestamp_datetime(expect_type, cast_ctx, in_obj, buf_obj, cast_ctx.cast_mode_);
break;
}
default: {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("it should not arrive here", K(ret), K(in_obj), K(expect_type), K(in_obj.get_type_class()));
}
}
if (OB_FAIL(ret)) {
LOG_WARN("failed to cast obj", K(ret), K(in_obj), K(expect_type), K(cast_ctx.cast_mode_));
} else {
res_obj = &buf_obj;
}
}
return ret;
}
int ObObjCaster::bool_to_json(const ObObjType expect_type,
ObCastCtx &cast_ctx,
const ObObj &in_obj,
ObObj &buf_obj,
const ObObj *&res_obj)
{
int ret = OB_SUCCESS;
res_obj = NULL;
cast_ctx.warning_ = OB_SUCCESS;
ObLength res_length = -1;
if (CM_IS_COLUMN_CONVERT(cast_ctx.cast_mode_)) {
ret = OB_ERR_INVALID_JSON_TEXT;
LOG_USER_ERROR(OB_ERR_INVALID_JSON_TEXT);
} else if (OB_UNLIKELY(cast_ctx.allocator_v2_ == NULL)) {
ret= OB_ERR_UNEXPECTED;
LOG_ERROR("NULL allocator in json cast function", K(ret), K(in_obj), K(expect_type));
} else {
int64_t in_val = in_obj.get_int();
bool bool_val = (in_obj.get_int() == 1) ? true : false;
ObJsonBoolean j_bool(bool_val);
ObIJsonBase *j_base = &j_bool;
ObString raw_bin;
if (OB_FAIL(j_base->get_raw_binary(raw_bin, cast_ctx.allocator_v2_))) {
LOG_WARN("fail to get bool json binary", K(ret), K(in_obj), K(expect_type));
} else {
buf_obj.set_json_value(expect_type, raw_bin.ptr(), raw_bin.length());
res_length = static_cast<ObLength>(raw_bin.length());
res_obj = &buf_obj;
}
}
ObObjCastParams &params = cast_ctx;
SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_STRING, DEFAULT_SCALE_FOR_TEXT, res_length);
return ret;
}
int ObObjCaster::enumset_to_json(const ObObjType expect_type,
ObCastCtx &cast_ctx,
const ObObj &in_obj,
ObObj &buf_obj,
const ObObj *&res_obj)
{
int ret = OB_SUCCESS;
res_obj = NULL;
cast_ctx.warning_ = OB_SUCCESS;
ObLength res_length = -1;
if (CM_IS_COLUMN_CONVERT(cast_ctx.cast_mode_)) {
ret = OB_ERR_INVALID_JSON_TEXT;
LOG_USER_ERROR(OB_ERR_INVALID_JSON_TEXT);
} else if (OB_UNLIKELY(cast_ctx.allocator_v2_ == NULL)) {
ret= OB_ERR_UNEXPECTED;
LOG_ERROR("NULL allocator in json cast function", K(ret), K(in_obj), K(expect_type));
} else {
ObIJsonBase *j_base = NULL;
ObJsonNull j_null;
ObString j_text = in_obj.get_string();
ObJsonString j_string(j_text.ptr(), j_text.length());
if (j_text.length() == 0) {
j_base = &j_null;
} else {
j_base = &j_string;
ObString raw_bin;
if (OB_FAIL(j_base->get_raw_binary(raw_bin, cast_ctx.allocator_v2_))) {
LOG_WARN("fail to get string json binary", K(ret), K(in_obj));
} else {
res_length = raw_bin.length();
buf_obj.set_json_value(expect_type, raw_bin.ptr(), raw_bin.length());
buf_obj.set_collation_type(cast_ctx.dest_collation_);
res_obj = &buf_obj;
}
}
}
ObObjCastParams &params = cast_ctx;
SET_RES_ACCURACY(DEFAULT_PRECISION_FOR_STRING, DEFAULT_SCALE_FOR_TEXT, res_length);
return ret;
}
// ObInnerEnumType and ObInnerSetType are not supported.
int ObObjCaster::to_type(
const ObExpectType& expect_type, ObCastCtx& cast_ctx, const ObObj& in_obj, ObObj& buf_obj, const ObObj*& res_obj)
{
int ret = OB_SUCCESS;
res_obj = NULL;
cast_ctx.warning_ = OB_SUCCESS;
ObObjType dest_type = expect_type.get_type();
cast_ctx.expect_obj_collation_ = expect_type.get_collation_type();
if (OB_UNLIKELY((dest_type == in_obj.get_type() && cast_ctx.dest_collation_ == in_obj.get_collation_type()) ||
ObNullType == in_obj.get_type())) {
res_obj = &in_obj;
} else if (ObEnumType == dest_type || ObSetType == dest_type) {
if (OB_FAIL(to_type(expect_type, cast_ctx, in_obj, buf_obj))) {
LOG_WARN("fail to cast to enum or set", K(expect_type), K(in_obj), K(cast_ctx.cast_mode_), K(ret));
} else {
res_obj = &buf_obj;
}
} else if (OB_FAIL(to_type(dest_type, expect_type.get_collation_type(), cast_ctx, in_obj, buf_obj))) {
LOG_WARN("failed to cast obj", K(in_obj), K(expect_type), K(cast_ctx.cast_mode_), K(ret));
} else {
res_obj = &buf_obj;
}
return ret;
}
int ObObjCaster::to_type(const ObObjType expect_type, ObCastCtx& cast_ctx, const ObObj& in_obj, ObObj& out_obj)
{
int ret = OB_SUCCESS;
ObObjType in_type = in_obj.get_type();
bool is_string = ob_is_string_type(in_type) || ob_is_lob_locator(in_type);
if (OB_UNLIKELY((expect_type == in_type && (!is_string)) || ObNullType == in_type)) {
out_obj = in_obj;
} else if (in_obj.get_collation_type() == cast_ctx.dest_collation_ &&
(ObVarcharType == in_type || ObCharType == in_type || ob_is_nstring_type(in_type)) &&
(ObVarcharType == expect_type || ObCharType == expect_type || ob_is_nstring_type(expect_type)) &&
NULL == cast_ctx.zf_info_ && NULL == cast_ctx.res_accuracy_) {
// fast path for char/varchar string_string cast.
out_obj = in_obj;
const_cast<ObObjMeta&>(out_obj.get_meta()).set_type_simple(expect_type);
} else {
if (share::is_oracle_mode() && in_obj.is_character_type()) {
ObCollationType dest_collation = ob_is_nstring_type(expect_type) ? cast_ctx.dtc_params_.nls_collation_nation_
: cast_ctx.dtc_params_.nls_collation_;
if (CS_TYPE_INVALID != dest_collation) {
cast_ctx.dest_collation_ = dest_collation;
}
}
ret = to_type(
expect_type, is_string ? in_obj.get_collation_type() : cast_ctx.dest_collation_, cast_ctx, in_obj, out_obj);
}
return ret;
}
int ObObjCaster::to_type(const ObObjType expect_type, ObCollationType expect_cs_type, ObCastCtx& cast_ctx,
const ObObj& in_obj, ObObj& out_obj)
{
int ret = OB_SUCCESS;
const ObObjTypeClass in_tc = in_obj.get_type_class();
const ObObjTypeClass out_tc = ob_obj_type_class(expect_type);
cast_ctx.warning_ = OB_SUCCESS;
if (CS_TYPE_INVALID != cast_ctx.dest_collation_) {
expect_cs_type = cast_ctx.dest_collation_;
} else {
cast_ctx.dest_collation_ = expect_cs_type;
}
if (OB_UNLIKELY(ob_is_invalid_obj_tc(in_tc) || ob_is_invalid_obj_tc(out_tc))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected type", K(ret), K(in_obj), K(expect_type));
} else if (lib::is_oracle_mode()) {
/*if (CM_IS_EXPLICIT_CAST(cast_ctx.cast_mode_)) {
if (OB_FAIL(OBJ_CAST_ORACLE_EXPLICIT[in_tc][out_tc](expect_type, cast_ctx, in_obj, out_obj, cast_ctx.cast_mode_)))
{ LOG_WARN("failed to cast obj", K(ret), K(in_obj), K(in_tc), K(out_tc), K(expect_type), K(cast_ctx.cast_mode_));
}
} else {*/
if (OB_FAIL(OBJ_CAST_ORACLE_IMPLICIT[in_tc][out_tc](expect_type, cast_ctx, in_obj, out_obj, cast_ctx.cast_mode_))) {
LOG_WARN("failed to cast obj", K(ret), K(in_obj), K(in_tc), K(out_tc), K(expect_type), K(cast_ctx.cast_mode_));
}
//}
} else {
if (OB_FAIL(OB_OBJ_CAST[in_tc][out_tc](expect_type, cast_ctx, in_obj, out_obj, cast_ctx.cast_mode_))) {
LOG_WARN("failed to cast obj", K(ret), K(in_obj), K(in_tc), K(out_tc), K(expect_type), K(cast_ctx.cast_mode_));
}
}
if (OB_SUCC(ret)) {
if (ObStringTC == out_tc || ObTextTC == out_tc || ObLobTC == out_tc) {
if (ObStringTC == in_tc || ObTextTC == in_tc || ObLobTC == out_tc) {
out_obj.set_collation_level(in_obj.get_collation_level());
} else {
out_obj.set_collation_level(CS_LEVEL_COERCIBLE);
}
if (OB_LIKELY(expect_cs_type != CS_TYPE_INVALID)) {
out_obj.set_collation_type(expect_cs_type);
} else {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected collation type", K(ret), K(in_obj), K(out_obj), K(expect_cs_type), K(common::lbt()));
}
}
}
LOG_DEBUG("succ to to_type", K(ret), "in_type", in_obj.get_type(), K(in_obj), K(expect_type), K(out_obj), K(lbt()));
return ret;
}
// use for cast to enum or set type
int ObObjCaster::to_type(const ObExpectType& expect_type, ObCastCtx& cast_ctx, const ObObj& in_obj, ObObj& out_obj)
{
int ret = OB_SUCCESS;
const ObObjTypeClass in_tc = in_obj.get_type_class();
const ObObjType out_type = expect_type.get_type();
if (OB_UNLIKELY(!ob_is_enumset_tc(expect_type.get_type())) || OB_UNLIKELY(ob_is_invalid_obj_tc(in_tc))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected expect_type", K(ret), K(expect_type), K(in_obj));
} else if (OB_FAIL(OB_CAST_ENUM_OR_SET[in_tc][ObSetType == out_type](expect_type, cast_ctx, in_obj, out_obj))) {
LOG_WARN("fail to cast to enum or set", K(ret), K(in_obj), K(expect_type));
} else {
LOG_DEBUG("succ to to_type", K(expect_type), K(in_obj), K(out_obj));
}
return ret;
}
int ObObjCaster::get_zero_value(const ObObjType expect_type, ObCollationType expect_cs_type, ObObj& zero_obj)
{
int ret = OB_SUCCESS;
// we need a ObObjCastParams object with warning is 1 to use SET_RES_XXX macro.
ObObjCastParams params;
ObCastMode cast_mode = CM_WARN_ON_FAIL;
params.warning_ = 1;
if (ob_is_string_tc(expect_type)) {
zero_obj.set_string(expect_type, "");
} else if (ob_is_text_tc(expect_type)) {
zero_obj.set_lob_value(expect_type, static_cast<const char *>(NULL), 0);
} else if (ob_is_int_tc(expect_type)) {
int64_t value = 0;
SET_RES_INT(zero_obj);
} else if (ob_is_uint_tc(expect_type)) {
uint64_t value = 0;
SET_RES_UINT(zero_obj);
} else if (ob_is_float_tc(expect_type)) {
double value = 0.0;
SET_RES_FLOAT(zero_obj);
} else if (ob_is_double_tc(expect_type)) {
double value = 0.0;
SET_RES_DOUBLE(zero_obj);
} else if (ob_is_number_tc(expect_type)) {
number::ObNumber value;
value.set_zero();
SET_RES_NUMBER(zero_obj);
} else if (ob_is_datetime_tc(expect_type)) {
int64_t value = 0;
SET_RES_DATETIME(zero_obj);
} else if (ob_is_date_tc(expect_type)) {
int32_t value = 0;
SET_RES_DATE(zero_obj);
} else if (ob_is_time_tc(expect_type)) {
int32_t value = 0;
SET_RES_TIME(zero_obj);
} else if (ob_is_year_tc(expect_type)) {
int64_t value = 0;
SET_RES_YEAR(zero_obj);
} else if (ob_is_bit_tc(expect_type)) {
uint64_t value = 0;
SET_RES_BIT(zero_obj);
} else if (ObEnumType == expect_type) {
uint64_t value = 0;
SET_RES_ENUM(zero_obj);
} else if (ObSetType == expect_type) {
uint64_t value = 0;
SET_RES_SET(zero_obj);
} else if (ob_is_otimestampe_tc(expect_type)) {
ObOTimestampData value;
SET_RES_OTIMESTAMP(zero_obj);
} else if (ob_is_interval_ym(expect_type)) {
ObIntervalYMValue value;
SET_RES_INTERVAL_YM(zero_obj);
} else if (ob_is_interval_ds(expect_type)) {
ObIntervalDSValue value;
SET_RES_INTERVAL_DS(zero_obj);
} else if (ob_is_urowid(expect_type)) {
ret = OB_NOT_SUPPORTED;
LOG_WARN("urowid with default value not supported");
}
if (OB_SUCC(ret)) {
zero_obj.set_collation_type(expect_cs_type);
}
return ret;
}
int ObObjCaster::enumset_to_inner(const ObObjMeta& expect_meta, const ObObj& in_obj, ObObj& out_obj,
common::ObIAllocator& allocator, const common::ObIArray<common::ObString>& str_values)
{
int ret = OB_SUCCESS;
if (ObEnumType != in_obj.get_type() && ObSetType != in_obj.get_type()) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected expect_type", K(ret), K(in_obj));
} else {
const ObObjType expect_type = (ObEnumType == in_obj.get_type() ? ObEnumInnerType : ObSetInnerType);
const int64_t element_num = str_values.count();
const uint64_t element_val = in_obj.get_enum();
if (ObEnumInnerType == expect_type) {
int64_t element_idx = static_cast<int64_t>(element_val - 1); // enum value start from 1
ObString element_str;
if (OB_UNLIKELY(element_num < 1)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("str_values_ should not be empty", K(str_values), K(ret));
} else if (OB_UNLIKELY(0 == element_val)) {
// do nothing just keep element_string empty
} else {
if (OB_UNLIKELY(element_idx > element_num - 1)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("invalid enum value", K(element_idx), K(element_num), K(element_val), K(in_obj), K(ret));
} else {
element_str = str_values.at(element_idx);
}
}
if (OB_SUCC(ret)) {
ObEnumSetInnerValue inner_value(element_val, element_str);
char* buf = NULL;
const int64_t BUF_LEN = inner_value.get_serialize_size();
int64_t pos = 0;
if (OB_ISNULL(buf = static_cast<char*>(allocator.alloc(BUF_LEN)))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("alloc memory failed", K(ret), KP(buf), K(BUF_LEN));
} else if (OB_FAIL(inner_value.serialize(buf, BUF_LEN, pos))) {
LOG_WARN("failed to serialize inner_value", K(BUF_LEN), K(ret));
} else {
out_obj.set_varchar(buf, static_cast<ObString::obstr_size_t>(pos));
out_obj.set_type(expect_type);
out_obj.set_collation(expect_meta);
}
}
} else { // to setinner
static const int64_t EFFECTIVE_COUNT = 64;
if (OB_UNLIKELY(element_num < 1)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("invalid element_num", K(str_values), K(element_num), K(ret));
} else if (OB_UNLIKELY(element_num < EFFECTIVE_COUNT) && OB_UNLIKELY(element_val >= (1ULL << element_num))) {
// check the validation of element_val
ret = OB_ERR_UNEXPECTED;
LOG_WARN("set value out of range", K(element_val), K(element_num));
}
ObSqlString sql_string;
uint64_t index = 1ULL;
const ObString& sep = ObCharsetUtils::get_const_str(expect_meta.get_collation_type(), ',');
for (int64_t i = 0; OB_SUCC(ret) && i < element_num && i < EFFECTIVE_COUNT && element_val >= index;
++i, index = index << 1) {
if (element_val & (index)) {
const ObString& tmp_val = str_values.at(i);
if (OB_FAIL(sql_string.append(tmp_val))) {
LOG_WARN("fail to deep copy str", K(element_val), K(i), K(ret));
} else if ((element_val >= (index << 1)) && (OB_FAIL(sql_string.append(sep)))) {
LOG_WARN("fail to deep copy comma", K(element_val), K(tmp_val), K(i), K(ret));
}
}
}
if (OB_SUCC(ret)) {
ObString string_value(sql_string.length(), sql_string.ptr());
ObEnumSetInnerValue inner_value(element_val, string_value);
char* buf = NULL;
const int64_t BUF_LEN = inner_value.get_serialize_size();
int64_t pos = 0;
if (OB_ISNULL(buf = static_cast<char*>(allocator.alloc(BUF_LEN)))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("alloc memory failed", K(ret), KP(buf), K(BUF_LEN));
} else if (OB_FAIL(inner_value.serialize(buf, BUF_LEN, pos))) {
LOG_WARN("failed to serialize inner_value", K(BUF_LEN), K(ret));
} else {
out_obj.set_varchar(buf, static_cast<ObString::obstr_size_t>(pos));
out_obj.set_type(expect_type);
out_obj.set_collation(expect_meta);
}
}
}
}
return ret;
}
// given two objects with type A: a1 and a2, cast them to type B: b1 and b2,
// if in any case:
// a1 > a2 means b1 > b2, and
// a1 < a2 means b1 < b2, and
// a1 = a2 means b1 = b2,
// then type A and B is cast monotonic.
int ObObjCaster::is_cast_monotonic(ObObjType t1, ObObjType t2, bool& is_monotonic)
{
int ret = OB_SUCCESS;
ObObjTypeClass tc1 = ob_obj_type_class(t1);
ObObjTypeClass tc2 = ob_obj_type_class(t2);
if (OB_UNLIKELY(ob_is_invalid_obj_tc(tc1) || ob_is_invalid_obj_tc(tc2))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected type", K(ret), K(t1), K(t2), K(tc1), K(tc2));
} else {
is_monotonic = CAST_MONOTONIC[tc1][tc2];
}
return ret;
}
/*
* c1 = 'A' check if c1 can be ordering
*/
int ObObjCaster::is_const_consistent(const ObObjMeta& const_mt, const ObObjMeta& column_mt, const ObObjType calc_type,
const ObCollationType calc_collation, bool& result)
{
int ret = OB_SUCCESS;
result = false;
ObObjTypeClass tc1 = const_mt.get_type_class();
ObObjTypeClass tc2 = column_mt.get_type_class();
if (OB_UNLIKELY(ob_is_invalid_obj_tc(tc1) || ob_is_invalid_obj_tc(tc2))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected obj type class", K(ret), K(const_mt), K(column_mt));
} else if (const_mt.is_string_or_lob_locator_type() && column_mt.is_string_or_lob_locator_type()) {
if (column_mt.get_collation_type() == calc_collation) {
result = true;
} else {
// false
}
} else {
if (OB_FAIL(ObObjCaster::is_cast_monotonic(column_mt.get_type(), calc_type, result))) {
LOG_WARN("check is cast monotonic failed", K(ret));
} else if (!result) {
// false
} else if (OB_FAIL(ObObjCaster::is_cast_monotonic(calc_type, column_mt.get_type(), result))) {
LOG_WARN("check is cast monotonic failed", K(ret));
} else {
// do nothing
}
}
return ret;
}
/* make sure that you have read the doc before you call these functions !*/
int ObObjCaster::is_order_consistent(const ObObjMeta& from, const ObObjMeta& to, bool& result)
{
int ret = OB_SUCCESS;
result = false;
ObObjTypeClass tc1 = from.get_type_class();
ObObjTypeClass tc2 = to.get_type_class();
if (OB_UNLIKELY(ob_is_invalid_obj_tc(tc1) || ob_is_invalid_obj_tc(tc2))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected obj type class", K(ret), K(from), K(to));
} else if (from.is_string_or_lob_locator_type() && to.is_string_or_lob_locator_type()) {
ObCollationType res_cs_type = CS_TYPE_INVALID;
ObCollationLevel res_cs_level = CS_LEVEL_INVALID;
ObCollationType from_cs_type = from.get_collation_type();
ObCollationType to_cs_type = to.get_collation_type();
if (OB_FAIL(ObCharset::aggregate_collation(from.get_collation_level(),
from_cs_type,
to.get_collation_level(),
to_cs_type,
res_cs_level,
res_cs_type))) {
LOG_WARN("fail to aggregate collation", K(ret), K(from), K(to));
} else {
int64_t idx_from = get_idx_of_collate(from_cs_type);
int64_t idx_to = get_idx_of_collate(to_cs_type);
int64_t idx_res = get_idx_of_collate(res_cs_type);
if (OB_UNLIKELY(idx_from < 0 || idx_to < 0 || idx_res < 0 || idx_from >= ObCharset::VALID_COLLATION_TYPES ||
idx_to >= ObCharset::VALID_COLLATION_TYPES || idx_res >= ObCharset::VALID_COLLATION_TYPES)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected collation type", K(ret), K(from), K(to));
} else {
result = ORDER_CONSISTENT_WITH_BOTH_STRING[idx_from][idx_to][idx_res];
}
}
} else {
result = ORDER_CONSISTENT[tc1][tc2];
}
return ret;
}
/* make sure that you have read the doc before you call these functions !*/
int ObObjCaster::is_injection(const ObObjMeta& from, const ObObjMeta& to, bool& result)
{
int ret = OB_SUCCESS;
result = false;
ObObjTypeClass tc1 = from.get_type_class();
ObObjTypeClass tc2 = to.get_type_class();
if (OB_UNLIKELY(ob_is_invalid_obj_tc(tc1) || ob_is_invalid_obj_tc(tc2))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected obj type class", K(ret), K(from), K(to));
} else if (from.is_string_or_lob_locator_type() && to.is_string_or_lob_locator_type()) {
ObCollationType res_cs_type = CS_TYPE_INVALID;
ObCollationLevel res_cs_level = CS_LEVEL_INVALID;
ObCollationType from_cs_type = from.get_collation_type();
ObCollationType to_cs_type = to.get_collation_type();
if (OB_FAIL(ObCharset::aggregate_collation(from.get_collation_level(),
from_cs_type,
to.get_collation_level(),
to_cs_type,
res_cs_level,
res_cs_type))) {
LOG_WARN("fail to aggregate collation", K(ret), K(from), K(to));
} else {
int64_t idx_from = get_idx_of_collate(from_cs_type);
int64_t idx_to = get_idx_of_collate(to_cs_type);
int64_t idx_res = get_idx_of_collate(res_cs_type);
if (OB_UNLIKELY(idx_from < 0 || idx_to < 0 || idx_res < 0 || idx_from >= ObCharset::VALID_COLLATION_TYPES ||
idx_to >= ObCharset::VALID_COLLATION_TYPES || idx_res >= ObCharset::VALID_COLLATION_TYPES)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected collation type", K(ret), K(from), K(to));
} else {
result = INJECTION_WITH_BOTH_STRING[idx_from][idx_to][idx_res];
}
}
} else {
result = INJECTION[tc1][tc2];
}
return ret;
}
// more than 40 bytes: scientific notation.
// less or equal to 40 bytes: print directly.
int ObObjCaster::oracle_number_to_char(const number::ObNumber& number_val, const bool is_from_number_type,
const int16_t scale, const int64_t len, char* buf, int64_t& pos)
{
int ret = OB_SUCCESS;
const int64_t COSNT_BUF_SIZE = 256;
char ptr[COSNT_BUF_SIZE];
int64_t str_len = 0;
int64_t origin = pos;
const int64_t SCI_NUMBER_LENGTH = 40;
if (OB_UNLIKELY(pos > len || len < 0 || pos < 0 || NULL == buf)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid value", K(ret), K(pos), K(len), KP(buf));
} else if (is_from_number_type) {
if (OB_FAIL(number_val.format_with_oracle_limit(ptr, COSNT_BUF_SIZE, str_len, scale))) {
LOG_WARN("fail to format", K(ret));
}
} else {
if (OB_FAIL(number_val.format(ptr, COSNT_BUF_SIZE, str_len, scale))) {
LOG_WARN("failed to format number to string", K(ret));
}
}
if (OB_FAIL(ret)) {
} else if (str_len <= SCI_NUMBER_LENGTH) {
if (OB_UNLIKELY(str_len + pos > len)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("the length of buffer is not enough", K(ret));
} else {
MEMCPY(buf + pos, ptr, str_len);
pos += str_len;
}
} else if (OB_UNLIKELY(len - pos < SCI_NUMBER_LENGTH)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("invalid value", K(ret), K(pos));
} else {
int64_t raw_pos = 0;
char pow_str[6];
int64_t pow_index = 0;
bool pre_dot = false;
pow_str[pow_index++] = 'E';
pow_str[pow_index++] = '+';
if ('-' == ptr[raw_pos]) {
raw_pos++;
buf[pos++] = '-';
}
if ('.' == ptr[raw_pos]) {
raw_pos++;
pre_dot = true;
pow_str[pow_index - 1] = '-';
}
int64_t zero_count = 0;
while ('0' == ptr[raw_pos] && raw_pos < str_len) {
raw_pos++;
zero_count++;
}
buf[pos++] = ptr[raw_pos++];
buf[pos++] = '.';
if (pre_dot) {
if (OB_FAIL(databuff_printf(pow_str, sizeof(pow_str), pow_index, "%ld", zero_count + 1))) {
LOG_WARN("fail to generate pow str", K(ret));
} else {
// pad zero to 40 bytes.
while (pos < SCI_NUMBER_LENGTH - pow_index + origin) {
if (raw_pos >= str_len) {
buf[pos++] = '0';
} else {
buf[pos++] = ptr[raw_pos++];
}
}
}
} else if (!pre_dot && 0 == zero_count) {
int64_t count = 0;
bool enable_count = true;
int64_t width_count = 0;
while (pos < SCI_NUMBER_LENGTH - pow_index - width_count + origin) {
if (raw_pos >= str_len) {
buf[pos++] = '0';
} else if ('.' == ptr[raw_pos]) {
raw_pos++;
enable_count = false;
} else {
if (enable_count) {
count++;
if (count >= 0 && count <= 9) {
width_count = 1;
} else if (count >= 10 && count <= 99) {
width_count = 2;
} else {
width_count = 3;
}
}
buf[pos++] = ptr[raw_pos++];
}
}
for (int64_t i = raw_pos; enable_count && i < str_len && ptr[i] != '.'; ++i) {
count++;
}
if (OB_FAIL(databuff_printf(pow_str, sizeof(pow_str), pow_index, "%ld", count))) {
LOG_WARN("fail to generate pow str", K(ret));
}
} else {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("the number raw str is unexpected", K(ret));
}
// round the last digit and handle the carry.
if (OB_SUCC(ret)) {
int64_t carry = 0;
int64_t carry_pos = pos;
if (raw_pos < str_len && ptr[raw_pos] >= '5' && ptr[raw_pos] <= '9') {
carry = 1;
carry_pos--;
while (carry && carry_pos >= origin && OB_SUCC(ret)) {
if (buf[carry_pos] >= '0' && buf[carry_pos] <= '8') {
buf[carry_pos] = (char)((int)buf[carry_pos] + carry);
carry = 0;
carry_pos--;
} else if ('9' == buf[carry_pos]) {
carry = 1;
buf[carry_pos--] = '0';
} else if ('.' == buf[carry_pos]) {
carry_pos--;
} else {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("It's unexpected to round the number sci", K(ret));
}
}
// right shift if get carry here.
if (1 == carry && origin - 1 == carry_pos && OB_SUCC(ret)) {
for (int64_t i = pos - 1; i >= origin + 1; --i) {
buf[i] = buf[i - 1];
}
buf[origin] = '1';
}
}
}
// print power
if (OB_SUCC(ret)) {
for (int i = 0; i < pow_index; ++i) {
buf[pos++] = pow_str[i];
}
}
// check pos
if (OB_SUCC(ret)) {
if (str_len > SCI_NUMBER_LENGTH && pos - origin != SCI_NUMBER_LENGTH) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("the value of pos is invalid after number to char in oracle mode", K(pos), K(origin), K(ret));
}
}
}
return ret;
}
int ObObjCaster::can_cast_in_oracle_mode(const ObObjTypeClass expect_type, const ObObjTypeClass obj_type)
{
int ret = OB_SUCCESS;
if (cast_not_expected == OBJ_CAST_ORACLE_IMPLICIT[obj_type][expect_type]) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("not expected obj type convert", K(obj_type), K(expect_type), K(ret));
} else if (cast_inconsistent_types == OBJ_CAST_ORACLE_IMPLICIT[obj_type][expect_type]) {
ret = OB_ERR_INVALID_TYPE_FOR_OP;
LOG_WARN("inconsistent datatypes", "expected", expect_type, "got", obj_type, K(ret));
}
return ret;
}
const bool ObObjCaster::CAST_MONOTONIC[ObMaxTC][ObMaxTC] = {
// null
{
false, // null
false, // int
false, // uint
false, // float
false, // double
false, // number
false, // datetime
false, // date
false, // time
false, // year
false, // string
false, // extend
false, // unknown
false, // text
false, // bit
false, // enumset
false, // enumsetinner
false, // OTimestamp
false, // raw
false, // interval
false, // rowid
false, // lob
false, // json
},
// int
{
false, // null
true, // int
true, // uint
false, // float
false, // double
true, // number
false, // datetime
false, // date
false, // time
false, // year
false, // string
false, // extend
false, // unknown
false, // text
true, // bit
false, // enumset
false, // enumsetInner
false, // OTimestamp
false, // raw
false, // interval
false, // rowid
false, // lob
false, // json
},
// uint
{
false, // null
true, // int
true, // uint
false, // float
false, // double
true, // number
false, // datetime
false, // date
false, // time
false, // year
false, // string
false, // extend
false, // unknown
false, // text
true, // bit
false, // enumset
false, // enumsetInner
false, // OTimestamp
false, // raw
false, // interval
false, // rowid
false, // lob
false, // json
},
// float
{
false, // null
true, // int
true, // uint
true, // float
true, // double
true, // number
false, // datetime
false, // date
false, // time
false, // year
false, // string
false, // extend
false, // unknown
false, // text
false, // enumset
false, // enumsetInner
true, // bit
false, // OTimestamp
false, // raw
false, // interval
false, // rowid
false, // lob
false, // json
},
// double
{
false, // null
true, // int
true, // uint
true, // float
true, // double
true, // number
false, // datetime
false, // date
false, // time
false, // year
false, // string
false, // extend
false, // unknown
false, // text
true, // bit
false, // enumset
false, // enumsetInner
false, // OTimestamp
false, // raw
false, // interval
false, // rowid
false, // lob
false, // json
},
// number
{
false, // null
true, // int
true, // uint
true, // float
true, // double
true, // number
false, // datetime
false, // date
false, // time
false, // year
false, // string
false, // extend
false, // unknown
false, // text
true, // bit
false, // enumset
false, // enumsetInner
false, // OTimestamp
false, // raw
false, // interval
false, // rowid
false, // lob
false, // json
},
// datetime
{
false, // null
true, // int
true, // uint
true, // float
true, // double
true, // number
true, // datetime
true, // date
false, // time
true, // year
true, // string
false, // extend
false, // unknown
true, // text
true, // bit
false, // enumset
false, // enumsetInner
true, // OTimestamp
false, // raw
false, // interval
false, // rowid
true, // lob
true, // json
},
// date
{
false, // null
true, // int
true, // uint
true, // float
true, // double
true, // number
true, // datetime
true, // date
false, // time
true, // year
true, // string
false, // extend
false, // unknown
true, // text
true, // bit
false, // enumset
false, // enumsetInner
true, // OTimestamp
false, // raw
false, // interval
false, // rowid
true, // lob
true, // json
},
// time
{
false, // null
true, // int
true, // uint
true, // float
true, // double
true, // number
true, // datetime
false, // date
true, // time
false, // year
false, // string
false, // extend
false, // unknown
true, // text
true, // bit
false, // enumset
false, // enumsetInner
true, // OTimestamp
false, // raw
false, // interval
false, // rowid
true, // lob
true, // json
},
// year
{
false, // null
true, // int
true, // uint
true, // float
true, // double
true, // number
true, // datetime
true, // date
false, // time
true, // year
true, // string
false, // extend
false, // unknown
true, // text
true, // bit
false, // enumset
false, // enumsetInner
true, // OTimestamp
false, // raw
false, // interval
false, // rowid
true, // lob
true, // json
},
// string
{
false, // null
false, // int
false, // uint
false, // float
false, // double
false, // number
false, // datetime
false, // date
false, // time
false, // year
true, // string
false, // extend
false, // unknown
true, // text
false, // bit
false, // enumset
false, // enumsetInner
false, // OTimestamp
true, // raw
true, // interval
true, // rowid
true, // lob
false, // json
},
// extend
{
false, // null
false, // int
false, // uint
false, // float
false, // double
false, // number
false, // datetime
false, // date
false, // time
false, // year
false, // string
false, // extend
false, // unknown
false, // text
false, // bit
false, // enumset
false, // enumsetInner
false, // OTimestamp
false, // raw
false, // interval
false, // rowid
false, // lob
false, // json
},
// unknown
{
false, // null
false, // int
false, // uint
false, // float
false, // double
false, // number
false, // datetime
false, // date
false, // time
false, // year
false, // string
false, // extend
false, // unknown
false, // text
false, // bit
false, // enumset
false, // enumsetInner
false, // OTimestamp
false, // raw
false, // interval
false, // rowid
false, // lob
false, // json
},
// text
{
false, // null
false, // int
false, // uint
false, // float
false, // double
false, // number
false, // datetime
false, // date
false, // time
false, // year
true, // string
false, // extend
false, // unknown
true, // text
false, // bit
false, // enumset
false, // enumsetInner
false, // OTimestamp
false, // raw
false, // interval
false, // rowid
true, // lob
false, // json
},
// bit
{
false, // null
true, // int
true, // uint
true, // float
true, // double
true, // number
false, // datetime
false, // date
false, // time
false, // year
false, // string
false, // extend
false, // unknown
false, // text
true, // bit
false, // enumset
false, // enumsetInner
false, // OTimestamp
false, // raw
false, // interval
false, // rowid
false, // lob
false, // json
},
// enumset
{
false, // null
false, // int
false, // uint
false, // float
false, // double
false, // number
false, // datetime
false, // date
false, // time
false, // year
false, // string
false, // extend
false, // unknown
false, // text
false, // bit
false, // enumset
false, // enumsetInner
false, // OTimestamp
false, // raw
false, // interval
false, // rowid
false, // lob
false, // json
},
// enumsetinner
{
false, // null
false, // int
false, // uint
false, // float
false, // double
false, // number
false, // datetime
false, // date
false, // time
false, // year
false, // string
false, // extend
false, // unknown
false, // text
false, // bit
false, // enumset
false, // enumsetInner
false, // OTimestamp
false, // raw
false, // interval
false, // rowid
false, // text
false, // json
},
// OTimestamp
{
false, // null
true, // int
true, // uint
true, // float
true, // double
true, // number
true, // datetime
true, // date
false, // time
true, // year
true, // string
false, // extend
false, // unknown
true, // text
true, // bit
false, // enumset
false, // enumsetInner
true, // OTimestamp
false, // raw
false, // interval
false, // rowid
true, // lob
true, // json
},
// raw
{
false, // null
false, // int
false, // uint
false, // float
false, // double
false, // number
false, // datetime
false, // date
false, // time
false, // year
true, // string
false, // extend
false, // unknown
false, // text
false, // bit
false, // enumset
false, // enumsetInner
false, // OTimestamp
true, // raw
false, // interval,
false, // rowid
false, // lob
false, // json
},
// interval
{
false, // null
false, // int
false, // uint
false, // float
false, // double
false, // number
false, // datetime
false, // date
false, // time
false, // year
false, // string
false, // extend
false, // unknown
false, // text
false, // bit
false, // enumset
false, // enumsetInner
false, // OTimestamp
false, // raw
true, // interval,
false, // rowid
false, // lob
false, // json
},
// rowid
{
false, // null
false, // int
false, // uint
false, // float
false, // double
false, // number
false, // datetime
false, // date
false, // time
false, // year
true, // string
false, // extend
false, // unknown
false, // text
false, // bit
false, // enumset
false, // enumsetInner
false, // OTimestamp
false, // raw
false, // interval,
true, // rowid
false, // lob
false, // json
},
// lob
{
false, // null
false, // int
false, // uint
false, // float
false, // double
false, // number
false, // datetime
false, // date
false, // time
false, // year
true, // string
false, // extend
false, // unknown
true, // text
false, // bit
false, // enumset
false, // enumsetInner
false, // OTimestamp
false, // raw
false, // interval
false, // rowid
true, // lob
false, // json
},
// json
{
false, // null
false, // int
false, // uint
false, // float
false, // double
false, // number
false, // datetime
false, // date
false, // time
false, // year
false, // string
false, // extend
false, // unknown
false, // text
false, // bit
false, // enumset
false, // enumsetInner
false, // OTimestamp
false, // raw
false, // interval
false, // rowid
false, // lob
true, // json
},
};
const bool ObObjCaster::ORDER_CONSISTENT[ObMaxTC][ObMaxTC] = {
// null
{
false, // null
false, // int
false, // uint
false, // float
false, // double
false, // number
false, // datetime
false, // date
false, // time
false, // year
false, // string
false, // extend
false, // unknown
false, // lob
false, // bit
false, // enumset
false, // enumsetInner
false, // OTimestamp
false, // raw
},
// int
{
false, // null
true, // int
true, // uint
true, // float
true, // double
true, // number
false, // datetime
false, // date
false, // time
true, // year
false, // string
false, // extend
false, // unknown
false, // lob
true, // bit
true, // enumset
false, // enumsetInner
false, // OTimestamp
false, // raw
},
// uint
{
false, // null
true, // int
true, // uint
true, // float
true, // double
true, // number
false, // datetime
false, // date
false, // time
false, // year
false, // string
false, // extend
false, // unknown
false, // lob
true, // bit
true, // enumset
false, // enumsetInner
false, // OTimestamp
false, // raw
},
// float
{
false, // null
false, // int
false, // uint
true, // float
true, // double
false, // number
false, // datetime
false, // date
false, // time
false, // year
false, // string
false, // extend
false, // unknown
false, // lob
false, // bit
false, // enumset
false, // enumsetInner
false, // OTimestamp
false, // raw
},
// double
{
false, // null
false, // int
false, // uint
true, // float
true, // double
false, // number
false, // datetime
false, // date
false, // time
false, // year
false, // string
false, // extend
false, // unknown
false, // lob
false, // bit
false, // enumset
false, // enumsetInner
false, // OTimestamp
false, // raw
},
// number
{
false, // null
true, // int
true, // uint
true, // float
true, // double
true, // number
false, // datetime
false, // date
false, // time
true, // year
false, // string
false, // extend
false, // unknown
false, // lob
true, // bit
true, // enumset
false, // enumsetInner
false, // OTimestamp
false, // raw
},
// datetime
{
false, // null
false, // int
false, // uint
false, // float
false, // double
false, // number
true, // datetime
true, // date
true, // time
true, // year
false, // string
false, // extend
false, // unknown
false, // lob
false, // bit
false, // enumset
false, // enumsetInner
true, // OTimestamp
false, // raw
},
// date
{
false, // null
false, // int
false, // uint
false, // float
false, // double
false, // number
true, // datetime
true, // date
true, // time
true, // year
false, // string
false, // extend
false, // unknown
false, // lob
false, // bit
false, // enumset
false, // enumsetInner
true, // OTimestamp
false, // raw
},
// time
{
false, // null
false, // int
false, // uint
false, // float
false, // double
false, // number
true, // datetime
true, // date
true, // time
true, // year
false, // string
false, // extend
false, // unknown
false, // lob
false, // bit
false, // enumset
false, // enumsetInner
true, // OTimestamp
false, // raw
},
// year //0000-9999
{
false, // null
true, // int
true, // uint
true, // float
true, // double
true, // number
false, // datetime
false, // date
false, // time
true, // year
false, // string
false, // extend
false, // unknown
false, // lob
true, // bit
true, // enumset
false, // enumsetInner
false, // OTimestamp
false, // raw
},
// string
{
false, // null
false, // int
false, // uint
false, // float
false, // double
false, // number
false, // datetime
false, // date
false, // time
false, // year
false, // string
false, // extend
false, // unknown
false, // lob
false, // bit
false, // enumset
false, // enumsetInner
false, // OTimestamp
false, // raw
},
// extend
{
false, // null
false, // int
false, // uint
false, // float
false, // double
false, // number
false, // datetime
false, // date
false, // time
false, // year
false, // string
false, // extend
false, // unknown
false, // lob
false, // bit
false, // enumset
false, // enumsetInner
false, // OTimestamp
false, // raw
},
// unknown
{
false, // null
false, // int
false, // uint
false, // float
false, // double
false, // number
false, // datetime
false, // date
false, // time
false, // year
false, // string
false, // extend
false, // unknown
false, // lob
false, // bit
false, // enumset
false, // enumsetInner
false, // OTimestamp
false, // raw
},
// lob
{
false, // null
false, // int
false, // uint
false, // float
false, // double
false, // number
false, // datetime
false, // date
false, // time
false, // year
false, // string
false, // extend
false, // unknown
false, // lob
false, // bit
false, // enumset
false, // enumsetInner
false, // OTimestamp
false, // raw
},
// bit
{
false, // null
true, // int
true, // uint
true, // float
true, // double
true, // number
false, // datetime
false, // date
false, // time
false, // year
false, // string
false, // extend
false, // unknown
false, // lob
true, // bit
true, // enumset
false, // enumsetInner
false, // OTimestamp
false, // raw
},
// enumset
{
false, // null
true, // int
true, // uint
true, // float
true, // double
true, // number
false, // datetime
false, // date
false, // time
false, // year
false, // string
false, // extend
false, // unknown
false, // lob
true, // bit
true, // enumset
false, // enumsetInner
false, // OTimestamp
false, // raw
},
// enumsetInner
{
false, // null
false, // int
false, // uint
false, // float
false, // double
false, // number
false, // datetime
false, // date
false, // time
false, // year
false, // string
false, // extend
false, // unknown
false, // lob
false, // bit
false, // enumset
false, // enumsetInner
false, // OTimestamp
false, // raw
},
// OTimestamp
{
false, // null
false, // int
false, // uint
false, // float
false, // double
false, // number
true, // datetime
true, // date
true, // time
true, // year
false, // string
false, // extend
false, // unknown
false, // lob
false, // bit
false, // enumset
false, // enumsetInner
true, // OTimestamp
false, // raw
},
// raw
{
false, // null
false, // int
false, // uint
false, // float
false, // double
false, // number
false, // datetime
false, // date
false, // time
false, // year
false, // string
false, // extend
false, // unknown
false, // lob
false, // bit
false, // enumset
false, // enumsetInner
false, // OTimestamp
false, // raw
},
};
const bool ObObjCaster::ORDER_CONSISTENT_WITH_BOTH_STRING[ObCharset::VALID_COLLATION_TYPES]
[ObCharset::VALID_COLLATION_TYPES]
[ObCharset::VALID_COLLATION_TYPES] = {
// CS_TYPE_UTF8MB4_GENERAL_CI
{
// ci //utf8bin //bin
{true, true, true},
{false, false, false},
{false, false, false},
},
// CS_TYPE_UTF8MB4_BIN
{
// ci //utf8bin //bin
{true, true, true},
{false, true, true},
{false, true, true},
},
// CS_TYPE_BINARY
{
// ci //utf8bin //bin
{true, true, true},
{false, true, true},
{false, true, true},
},
};
const bool ObObjCaster::INJECTION[ObMaxTC][ObMaxTC] = {
// null
{
false, // null
false, // int
false, // uint
false, // float
false, // double
false, // number
false, // datetime
false, // date
false, // time
false, // year
false, // string
false, // extend
false, // unknown
false, // lob
false, // bit
false, // enumset
false, // enumsetInner
false, // OTimestamp
false, // raw
},
// int
{
false, // null
true, // int
true, // uint
true, // float
true, // double
true, // number
true, // datetime
true, // date
true, // time
true, // year
false, // string
false, // extend
false, // unknown
false, // lob
true, // bit
true, // enumset
false, // enumsetInner
true, // OTimestamp
false, // raw
},
// uint
{
false, // null
true, // int
true, // uint
true, // float
true, // double
true, // number
true, // datetime
true, // date
true, // time
true, // year
false, // string
false, // extend
false, // unknown
false, // lob
true, // bit
true, // enumset
false, // enumsetInner
true, // OTimestamp
false, // raw
},
// float
{
false, // null
false, // int
false, // uint
true, // float
true, // double
false, // number
true, // datetime
true, // date
true, // time
true, // year
false, // string
false, // extend
false, // unknown
false, // lob
false, // bit
false, // enumset
false, // enumsetInner
true, // OTimestamp
false, // raw
},
// double
{
false, // null
false, // int
false, // uint
true, // float
true, // double
false, // number
true, // datetime
true, // date
true, // time
true, // year
false, // string
false, // extend
false, // unknown
false, // lob
false, // bit
false, // enumset
false, // enumsetInner
true, // OTimestamp
false, // raw
},
// number
{
false, // null
true, // int
true, // uint
true, // float
true, // double
true, // number
true, // datetime
true, // date
true, // time
true, // year
false, // string
false, // extend
false, // unknown
false, // lob
true, // bit
true, // enumset
false, // enumsetInner
true, // OTimestamp
false, // raw
},
// datetime
{
false, // null
false, // int
false, // uint
false, // float
false, // double
false, // number //2010-01-01 12:34:56.12345 = 20100101123456.1234520 and 2010-01-01 12:34:56.12345 =
// 20100101123456.1234530
true, // datetime
true, // date
true, // time
true, // year
false, // string
false, // extend
false, // unknown
false, // lob
false, // bit
false, // enumset
false, // enumsetInner
true, // OTimestamp
false, // raw
},
// date
{
false, // null
false, // int //think about 0000-00-00
false, // uint
false, // float
false, // double
false, // number
true, // datetime
true, // date
true, // time
true, // year
false, // string
false, // extend
false, // unknown
false, // lob
false, // bit
false, // enumset
false, // enumsetInner
true, // OTimestamp
false, // raw
},
// time
{
false, // null
false, // int
false, // uint
false, // float
false, // double
false, // number //think about time(5) = decimal(40,7)
true, // datetime
true, // date
true, // time
true, // year
false, // string //00:12:34 = "00:12:34" and 00:12:34 = "00:12:34.000"
false, // extend
false, // unknown
false, // lob
false, // bit
false, // enumset
false, // enumsetInner
true, // OTimestamp
false, // raw
},
// year //0000-9999
{
false, // null
true, // int
true, // uint
true, // float
true, // double
true, // number
true, // datetime //1999 = 1999-00-00 00:00:00
true, // date //1999 = 1999-00-00
true, // time
true, // year
false, // string //1999 = "99" and 1999 = "1999"
false, // extend
false, // unknown
false, // lob
true, // bit
true, // enumset
false, // enumsetInner
true, // OTimestamp
false, // raw
},
// string
{
false, // null
true, // int
true, // uint
true, // float
true, // double
true, // number
true, // datetime
true, // date
true, // time
true, // year
false, // string
false, // extend
false, // unknown
false, // lob
true, // bit
true, // enumset
false, // enumsetInner
true, // OTimestamp
false, // raw
},
// extend
{
false, // null
false, // int
false, // uint
false, // float
false, // double
false, // number
false, // datetime
false, // date
false, // time
false, // year
false, // string
false, // extend
false, // unknown
false, // lob
false, // bit
false, // enumset
false, // enumsetInner
false, // OTimestamp
false, // raw
},
// unknown
{
false, // null
false, // int
false, // uint
false, // float
false, // double
false, // number
false, // datetime
false, // date
false, // time
false, // year
false, // string
false, // extend
false, // unknown
false, // lob
false, // bit
false, // enumset
false, // enumsetInner
false, // OTimestamp
false, // raw
},
// lob
{
false, // null
true, // int
true, // uint
true, // float
true, // double
true, // number
true, // datetime
true, // date
true, // time
true, // year
false, // string
false, // extend
false, // unknown
false, // lob
true, // bit
true, // enumset
false, // enumsetInner
true, // OTimestamp
false, // raw
},
// bit
{
false, // null
true, // int
true, // uint
true, // float
true, // double
true, // number
true, // datetime
true, // date
true, // time
true, // year
false, // string
false, // extend
false, // unknown
false, // lob
true, // bit
true, // enumset
false, // enumsetInner
true, // OTimestamp
false, // raw
},
// setenum
{
false, // null
true, // int
true, // uint
true, // float
true, // double
true, // number
false, // datetime
false, // date
false, // time
true, // year
false, // string
false, // extend
false, // unknown
false, // lob
true, // bit
true, // enumset
false, // enumsetInner
false, // OTimestamp
false, // raw
},
// setenumInner
{
false, // null
false, // int
false, // uint
false, // float
false, // double
false, // number
false, // datetime
false, // date
false, // time
false, // year
false, // string
false, // extend
false, // unknown
false, // lob
false, // bit
false, // enumset
false, // enumsetInner
false, // OTimestamp
false, // raw
},
// OTimestamp
{
false, // null
false, // int
false, // uint
false, // float
false, // double
false, // number //2010-01-01 12:34:56.12345 = 20100101123456.1234520 and 2010-01-01 12:34:56.12345 =
// 20100101123456.1234530
true, // datetime
true, // date
true, // time
true, // year
false, // string
false, // extend
false, // unknown
false, // lob
false, // bit
false, // enumset
false, // enumsetInner
true, // OTimestamp
false, // raw
},
// raw
{
false, // null
true, // int
true, // uint
true, // float
true, // double
true, // number
true, // datetime
true, // date
true, // time
true, // year
false, // string
false, // extend
false, // unknown
false, // lob
true, // bit
true, // enumset
false, // enumsetInner
true, // OTimestamp
false, // raw
},
};
const bool ObObjCaster::INJECTION_WITH_BOTH_STRING[ObCharset::VALID_COLLATION_TYPES][ObCharset::VALID_COLLATION_TYPES]
[ObCharset::VALID_COLLATION_TYPES] = {
// CS_TYPE_UTF8MB4_GENERAL_CI
{
// ci //utf8bin //bin
{true, true, true}, // CS_TYPE_UTF8MB4_GENERAL_CI
{false, true, true}, // CS_TYPE_UTF8MB4_BIN
{false, true, true}, // CS_TYPE_BINARY
},
// CS_TYPE_UTF8MB4_BIN
{
// ci //utf8bin //bin
{true, true, true}, // CS_TYPE_UTF8MB4_GENERAL_CI
{false, true, true}, // CS_TYPE_UTF8MB4_BIN
{false, true, true}, // CS_TYPE_BINARY
},
// CS_TYPE_BINARY
{
// ci //utf8bin //bin
{true, true, true}, // CS_TYPE_UTF8MB4_GENERAL_CI
{false, true, true}, // CS_TYPE_UTF8MB4_BIN
{false, true, true}, // CS_TYPE_BINARY
}};
int ObObjEvaluator::is_true(const ObObj& obj, ObCastMode cast_mode, bool& result)
{
int ret = OB_SUCCESS;
result = false;
if (obj.is_null()) {
// result is unkown
// do nothing
} else if (obj.is_numeric_type()) {
result = !obj.is_zero();
} else if (lib::is_oracle_mode() && obj.is_varchar_or_char() && 0 == obj.get_string_len()) {
result = true;
} else {
ObArenaAllocator allocator(ObModIds::BLOCK_ALLOC);
ObCastCtx cast_ctx(&allocator, NULL, cast_mode, CS_TYPE_INVALID);
ObObj buf_obj;
const ObObj* res_obj = NULL;
if (OB_FAIL(ObObjCaster::to_type(ObNumberType, cast_ctx, obj, buf_obj, res_obj))) {
LOG_WARN("failed to cast object to tinyint", K(ret), K(obj));
} else if (NULL == res_obj || (!(res_obj->is_number()))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("res_obj is NULL or unexpected obj type", K(ret), K(obj), K(res_obj));
} else {
result = !(res_obj->is_zero_number());
}
}
return ret;
}
int ObObjEvaluator::is_false(const ObObj& obj, ObCastMode cast_mode, bool& b_result)
{
int ret = OB_SUCCESS;
b_result = true;
if (OB_FAIL(is_true(obj, cast_mode, b_result))) {
LOG_WARN("fail to evaluate obj", K(ret));
} else {
b_result = !b_result;
}
if (OB_SUCC(ret)) {
if (obj.is_null()) {
// result is unkown, unkown != false
b_result = false;
}
}
return ret;
}
} // end namespace common
} // end namespace oceanbase