Files
oceanbase/src/sql/engine/expr/ob_expr_json_utils.cpp

3198 lines
97 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.
* This file is for implement of func json expr helper
*/
#define USING_LOG_PREFIX SQL_ENG
#include "lib/ob_errno.h"
#include "sql/engine/expr/ob_expr_cast.h"
#include "sql/engine/ob_exec_context.h"
#include "sql/engine/expr/ob_datum_cast.h"
#include "sql/engine/expr/ob_json_param_type.h"
#include "ob_expr_json_func_helper.h"
#include "lib/encode/ob_base64_encode.h" // for ObBase64Encoder
#include "lib/utility/ob_fast_convert.h" // ObFastFormatInt::format_unsigned
#include "lib/charset/ob_dtoa.h" // ob_gcvt_opt
#include "rpc/obmysql/ob_mysql_global.h" // DOUBLE_TO_STRING_CONVERSION_BUFFER_SIZE
#include "sql/ob_result_set.h"
#include "sql/ob_spi.h"
#include "ob_expr_json_utils.h"
#include "share/object/ob_obj_cast_util.h"
#include "share/object/ob_obj_cast.h"
using namespace oceanbase::common;
using namespace oceanbase::sql;
namespace oceanbase
{
namespace sql
{
#define CAST_FAIL(stmt) \
(OB_UNLIKELY((OB_SUCCESS != (ret = get_cast_ret((stmt))))))
#define GET_SESSION() \
ObBasicSessionInfo *session = ctx.exec_ctx_.get_my_session(); \
if (OB_ISNULL(session)) { \
ret = OB_ERR_UNEXPECTED; \
LOG_WARN("session is NULL", K(ret)); \
} else
int ObExprJsonQueryParamInfo::deep_copy(common::ObIAllocator &allocator,
const ObExprOperatorType type,
ObIExprExtraInfo *&copied_info) const
{
INIT_SUCC(ret);
if (OB_FAIL(ObExprExtraInfoFactory::alloc(allocator, type, copied_info))) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("allocate memory failed", K(ret));
} else {
ObExprJsonQueryParamInfo& other = *static_cast<ObExprJsonQueryParamInfo *>(copied_info);
other.truncate_ = truncate_;
other.format_json_ = format_json_;
other.wrapper_ = wrapper_;
other.empty_type_ = empty_type_;
other.error_type_ = error_type_;
other.pretty_type_ = pretty_type_;
other.ascii_type_ = ascii_type_;
other.scalars_type_ = scalars_type_;
other.j_path_ = NULL;
if (OB_FAIL(ob_write_string(allocator, path_str_, other.path_str_, true))) {
LOG_WARN("fail to deep copy path str", K(ret));
} else if (OB_FAIL(other.on_mismatch_.assign(on_mismatch_))) {
LOG_WARN("fail to assign mismatch array", K(ret));
} else if (OB_FAIL(other.on_mismatch_type_.assign(on_mismatch_type_))) {
LOG_WARN("fail to assgin mismatch type", K(ret));
} else if (OB_FAIL(other.parse_json_path(path_str_, other.j_path_))) {
LOG_WARN("fail to resolve json path", K(ret));
}
}
return ret;
}
int ObExprJsonQueryParamInfo::parse_json_path(ObString path_str, ObJsonPath*& j_path_)
{
INIT_SUCC(ret);
j_path_ = NULL;
void* buf = allocator_.alloc(sizeof(ObJsonPath));
if (path_str.empty()) {
allocator_.free(buf);
} else if (OB_ISNULL(buf)) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("fail to alloc path.", K(ret));
} else {
j_path_ = new (buf) ObJsonPath(path_str, &allocator_);
if (OB_FAIL(j_path_->parse_path())) {
LOG_WARN("wrong path expression, parse path failed or with wildcards", K(ret), K(path_str));
}
}
return ret;
}
OB_DEF_SERIALIZE_SIZE(ObExprJsonQueryParamInfo)
{
int64_t len = 0;
LST_DO_CODE(OB_UNIS_ADD_LEN,
truncate_,
format_json_,
wrapper_,
empty_type_,
error_type_,
pretty_type_,
ascii_type_,
scalars_type_,
path_str_,
on_mismatch_,
on_mismatch_type_);
return len;
}
OB_DEF_SERIALIZE(ObExprJsonQueryParamInfo)
{
INIT_SUCC(ret);
LST_DO_CODE(OB_UNIS_ENCODE,
truncate_,
format_json_,
wrapper_,
empty_type_,
error_type_,
pretty_type_,
ascii_type_,
scalars_type_,
path_str_,
on_mismatch_,
on_mismatch_type_);
return ret;
}
OB_DEF_DESERIALIZE(ObExprJsonQueryParamInfo)
{
INIT_SUCC(ret);
LST_DO_CODE(OB_UNIS_DECODE,
truncate_,
format_json_,
wrapper_,
empty_type_,
error_type_,
pretty_type_,
ascii_type_,
scalars_type_,
path_str_,
on_mismatch_,
on_mismatch_type_);
OZ(parse_json_path(path_str_, j_path_));
return ret;
}
int ObJsonUtil::set_mismatch_val(ObIArray<int8_t>& val, ObIArray<int8_t>& type, int64_t& opt_val, uint32_t& pos)
{
INIT_SUCC(ret);
if (opt_val >= OB_JSON_ON_MISMATCH_ERROR &&
opt_val <= OB_JSON_ON_MISMATCH_IMPLICIT) {
pos ++;
if (OB_FAIL(val.push_back(static_cast<int8_t>(opt_val)))) {
LOG_WARN("mismtach add fail", K(ret));
} else if (OB_FAIL(type.push_back(0))) {
LOG_WARN("mismatch option add fail", K(ret));
}
} else if (opt_val >= OB_JSON_TYPE_MISSING_DATA &&
opt_val <= OB_JSON_TYPE_DOT) {
/* one mismatch val has multi mismatch type*/
uint8_t t_value = type.at(pos);
type.pop_back();
switch(opt_val) {
case OB_JSON_TYPE_MISSING_DATA :{
t_value |= 1;
break;
}
case OB_JSON_TYPE_EXTRA_DATA :{
t_value |= 2;
break;
}
case OB_JSON_TYPE_TYPE_ERROR :{
t_value |= 4;
break;
}
default :{
break;
}
}
type.push_back(t_value);
} else {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("option type error", K(opt_val), K(ret));
}
return ret;
}
int ObJsonUtil::init_json_path(ObIAllocator &alloc, ObExprCGCtx &op_cg_ctx,
const ObRawExpr* path,
ObExprJsonQueryParamInfo& res)
{
INIT_SUCC(ret);
ObObj const_data;
bool got_data = false;
ObExecContext *exec_ctx = op_cg_ctx.session_->get_cur_exec_ctx();
if (OB_NOT_NULL(path)
&& (path->is_const_expr() || path->is_static_scalar_const_expr())
&& path->get_expr_type() != T_OP_GET_USER_VAR) {
void* buf = alloc.alloc(sizeof(ObJsonPath));
if (OB_ISNULL(buf)) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("fail to alloc path.", K(ret));
} else if (OB_FAIL(ObSQLUtils::calc_const_or_calculable_expr(exec_ctx,
path,
const_data,
got_data,
alloc))) {
LOG_WARN("failed to calc offset expr", K(ret));
} else if (!got_data || const_data.is_null()
|| !ob_is_string_type(const_data.get_type())) {
ret = OB_ERR_INVALID_INPUT_ARGUMENT;
LOG_WARN("fail to get int value", K(ret));
} else {
ObString path_str = const_data.get_string();
res.j_path_ = new (buf) ObJsonPath(path_str, &alloc);
if (OB_FAIL(res.j_path_->parse_path())) {
if (lib::is_oracle_mode()) {
ret = OB_ERR_JSON_PATH_EXPRESSION_SYNTAX_ERROR;
LOG_USER_ERROR(OB_ERR_JSON_PATH_EXPRESSION_SYNTAX_ERROR, path_str.length(), path_str.ptr());
} else {
ret = OB_ERR_INVALID_JSON_PATH;
LOG_USER_ERROR(OB_ERR_INVALID_JSON_PATH);
}
LOG_WARN("wrong path expression, parse path failed or with wildcards", K(ret), K(path_str));
} else if (OB_FAIL(ob_write_string(alloc, path_str, res.path_str_, true))) {
LOG_WARN("fail to deep copy path str", K(ret), K(path_str));
}
}
}
return ret;
}
int ObJsonUtil::datetime_scale_check(const ObAccuracy &accuracy,
int64_t &value,
bool strict)
{
INIT_SUCC(ret);
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)) {
// first check zero
if (strict &&
(value == ObTimeConverter::ZERO_DATE ||
value == ObTimeConverter::ZERO_DATETIME)) {
ret = OB_INVALID_DATE_VALUE;
LOG_WARN("Zero datetime is invalid in json_value.", K(value));
} else {
int64_t temp_value = value;
ObTimeConverter::round_datetime(scale, temp_value);
if (strict && temp_value != value) {
ret = OB_OPERATE_OVERFLOW;
LOG_WARN("Invalid input value.", K(value), K(scale));
} else if (ObTimeConverter::is_valid_datetime(temp_value)) {
value = temp_value;
} else {
ret = OB_ERR_NULL_VALUE; // set null for res
LOG_DEBUG("Invalid datetime val, return set_null", K(temp_value));
}
}
}
return ret;
}
int ObJsonUtil::get_accuracy(const ObExpr &expr,
ObEvalCtx &ctx,
ObAccuracy &accuracy,
ObObjType &dest_type,
bool &is_cover_by_error)
{
INIT_SUCC(ret);
ObDatum *dst_type_dat = NULL;
if (OB_ISNULL(expr.args_) || OB_ISNULL(expr.args_[2])) {
ret = OB_ERR_UNEXPECTED;
is_cover_by_error = false;
LOG_WARN("unexpected expr", K(ret), K(expr.arg_cnt_), KP(expr.args_));
} else if (OB_FAIL(expr.args_[2]->eval(ctx, dst_type_dat))) {
is_cover_by_error = false;
LOG_WARN("eval dst type datum failed", K(ret));
} else {
ret = ObJsonUtil::get_accuracy_internal(accuracy,
ctx,
dest_type,
dst_type_dat->get_int(),
expr.datum_meta_.length_semantics_);
}
return ret;
}
/*json cast to sql scalar*/
int ObJsonUtil::get_accuracy_internal(ObAccuracy &accuracy,
ObEvalCtx& ctx,
ObObjType &dest_type,
const int64_t value,
const ObLengthSemantics &length_semantics)
{
INIT_SUCC(ret);
ParseNode node;
node.value_ = value;
dest_type = static_cast<ObObjType>(node.int16_values_[0]);
if (ObFloatType == dest_type) {
// boundaries already checked in calc result type
if (node.int16_values_[OB_NODE_CAST_N_PREC_IDX] > OB_MAX_FLOAT_PRECISION) {
dest_type = ObDoubleType;
}
}
ObObjTypeClass dest_tc = ob_obj_type_class(dest_type);
if (ObStringTC == dest_tc) {
// parser will abort all negative number
// if length < 0 means DEFAULT_STR_LENGTH or OUT_OF_STR_LEN.
accuracy.set_full_length(node.int32_values_[1], length_semantics,
lib::is_oracle_mode());
} else if (ObRawTC == dest_tc) {
accuracy.set_length(node.int32_values_[1]);
} else if(ObTextTC == dest_tc || ObJsonTC == dest_tc) {
accuracy.set_length(node.int32_values_[1] < 0 ?
ObAccuracy::DDL_DEFAULT_ACCURACY[dest_type].get_length() : node.int32_values_[1]);
} else if (ObIntervalTC == dest_tc) {
if (OB_UNLIKELY(!ObIntervalScaleUtil::scale_check(node.int16_values_[3]) ||
!ObIntervalScaleUtil::scale_check(node.int16_values_[2]))) {
ret = OB_ERR_DATETIME_INTERVAL_PRECISION_OUT_OF_RANGE;
LOG_WARN("Invalid scale.", K(ret), K(node.int16_values_[3]), K(node.int16_values_[2]));
} else {
ObScale scale = (dest_type == ObIntervalYMType) ?
ObIntervalScaleUtil::interval_ym_scale_to_ob_scale(
static_cast<int8_t>(node.int16_values_[3]))
: ObIntervalScaleUtil::interval_ds_scale_to_ob_scale(
static_cast<int8_t>(node.int16_values_[2]),
static_cast<int8_t>(node.int16_values_[3]));
accuracy.set_scale(scale);
}
} else {
const ObAccuracy &def_acc =
ObAccuracy::DDL_DEFAULT_ACCURACY2[lib::is_oracle_mode()][dest_type];
if (ObNumberType == dest_type && 0 == node.int16_values_[2]) {
accuracy.set_precision(def_acc.get_precision());
} else {
accuracy.set_precision(node.int16_values_[2]);
}
accuracy.set_scale(node.int16_values_[3]);
if (lib::is_oracle_mode() && ObDoubleType == dest_type) {
accuracy.set_accuracy(def_acc.get_precision());
}
if (ObNumberType == dest_type
&& is_decimal_int_accuracy_valid(accuracy.get_precision(), accuracy.get_scale())) {
bool enable_decimalint = false;
if (OB_ISNULL(ctx.exec_ctx_.get_my_session())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("type_ctx.get_session() is null", K(ret));
} else if (OB_FAIL(ObSQLUtils::check_enable_decimalint(ctx.exec_ctx_.get_my_session(),
enable_decimalint))) {
LOG_WARN("fail to check_enable_decimalint_type",
K(ret), K(ctx.exec_ctx_.get_my_session()->get_effective_tenant_id()));
} else if (enable_decimalint) {
dest_type = ObDecimalIntType;
}
}
}
return ret;
}
int ObJsonUtil::time_scale_check(const ObAccuracy &accuracy, int64_t &value, bool strict)
{
INIT_SUCC(ret);
ObScale scale = accuracy.get_scale();
if (0 <= scale && scale < MAX_SCALE_FOR_TEMPORAL) {
int64_t temp_value = value;
ObTimeConverter::round_datetime(scale, temp_value);
if (strict && temp_value != value) { // round success
ret = OB_OPERATE_OVERFLOW;
LOG_WARN("Invalid input value.", K(value), K(scale));
} else {
value = temp_value;
}
}
return ret;
}
static OB_INLINE int get_cast_ret(int ret)
{
// compatibility for old ob
if (OB_ERR_UNEXPECTED_TZ_TRANSITION == ret ||
OB_ERR_UNKNOWN_TIME_ZONE == ret) {
ret = OB_INVALID_DATE_VALUE;
}
return ret;
}
int ObJsonUtil::number_range_check(const ObAccuracy &accuracy,
ObIAllocator *allocator,
number::ObNumber &val,
bool strict)
{
INIT_SUCC(ret);
ObPrecision precision = accuracy.get_precision();
ObScale scale = accuracy.get_scale();
const number::ObNumber *min_check_num = NULL;
const number::ObNumber *max_check_num = NULL;
const number::ObNumber *min_num_mysql = NULL;
const number::ObNumber *max_num_mysql = NULL;
bool is_finish = false;
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) {
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(val, *allocator))) {
} else if (OB_FAIL(num.round(scale))) {
} else if (val.compare(num) != 0) {
ret = OB_OPERATE_OVERFLOW;
LOG_WARN("input value is out of range.", K(scale), K(val));
} else {
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;
LOG_WARN("Invalid accuracy.", K(ret), K(scale), K(precision));
} 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 (val <= *min_check_num) {
if (lib::is_oracle_mode()) {
ret = OB_ERR_VALUE_LARGER_THAN_ALLOWED;
} else {
ret = OB_DATA_OUT_OF_RANGE;
}
LOG_WARN("val is out of min range check.", K(val), K(*min_check_num));
is_finish = true;
} else if (val >= *max_check_num) {
if (lib::is_oracle_mode()) {
ret = OB_ERR_VALUE_LARGER_THAN_ALLOWED;
} else {
ret = OB_DATA_OUT_OF_RANGE;
}
LOG_WARN("val is out of max range check.", K(val), K(*max_check_num));
is_finish = true;
} else {
ObNumStackOnceAlloc tmp_alloc;
number::ObNumber num;
if (OB_FAIL(num.from(val, tmp_alloc))) {
} else if (OB_FAIL(num.round(scale))) {
LOG_WARN("num.round failed", K(ret), K(scale));
} else {
if (strict) {
if (num.compare(val) != 0) {
ret = OB_OPERATE_OVERFLOW;
LOG_WARN("input value is out of range.", K(scale), K(val));
} else {
is_finish = true;
}
} else {
if (OB_ISNULL(allocator)) {
ret = OB_ERR_NULL_VALUE;
LOG_WARN("allocator is null", K(ret));
} else if (OB_FAIL(val.deep_copy_v3(num, *allocator))) {
LOG_WARN("val.deep_copy_v3 failed", K(ret), K(num));
} else {
is_finish = true;
}
}
}
}
}
if (OB_SUCC(ret) && !is_finish) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected situation, res is not set", K(ret));
}
LOG_DEBUG("number_range_check_v2 done", K(ret), K(is_finish), K(accuracy), K(val),
KPC(min_check_num), KPC(max_check_num));
return ret;
}
int ObJsonUtil::set_lob_datum(common::ObIAllocator *allocator,
const ObExpr &expr,
ObEvalCtx &ctx,
ObObjType dst_type,
uint8_t ascii_type,
ObDatum &res)
{
INIT_SUCC(ret);
if (res.is_null()) { // null value jump this process
} else {
switch (dst_type) {
case ObVarcharType:
case ObRawType:
case ObNVarchar2Type:
case ObNCharType:
case ObCharType:
case ObTinyTextType:
case ObTextType :
case ObMediumTextType:
case ObHexStringType:
case ObLongTextType: {
ObString val;
val = res.get_string();
ObTextStringDatumResult text_result(expr.datum_meta_.type_, &expr, &ctx, &res);
if (OB_FAIL(ret)) {
} else if (ascii_type == 0) {
if (OB_FAIL(text_result.init(val.length()))) {
LOG_WARN("init lob result failed");
} else if (OB_FAIL(text_result.append(val))) {
LOG_WARN("failed to append realdata", K(ret), K(val), K(text_result));
}
} else {
char *buf = NULL;
int64_t buf_len = val.length() * ObCharset::MAX_MB_LEN * 2;
int64_t reserve_len = 0;
int32_t length = 0;
if (OB_FAIL(text_result.init(buf_len))) {
LOG_WARN("init lob result failed");
} else if (OB_FAIL(text_result.get_reserved_buffer(buf, reserve_len))) {
LOG_WARN("fail to get reserved buffer", K(ret));
} else if (reserve_len != buf_len) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get reserve len is invalid", K(ret), K(reserve_len), K(buf_len));
} else if (OB_FAIL(ObJsonExprHelper::calc_asciistr_in_expr(val, expr.args_[0]->datum_meta_.cs_type_,
expr.datum_meta_.cs_type_,
buf, reserve_len, length))) {
LOG_WARN("fail to calc unistr", K(ret));
} else if (OB_FAIL(text_result.lseek(length, 0))) {
LOG_WARN("text_result lseek failed", K(ret), K(text_result), K(length));
}
}
if (OB_SUCC(ret)) {
// old engine set same alloctor for wrapper, so we can use val without copy
text_result.set_result();
}
break;
}
case ObJsonType: {
ObString out_val;
out_val = res.get_string();
ObTextStringDatumResult text_result(expr.datum_meta_.type_, &expr, &ctx, &res);
if (OB_SUCC(ret)) {
if (OB_FAIL(text_result.init(out_val.length()))) {
LOG_WARN("init lob result failed");
} else if (OB_FAIL(text_result.append(out_val))) {
LOG_WARN("failed to append realdata", K(ret), K(out_val), K(text_result));
} else {
text_result.set_result();
}
}
break;
}
default: {
break;
}
}
}
return ret;
}
int ObJsonUtil::bit_length_check(const ObAccuracy &accuracy,
uint64_t &value)
{
int ret = OB_SUCCESS;
int32_t bit_len = 0;
int32_t dst_bit_len = accuracy.get_precision();
bit_len = ObJsonBaseUtil::get_bit_len(value);
if(OB_UNLIKELY(bit_len <= 0)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("bit length is negative", K(ret), K(value), K(bit_len));
} else {
if (OB_UNLIKELY(bit_len > dst_bit_len)) {
ret = OB_ERR_DATA_TOO_LONG;
LOG_WARN("bit type length is too long", K(ret), K(bit_len),
K(dst_bit_len), K(value));
}
}
return ret;
}
// padding %padding_cnt character, we also need to convert collation type here.
// eg: select cast('abc' as nchar(100)) from dual;
// the space must be in utf16, because dst_type is nchar
int ObJsonUtil::padding_char_for_cast(int64_t padding_cnt,
const ObCollationType &padding_cs_type,
ObIAllocator &alloc,
ObString &padding_res)
{
int ret = OB_SUCCESS;
padding_res.reset();
const ObCharsetType &cs = ObCharset::charset_type_by_coll(padding_cs_type);
char padding_char = (CHARSET_BINARY == cs) ? OB_PADDING_BINARY : OB_PADDING_CHAR;
int64_t padding_str_size = sizeof(padding_char) * padding_cnt;
char *padding_str_ptr = reinterpret_cast<char*>(alloc.alloc(padding_str_size));
if (OB_ISNULL(padding_str_ptr)) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("alloc memory failed", K(ret));
} else if (CHARSET_BINARY == cs) {
MEMSET(padding_str_ptr, padding_char, padding_str_size);
padding_res.assign_ptr(padding_str_ptr, padding_str_size);
} else {
MEMSET(padding_str_ptr, padding_char, padding_str_size);
ObString padding_str(padding_str_size, padding_str_ptr);
if (OB_FAIL(ObExprUtil::convert_string_collation(padding_str,
ObCharset::get_system_collation(),
padding_res,
padding_cs_type,
alloc))) {
LOG_WARN("convert padding str collation faield", K(ret), K(padding_str),
K(padding_cs_type));
}
}
LOG_DEBUG("pad char done", K(ret), K(padding_cnt), K(padding_cs_type), K(padding_res));
return ret;
}
int cast_to_null(common::ObIAllocator *allocator,
ObEvalCtx &ctx,
ObIJsonBase *j_base,
common::ObAccuracy &accuracy,
ObJsonCastParam &cast_param,
ObDatum &res,
uint8_t &is_type_mismatch)
{
INIT_SUCC(ret);
UNUSED(allocator);
UNUSED(ctx);
UNUSED(j_base);
UNUSED(accuracy);
UNUSED(cast_param);
UNUSED(is_type_mismatch);
if (!cast_param.is_only_check_) {
res.set_null();
}
return ret;
}
int cast_to_int(common::ObIAllocator *allocator,
ObEvalCtx &ctx,
ObIJsonBase *j_base,
common::ObAccuracy &accuracy,
ObJsonCastParam &cast_param,
ObDatum &res,
uint8_t &is_type_mismatch)
{
INIT_SUCC(ret);
UNUSED(allocator);
UNUSED(ctx);
UNUSED(accuracy);
UNUSED(is_type_mismatch);
int64_t val = 0;
if (OB_ISNULL(j_base)) {
ret = OB_ERR_NULL_VALUE;
LOG_WARN("json base is null", K(ret));
} else if (CAST_FAIL(j_base->to_int(val, true))) {
ret = OB_OPERATE_OVERFLOW;
LOG_USER_ERROR(OB_OPERATE_OVERFLOW, "SIGNED", "json_value");
LOG_WARN("cast to int failed", K(ret), K(*j_base));
} else if (cast_param.dst_type_ < ObIntType &&
CAST_FAIL(int_range_check(cast_param.dst_type_, val, val))) {
ret = OB_OPERATE_OVERFLOW;
LOG_USER_ERROR(OB_OPERATE_OVERFLOW, "SIGNED", "json_value");
} else if (!cast_param.is_only_check_) {
if (cast_param.dst_type_ == ObIntType) {
res.set_int(val);
} else {
res.set_int32(static_cast<int32_t>(val));
}
}
return ret;
}
template<>
void ObJsonUtil::wrapper_set_uint(ObObjType type, uint64_t val, ObObj& obj)
{
obj.set_uint(type, val);
}
template<>
void ObJsonUtil::wrapper_set_uint(ObObjType type, uint64_t val, ObDatum& obj)
{
obj.set_uint(val);
}
template<>
void ObJsonUtil::wrapper_set_timestamp_tz(ObObjType type, ObOTimestampData val, ObObj& res)
{
if (type == ObTimestampTZType) {
res.set_timestamp_tz(val);
} else {
res.set_timestamp_ltz(val);
}
}
template<>
void ObJsonUtil::wrapper_set_timestamp_tz(ObObjType type, ObOTimestampData val, ObDatum& res)
{
if (type == ObTimestampTZType) {
res.set_otimestamp_tz(val);
} else {
res.set_otimestamp_tiny(val);
}
}
template<>
void ObJsonUtil::wrapper_set_decimal_int(const common::ObDecimalInt *decint, ObScale scale, int32_t int_bytes, ObDatum& res)
{
res.set_decimal_int(decint, int_bytes);
}
template<>
void ObJsonUtil::wrapper_set_decimal_int(const common::ObDecimalInt *decint, ObScale scale, int32_t int_bytes, ObObj& res)
{
res.set_decimal_int(int_bytes, scale, const_cast<common::ObDecimalInt *>(decint));
}
template<>
void ObJsonUtil::wrapper_set_string(ObObjType type, ObString& val, ObObj& obj)
{
obj.set_string(type, val);
}
template<>
void ObJsonUtil::wrapper_set_string(ObObjType type, ObString& val, ObDatum& obj)
{
obj.set_string(val);
}
int cast_to_uint(common::ObIAllocator *allocator,
ObEvalCtx &ctx,
ObIJsonBase *j_base,
common::ObAccuracy &accuracy,
ObJsonCastParam &cast_param,
ObDatum &res,
uint8_t &is_type_mismatch)
{
INIT_SUCC(ret);
UNUSED(allocator);
UNUSED(ctx);
UNUSED(accuracy);
UNUSED(is_type_mismatch);
uint64_t val = 0;
if (OB_ISNULL(j_base)) {
ret = OB_ERR_NULL_VALUE;
LOG_WARN("json base is null", K(ret));
} else if (CAST_FAIL(j_base->to_uint(val, true, true))) {
LOG_WARN("cast to uint failed", K(ret), K(*j_base));
if (ret == OB_OPERATE_OVERFLOW) {
LOG_USER_ERROR(OB_OPERATE_OVERFLOW, "UNSIGNED", "json_value");
}
} else if (cast_param.dst_type_ < ObUInt64Type &&
CAST_FAIL(uint_upper_check(cast_param.dst_type_, val))) {
LOG_WARN("uint_upper_check failed", K(ret));
} else if (!cast_param.is_only_check_) {
if (cast_param.dst_type_ == ObUInt64Type) {
ObJsonUtil::wrapper_set_uint(cast_param.dst_type_, val, res);
res.set_uint(val);
} else {
res.set_uint32(static_cast<uint32_t>(val));
}
}
return ret;
}
int cast_to_string(common::ObIAllocator *allocator,
ObEvalCtx &ctx,
ObIJsonBase *j_base,
common::ObAccuracy &accuracy,
ObJsonCastParam &cast_param,
ObDatum &res,
uint8_t &is_type_mismatch)
{
INIT_SUCC(ret);
UNUSED(ctx);
ObString val;
if (OB_ISNULL(j_base)) {
ret = OB_ERR_NULL_VALUE;
LOG_WARN("json base is null", K(ret));
} else if (OB_ISNULL(allocator)) {
ret = OB_ERR_NULL_VALUE;
LOG_WARN("allocator is null", K(ret));
} else {
ObJsonBuffer j_buf(allocator);
if (CAST_FAIL(j_base->print(j_buf, cast_param.is_quote_, cast_param.is_pretty_))) {
is_type_mismatch = 1;
LOG_WARN("fail to_string as json", K(ret));
} else {
ObObjType in_type = ObLongTextType;
ObString temp_str_val(j_buf.length(), j_buf.ptr());
bool is_need_string_string_convert = ((CS_TYPE_BINARY == cast_param.dst_coll_type_)
|| (ObCharset::charset_type_by_coll(cast_param.in_coll_type_) !=
ObCharset::charset_type_by_coll(cast_param.dst_coll_type_)))
&& !(lib::is_mysql_mode() && temp_str_val.length() == 0);
if (is_need_string_string_convert) {
if (CS_TYPE_BINARY != cast_param.in_coll_type_
&& CS_TYPE_BINARY != cast_param.dst_coll_type_
&& (ObCharset::charset_type_by_coll(cast_param.in_coll_type_) !=
ObCharset::charset_type_by_coll(cast_param.dst_coll_type_))) {
char *buf = NULL;
int64_t buf_len = (temp_str_val.length() == 0 ? 1 : temp_str_val.length()) * ObCharset::CharConvertFactorNum;
uint32_t result_len = 0;
buf = reinterpret_cast<char*>(allocator->alloc(buf_len));
if (OB_ISNULL(buf)) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("alloc memory failed", K(ret));
} else if (OB_FAIL(ObCharset::charset_convert(cast_param.in_coll_type_, temp_str_val.ptr(),
temp_str_val.length(), cast_param.dst_coll_type_, buf,
buf_len, result_len))) {
LOG_WARN("charset convert failed", K(ret));
} else {
val.assign_ptr(buf, result_len);
}
} else {
if (CS_TYPE_BINARY == cast_param.in_coll_type_ || CS_TYPE_BINARY == cast_param.dst_coll_type_) {
// just copy string when in_cs_type or out_cs_type is binary
const ObCharsetInfo *cs = NULL;
int64_t align_offset = 0;
if (CS_TYPE_BINARY == cast_param.in_coll_type_ && lib::is_mysql_mode()
&& (NULL != (cs = ObCharset::get_charset(cast_param.dst_coll_type_)))) {
if (cs->mbminlen > 0 && temp_str_val.length() % cs->mbminlen != 0) {
align_offset = cs->mbminlen - temp_str_val.length() % cs->mbminlen;
}
}
int64_t len = align_offset + temp_str_val.length();
char *buf = reinterpret_cast<char*>(allocator->alloc(len));
if (OB_ISNULL(buf)) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("allocate memory failed", K(ret));
} else {
MEMMOVE(buf + align_offset, temp_str_val.ptr(), len - align_offset);
MEMSET(buf, 0, align_offset);
val.assign_ptr(buf, len);
}
} else {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("same charset should not be here, just use cast_eval_arg", K(ret),
K(in_type), K(cast_param.dst_type_), K(cast_param.in_coll_type_), K(cast_param.dst_coll_type_));
}
}
} else {
val.assign_ptr(temp_str_val.ptr(), temp_str_val.length());
}
ObLengthSemantics senmactics = accuracy.get_length_semantics();
// do str length check
const int32_t str_len_char = static_cast<int32_t>(ObCharset::strlen_char(
senmactics == LS_BYTE ? CS_TYPE_BINARY : cast_param.dst_coll_type_, val.ptr(), val.length()));
ObLength max_accuracy_len;
if (lib::is_oracle_mode()) {
max_accuracy_len = (cast_param.dst_type_ == ObLongTextType) ? OB_MAX_LONGTEXT_LENGTH : accuracy.get_length();
} else { // mysql mode
max_accuracy_len = (ob_obj_type_class(cast_param.dst_type_) == ObTextTC)
? ObAccuracy::DDL_DEFAULT_ACCURACY[cast_param.dst_type_].get_length()
: accuracy.get_length();
}
if (max_accuracy_len > 0 && lib::is_oracle_mode()) {
max_accuracy_len *= (senmactics == LS_BYTE ? 1 : 2);
}
uint32_t byte_len = 0;
byte_len = ObCharset::charpos(senmactics == LS_BYTE ? CS_TYPE_BINARY : cast_param.dst_coll_type_, val.ptr(), str_len_char, max_accuracy_len);
if (OB_SUCC(ret)) {
if (max_accuracy_len == DEFAULT_STR_LENGTH) { // default string len
} else if (cast_param.is_trunc_ && max_accuracy_len < str_len_char) {
if (!cast_param.is_const_ && (j_base->json_type() == ObJsonNodeType::J_INT
|| j_base->json_type() == ObJsonNodeType::J_UINT
|| j_base->json_type() == ObJsonNodeType::J_BOOLEAN
|| j_base->json_type() == ObJsonNodeType::J_DOUBLE
|| j_base->json_type() == ObJsonNodeType::J_DECIMAL)) {
ret = OB_ERR_VALUE_EXCEEDED_MAX;
} else {
// bugfix:
// Q1:SELECT c1 ,jt.ww b_c1 FROM t1, json_table ( c2 columns( ww varchar2(2 char) truncate path '$.a')) jt ;
// Q2:SELECT c1 ,jt.ww b_c1 FROM t1, json_table ( c2 columns( ww varchar2(2 byte) truncate path '$.a')) jt;
// should not split in the middle of char
if (byte_len == 0) { // value has zero length
val.assign_ptr("", 0);
} else if (senmactics == LS_BYTE && cast_param.dst_coll_type_ != CS_TYPE_BINARY) {
int64_t char_len; // not used
// zero max_accuracy_len not allowed
byte_len = ObCharset::max_bytes_charpos(cast_param.dst_coll_type_, val.ptr(), str_len_char, max_accuracy_len, char_len);
if (byte_len == 0) { // buffer not enough for one bytes
ret = OB_OPERATE_OVERFLOW;
} else {
val.assign_ptr(val.ptr(), byte_len);
}
} else {
val.assign_ptr(val.ptr(), byte_len);
}
}
} else if (max_accuracy_len <= 0 || str_len_char > max_accuracy_len) {
ret = OB_OPERATE_OVERFLOW;
LOG_USER_ERROR(OB_OPERATE_OVERFLOW, "STRING", "json expr");
}
}
if (OB_SUCC(ret) && ObCharType == cast_param.dst_type_ && CS_TYPE_BINARY == cast_param.dst_coll_type_) { // binary need padding
int64_t text_length = val.length();
if (max_accuracy_len > text_length) {
int64_t padding_cnt = max_accuracy_len - text_length;
ObString padding_res;
if (OB_FAIL(ObJsonUtil::padding_char_for_cast(padding_cnt, cast_param.dst_coll_type_, *allocator,
padding_res))) {
LOG_WARN("padding char failed", K(ret), K(padding_cnt), K(cast_param.dst_coll_type_));
} else {
int64_t padding_size = padding_res.length() + val.length();
char *buf = reinterpret_cast<char*>(allocator->alloc(padding_size));
if (OB_ISNULL(buf)) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("allocate memory failed", K(ret));
} else {
MEMMOVE(buf, val.ptr(), val.length());
MEMMOVE(buf + val.length(), padding_res.ptr(), padding_res.length());
val.assign_ptr(buf, padding_size);
}
}
}
}
if (OB_SUCC(ret) && !cast_param.is_only_check_) {
ObJsonUtil::wrapper_set_string(cast_param.dst_type_, val, res);
res.set_string(val);
}
}
}
return ret;
}
bool ObJsonUtil::type_cast_to_string(ObString &json_string,
common::ObIAllocator *allocator,
ObEvalCtx &ctx,
ObIJsonBase *j_base,
common::ObAccuracy &accuracy) {
int res = 0;
ObDatum t_res;
uint8_t is_type_mismatch = false;
ObJsonCastParam cast_param(ObLongTextType, CS_TYPE_BINARY, CS_TYPE_BINARY, false);
res = cast_to_string(allocator, ctx, j_base, accuracy, cast_param, t_res, is_type_mismatch);
if (res == 0) {
json_string = t_res.get_string();
}
return res == 0 ? true : false;
}
int cast_to_datetime(common::ObIAllocator *allocator,
ObEvalCtx &ctx,
ObIJsonBase *j_base,
common::ObAccuracy &accuracy,
ObJsonCastParam &cast_param,
ObDatum &res,
uint8_t &is_type_mismatch)
{
INIT_SUCC(ret);
UNUSED(cast_param);
ObString json_string;
int64_t val;
GET_SESSION()
{
oceanbase::common::ObTimeConvertCtx cvrt_ctx(session->get_timezone_info(), false);
if (OB_ISNULL(j_base)) {
ret = OB_ERR_NULL_VALUE;
LOG_WARN("json base is null", K(ret));
} else if (lib::is_oracle_mode()) {
if (OB_FAIL(common_get_nls_format(session, ctx, cast_param.rt_expr_, ObDateTimeType,
true,
cvrt_ctx.oracle_nls_format_))) {
LOG_WARN("common_get_nls_format failed", K(ret));
} else if (!j_base->is_json_date(j_base->json_type())
&& ObJsonUtil::type_cast_to_string(json_string, allocator, ctx, j_base, accuracy) && json_string.length() > 0) {
ObJsonString json_str(json_string.ptr(),json_string.length());
if (CAST_FAIL(json_str.to_datetime(val, &cvrt_ctx))) {
is_type_mismatch = 1;
LOG_WARN("wrapper to datetime failed.", K(ret), K(*j_base));
}
} else if (CAST_FAIL(j_base->to_datetime(val, &cvrt_ctx))) {
is_type_mismatch = 1;
LOG_WARN("wrapper to datetime failed.", K(ret), K(*j_base));
}
if (OB_SUCC(ret) && CAST_FAIL(ObJsonUtil::datetime_scale_check(accuracy, val))) {
LOG_WARN("datetime_scale_check failed.", K(ret));
}
} else {
if (CAST_FAIL(j_base->to_datetime(val, &cvrt_ctx))) {
LOG_WARN("wrapper to datetime failed.", K(ret), K(*j_base));
} else if (CAST_FAIL(ObJsonUtil::datetime_scale_check(accuracy, val))) {
LOG_WARN("datetime_scale_check failed.", K(ret));
}
}
}
if (cast_param.is_only_check_) {
} else if (ret == OB_ERR_NULL_VALUE) {
res.set_null();
} else if (OB_SUCC(ret)) {
res.set_datetime(val);
}
return ret;
}
int cast_to_timstamp(common::ObIAllocator *allocator,
ObEvalCtx &ctx,
ObIJsonBase *j_base,
common::ObAccuracy &accuracy,
ObJsonCastParam &cast_param,
ObDatum &res,
uint8_t &is_type_mismatch)
{
INIT_SUCC(ret);
UNUSED(allocator);
ObOTimestampData out_val;
int64_t val;
oceanbase::common::ObTimeConvertCtx cvrt_ctx(NULL, cast_param.dst_type_ == ObTimestampType);
GET_SESSION()
{
if (OB_ISNULL(j_base)) {
ret = OB_ERR_NULL_VALUE;
LOG_WARN("json base is null", K(ret));
} else {
cvrt_ctx.tz_info_ = session->get_timezone_info();
if (lib::is_oracle_mode()) {
if (OB_FAIL(common_get_nls_format(session, ctx, cast_param.rt_expr_, ObDateTimeType,
true,
cvrt_ctx.oracle_nls_format_))) {
LOG_WARN("common_get_nls_format failed", K(ret));
}
}
}
}
if (OB_SUCC(ret)) {
if (CAST_FAIL(j_base->to_datetime(val, &cvrt_ctx))) {
is_type_mismatch = 1;
LOG_WARN("wrapper to datetime failed.", K(ret), K(*j_base));
} else if (cast_param.dst_type_ == ObTimestampType) {
out_val.time_us_ = val;
out_val.time_ctx_.tail_nsec_ = 0;
} else if (OB_FAIL(ObTimeConverter::odate_to_otimestamp(val, cvrt_ctx.tz_info_, cast_param.dst_type_, out_val))) {
is_type_mismatch = 1;
LOG_WARN("fail to timestamp_to_timestamp_tz", K(ret), K(val), K(cast_param.dst_type_));
}
if (OB_SUCC(ret)) {
ObScale scale = accuracy.get_scale();
if (OB_UNLIKELY(0 <= scale && scale < MAX_SCALE_FOR_ORACLE_TEMPORAL)) {
ObOTimestampData ot_data = ObTimeConverter::round_otimestamp(scale, out_val);
if (ObTimeConverter::is_valid_otimestamp(ot_data.time_us_,
static_cast<int32_t>(ot_data.time_ctx_.tail_nsec_))) {
out_val = ot_data;
} else {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("invalid otimestamp, set it null ", K(ot_data), K(scale), "orig_date", out_val);
}
}
}
if (OB_SUCC(ret) && (!cast_param.is_only_check_)) {
if (cast_param.dst_type_ == ObTimestampTZType) {
res.set_otimestamp_tz(out_val);
} else if (cast_param.dst_type_ == ObTimestampType) {
res.set_datetime(out_val.time_us_);
} else {
res.set_otimestamp_tiny(out_val);
}
}
}
return ret;
}
int cast_to_date_time(common::ObIAllocator *allocator,
ObEvalCtx &ctx,
ObIJsonBase *j_base,
common::ObAccuracy &accuracy,
ObJsonCastParam &cast_param,
ObDatum &res,
uint8_t &is_type_mismatch)
{
INIT_SUCC(ret);
if (cast_param.dst_type_ == oceanbase::common::ObTimestampType) {
ret = cast_to_timstamp(allocator, ctx, j_base, accuracy, cast_param, res, is_type_mismatch);
} else {
ret = cast_to_datetime(allocator, ctx, j_base, accuracy, cast_param, res, is_type_mismatch);
}
return ret;
}
int cast_to_date(common::ObIAllocator *allocator,
ObEvalCtx &ctx,
ObIJsonBase *j_base,
common::ObAccuracy &accuracy,
ObJsonCastParam &cast_param,
ObDatum &res,
uint8_t &is_type_mismatch)
{
INIT_SUCC(ret);
UNUSED(allocator);
UNUSED(cast_param);
UNUSED(ctx);
UNUSED(accuracy);
int32_t val;
if (OB_ISNULL(j_base)) {
ret = OB_ERR_NULL_VALUE;
LOG_WARN("json base is null", K(ret));
} else if (j_base->json_type() == ObJsonNodeType::J_NULL) {
res.set_null();
} else if (CAST_FAIL(j_base->to_date(val))) {
is_type_mismatch = 1;
LOG_WARN("wrapper to date failed.", K(ret), K(*j_base));
ret = OB_OPERATE_OVERFLOW;
LOG_USER_ERROR(OB_OPERATE_OVERFLOW, "DATE", "json_value");
} else if (!cast_param.is_only_check_) {
res.set_date(val);
}
return ret;
}
int cast_to_time(common::ObIAllocator *allocator,
ObEvalCtx &ctx,
ObIJsonBase *j_base,
common::ObAccuracy &accuracy,
ObJsonCastParam &cast_param,
ObDatum &res,
uint8_t &is_type_mismatch)
{
INIT_SUCC(ret);
UNUSED(allocator);
UNUSED(ctx);
UNUSED(is_type_mismatch);
int64_t val = 0;
if (OB_ISNULL(j_base)) {
ret = OB_ERR_NULL_VALUE;
LOG_WARN("json base is null", K(ret));
} else if (CAST_FAIL(j_base->to_time(val))) {
if (ret == OB_ERR_UNEXPECTED
&& cast_param.relaxed_time_convert_) {
if (j_base->json_type() == ObJsonNodeType::J_INT) {
ret = OB_SUCCESS;
int64_t in_val = j_base->get_int();
if (OB_FAIL(ObTimeConverter::int_to_time(in_val, val))) {
LOG_WARN("int_to_time failed", K(ret), K(in_val), K(val));
}
} else if (j_base->json_type() == ObJsonNodeType::J_DOUBLE) {
// double to time, refer to: datum_cast common_double_time
ret = OB_SUCCESS;
double in_val = j_base->get_double();
char buf[MAX_DOUBLE_PRINT_SIZE];
MEMSET(buf, 0, MAX_DOUBLE_PRINT_SIZE);
int64_t length = ob_gcvt(in_val, OB_GCVT_ARG_DOUBLE, sizeof(buf) - 1, buf, NULL);
ObString str(sizeof(buf), static_cast<int32_t>(length), buf);
ObScale res_scale;
if (CAST_FAIL(ObTimeConverter::str_to_time(str, val, &res_scale))) {
LOG_WARN("str_to_time failed", K(ret));
}
} else {
LOG_WARN("wrapper to time failed.", K(ret), K(*j_base));
ret = OB_OPERATE_OVERFLOW;
LOG_USER_ERROR(OB_OPERATE_OVERFLOW, "TIME", "json_value");
}
} else {
LOG_WARN("wrapper to time failed.", K(ret), K(*j_base));
ret = OB_OPERATE_OVERFLOW;
LOG_USER_ERROR(OB_OPERATE_OVERFLOW, "TIME", "json_value");
}
}
if (OB_FAIL(ret)) {
} else if (CAST_FAIL(ObJsonUtil::time_scale_check(accuracy, val))) {
LOG_WARN("time_scale_check failed.", K(ret));
} else if (!cast_param.is_only_check_) {
res.set_time(val);
}
return ret;
}
int cast_to_year(common::ObIAllocator *allocator,
ObEvalCtx &ctx,
ObIJsonBase *j_base,
common::ObAccuracy &accuracy,
ObJsonCastParam &cast_param,
ObDatum &res,
uint8_t &is_type_mismatch)
{
INIT_SUCC(ret);
UNUSED(allocator);
UNUSED(cast_param);
UNUSED(ctx);
UNUSED(accuracy);
UNUSED(is_type_mismatch);
// Compatible with mysql.
// There is no year type in json binary, it is store as a full int.
// For example, 1901 is stored as 1901, not 01.
// in mysql 8.0, json is converted to int first, then converted to year.
// However, json value returning as different behavior to cast expr.
int64_t int_val;
uint8_t val = 0;
const uint16 min_year = 1901;
const uint16 max_year = 2155;
if (OB_ISNULL(j_base)) {
ret = OB_ERR_NULL_VALUE;
LOG_WARN("json base is null", K(ret));
} else if (CAST_FAIL(j_base->to_int(int_val))) {
LOG_WARN("wrapper to year failed.", K(ret), K(*j_base));
} else if ((lib::is_oracle_mode() || !cast_param.relaxed_time_convert_)
&& (0 != int_val && (int_val < min_year || int_val > max_year))) {
// different with cast, if 0 < int val < 100, do not add base year
LOG_DEBUG("int out of year range", K(int_val));
ret = OB_DATA_OUT_OF_RANGE;
} else if(CAST_FAIL(ObTimeConverter::int_to_year(int_val, val))) {
LOG_WARN("int to year failed.", K(ret), K(int_val));
} else if (!cast_param.is_only_check_) {
res.set_year(val);
}
return ret;
}
int cast_to_float(common::ObIAllocator *allocator,
ObEvalCtx &ctx,
ObIJsonBase *j_base,
common::ObAccuracy &accuracy,
ObJsonCastParam &cast_param,
ObDatum &res,
uint8_t &is_type_mismatch)
{
INIT_SUCC(ret);
UNUSED(allocator);
UNUSED(ctx);
UNUSED(accuracy);
UNUSED(is_type_mismatch);
double tmp_val;
float val = 0;
if (OB_ISNULL(j_base)) {
ret = OB_ERR_NULL_VALUE;
LOG_WARN("json base is null", K(ret));
} else if (CAST_FAIL(j_base->to_double(tmp_val))) {
LOG_WARN("wrapper to date failed.", K(ret), K(*j_base));
} else {
val = static_cast<float>(tmp_val);
if (lib::is_mysql_mode() && CAST_FAIL(real_range_check(cast_param.dst_type_, tmp_val, val))) {
LOG_WARN("real_range_check failed", K(ret), K(tmp_val));
} else if (!cast_param.is_only_check_) {
res.set_float(val);
}
}
return ret;
}
int cast_to_double(common::ObIAllocator *allocator,
ObEvalCtx &ctx,
ObIJsonBase *j_base,
common::ObAccuracy &accuracy,
ObJsonCastParam &cast_param,
ObDatum &res,
uint8_t &is_type_mismatch)
{
INIT_SUCC(ret);
UNUSED(allocator);
UNUSED(ctx);
UNUSED(accuracy);
UNUSED(is_type_mismatch);
double val = 0;
if (OB_ISNULL(j_base)) {
ret = OB_ERR_NULL_VALUE;
LOG_WARN("json base is null", K(ret));
} else if (CAST_FAIL(j_base->to_double(val))) {
LOG_WARN("wrapper to date failed.", K(ret), K(*j_base));
} else if (ObUDoubleType == cast_param.dst_type_ && CAST_FAIL(numeric_negative_check(val))) {
LOG_WARN("numeric_negative_check failed", K(ret), K(val));
} else if (!cast_param.is_only_check_) {
res.set_double(val);
}
return ret;
}
int ObJsonUtil::cast_to_number_type(common::ObIAllocator *allocator,
ObIJsonBase *j_base,
common::ObAccuracy &accuracy,
ObJsonCastParam &cast_param,
uint8_t &is_type_mismatch,
number::ObNumber &val)
{
INIT_SUCC(ret);
if (OB_ISNULL(j_base)) {
ret = OB_ERR_NULL_VALUE;
LOG_WARN("json base is null", K(ret));
} else if (CAST_FAIL(j_base->to_number(allocator, val))) {
is_type_mismatch = 1;
LOG_WARN("fail to cast json as decimal", K(ret));
} else if (ObUNumberType == cast_param.dst_type_ && CAST_FAIL(numeric_negative_check(val))) {
LOG_WARN("numeric_negative_check failed", K(ret), K(val));
} else if (CAST_FAIL(ObJsonUtil::number_range_check(accuracy, allocator, val))) {
LOG_WARN("number_range_check failed", K(ret), K(val));
}
return ret;
}
int cast_to_number(common::ObIAllocator *allocator,
ObEvalCtx &ctx,
ObIJsonBase *j_base,
common::ObAccuracy &accuracy,
ObJsonCastParam &cast_param,
ObDatum &res,
uint8_t &is_type_mismatch)
{
INIT_SUCC(ret);
UNUSED(ctx);
number::ObNumber val;
if (OB_FAIL(ObJsonUtil::cast_to_number_type(allocator, j_base, accuracy, cast_param, is_type_mismatch, val))) {
LOG_WARN("failed to cast to number type failed.", K(ret));
} else if (!cast_param.is_only_check_) {
res.set_number(val);
}
return ret;
}
int cast_to_decimalint(common::ObIAllocator *allocator,
ObEvalCtx &ctx,
ObIJsonBase *j_base,
common::ObAccuracy &accuracy,
ObJsonCastParam &cast_param,
ObDatum &res,
uint8_t &is_type_mismatch)
{
INIT_SUCC(ret);
// TODO:@xiaofeng.lby, modify this after support cast json into decimalint directly in json_decimalint
number::ObNumber temp_num;
ObDecimalInt *decint = nullptr;
int32_t int_bytes;
number::ObNumber val;
if (OB_FAIL(ObJsonUtil::cast_to_number_type(allocator, j_base, accuracy, cast_param, is_type_mismatch, val))) {
LOG_WARN("cast to number failed", K(ret));
} else if (OB_FAIL(wide::from_number(val, *allocator, accuracy.scale_, decint, int_bytes))) {
LOG_WARN("cast number to decimal int failed", K(ret));
}
if (OB_SUCC(ret)) {
const int len = wide::ObDecimalIntConstValue::get_int_bytes_by_precision(accuracy.precision_);
if (len < int_bytes) {
res.set_null();
} else if (len > int_bytes) {
ObDecimalIntBuilder res_builder;
res_builder.from(decint, int_bytes);
res_builder.extend(len);
res.set_decimal_int(res_builder.get_decimal_int(), res_builder.get_int_bytes());
} else {
res.set_decimal_int(decint, int_bytes);
}
}
return ret;
}
int cast_to_bit(common::ObIAllocator *allocator,
ObEvalCtx &ctx,
ObIJsonBase *j_base,
common::ObAccuracy &accuracy,
ObJsonCastParam &cast_param,
ObDatum &res,
uint8_t &is_type_mismatch)
{
INIT_SUCC(ret);
UNUSED(allocator);
UNUSED(ctx);
UNUSED(accuracy);
UNUSED(cast_param);
UNUSED(is_type_mismatch);
uint64_t val = 0;
int64_t int_val;
if (OB_ISNULL(j_base)) {
ret = OB_ERR_NULL_VALUE;
LOG_WARN("json base is null", K(ret));
} else if (CAST_FAIL(j_base->to_int(int_val))) {
ret = OB_ERR_INVALID_JSON_VALUE_FOR_CAST;
LOG_WARN("fail get int from json", K(ret));
} else {
val = static_cast<uint64_t>(int_val);
if (OB_FAIL(ObJsonUtil::bit_length_check(accuracy, val))) {
LOG_WARN("fail to check bit range", K(ret));
} else if (!cast_param.is_only_check_) {
ObJsonUtil::wrapper_set_uint(cast_param.dst_type_, val, res);
res.set_uint(val);
}
}
return ret;
}
int cast_to_json(common::ObIAllocator *allocator,
ObEvalCtx &ctx,
ObIJsonBase *j_base,
common::ObAccuracy &accuracy,
ObJsonCastParam &cast_param,
ObDatum &res,
uint8_t &is_type_mismatch)
{
INIT_SUCC(ret);
UNUSED(ctx);
UNUSED(cast_param);
ObString val;
if (OB_ISNULL(j_base)) {
ret = OB_ERR_NULL_VALUE;
LOG_WARN("json base is null", K(ret));
} else if (CAST_FAIL(j_base->get_raw_binary(val, allocator))) {
is_type_mismatch = 1;
LOG_WARN("failed to get raw binary", K(ret));
} else {
char *buf = static_cast<char *>(allocator->alloc(val.length()));
if (OB_UNLIKELY(buf == NULL)) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("fail to alloc memory for json array result", K(ret), K(val.length()));
} else {
MEMCPY(buf, val.ptr(), val.length());
val.assign_ptr(buf, val.length());
if (!cast_param.is_only_check_) {
ObJsonUtil::wrapper_set_string(cast_param.dst_type_, val, res);
res.set_string(val);
}
}
}
return ret;
}
int cast_not_expected(common::ObIAllocator *allocator,
ObEvalCtx &ctx,
ObIJsonBase *j_base,
common::ObAccuracy &accuracy,
ObJsonCastParam &cast_param,
ObDatum &res,
uint8_t &is_type_mismatch)
{
int ret = OB_ERR_UNEXPECTED;
UNUSED(allocator);
UNUSED(ctx);
UNUSED(j_base);
UNUSED(accuracy);
UNUSED(res);
UNUSED(is_type_mismatch);
LOG_WARN("unexpected dst_type", K(cast_param.dst_type_));
return ret;
}
int ObJsonUtil::cast_to_res(common::ObIAllocator *allocator,
ObEvalCtx &ctx,
ObIJsonBase *j_base,
ObAccuracy &accuracy,
ObJsonCastParam &cast_param,
ObDatum &res,
uint8_t &is_type_mismatch)
{
INIT_SUCC(ret);
ObJsonUtil::ObJsonCastSqlScalar cast_func_ = get_json_cast_func(cast_param.dst_type_);
if (OB_ISNULL(j_base)
|| (lib::is_mysql_mode() && j_base->json_type() == common::ObJsonNodeType::J_NULL)) {
res.set_null();
} else if (OB_ISNULL(cast_func_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("eval func can not be null", K(ret));
} else if (OB_FAIL(((ObJsonUtil::ObJsonCastSqlScalar)(cast_func_))(allocator,
ctx, j_base, accuracy, cast_param,
res, is_type_mismatch))) {
LOG_WARN("fail to deal json cast to sql scalar", K(ret));
}
LOG_DEBUG("finish cast_to_res.", K(ret), K(cast_param.dst_type_));
return ret;
}
int ObJsonUtil::cast_json_scalar_to_sql_obj(common::ObIAllocator *allocator,
ObEvalCtx& ctx,
ObIJsonBase *j_base,
ObCollationType collation,
ObAccuracy &accuracy,
ObObjType obj_type,
ObScale scale,
ObObj &res_obj)
{
INIT_SUCC(ret);
if (OB_ISNULL(allocator) || OB_ISNULL(j_base)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("expr is null.", K(ret));
} else {
bool is_use_dynamic_buffer = (ob_is_number_or_decimal_int_tc(obj_type));
ObDatum res_datum;
char datum_buffer[OBJ_DATUM_STRING_RES_SIZE] = {0};
res_datum.ptr_ = datum_buffer;
if (is_use_dynamic_buffer) {
void* buffer = allocator->alloc(OBJ_DATUM_STRING_RES_SIZE);
if (OB_ISNULL(buffer)) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("allocate tmp buffer failed.", K(ret));
} else {
res_datum.ptr_ = static_cast<char*>(buffer);
}
}
ObJsonCastParam cast_param(obj_type, ObCollationType::CS_TYPE_UTF8MB4_BIN, collation, false);
cast_param.relaxed_time_convert_ = true;
uint8_t is_type_mismatch = false;
if (OB_FAIL(ret)) {
} else if (OB_FAIL(cast_to_res(allocator, ctx, j_base, accuracy, cast_param, res_datum, is_type_mismatch))) {
LOG_WARN("fail to cast.", K(ret));
} else {
res_obj.set_type(obj_type);
res_obj.set_collation_type(collation);
res_obj.set_scale(scale);
if (OB_FAIL(res_datum.to_obj(res_obj, res_obj.meta_))) {
LOG_WARN("fail datum to obj.", K(ret));
}
}
}
return ret;
}
int ObJsonUtil::cast_json_scalar_to_sql_obj(common::ObIAllocator *allocator,
ObExecContext* exec_ctx,
ObIJsonBase *j_base,
ObExprResType col_res_type,
ObObj &res_obj) {
// ToDo: refine
INIT_SUCC(ret);
if (OB_ISNULL(allocator) || OB_ISNULL(j_base)) {
ret = OB_INVALID_ARGUMENT;
LOG_WARN("expr is null.", K(ret));
} else {
ObEvalCtx ctx(*exec_ctx);
ObAccuracy temp_accuracy = col_res_type.get_accuracy();
ret = cast_json_scalar_to_sql_obj(allocator, ctx, j_base,
col_res_type.get_collation_type(),
temp_accuracy,
col_res_type.get_type(),
col_res_type.get_scale(),
res_obj);
}
return ret;
}
/*
ObJsonUtil::ObJsonCastSqlDatum OB_JSON_CAST_DATUM_EXPLICIT[ObMaxTC] =
{
// ObNullTC = 0, // null
cast_to_null<ObDatum>,
// ObIntTC = 1, // int8, int16, int24, int32, int64.
cast_to_int<ObDatum>,
// ObUIntTC = 2, // uint8, uint16, uint24, uint32, uint64.
cast_to_uint<ObDatum>,
// ObFloatTC = 3, // float, ufloat.
cast_to_float<ObDatum>,
// ObDoubleTC = 4, // double, udouble.
cast_to_double<ObDatum>,
// ObNumberTC = 5, // number, unumber.
cast_to_number<ObDatum>,
// ObDateTimeTC = 6, // datetime, timestamp.
cast_to_date_time<ObDatum>,
// ObDateTC = 7, // date
cast_to_date<ObDatum>,
// ObTimeTC = 8, // time
cast_to_time<ObDatum>,
// ObYearTC = 9, // year
cast_to_year<ObDatum>,
// ObStringTC = 10, // varchar, char, varbinary, binary.
cast_to_string<ObDatum>,
// ObExtendTC = 11, // extend
cast_not_expected<ObDatum>,
// ObUnknownTC = 12, // unknown
cast_not_expected<ObDatum>,
// ObTextTC = 13, // TinyText,MediumText, Text ,LongText, TinyBLOB,MediumBLOB, // BLOB ,LongBLOB
cast_to_string<ObDatum>,
// ObBitTC = 14, // bit
cast_to_bit<ObDatum>,
// ObEnumSetTC = 15, // enum, set
cast_not_expected<ObDatum>,
// ObEnumSetInnerTC = 16,
cast_not_expected<ObDatum>,
// ObOTimestampTC = 17, //timestamp with time zone
cast_to_timstamp<ObDatum>,
// ObRawTC = 18, // raw
cast_to_string<ObDatum>,
// ObIntervalTC = 19, //oracle interval type class include interval year to month and interval day to second
cast_not_expected<ObDatum>,
// ObRowIDTC = 20, // oracle rowid typeclass, includes urowid and rowid
cast_not_expected<ObDatum>,
// ObLobTC = 21, //oracle lob typeclass ObLobType not use
cast_not_expected<ObDatum>,
// ObJsonTC = 22, // json type class
cast_to_json<ObDatum>,
// ObGeometryTC = 23, // geometry type class
cast_not_expected<ObDatum>,
// ObUserDefinedSQLTC = 24, // user defined type class in SQL
cast_not_expected<ObDatum>,
};
ObJsonUtil::ObJsonCastSqlObj OB_JSON_CAST_OBJ_EXPLICIT[ObMaxTC] =
{
// ObNullTC = 0, // null
cast_to_null<ObObj>,
// ObIntTC = 1, // int8, int16, int24, int32, int64.
cast_to_int<ObObj>,
// ObUIntTC = 2, // uint8, uint16, uint24, uint32, uint64.
cast_to_uint<ObObj>,
// ObFloatTC = 3, // float, ufloat.
cast_to_float<ObObj>,
// ObDoubleTC = 4, // double, udouble.
cast_to_double<ObObj>,
// ObNumberTC = 5, // number, unumber.
cast_to_number<ObObj>,
// ObDateTimeTC = 6, // datetime, timestamp.
cast_to_date_time<ObObj>,
// ObDateTC = 7, // date
cast_to_date<ObObj>,
// ObTimeTC = 8, // time
cast_to_time<ObObj>,
// ObYearTC = 9, // year
cast_to_year<ObObj>,
// ObStringTC = 10, // varchar, char, varbinary, binary.
cast_to_string<ObObj>,
// ObExtendTC = 11, // extend
cast_not_expected<ObObj>,
// ObUnknownTC = 12, // unknown
cast_not_expected<ObObj>,
// ObTextTC = 13, // TinyText,MediumText, Text ,LongText, TinyBLOB,MediumBLOB, // BLOB ,LongBLOB
cast_to_string<ObObj>,
// ObBitTC = 14, // bit
cast_to_bit<ObObj>,
// ObEnumSetTC = 15, // enum, set
cast_not_expected<ObObj>,
// ObEnumSetInnerTC = 16,
cast_not_expected<ObObj>,
// ObOTimestampTC = 17, //timestamp with time zone
cast_to_timstamp<ObObj>,
// ObRawTC = 18, // raw
cast_to_string<ObObj>,
// ObIntervalTC = 19, //oracle interval type class include interval year to month and interval day to second
cast_not_expected<ObObj>,
// ObRowIDTC = 20, // oracle rowid typeclass, includes urowid and rowid
cast_not_expected<ObObj>,
// ObLobTC = 21, //oracle lob typeclass ObLobType not use
cast_not_expected<ObObj>,
// ObJsonTC = 22, // json type class
cast_to_json<ObObj>,
// ObGeometryTC = 23, // geometry type class
cast_not_expected<ObObj>,
// ObUserDefinedSQLTC = 24, // user defined type class in SQL
cast_not_expected<ObObj>,
};
*/
ObJsonUtil::ObJsonCastSqlScalar OB_JSON_CAST_SQL_EXPLICIT[ObMaxTC] =
{
// ObNullTC = 0, // null
cast_to_null,
// ObIntTC = 1, // int8, int16, int24, int32, int64.
cast_to_int,
// ObUIntTC = 2, // uint8, uint16, uint24, uint32, uint64.
cast_to_uint,
// ObFloatTC = 3, // float, ufloat.
cast_to_float,
// ObDoubleTC = 4, // double, udouble.
cast_to_double,
// ObNumberTC = 5, // number, unumber.
cast_to_number,
// ObDateTimeTC = 6, // datetime, timestamp.
cast_to_date_time,
// ObDateTC = 7, // date
cast_to_date,
// ObTimeTC = 8, // time
cast_to_time,
// ObYearTC = 9, // year
cast_to_year,
// ObStringTC = 10, // varchar, char, varbinary, binary.
cast_to_string,
// ObExtendTC = 11, // extend
cast_not_expected,
// ObUnknownTC = 12, // unknown
cast_not_expected,
// ObTextTC = 13, // TinyText,MediumText, Text ,LongText, TinyBLOB,MediumBLOB, // BLOB ,LongBLOB
cast_to_string,
// ObBitTC = 14, // bit
cast_to_bit,
// ObEnumSetTC = 15, // enum, set
cast_not_expected,
// ObEnumSetInnerTC = 16,
cast_not_expected,
// ObOTimestampTC = 17, //timestamp with time zone
cast_to_timstamp,
// ObRawTC = 18, // raw
cast_to_string,
// ObIntervalTC = 19, //oracle interval type class include interval year to month and interval day to second
cast_not_expected,
// ObRowIDTC = 20, // oracle rowid typeclass, includes urowid and rowid
cast_not_expected,
// ObLobTC = 21, //oracle lob typeclass ObLobType not use
cast_not_expected,
// ObJsonTC = 22, // json type class
cast_to_json,
// ObGeometryTC = 23, // geometry type class
cast_not_expected,
// ObUserDefinedSQLTC = 24, // user defined type class in SQL
cast_not_expected,
// ObDecimalIntTC = 25, // decimal int class
cast_to_decimalint,
};
#undef CAST_FAIL
#undef GET_SESSION
int ObJsonUtil::get_json_path(ObExpr* expr,
ObEvalCtx &ctx,
bool &is_null_result,
ObJsonParamCacheCtx *&param_ctx,
common::ObIAllocator &temp_allocator,
bool &is_cover_by_error)
{
INIT_SUCC(ret);
ObDatum *json_datum = NULL;
ObObjType type = expr->datum_meta_.type_;
ObJsonPathCache ctx_cache(&temp_allocator);
ObJsonPath* j_path = nullptr;
ObString j_path_text;
ObJsonPathCache* path_cache = path_cache = param_ctx->get_path_cache();
// parse json path
if (!param_ctx->is_first_exec_ && param_ctx->is_json_path_const_
&& OB_NOT_NULL(path_cache)) {
} else {
type = expr->datum_meta_.type_;
if (OB_FAIL(expr->eval(ctx, json_datum))) {
is_cover_by_error = false;
LOG_WARN("eval json arg failed", K(ret));
} else if (type == ObNullType || json_datum->is_null()) {
is_null_result = true;
} else if (!ob_is_string_type(type)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("input type error", K(type));
}
if OB_SUCC(ret) {
j_path_text = json_datum->get_string();
if (OB_FAIL(ObJsonExprHelper::get_json_or_str_data(expr, ctx, temp_allocator, j_path_text, is_null_result))) {
LOG_WARN("fail to get real data.", K(ret), K(j_path_text));
} else if (j_path_text.length() == 0) { // maybe input json doc is null type
is_null_result = true;
} else if (OB_FAIL(ObJsonExprHelper::convert_string_collation_type(expr->datum_meta_.cs_type_,
CS_TYPE_UTF8MB4_BIN,
&ctx.exec_ctx_.get_allocator(),
j_path_text,
j_path_text))) {
LOG_WARN("convert string memory failed", K(ret), K(j_path_text));
}
path_cache = ((path_cache != NULL) ? path_cache : &ctx_cache);
}
}
if (OB_SUCC(ret)) {
if (j_path_text.empty()) {
param_ctx->json_param_.json_path_ = nullptr;
} else if (OB_FAIL(ObJsonExprHelper::find_and_add_cache(path_cache, j_path, j_path_text, 0, true, param_ctx->is_json_path_const_))) {
is_cover_by_error = false;
if (lib::is_oracle_mode()) {
ret = OB_ERR_JSON_PATH_EXPRESSION_SYNTAX_ERROR;
LOG_USER_ERROR(OB_ERR_JSON_PATH_EXPRESSION_SYNTAX_ERROR, j_path_text.length(), j_path_text.ptr());
}
} else {
param_ctx->json_param_.json_path_ = j_path;
}
}
return ret;
}
int ObJsonUtil::get_json_doc(ObExpr *expr,
ObEvalCtx &ctx,
common::ObIAllocator &allocator,
ObIJsonBase*& j_base,
bool &is_null, bool & is_cover_by_error,
bool relax)
{
INIT_SUCC(ret);
ObDatum *json_datum = NULL;
ObObjType val_type = expr->datum_meta_.type_;
ObCollationType cs_type = expr->datum_meta_.cs_type_;
bool is_oracle = lib::is_oracle_mode();
if (OB_UNLIKELY(OB_FAIL(expr->eval(ctx, json_datum)))) {
is_cover_by_error = false;
LOG_WARN("eval json arg failed", K(ret));
} else if (val_type == ObNullType || json_datum->is_null()) {
is_null = true;
} else if (val_type != ObJsonType && !ob_is_string_type(val_type)) {
ret = OB_ERR_INVALID_TYPE_FOR_OP;
LOG_WARN("input type error", K(val_type));
} else if (lib::is_mysql_mode() && OB_FAIL(ObJsonExprHelper::ensure_collation(val_type, cs_type))) {
LOG_WARN("fail to ensure collation", K(ret), K(val_type), K(cs_type));
} else {
ObString j_str;
if (OB_FAIL(ObJsonExprHelper::get_json_or_str_data(expr, ctx, allocator, j_str, is_null))) {
LOG_WARN("fail to get real data.", K(ret), K(j_str));
} else if (is_null) {
} else {
ObJsonInType j_in_type = ObJsonExprHelper::get_json_internal_type(val_type);
ObJsonInType expect_type = j_in_type;
bool relax_json = (is_oracle && relax);
uint32_t parse_flag = relax_json ? ObJsonParser::JSN_RELAXED_FLAG : 0;
if (is_oracle && j_str.length() == 0) {
is_null = true;
} else if (OB_FAIL(ObJsonBaseFactory::get_json_base(&allocator, j_str, j_in_type,
expect_type, j_base, parse_flag,
ObJsonExprHelper::get_json_max_depth_config()))) {
LOG_WARN("fail to get json base", K(ret), K(j_in_type));
if (ret == OB_ERR_JSON_OUT_OF_DEPTH) {
is_cover_by_error = false;
} else if (is_oracle) {
ret = OB_ERR_JSON_SYNTAX_ERROR;
} else {
ret = OB_ERR_INVALID_JSON_TEXT_IN_PARAM;
LOG_USER_ERROR(OB_ERR_INVALID_JSON_TEXT_IN_PARAM);
}
} else if (j_base->is_bin()) {
// only use json doc to search
static_cast<ObJsonBin*>(j_base)->set_seek_flag(true);
}
}
}
return ret;
}
int func_upper_json_string(ObIJsonBase*& in,
bool &is_null_result,
common::ObIAllocator *allocator,
uint8_t &is_type_mismatch)
{
UNUSED(is_null_result);
UNUSED(allocator);
UNUSED(is_type_mismatch);
if (((ObJsonString *)in)->get_is_null_to_str()) {
is_null_result = true;
}
return OB_SUCCESS;
}
int func_conversion_fail(ObIJsonBase*& in,
bool &is_null_result,
common::ObIAllocator *allocator,
uint8_t &is_type_mismatch)
{
INIT_SUCC(ret);
UNUSED(in);
UNUSED(allocator);
UNUSED(is_type_mismatch);
UNUSED(is_null_result);
ret = OB_ERR_CONVERSION_FAIL;
LOG_WARN("data seek fail", K(ret));
return ret;
}
int func_str_json_null(ObIJsonBase*& in,
bool &is_null_result,
common::ObIAllocator *allocator,
uint8_t &is_type_mismatch)
{
INIT_SUCC(ret);
UNUSED(allocator);
if (!in->is_real_json_null(in)) {
ret = OB_INVALID_NUMERIC;
is_type_mismatch = 1;
LOG_WARN("string only function meet non-string data", K(ret));
}
return ret;
}
int func_num_json_null(ObIJsonBase*& in,
bool &is_null_result,
common::ObIAllocator *allocator,
uint8_t &is_type_mismatch)
{
INIT_SUCC(ret);
UNUSED(allocator);
if (!in->is_real_json_null(in)) {
ret = OB_INVALID_NUMERIC;
is_type_mismatch = 1;
LOG_WARN("number only function meet non-number data", K(ret));
}
return ret;
}
int set_null_result(ObIJsonBase*& in,
bool &is_null_result,
common::ObIAllocator *allocator,
uint8_t &is_type_mismatch)
{
UNUSED(in);
UNUSED(allocator);
UNUSED(is_type_mismatch);
is_null_result = true;
return OB_SUCCESS;
}
int cast_succ(ObIJsonBase*& in,
bool &is_null_result,
common::ObIAllocator *allocator,
uint8_t &is_type_mismatch)
{
UNUSED(in);
UNUSED(is_null_result);
UNUSED(allocator);
UNUSED(is_type_mismatch);
return OB_SUCCESS;
}
int func_path_syntax_fail(ObIJsonBase*& in,
bool &is_null_result,
common::ObIAllocator *allocator,
uint8_t &is_type_mismatch)
{
INIT_SUCC(ret);
UNUSED(in);
UNUSED(allocator);
UNUSED(is_type_mismatch);
UNUSED(is_null_result);
ret = OB_ERR_JSON_PATH_SYNTAX_ERROR;
LOG_WARN("boolean only function meet non-boolean data", K(ret));
return ret;
}
int func_bool_json_int(ObIJsonBase*& in,
bool &is_null_result,
common::ObIAllocator *allocator,
uint8_t &is_type_mismatch)
{
INIT_SUCC(ret);
if (in->get_int() == 1 || in->get_int() == 0) {
bool is_true = (in->get_int() == 1);
ObJsonBoolean* tmp_ans = static_cast<ObJsonBoolean*> (allocator->alloc(sizeof(ObJsonBoolean)));
if (OB_ISNULL(tmp_ans)) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("allocate row buffer failed at ObJsonDecimal", K(ret));
} else {
tmp_ans = new (tmp_ans) ObJsonBoolean(is_true);
in = tmp_ans;
}
} else {
is_null_result = true;
}
return ret;
}
int func_bool_json_double(ObIJsonBase*& in,
bool &is_null_result,
common::ObIAllocator *allocator,
uint8_t &is_type_mismatch)
{
INIT_SUCC(ret);
if (in->get_double() == 1.0 || in->get_double() == 0.0) {
bool is_true = (in->get_double() == 1.0);
ObJsonBoolean* tmp_ans = static_cast<ObJsonBoolean*> (allocator->alloc(sizeof(ObJsonBoolean)));
if (OB_ISNULL(tmp_ans)) {
ret = OB_ALLOCATE_MEMORY_FAILED;
LOG_WARN("allocate row buffer failed at ObJsonDecimal", K(ret));
} else {
tmp_ans = new (tmp_ans) ObJsonBoolean(is_true);
in = tmp_ans;
}
} else {
is_null_result = true;
}
return ret;
}
// 17 * 30
ObJsonUtil::ObItemMethodValid OB_JSON_VALUE_ITEM_METHOD_CAST_FUNC[ObMaxItemMethod][ObMaxJsonType] =
{
{
// abs -> **
cast_succ, // j_null
cast_succ, // decimal
cast_succ, // int
cast_succ, // uint
cast_succ, // double
cast_succ, // string
cast_succ, //object
cast_succ, //array
cast_succ, // boolean
cast_succ, // date
cast_succ, //time
cast_succ, // datetime
cast_succ, //timestamp
cast_succ, // opaque
cast_succ, // empty
cast_succ, //ofloat
cast_succ, // odouble
cast_succ, // odeciaml
cast_succ, // oint
cast_succ, // olong
cast_succ, // obinary
cast_succ, // oid
cast_succ, //rawhex
cast_succ, // rawid
cast_succ, // oracledate
cast_succ, // odate
cast_succ, // otimestamp
cast_succ, // otimestamptz
cast_succ, // odaysecond
cast_succ, // oyearmonth
},
{
// boolean - > ***
set_null_result, // null
set_null_result, // decimal
func_bool_json_int, // int
set_null_result, // uint
func_bool_json_double, // double
set_null_result, // string
set_null_result, //object
set_null_result, //array
cast_succ, // boolean
set_null_result, // date
set_null_result, //time
set_null_result, // datetime
set_null_result, //timestamp
set_null_result, // opaque
cast_succ, // empty
set_null_result, //ofloat
set_null_result, // odouble
set_null_result, // odeciaml
func_bool_json_int, // oint
set_null_result, // olong
set_null_result, // obinary
set_null_result, // oid
set_null_result, //rawhex
set_null_result, // rawid
set_null_result, // oracledate
set_null_result, // odate
set_null_result, // otimestamp
set_null_result, // otimestamptz
set_null_result, // odaysecond
set_null_result, // oyearmonth
},
{
// bool_only -> ***
func_path_syntax_fail, // null
func_path_syntax_fail, // decimal
func_path_syntax_fail, // int
func_path_syntax_fail, // uint
func_path_syntax_fail, // double
func_path_syntax_fail, // string
func_path_syntax_fail, //object
func_path_syntax_fail, //array
cast_succ, // boolean
func_path_syntax_fail, // date
func_path_syntax_fail, //time
func_path_syntax_fail, // datetime
func_path_syntax_fail, //timestamp
func_path_syntax_fail, // opaque
cast_succ, // empty
func_path_syntax_fail, //ofloat
func_path_syntax_fail, // odouble
func_path_syntax_fail, // odeciaml
func_path_syntax_fail, // oint
func_path_syntax_fail, // olong
func_path_syntax_fail, // obinary
func_path_syntax_fail, // oid
func_path_syntax_fail, //rawhex
func_path_syntax_fail, // rawid
func_path_syntax_fail, // oracledate
func_path_syntax_fail, // odate
func_path_syntax_fail, // otimestamp
func_path_syntax_fail, // otimestamptz
func_path_syntax_fail, // odaysecond
func_path_syntax_fail, // oyearmonth
},
{
// ceiling -> **
cast_succ, // j_null
cast_succ, // decimal
cast_succ, // int
cast_succ, // uint
cast_succ, // double
cast_succ, // string
cast_succ, //object
cast_succ, //array
cast_succ, // boolean
cast_succ, // date
cast_succ, //time
cast_succ, // datetime
cast_succ, //timestamp
cast_succ, // opaque
cast_succ, // empty
cast_succ, //ofloat
cast_succ, // odouble
cast_succ, // odeciaml
cast_succ, // oint
cast_succ, // olong
cast_succ, // obinary
cast_succ, // oid
cast_succ, //rawhex
cast_succ, // rawid
cast_succ, // oracledate
cast_succ, // odate
cast_succ, // otimestamp
cast_succ, // otimestamptz
cast_succ, // odaysecond
cast_succ, // oyearmonth
},
{
// date -> ***
func_conversion_fail, // j_null
func_conversion_fail, // decimal
func_conversion_fail, // int
func_conversion_fail, // uint
func_conversion_fail, // double
cast_succ, // string
func_conversion_fail, //object
func_conversion_fail, //array
func_conversion_fail, // boolean
cast_succ, // date
cast_succ, //time
cast_succ, // datetime
cast_succ, //timestamp
func_conversion_fail, // opaque
func_conversion_fail, // empty
func_conversion_fail, //ofloat
func_conversion_fail, // odouble
func_conversion_fail, // odeciaml
func_conversion_fail, // oint
func_conversion_fail, // olong
cast_succ, // obinary
cast_succ, // oid
cast_succ, //rawhex
cast_succ, // rawid
cast_succ, // oracledate
cast_succ, // odate
cast_succ, // otimestamp
cast_succ, // otimestamptz
cast_succ, // odaysecond
cast_succ, // oyearmonth
},
{
// double -> ***
func_conversion_fail, // j_null
cast_succ, // decimal
cast_succ, // int
cast_succ, // uint
cast_succ, // double
func_conversion_fail, // string
func_conversion_fail, //object
func_conversion_fail, //array
func_conversion_fail, // boolean
func_conversion_fail, // date
func_conversion_fail, //time
func_conversion_fail, // datetime
func_conversion_fail, //timestamp
func_conversion_fail, // opaque
func_conversion_fail, // empty
cast_succ, //ofloat
cast_succ, // odouble
cast_succ, // odeciaml
cast_succ, // oint
cast_succ, // olong
func_conversion_fail, // obinary
func_conversion_fail, // oid
func_conversion_fail, //rawhex
func_conversion_fail, // rawid
func_conversion_fail, // oracledate
func_conversion_fail, // odate
func_conversion_fail, // otimestamp
func_conversion_fail, // otimestamptz
func_conversion_fail, // odaysecond
func_conversion_fail, // oyearmonth
},
{
// floor ->**
cast_succ, // j_null
cast_succ, // decimal
cast_succ, // int
cast_succ, // uint
cast_succ, // double
cast_succ, // string
cast_succ, //object
cast_succ, //array
cast_succ, // boolean
cast_succ, // date
cast_succ, //time
cast_succ, // datetime
cast_succ, //timestamp
cast_succ, // opaque
cast_succ, // empty
cast_succ, //ofloat
cast_succ, // odouble
cast_succ, // odeciaml
cast_succ, // oint
cast_succ, // olong
cast_succ, // obinary
cast_succ, // oid
cast_succ, //rawhex
cast_succ, // rawid
cast_succ, // oracledate
cast_succ, // odate
cast_succ, // otimestamp
cast_succ, // otimestamptz
cast_succ, // odaysecond
cast_succ, // oyearmonth
},
{
// length -> **
cast_succ, // j_null
cast_succ, // decimal
cast_succ, // int
cast_succ, // uint
cast_succ, // double
cast_succ, // string
cast_succ, //object
cast_succ, //array
cast_succ, // boolean
cast_succ, // date
cast_succ, //time
cast_succ, // datetime
cast_succ, //timestamp
cast_succ, // opaque
cast_succ, // empty
cast_succ, //ofloat
cast_succ, // odouble
cast_succ, // odeciaml
cast_succ, // oint
cast_succ, // olong
cast_succ, // obinary
cast_succ, // oid
cast_succ, //rawhex
cast_succ, // rawid
cast_succ, // oracledate
cast_succ, // odate
cast_succ, // otimestamp
cast_succ, // otimestamptz
cast_succ, // odaysecond
cast_succ, // oyearmonth
},
{
// lower -> ***
cast_succ, // j_null
cast_succ, // decimal
cast_succ, // int
cast_succ, // uint
cast_succ, // double
func_upper_json_string, // string
cast_succ, //object
cast_succ, //array
cast_succ, // boolean
cast_succ, // date
cast_succ, //time
cast_succ, // datetime
cast_succ, //timestamp
cast_succ, // opaque
cast_succ, // empty
cast_succ, //ofloat
cast_succ, // odouble
cast_succ, // odeciaml
cast_succ, // oint
cast_succ, // olong
cast_succ, // obinary
cast_succ, // oid
cast_succ, //rawhex
cast_succ, // rawid
cast_succ, // oracledate
cast_succ, // odate
cast_succ, // otimestamp
cast_succ, // otimestamptz
cast_succ, // odaysecond
cast_succ, // oyearmonth
},
{
// number ->
func_num_json_null, // j_null
cast_succ, // decimal
cast_succ, // int
cast_succ, // uint
cast_succ, // double
cast_succ, // string
cast_succ, //object
cast_succ, //array
cast_succ, // boolean
cast_succ, // date
cast_succ, //time
cast_succ, // datetime
cast_succ, //timestamp
cast_succ, // opaque
cast_succ, // empty
cast_succ, //ofloat
cast_succ, // odouble
cast_succ, // odeciaml
cast_succ, // oint
cast_succ, // olong
cast_succ, // obinary
cast_succ, // oid
cast_succ, //rawhex
cast_succ, // rawid
cast_succ, // oracledate
cast_succ, // odate
cast_succ, // otimestamp
cast_succ, // otimestamptz
cast_succ, // odaysecond
cast_succ, // oyearmonth
},
{
// num_only -> ***
func_num_json_null, // j_null
cast_succ, // decimal
cast_succ, // int
cast_succ, // uint
cast_succ, // double
cast_succ, // string
cast_succ, //object
cast_succ, //array
cast_succ, // boolean
cast_succ, // date
cast_succ, //time
cast_succ, // datetime
cast_succ, //timestamp
cast_succ, // opaque
cast_succ, // empty
cast_succ, //ofloat
cast_succ, // odouble
cast_succ, // odeciaml
cast_succ, // oint
cast_succ, // olong
cast_succ, // obinary
cast_succ, // oid
cast_succ, //rawhex
cast_succ, // rawid
cast_succ, // oracledate
cast_succ, // odate
cast_succ, // otimestamp
cast_succ, // otimestamptz
cast_succ, // odaysecond
cast_succ, // oyearmonth
},
{
// size ->**
cast_succ, // j_null
cast_succ, // decimal
cast_succ, // int
cast_succ, // uint
cast_succ, // double
cast_succ, // string
cast_succ, //object
cast_succ, //array
cast_succ, // boolean
cast_succ, // date
cast_succ, //time
cast_succ, // datetime
cast_succ, //timestamp
cast_succ, // opaque
cast_succ, // empty
cast_succ, //ofloat
cast_succ, // odouble
cast_succ, // odeciaml
cast_succ, // oint
cast_succ, // olong
cast_succ, // obinary
cast_succ, // oid
cast_succ, //rawhex
cast_succ, // rawid
cast_succ, // oracledate
cast_succ, // odate
cast_succ, // otimestamp
cast_succ, // otimestamptz
cast_succ, // odaysecond
cast_succ, // oyearmonth
},
{
// string-> ***
func_str_json_null, // j_null
cast_succ, // decimal
cast_succ, // int
cast_succ, // uint
cast_succ, // double
cast_succ, // string
cast_succ, //object
cast_succ, //array
cast_succ, // boolean
cast_succ, // date
cast_succ, //time
cast_succ, // datetime
cast_succ, //timestamp
cast_succ, // opaque
cast_succ, // empty
cast_succ, //ofloat
cast_succ, // odouble
cast_succ, // odeciaml
cast_succ, // oint
cast_succ, // olong
cast_succ, // obinary
cast_succ, // oid
cast_succ, //rawhex
cast_succ, // rawid
cast_succ, // oracledate
cast_succ, // odate
cast_succ, // otimestamp
cast_succ, // otimestamptz
cast_succ, // odaysecond
cast_succ, // oyearmonth
},
{
// str_only -> ***
func_str_json_null, // j_null
cast_succ, // decimal
cast_succ, // int
cast_succ, // uint
cast_succ, // double
cast_succ, // string
cast_succ, //object
cast_succ, //array
cast_succ, // boolean
cast_succ, // date
cast_succ, //time
cast_succ, // datetime
cast_succ, //timestamp
cast_succ, // opaque
cast_succ, // empty
cast_succ, //ofloat
cast_succ, // odouble
cast_succ, // odeciaml
cast_succ, // oint
cast_succ, // olong
cast_succ, // obinary
cast_succ, // oid
cast_succ, //rawhex
cast_succ, // rawid
cast_succ, // oracledate
cast_succ, // odate
cast_succ, // otimestamp
cast_succ, // otimestamptz
cast_succ, // odaysecond
cast_succ, // oyearmonth
},
{
// timestamp -> ***
func_conversion_fail, // j_null
func_conversion_fail, // decimal
func_conversion_fail, // int
func_conversion_fail, // uint
func_conversion_fail, // double
cast_succ, // string
func_conversion_fail, //object
func_conversion_fail, //array
func_conversion_fail, // boolean
cast_succ, // date
cast_succ, //time
cast_succ, // datetime
cast_succ, //timestamp
func_conversion_fail, // opaque
func_conversion_fail, // empty
func_conversion_fail, //ofloat
func_conversion_fail, // odouble
func_conversion_fail, // odeciaml
func_conversion_fail, // oint
func_conversion_fail, // olong
cast_succ, // obinary
cast_succ, // oid
cast_succ, //rawhex
cast_succ, // rawid
cast_succ, // oracledate
cast_succ, // odate
cast_succ, // otimestamp
cast_succ, // otimestamptz
cast_succ, // odaysecond
cast_succ, // oyearmonth
},
{
// type ->**
cast_succ, // j_null
cast_succ, // decimal
cast_succ, // int
cast_succ, // uint
cast_succ, // double
cast_succ, // string
cast_succ, //object
cast_succ, //array
cast_succ, // boolean
cast_succ, // date
cast_succ, //time
cast_succ, // datetime
cast_succ, //timestamp
cast_succ, // opaque
cast_succ, // empty
cast_succ, //ofloat
cast_succ, // odouble
cast_succ, // odeciaml
cast_succ, // oint
cast_succ, // olong
cast_succ, // obinary
cast_succ, // oid
cast_succ, //rawhex
cast_succ, // rawid
cast_succ, // oracledate
cast_succ, // odate
cast_succ, // otimestamp
cast_succ, // otimestamptz
cast_succ, // odaysecond
cast_succ, // oyearmonth
},
{
// upper -> ***
func_num_json_null, // j_null
cast_succ, // decimal
cast_succ, // int
cast_succ, // uint
cast_succ, // double
func_upper_json_string, // string
cast_succ, //object
cast_succ, //array
cast_succ, // boolean
cast_succ, // date
cast_succ, //time
cast_succ, // datetime
cast_succ, //timestamp
cast_succ, // opaque
cast_succ, // empty
cast_succ, //ofloat
cast_succ, // odouble
cast_succ, // odeciaml
cast_succ, // oint
cast_succ, // olong
cast_succ, // obinary
cast_succ, // oid
cast_succ, //rawhex
cast_succ, // rawid
cast_succ, // oracledate
cast_succ, // odate
cast_succ, // otimestamp
cast_succ, // otimestamptz
cast_succ, // odaysecond
cast_succ, // oyearmonth
},
};
// ItemJsonCompare
int OB_JSON_QUERY_ITEM_METHOD_NULL_OPTION[ObMaxItemMethod][ObMaxJsonType] =
{
{
// abs -> **
0, // null
0, // decimal
0, // int
0, // uint
0, // double
0, // string
0, //object
0, //array
0, // boolean
0, // date
0, //time
0, // datetime
0, //timestamp
0, // opaque
0, // empty
0, //ofloat
0, // odouble
0, // odeciaml
0, // oint
0, // olong
0, // obinary
0, // oid
0, //rawhex
0, // rawid
0, // oracledate
0, // odate
0, // otimestamp
0, // otimestamptz
0, // odaysecond
0, // oyearmonth
},
{
// boolean - > ***
1, // null
1, // decimal
1, // int
1, // uint
1, // double
0, // string
0, //object
0, //array
0, // boolean
0, // date
0, //time
0, // datetime
0, //timestamp
0, // opaque
0, // empty
1, //ofloat
1, // odouble
1, // odeciaml
1, // oint
1, // olong
0, // obinary
0, // oid
0, //rawhex
0, // rawid
0, // oracledate
0, // odate
0, // otimestamp
0, // otimestamptz
0, // odaysecond
0, // oyearmonth
},
{
// bool_only -> ***
0, // null
0, // decimal
0, // int
0, // uint
0, // double
0, // string
0, //object
0, //array
0, // boolean
0, // date
0, //time
0, // datetime
0, //timestamp
0, // opaque
0, // empty
0, //ofloat
0, // odouble
0, // odeciaml
0, // oint
0, // olong
0, // obinary
0, // oid
0, //rawhex
0, // rawid
0, // oracledate
0, // odate
0, // otimestamp
0, // otimestamptz
0, // odaysecond
0, // oyearmonth
},
{
// ceiling -> **
0, // null
0, // decimal
0, // int
0, // uint
0, // double
0, // string
0, //object
0, //array
0, // boolean
0, // date
0, //time
0, // datetime
0, //timestamp
0, // opaque
0, // empty
0, //ofloat
0, // odouble
0, // odeciaml
0, // oint
0, // olong
0, // obinary
0, // oid
0, //rawhex
0, // rawid
0, // oracledate
0, // odate
0, // otimestamp
0, // otimestamptz
0, // odaysecond
0, // oyearmonth
},
{
// date -> ***
1, // null
1, // decimal
1, // int
1, // uint
1, // double
1, // string
1, //object
1, //array
1, // boolean
0, // date
0, //time
0, // datetime
0, //timestamp
1, // opaque
1, // empty
1, //ofloat
1, // odouble
1, // odeciaml
1, // oint
1, // olong
1, // obinary
1, // oid
1, //rawhex
1, // rawid
0, // oracledate
0, // odate
0, // otimestamp
0, // otimestamptz
1, // odaysecond
1, // oyearmonth
},
{
// double -> ***
0, // null
0, // decimal
0, // int
0, // uint
0, // double
1, // string
1, //object
1, //array
1, // boolean
1, // date
1, //time
1, // datetime
1, //timestamp
1, // opaque
1, // empty
0, //ofloat
0, // odouble
0, // odeciaml
0, // oint
0, // olong
1, // obinary
1, // oid
1, //rawhex
1, // rawid
1, // oracledate
1, // odate
1, // otimestamp
1, // otimestamptz
1, // odaysecond
1, // oyearmonth
},
{
// floor ->**
0, // null
0, // decimal
0, // int
0, // uint
0, // double
0, // string
0, //object
0, //array
0, // boolean
0, // date
0, //time
0, // datetime
0, //timestamp
0, // opaque
0, // empty
0, //ofloat
0, // odouble
0, // odeciaml
0, // oint
0, // olong
0, // obinary
0, // oid
0, //rawhex
0, // rawid
0, // oracledate
0, // odate
0, // otimestamp
0, // otimestamptz
0, // odaysecond
0, // oyearmonth
},
{
// length -> **
1, // null
1, // decimal
1, // int
0, // uint
1, // double
1, // string
1, //object
1, //array
1, // boolean
1, // date
1, //time
1, // datetime
1, //timestamp
1, // opaque
1, // empty
1, //ofloat
1, // odouble
1, // odeciaml
1, // oint
1, // olong
1, // obinary
1, // oid
1, //rawhex
1, // rawid
1, // oracledate
1, // odate
1, // otimestamp
1, // otimestamptz
1, // odaysecond
1, // oyearmonth
},
{
// lower -> ***
0, // null
0, // decimal
0, // int
0, // uint
0, // double
0, // string
1, //object
1, //array
0, // boolean
0, // date
0, //time
0, // datetime
0, //timestamp
0, // opaque
0, // empty
0, //ofloat
0, // odouble
0, // odeciaml
0, // oint
0, // olong
0, // obinary
0, // oid
0, //rawhex
0, // rawid
0, // oracledate
0, // odate
0, // otimestamp
0, // otimestamptz
0, // odaysecond
0, // oyearmonth
},
{
// number ->
0, // null
0, // decimal
0, // int
0, // uint
0, // double
1, // string
1, //object
1, //array
1, // boolean
1, // date
1, //time
1, // datetime
1, //timestamp
1, // opaque
1, // empty
0, //ofloat
0, // odouble
0, // odeciaml
0, // oint
0, // olong
1, // obinary
1, // oid
1, //rawhex
1, // rawid
1, // oracledate
1, // odate
1, // otimestamp
1, // otimestamptz
1, // odaysecond
1, // oyearmonth
},
{
// num_only -> ***
0, // null
0, // decimal
0, // int
0, // uint
0, // double
1, // string
1, //object
1, //array
1, // boolean
1, // date
1, //time
1, // datetime
1, //timestamp
1, // opaque
1, // empty
0, //ofloat
0, // odouble
0, // odeciaml
0, // oint
0, // olong
1, // obinary
1, // oid
1, //rawhex
1, // rawid
1, // oracledate
1, // odate
1, // otimestamp
1, // otimestamptz
1, // odaysecond
1, // oyearmonth
},
{
// size ->**
0, // j_null
0, // decimal
0, // int
0, // uint
0, // double
0, // string
0, //object
0, //array
0, // boolean
0, // date
0, //time
0, // datetime
0, //timestamp
0, // opaque
0, // empty
0, //ofloat
0, // odouble
0, // odeciaml
0, // oint
0, // olong
0, // obinary
0, // oid
0, //rawhex
0, // rawid
0, // oracledate
0, // odate
0, // otimestamp
0, // otimestamptz
0, // odaysecond
0, // oyearmonth
},
{
// string-> ***
0, // null
0, // decimal
0, // int
0, // uint
0, // double
0, // string
1, //object
1, //array
0, // boolean
0, // date
0, //time
0, // datetime
0, //timestamp
0, // opaque
0, // empty
0, //ofloat
0, // odouble
0, // odeciaml
0, // oint
0, // olong
0, // obinary
0, // oid
0, //rawhex
0, // rawid
0, // oracledate
0, // odate
0, // otimestamp
0, // otimestamptz
0, // odaysecond
0, // oyearmonth
},
{
// str_only -> ***
0, // null
0, // decimal
0, // int
0, // uint
0, // double
0, // string
1, //object
1, //array
0, // boolean
0, // date
0, //time
0, // datetime
0, //timestamp
0, // opaque
0, // empty
0, //ofloat
0, // odouble
0, // odeciaml
0, // oint
0, // olong
0, // obinary
0, // oid
0, //rawhex
0, // rawid
0, // oracledate
0, // odate
0, // otimestamp
0, // otimestamptz
0, // odaysecond
0, // oyearmonth
},
{
// timestamp -> ***
1, // null
1, // decimal
1, // int
1, // uint
1, // double
1, // string
1, //object
1, //array
1, // boolean
0, // date
0, //time
0, // datetime
0, //timestamp
1, // opaque
1, // empty
1, //ofloat
1, // odouble
1, // odeciaml
1, // oint
1, // olong
1, // obinary
1, // oid
1, //rawhex
1, // rawid
0, // oracledate
0, // odate
0, // otimestamp
0, // otimestamptz
1, // odaysecond
1, // oyearmonth
},
{
// type ->**
0, // j_null
0, // decimal
0, // int
0, // uint
0, // double
0, // string
0, //object
0, //array
0, // boolean
0, // date
0, //time
0, // datetime
0, //timestamp
0, // opaque
0, // empty
0, //ofloat
0, // odouble
0, // odeciaml
0, // oint
0, // olong
0, // obinary
0, // oid
0, //rawhex
0, // rawid
0, // oracledate
0, // odate
0, // otimestamp
0, // otimestamptz
0, // odaysecond
0, // oyearmonth
},
{
// upper -> ***
0, // null
0, // decimal
0, // int
0, // uint
0, // double
0, // string
1, //object
1, //array
0, // boolean
0, // date
0, //time
0, // datetime
0, //timestamp
0, // opaque
0, // empty
0, //ofloat
0, // odouble
0, // odeciaml
0, // oint
0, // olong
0, // obinary
0, // oid
0, //rawhex
0, // rawid
0, // oracledate
0, // odate
0, // otimestamp
0, // otimestamptz
0, // odaysecond
0, // oyearmonth
},
};
int ObJsonUtil::get_query_item_method_null_option(ObJsonPath* j_path,
ObIJsonBase* j_base)
{
size_t item_method = static_cast<uint8_t>(j_path->get_last_node_type());
size_t json_type = static_cast<uint8_t>(j_base->json_type());
int is_null_res = 0;
// first item method pos is JPN_ABS
if (!j_path->is_last_func()) {
// do nothing
} else {
is_null_res = OB_JSON_QUERY_ITEM_METHOD_NULL_OPTION[item_method - ObJsonPathNodeType::JPN_ABS][json_type];
}
return is_null_res;
}
ObJsonUtil::ObItemMethodValid ObJsonUtil::get_item_method_cast_res_func(ObJsonPath* j_path,
ObIJsonBase* j_base)
{
INIT_SUCC(ret);
size_t item_method = static_cast<uint8_t>(j_path->get_last_node_type());
size_t json_type = static_cast<uint8_t>(j_base->json_type());
// first item method pos is 13
return OB_JSON_VALUE_ITEM_METHOD_CAST_FUNC[item_method - ObJsonPathNodeType::JPN_ABS][json_type];
}
/*
ObJsonUtil::ObJsonCastSqlObj ObJsonUtil::get_json_obj_cast_func(ObObjType dst_type)
{
return OB_JSON_CAST_OBJ_EXPLICIT[OBJ_TYPE_TO_CLASS[dst_type]];
}
ObJsonUtil::ObJsonCastSqlDatum ObJsonUtil::get_json_datum_cast_func(ObObjType dst_type)
{
return OB_JSON_CAST_DATUM_EXPLICIT[OBJ_TYPE_TO_CLASS[dst_type]];
}
*/
ObJsonUtil::ObJsonCastSqlScalar ObJsonUtil::get_json_cast_func(ObObjType dst_type)
{
return OB_JSON_CAST_SQL_EXPLICIT[OBJ_TYPE_TO_CLASS[dst_type]];
}
bool ObJsonUtil::is_number_item_method(ObJsonPath* j_path)
{
return j_path->get_last_node_type() == JPN_NUMBER
|| j_path->get_last_node_type() == JPN_NUM_ONLY
|| j_path->get_last_node_type() == JPN_LENGTH
|| j_path->get_last_node_type() == JPN_TYPE
|| j_path->get_last_node_type() == JPN_SIZE;
}
} // sql
} // oceanbase