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 56d3f28655..b8fefb15b0 100644 --- a/deps/oblib/src/lib/json_type/ob_json_base.cpp +++ b/deps/oblib/src/lib/json_type/ob_json_base.cpp @@ -4934,9 +4934,9 @@ int ObIJsonBase::to_int(int64_t &value, bool check_range, bool force_convert) co ret = OB_ERR_DATA_TRUNCATED; LOG_WARN("fail to cast string to int", K(ret), K(length), KCSTRING(start)); } + value = val; } } - break; } @@ -5079,6 +5079,7 @@ int ObIJsonBase::to_uint(uint64_t &value, bool fail_on_negative, bool check_rang } } } + value = val; break; } @@ -5207,6 +5208,7 @@ int ObIJsonBase::to_double(double &value) const LOG_DEBUG("check_convert_str_err", K(length), K(data - endptr)); } } + value = val; } } } @@ -5285,6 +5287,7 @@ int ObIJsonBase::to_number(ObIAllocator *allocator, number::ObNumber &number) co } else if (OB_FAIL(num.from(data, length, *allocator))) { LOG_WARN("fail to create number from string", K(ret), KP(data)); } + number = num; break; } @@ -5429,6 +5432,31 @@ int ObIJsonBase::to_datetime(int64_t &value, ObTimeConvertCtx *cvrt_ctx_t) const break; } + case ObJsonNodeType::J_UINT: + case ObJsonNodeType::J_OLONG: { + ObArenaAllocator tmp_allocator; + ObJsonBuffer str_data(&tmp_allocator); + if (OB_FAIL(print(str_data, false))) { + LOG_WARN("fail to print string date", K(ret)); + } else if (OB_ISNULL(str_data.ptr())) { + ret = OB_ERR_NULL_VALUE; + LOG_WARN("data is null", K(ret)); + } else { + ObString str = str_data.string(); + ObTimeConvertCtx cvrt_ctx(NULL, false); + if (lib::is_oracle_mode() && OB_NOT_NULL(cvrt_ctx_t)) { + ObTimeConvertCtx cvrt_ctx(cvrt_ctx_t->tz_info_, cvrt_ctx_t->oracle_nls_format_, false); + if (OB_FAIL(ObTimeConverter::str_to_date_oracle(str, cvrt_ctx, datetime))) { + LOG_WARN("oracle fail to cast string to date", K(ret), K(str)); + } + } else { + if (OB_FAIL(ObTimeConverter::str_to_datetime(str, cvrt_ctx, datetime))) { + LOG_WARN("fail to cast string to datetime", K(ret), K(str)); + } + } + } + break; + } case ObJsonNodeType::J_STRING: { uint64_t length = get_data_length(); const char *data = get_data(); @@ -5438,7 +5466,7 @@ int ObIJsonBase::to_datetime(int64_t &value, ObTimeConvertCtx *cvrt_ctx_t) const } else { ObString str(static_cast(length), static_cast(length), data); ObTimeConvertCtx cvrt_ctx(NULL, false); - if (lib::is_oracle_mode() && !OB_ISNULL(cvrt_ctx_t)) { + if (lib::is_oracle_mode() && OB_NOT_NULL(cvrt_ctx_t)) { ObTimeConvertCtx cvrt_ctx(cvrt_ctx_t->tz_info_, cvrt_ctx_t->oracle_nls_format_, false); if (OB_FAIL(ObTimeConverter::str_to_date_oracle(str, cvrt_ctx, datetime))) { LOG_WARN("oracle fail to cast string to date", K(ret), K(str)); diff --git a/src/share/object/ob_obj_cast.cpp b/src/share/object/ob_obj_cast.cpp index f2bda09b3f..4d8304a504 100644 --- a/src/share/object/ob_obj_cast.cpp +++ b/src/share/object/ob_obj_cast.cpp @@ -6000,20 +6000,30 @@ static int string_json(const ObObjType expect_type, ObObjCastParams ¶ms, ObJsonNull j_null; ObJsonNode *j_tree = NULL; uint32_t parse_flag = ObJsonParser::JSN_RELAXED_FLAG; + bool is_oracle = lib::is_oracle_mode(); + ObObjType in_type = in.get_type(); + bool is_convert_jstr_type = (in_type == ObTinyTextType + || in_type == ObTextType + || in_type == ObMediumTextType + || in_type == ObLongTextType); if (expect_type == ObJsonType && j_text.length() == 0 && cast_mode == 0) { // add column json null j_base = &j_null; - } else if (lib::is_oracle_mode() && (OB_ISNULL(j_text.ptr()) || j_text.length() == 0)) { + } else if (is_oracle && (OB_ISNULL(j_text.ptr()) || j_text.length() == 0)) { j_base = &j_null; - } else if (lib::is_mysql_mode() && CS_TYPE_BINARY == in.get_collation_type()) { + } else if (!is_oracle && CS_TYPE_BINARY == in.get_collation_type()) { j_base = &j_opaque; - } else if (lib::is_mysql_mode() - && CM_IS_IMPLICIT_CAST(cast_mode) && !CM_IS_COLUMN_CONVERT(cast_mode) - && !CM_IS_JSON_VALUE(cast_mode) && ob_is_string_type(in.get_type())) { + } else if (!is_oracle + && CM_IS_IMPLICIT_CAST(cast_mode) + && !CM_IS_COLUMN_CONVERT(cast_mode) + && !CM_IS_JSON_VALUE(cast_mode) + && is_convert_jstr_type) { // consistent with mysql: TINYTEXT, TEXT, MEDIUMTEXT, and LONGTEXT. We want to treat them like strings ret = OB_SUCCESS; j_base = &j_string; } else if (OB_FAIL(ObJsonParser::get_tree(params.allocator_v2_, j_text, j_tree, parse_flag))) { - if (lib::is_mysql_mode() && CM_IS_IMPLICIT_CAST(cast_mode) && !CM_IS_COLUMN_CONVERT(cast_mode)) { + if (!is_oracle && CM_IS_IMPLICIT_CAST(cast_mode) + && !CM_IS_COLUMN_CONVERT(cast_mode) + && is_convert_jstr_type) { ret = OB_SUCCESS; j_base = &j_string; } else { diff --git a/src/sql/engine/basic/ob_json_table_op.cpp b/src/sql/engine/basic/ob_json_table_op.cpp index a87793ecdc..756daa4d74 100644 --- a/src/sql/engine/basic/ob_json_table_op.cpp +++ b/src/sql/engine/basic/ob_json_table_op.cpp @@ -762,14 +762,18 @@ int JtFuncHelpler::cast_to_number(common::ObIAllocator *allocator, int JtFuncHelpler::cast_to_bit(ObIJsonBase *j_base, uint64_t &val, common::ObAccuracy &accuracy) { INIT_SUCC(ret); - + int64_t int_val; if (OB_ISNULL(j_base)) { ret = OB_ERR_NULL_VALUE; LOG_WARN("json base is null", K(ret)); - } else if (OB_FAIL(j_base->to_bit(val))) { - LOG_WARN("fail get bit from json", K(ret)); - } else if (OB_FAIL(bit_length_check(accuracy, val))) { - LOG_WARN("fail to check bit range", K(ret)); + } else if (OB_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(int_val); + if (OB_FAIL(bit_length_check(accuracy, val))) { + LOG_WARN("fail to check bit range", K(ret)); + } } return ret; @@ -1051,7 +1055,7 @@ int JtFuncHelpler::cast_json_to_res(JtScanCtx* ctx, ObIJsonBase* js_val, JtColNo LOG_WARN("failed to set error val.", K(tmp_ret)); } } else { - res.set_bit(out_val); + res.set_uint(out_val); } break; } @@ -2009,15 +2013,32 @@ int JtColNode::get_default_value_pre_mysql(ObExpr* default_expr, } else { ObBasicSessionInfo *session = ctx->exec_ctx_->get_my_session(); ObIJsonBase* tmp_node = nullptr; - const ObDatum& datum = *tmp_datum; + ObObjType val_type = default_expr->datum_meta_.type_; + ObCollationType cs_type = default_expr->datum_meta_.cs_type_; + // const ObDatum& datum = *tmp_datum; + ObDatum converted_datum; + converted_datum.set_datum(*tmp_datum); + // convert string charset if needed + if (ob_is_string_type(val_type) + && (ObCharset::charset_type_by_coll(cs_type) != CHARSET_UTF8MB4)) { + ObString origin_str = converted_datum.get_string(); + ObString converted_str; + if (OB_FAIL(ObExprUtil::convert_string_collation(origin_str, cs_type, converted_str, + CS_TYPE_UTF8MB4_BIN, ctx->row_alloc_))) { + LOG_WARN("convert string collation failed", K(ret), K(cs_type), K(origin_str.length())); + } else { + converted_datum.set_string(converted_str); + cs_type = CS_TYPE_UTF8MB4_BIN; + } + } if (OB_FAIL(check_default_cast_allowed(default_expr))) { LOG_WARN("check default value can't cast return type", K(ret), K(default_expr->datum_meta_)); - } else if (ObJsonExprHelper::is_convertible_to_json(default_expr->datum_meta_.type_)) { - if (OB_FAIL(ObJsonExprHelper::transform_convertible_2jsonBase(datum, - default_expr->datum_meta_.type_, + } else if (ObJsonExprHelper::is_convertible_to_json(val_type)) { + if (OB_FAIL(ObJsonExprHelper::transform_convertible_2jsonBase(converted_datum, + val_type, &ctx->row_alloc_, - default_expr->datum_meta_.cs_type_, + cs_type, res, false, default_expr->obj_meta_.has_lob_header(), false, lib::is_oracle_mode(), true)) @@ -2025,7 +2046,7 @@ int JtColNode::get_default_value_pre_mysql(ObExpr* default_expr, ret = OB_INVALID_DEFAULT; LOG_USER_ERROR(OB_INVALID_DEFAULT, col_info_.col_name_.length(), col_info_.col_name_.ptr()); } - } else if (OB_FAIL(ObJsonExprHelper::transform_scalar_2jsonBase(datum, + } else if (OB_FAIL(ObJsonExprHelper::transform_scalar_2jsonBase(converted_datum, default_expr->datum_meta_.type_, &ctx->row_alloc_, default_expr->datum_meta_.scale_, @@ -2118,6 +2139,9 @@ int JtColNode::get_next_row(ObIJsonBase* in, JtScanCtx* ctx, bool& is_null_value bool need_pro_emtpy = false; if (lib::is_mysql_mode() && OB_ISNULL(in)) { + in_ = in; + need_cast_res = false; + curr_ = iter_ = nullptr; col_expr->locate_datum_for_write(*ctx->eval_ctx_).set_null(); } else if (col_type == COL_TYPE_ORDINALITY) { if (OB_ISNULL(in)) { @@ -2525,6 +2549,7 @@ int JtScanNode::get_next_row(ObIJsonBase* in, JtScanCtx* ctx, bool& is_null_valu } } else if (is_cur_end) { if (!is_curr_row_valid) { + reset_reg_columns(ctx); ret = OB_ITER_END; } is_sub_evaled_ = true; @@ -3230,10 +3255,20 @@ int ObJsonTableOp::inner_close() void ObJsonTableOp::reset_columns() { for (size_t i = 0; i < col_count_; ++i) { - ObExpr* col_expr = jt_ctx_.spec_ptr_->column_exprs_.at(i); - col_expr->locate_datum_for_write(*jt_ctx_.eval_ctx_).reset(); - col_expr->locate_datum_for_write(*jt_ctx_.eval_ctx_).set_null(); - col_expr->get_eval_info(*jt_ctx_.eval_ctx_).evaluated_ = true; + ObExpr* col_expr = jt_ctx_.spec_ptr_->column_exprs_.at(i); + col_expr->locate_datum_for_write(*jt_ctx_.eval_ctx_).reset(); + col_expr->locate_datum_for_write(*jt_ctx_.eval_ctx_).set_null(); + col_expr->get_eval_info(*jt_ctx_.eval_ctx_).evaluated_ = true; + } +} + +void JtScanNode::reset_reg_columns(JtScanCtx* ctx) +{ + for (size_t i = 0; i < reg_column_count(); ++i) { + ObExpr* col_expr = ctx->spec_ptr_->column_exprs_.at(reg_col_node(i)->col_info_.output_column_idx_); + col_expr->locate_datum_for_write(*ctx->eval_ctx_).reset(); + col_expr->locate_datum_for_write(*ctx->eval_ctx_).set_null(); + col_expr->get_eval_info(*ctx->eval_ctx_).evaluated_ = true; } } diff --git a/src/sql/engine/basic/ob_json_table_op.h b/src/sql/engine/basic/ob_json_table_op.h index 13d5f76a45..d4e5dbf2f2 100644 --- a/src/sql/engine/basic/ob_json_table_op.h +++ b/src/sql/engine/basic/ob_json_table_op.h @@ -248,6 +248,7 @@ public: JtColNode* nest_col_node() { return nest_col_def_; } JtColNode* reg_col_node(size_t i) { return reg_col_defs_.at(i); } ObIArray& child_node_ref() { return child_idx_; } + void reset_reg_columns(JtScanCtx* ctx); TO_STRING_KV(K_(node_type), K_(node_idx), diff --git a/src/sql/engine/expr/ob_expr_json_array.cpp b/src/sql/engine/expr/ob_expr_json_array.cpp index b005943b44..bbb5f29f89 100644 --- a/src/sql/engine/expr/ob_expr_json_array.cpp +++ b/src/sql/engine/expr/ob_expr_json_array.cpp @@ -195,9 +195,9 @@ int ObExprJsonArray::eval_ora_json_array(const ObExpr &expr, ObEvalCtx &ctx, ObD if (OB_FAIL(ret)) { } else if (OB_FAIL(ObJsonExprHelper::eval_oracle_json_val( - expr.args_[i], ctx, &temp_allocator, j_val, is_format_json, is_strict, false))) { + expr.args_[i], ctx, &temp_allocator, j_val, is_format_json, is_strict, false, is_null_absent))) { LOG_WARN("failed to get json value node.", K(ret), K(val_type)); - } else if (is_null_absent && j_val->json_type() == ObJsonNodeType::J_NULL) { + } else if (OB_ISNULL(j_val)) { } else if (OB_FAIL(j_arr.append(static_cast(j_val)))) { LOG_WARN("failed to append in array.", K(ret), K(i)); } 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 63e7c92e43..9f09acf998 100644 --- a/src/sql/engine/expr/ob_expr_json_func_helper.cpp +++ b/src/sql/engine/expr/ob_expr_json_func_helper.cpp @@ -314,7 +314,8 @@ int ObJsonExprHelper::eval_oracle_json_val(ObExpr *expr, ObIJsonBase*& j_base, bool is_format_json, bool is_strict, - bool is_bin) + bool is_bin, + bool is_absent_null) { INIT_SUCC(ret); ObDatum *json_datum = nullptr; @@ -323,6 +324,8 @@ int ObJsonExprHelper::eval_oracle_json_val(ObExpr *expr, if (OB_FAIL(json_arg->eval(ctx, json_datum))) { LOG_WARN("eval json arg failed", K(ret), K(json_arg->datum_meta_)); + } else if ((json_datum->is_null() || ob_is_null(json_arg->obj_meta_.get_type())) + && is_absent_null) { } else if (OB_FAIL(oracle_datum2_json_val(json_datum, json_arg->obj_meta_, allocator, @@ -1598,7 +1601,7 @@ int ObJsonExprHelper::calc_asciistr_in_expr(const ObString &src, } else { buf[pos++] = '\\'; } - if (OB_SUCC(ret)) { + if (OB_SUCC(ret) && '\\' != wchar) { int64_t hex_writtern_bytes = 0; if (OB_FAIL(hex_print(temp_buf + i*utf16_minmb_len, utf16_minmb_len, buf + pos, buf_len - pos, hex_writtern_bytes))) { 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 af3d099623..7919249d5d 100644 --- a/src/sql/engine/expr/ob_expr_json_func_helper.h +++ b/src/sql/engine/expr/ob_expr_json_func_helper.h @@ -98,7 +98,7 @@ public: bool format_json = false, bool is_strict = false, bool is_bin = false); static int eval_oracle_json_val(ObExpr *expr, ObEvalCtx &ctx, common::ObIAllocator *allocator, - ObIJsonBase*& j_base, bool format_json = false, bool is_strict = false, bool is_bin = false); + ObIJsonBase*& j_base, bool format_json = false, bool is_strict = false, bool is_bin = false, bool is_absent_null = false); /* replace json_old with json_new in json_doc diff --git a/src/sql/engine/expr/ob_expr_json_object.cpp b/src/sql/engine/expr/ob_expr_json_object.cpp index 770440040b..83df15f357 100644 --- a/src/sql/engine/expr/ob_expr_json_object.cpp +++ b/src/sql/engine/expr/ob_expr_json_object.cpp @@ -332,7 +332,7 @@ int ObExprJsonObject::eval_ora_json_object(const ObExpr &expr, ObEvalCtx &ctx, O bool is_format_json = format_type > 0; if (OB_FAIL(ObJsonExprHelper::eval_oracle_json_val( - arg_value, ctx, &temp_allocator, j_val, is_format_json, is_strict, false))) { + arg_value, ctx, &temp_allocator, j_val, is_format_json, is_strict, false, is_null_absent))) { LOG_WARN("failed to get json value node.", K(ret), K(value_data_type), K(i)); } else { bool is_key_already_exist = (j_obj.get_value(key) != nullptr); @@ -340,7 +340,7 @@ int ObExprJsonObject::eval_ora_json_object(const ObExpr &expr, ObEvalCtx &ctx, O if (is_key_already_exist && is_key_unique) { ret = OB_ERR_DUPLICATE_KEY; LOG_WARN("Found duplicate key inserted before!", K(key), K(ret)); - } else if (is_null_absent && j_val->json_type() == ObJsonNodeType::J_NULL) { + } else if (OB_ISNULL(j_val)) { } else if (OB_FAIL(j_obj.add(key, static_cast(j_val), false, false, is_overwrite))) { LOG_WARN("failed to get json value node.", K(ret), K(val_type)); }