diff --git a/deps/oblib/src/lib/json_type/ob_json_base.cpp b/deps/oblib/src/lib/json_type/ob_json_base.cpp index 3c30f6d77e..8a535432c2 100644 --- a/deps/oblib/src/lib/json_type/ob_json_base.cpp +++ b/deps/oblib/src/lib/json_type/ob_json_base.cpp @@ -5130,7 +5130,7 @@ int ObIJsonBase::to_uint(uint64_t &value, bool fail_on_negative, bool check_rang int err = 0; char *endptr = NULL; bool is_unsigned = true; - if (OB_ISNULL(data)) { + if (OB_ISNULL(data) || length == 0) { ret = OB_ERR_NULL_VALUE; LOG_WARN("data is null", K(ret)); } else if (data[0] == '-') { diff --git a/src/share/ob_fts_index_builder_util.cpp b/src/share/ob_fts_index_builder_util.cpp index 0dcb5889f3..330aeb84a8 100644 --- a/src/share/ob_fts_index_builder_util.cpp +++ b/src/share/ob_fts_index_builder_util.cpp @@ -2210,7 +2210,7 @@ int ObMulValueIndexBuilderUtil::generate_multivalue_column( if (OB_FAIL(ret)) { //do nothing } else if (OB_FAIL(databuff_printf(col_name_buf, OB_MAX_COLUMN_NAMES_LENGTH, pos, - "__mvi_%ld", /*naming rules are compatible with oracle*/ + "SYS_NC_mvi_%ld", /*naming rules are compatible with oracle*/ multival_col.get_column_id()))) { LOG_WARN("print generate column prefix name failed", K(ret)); } else if (OB_FAIL(multival_col.set_column_name(col_name_buf))) { @@ -2248,7 +2248,7 @@ int ObMulValueIndexBuilderUtil::generate_multivalue_column( multival_arr_col.set_accuracy(ObAccuracy::DDL_DEFAULT_ACCURACY[ObJsonType]); if (OB_FAIL(databuff_printf(col_name_buf, OB_MAX_COLUMN_NAMES_LENGTH, pos, - "__mvi_arr_%ld", /*naming rules are compatible with oracle*/ + "SYS_NC_mvi_arr_%ld", /*naming rules are compatible with oracle*/ multival_arr_col.get_column_id()))) { LOG_WARN("print generate column prefix name failed", K(ret)); } else if (OB_FAIL(multival_arr_col.set_column_name(col_name_buf))) { diff --git a/src/sql/engine/expr/ob_expr_json_contains.cpp b/src/sql/engine/expr/ob_expr_json_contains.cpp index 7767226b18..401e7d175c 100644 --- a/src/sql/engine/expr/ob_expr_json_contains.cpp +++ b/src/sql/engine/expr/ob_expr_json_contains.cpp @@ -49,11 +49,6 @@ int ObExprJsonContains::calc_result_typeN(ObExprResType& type, type.set_precision(DEFAULT_PRECISION_FOR_BOOL); type.set_scale(ObAccuracy::DDL_DEFAULT_ACCURACY[ObIntType].scale_); - if (ob_is_string_type(types_stack[1].get_type())) { - types_stack[1].set_calc_type(ObJsonType); - types_stack[1].set_calc_collation_type(CS_TYPE_UTF8MB4_BIN); - } - // set type for json_path if (OB_SUCC(ret) && param_num == 3) { if (OB_FAIL(ObJsonExprHelper::is_valid_for_path(types_stack, 2))) { diff --git a/src/sql/engine/expr/ob_expr_json_func_helper.cpp b/src/sql/engine/expr/ob_expr_json_func_helper.cpp index e90e071e50..0693b9928e 100644 --- a/src/sql/engine/expr/ob_expr_json_func_helper.cpp +++ b/src/sql/engine/expr/ob_expr_json_func_helper.cpp @@ -422,7 +422,7 @@ int ObJsonExprHelper::get_json_val(const common::ObObj &data, ObExecContext *ctx ObCollationType cs_type = data.get_collation_type(); if (OB_FAIL(ObJsonExprHelper::transform_convertible_2jsonBase(data, val_type, allocator, cs_type, j_base, ObConv2JsonParam(to_bin, - data.has_lob_header(), false)))) { + data.has_lob_header(), false, false, true, true)))) { LOG_WARN("failed: parse value to jsonBase", K(ret), K(val_type)); } } else { @@ -1680,7 +1680,17 @@ int ObJsonExprHelper::transform_convertible_2jsonBase(const T &datum, uint32_t parse_flag = flags.relax_type_ ? ObJsonParser::JSN_RELAXED_FLAG : ObJsonParser::JSN_STRICT_FLAG; ADD_FLAG_IF_NEED(flags.is_schema_, parse_flag, ObJsonParser::JSN_SCHEMA_FLAG); if(OB_FAIL(ObJsonExprHelper::cast_to_json_tree(j_str, allocator, parse_flag))) { - LOG_WARN("cast to json tree fail", K(ret)); + if (flags.wrap_on_fail_) { + if (OB_ISNULL(buf = allocator->alloc(sizeof(ObJsonString)))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("fail to allocate json string", K(ret)); + } else { + ret = OB_SUCCESS; + json_node = (ObJsonString*)new(buf)ObJsonString(j_str.ptr(), j_str.length()); + } + } else { + LOG_WARN("cast to json tree fail", K(ret)); + } } else { ObJsonInType to_type = flags.to_bin_ ? ObJsonInType::JSON_BIN : ObJsonInType::JSON_TREE; if (OB_FAIL(ObJsonBaseFactory::get_json_base(allocator, j_str, ObJsonInType::JSON_TREE, @@ -1693,13 +1703,11 @@ int ObJsonExprHelper::transform_convertible_2jsonBase(const T &datum, } } } else { - uint64_t len = j_str.length(); - const char *ptr = j_str.ptr(); - buf = allocator->alloc(sizeof(ObJsonString)); - if (OB_ISNULL(buf)) { + if (OB_ISNULL(buf = allocator->alloc(sizeof(ObJsonString)))) { ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("fail to allocate json string", K(ret)); } else { - json_node = (ObJsonString*)new(buf)ObJsonString(ptr, len); + json_node = (ObJsonString*)new(buf)ObJsonString(j_str.ptr(), j_str.length()); } } } diff --git a/src/sql/engine/expr/ob_expr_json_func_helper.h b/src/sql/engine/expr/ob_expr_json_func_helper.h index 75067d09b1..e1a169d7ab 100644 --- a/src/sql/engine/expr/ob_expr_json_func_helper.h +++ b/src/sql/engine/expr/ob_expr_json_func_helper.h @@ -154,12 +154,22 @@ struct ObConv2JsonParam { format_json_(format_json), is_schema_(is_schema) {} + + ObConv2JsonParam(bool to_bin, bool has_lob_header, bool deep_copy, bool relax_type, bool format_json, bool is_schema, bool is_wrap_fail) : + to_bin_(to_bin), + has_lob_header_(has_lob_header), + deep_copy_(deep_copy), + relax_type_(relax_type), + format_json_(format_json), + is_schema_(is_schema), + wrap_on_fail_(is_wrap_fail) {} bool to_bin_; bool has_lob_header_; bool deep_copy_ = false; bool relax_type_ = true; bool format_json_ = false; bool is_schema_ = false; + bool wrap_on_fail_ = false; }; class ObJsonExprHelper final diff --git a/src/sql/engine/expr/ob_expr_json_overlaps.cpp b/src/sql/engine/expr/ob_expr_json_overlaps.cpp index ee9e608c5f..32f1a37175 100644 --- a/src/sql/engine/expr/ob_expr_json_overlaps.cpp +++ b/src/sql/engine/expr/ob_expr_json_overlaps.cpp @@ -39,20 +39,11 @@ int ObExprJsonOverlaps::calc_result_type2(ObExprResType &type, { UNUSED(type_ctx); int ret = OB_SUCCESS; + bool is_strict = false; type.set_int32(); type.set_precision(DEFAULT_PRECISION_FOR_BOOL); type.set_scale(ObAccuracy::DDL_DEFAULT_ACCURACY[ObIntType].scale_); - - if (ob_is_string_type(type1.get_type()) && type1.get_collation_type() != CS_TYPE_BINARY) { - type1.set_calc_type(ObJsonType); - type1.set_calc_collation_type(CS_TYPE_UTF8MB4_BIN); - } - - if (ob_is_string_type(type2.get_type()) && type2.get_collation_type() != CS_TYPE_BINARY) { - type2.set_calc_type(ObJsonType); - type2.set_calc_collation_type(CS_TYPE_UTF8MB4_BIN); - } return ret; } diff --git a/src/sql/engine/expr/ob_expr_json_query.cpp b/src/sql/engine/expr/ob_expr_json_query.cpp index 4f29203aec..1dcad334f9 100644 --- a/src/sql/engine/expr/ob_expr_json_query.cpp +++ b/src/sql/engine/expr/ob_expr_json_query.cpp @@ -149,13 +149,10 @@ int ObExprJsonQuery::calc_returning_type(ObExprResType& type, } } else if (OB_FAIL(ObJsonExprHelper::get_cast_type(types_stack[JSN_QUE_RET], dst_type, type_ctx))) { LOG_WARN("get cast dest type failed", K(ret)); - } else if (!is_asis && - dst_type.get_type() != ObVarcharType - && dst_type.get_type() != ObLongTextType - && dst_type.get_type() != ObJsonType) { - ret = OB_ERR_INVALID_DATA_TYPE_RETURNING; - LOG_USER_ERROR(OB_ERR_INVALID_DATA_TYPE_RETURNING); + } else if (OB_FAIL(check_data_type_allowed(types_stack, dst_type))) { + LOG_WARN("check dest type failed", K(ret)); } + if (OB_SUCC(ret)) { if (OB_FAIL(ObJsonExprHelper::set_dest_type(types_stack[JSN_QUE_DOC], type, dst_type, type_ctx))) { LOG_WARN("set dest type failed", K(ret)); @@ -166,6 +163,29 @@ int ObExprJsonQuery::calc_returning_type(ObExprResType& type, return ret; } +int ObExprJsonQuery::check_data_type_allowed(const ObExprResType* types_stack, const ObExprResType& data_type) +{ + int ret = OB_SUCCESS; + bool is_asis = types_stack[JSN_QUE_ASIS].get_param().get_int() > 0; + bool is_multivalue = types_stack[JSN_QUE_MULTIVALUE].get_param().get_int() > 0; + + // multivalue genreated column __mvi_%ld + if (!is_asis && data_type.get_type() != ObVarcharType + && data_type.get_type() != ObLongTextType + && data_type.get_type() != ObJsonType) { + ret = OB_ERR_INVALID_DATA_TYPE_RETURNING; + LOG_USER_ERROR(OB_ERR_INVALID_DATA_TYPE_RETURNING); + } else if (is_asis && !is_multivalue) { + if (data_type.get_type() == ObCharType && + (data_type.get_length() > OB_MAX_CAST_CHAR_VARCHAR_LENGTH || data_type.get_length() == -1)) { + ret = OB_NOT_MULTIVALUE_SUPPORT; + LOG_USER_ERROR(OB_NOT_MULTIVALUE_SUPPORT, "CAST-ing data to array of char/binary BLOBs"); + } + } + + return ret; +} + int ObExprJsonQuery::extract_plan_cache_param(const ObExprJsonQueryParamInfo *info, ObJsonExprParam& json_param) { INIT_SUCC(ret); @@ -376,7 +396,7 @@ int ObExprJsonQuery::check_enable_cast_index_array(ObIJsonBase* json_base, bool } else if (json_base->json_type() == ObJsonNodeType::J_BOOLEAN) { ret = OB_NOT_MULTIVALUE_SUPPORT; LOG_USER_ERROR(OB_NOT_MULTIVALUE_SUPPORT, "CAST-ing JSON BOOLEAN type to array"); - } else if (!disable_container && json_base->json_type() == ObJsonNodeType::J_OBJECT) { + } else if (json_base->json_type() == ObJsonNodeType::J_OBJECT) { ret = OB_NOT_MULTIVALUE_SUPPORT; LOG_USER_ERROR(OB_NOT_MULTIVALUE_SUPPORT, "CAST-ing JSON OBJECT type to array"); } @@ -544,8 +564,8 @@ int ObExprJsonQuery::set_multivalue_result(ObEvalCtx& ctx, dst_collation, accuracy, dest_type, tmp_obj))) { LOG_WARN("failed to cast to res", K(ret), K(dest_type)); - ret = OB_ERR_JSON_VALUE_CAST_FUNCTION_INDEX; - LOG_USER_ERROR(OB_ERR_JSON_VALUE_CAST_FUNCTION_INDEX); + ret = OB_ERR_JSON_CONTAINER_CAST_SCALAR; + LOG_USER_ERROR(OB_ERR_JSON_CONTAINER_CAST_SCALAR); } else if (FALSE_IT(reserve_len = tmp_obj.get_serialize_size())) { } else if (OB_FAIL(str_buff.reserve(reserve_len + 128))) { LOG_WARN("failed to reserve size", K(ret), K(reserve_len)); diff --git a/src/sql/engine/expr/ob_expr_json_query.h b/src/sql/engine/expr/ob_expr_json_query.h index a57f6437e9..c29e8fed38 100644 --- a/src/sql/engine/expr/ob_expr_json_query.h +++ b/src/sql/engine/expr/ob_expr_json_query.h @@ -153,8 +153,10 @@ public: bool use_wrapper); static int get_error_option(int8_t &error_type, ObIJsonBase *&error_val, ObIJsonBase *jb_arr, ObIJsonBase *jb_obj, bool &is_null); static int get_mismatch_option(int8_t &mismatch_type, int &ret); - static int init_ctx_var(ObJsonParamCacheCtx*& param_ctx, const ObExpr &expr); static int extract_plan_cache_param(const ObExprJsonQueryParamInfo *info, ObJsonExprParam& json_param); - /* code from ob_expr_cast for cal_result_type */ + static int init_ctx_var(ObJsonParamCacheCtx*& param_ctx, const ObExpr &expr); + static int extract_plan_cache_param(const ObExprJsonQueryParamInfo *info, ObJsonExprParam& json_param); + static int check_data_type_allowed(const ObExprResType* types_stack, const ObExprResType& data_type); + /* code from ob_expr_cast for cal_result_type */ const static int32_t OB_LITERAL_MAX_INT_LEN = 21; DISALLOW_COPY_AND_ASSIGN(ObExprJsonQuery); diff --git a/src/sql/rewrite/ob_query_range.cpp b/src/sql/rewrite/ob_query_range.cpp index 098dd9edbf..654feba39f 100644 --- a/src/sql/rewrite/ob_query_range.cpp +++ b/src/sql/rewrite/ob_query_range.cpp @@ -4182,7 +4182,13 @@ int ObQueryRange::get_contain_or_overlaps_keyparts(const common::ObObj &const_pa } } else if (j_base->json_type() == common::ObJsonNodeType::J_ARRAY) { int size = j_base->element_count(); - if (size > MAX_JSON_ARRAY_CHANGE_TO_OR_SIZE && is_single_op + if (size == 0) { + if (OB_FAIL(set_normal_key_true_or_false(out_key_part, true))) { + LOG_WARN("failed set normal key", K(ret)); + } else if (OB_NOT_NULL(query_range_ctx_)) { + query_range_ctx_->cur_expr_is_precise_ = false; + } + } else if (size > MAX_JSON_ARRAY_CHANGE_TO_OR_SIZE && is_single_op && (OB_NOT_NULL(query_range_ctx_) && query_range_ctx_->use_in_optimization_)) { if (OB_FAIL(get_json_array_in_keyparts(j_base, out_key_part, exec_ctx, dtc_params))) { LOG_WARN("fail to get json_array in keyparts", K(ret)); diff --git a/src/storage/ob_parallel_external_sort.h b/src/storage/ob_parallel_external_sort.h index e9010f435d..88c899a3b6 100644 --- a/src/storage/ob_parallel_external_sort.h +++ b/src/storage/ob_parallel_external_sort.h @@ -1633,7 +1633,9 @@ int ObMemorySortRound::get_next_item(const T *&item) ret = common::OB_ERR_UNEXPECTED; STORAGE_LOG(WARN, "error unexpected, iter must not be null", K(ret), KP(iter_)); } else if (OB_FAIL(iter_->get_next_item(item))) { - STORAGE_LOG(WARN, "fail to get next item", K(ret)); + if (ret != OB_ITER_END) { + STORAGE_LOG(WARN, "fail to get next item", K(ret)); + } } } return ret;