From 3897e45a839d19d86e03d12fa2065be370b84409 Mon Sep 17 00:00:00 2001 From: obdev Date: Fri, 9 Feb 2024 14:49:24 +0000 Subject: [PATCH] [CP]sync bugfix from 42x. fix:json compare with const string, behavior not consistent with mysql --- src/share/object/ob_obj_cast.cpp | 14 +++++++++----- src/share/object/ob_obj_cast.h | 8 +++++--- src/sql/engine/expr/ob_datum_cast.cpp | 4 ++++ src/sql/engine/expr/ob_expr_json_pretty.cpp | 1 + src/sql/engine/expr/ob_expr_json_quote.cpp | 1 + src/sql/engine/expr/ob_expr_json_unquote.cpp | 1 + src/sql/engine/expr/ob_expr_operator.cpp | 3 +-- src/sql/resolver/expr/ob_raw_expr_deduce_type.cpp | 7 +++++++ 8 files changed, 29 insertions(+), 10 deletions(-) diff --git a/src/share/object/ob_obj_cast.cpp b/src/share/object/ob_obj_cast.cpp index fa655c39c2..28b46f6971 100644 --- a/src/share/object/ob_obj_cast.cpp +++ b/src/share/object/ob_obj_cast.cpp @@ -6093,14 +6093,18 @@ static int string_json(const ObObjType expect_type, ObObjCastParams ¶ms, j_base = &j_null; } else if (!is_oracle && CS_TYPE_BINARY == in.get_collation_type()) { j_base = &j_opaque; - } 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) { + } else if (!is_oracle && ( + (CM_IS_SQL_AS_JSON_SCALAR(cast_mode) && ob_is_string_type(in_type)) + || (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; + if ((CM_IS_SQL_AS_JSON_SCALAR(cast_mode) && ob_is_string_type(in_type)) && j_text.compare("null") == 0) { + j_base = &j_null; + } } else if (OB_FAIL(ObJsonParser::get_tree(params.allocator_v2_, j_text, j_tree, parse_flag))) { if (!is_oracle && CM_IS_IMPLICIT_CAST(cast_mode) && !CM_IS_COLUMN_CONVERT(cast_mode) diff --git a/src/share/object/ob_obj_cast.h b/src/share/object/ob_obj_cast.h index 49c3ecd5b3..d1325473fb 100644 --- a/src/share/object/ob_obj_cast.h +++ b/src/share/object/ob_obj_cast.h @@ -64,12 +64,11 @@ namespace common #define CM_GEOMETRY_TYPE_RESERVED3 (1ULL << 14) #define CM_GEOMETRY_TYPE_RESERVED4 (1ULL << 15) #define CM_GEOMETRY_TYPE_RESERVED5 (1ULL << 16) - -#define CM_CONST_TO_DECIMAL_INT_UP (1ULL << 17) +#define CM_SQL_TO_JSON_SCALAR (1ULL << 17) #define CM_CONST_TO_DECIMAL_INT_DOWN (1ULL << 18) #define CM_CONST_TO_DECIMAL_INT_EQ (1ULL << 19) #define CM_BY_TRANSFORMER (1ULL << 20) - +#define CM_CONST_TO_DECIMAL_INT_UP (1ULL << 21) // string->integer(int/uint)时默认进行round(round to nearest), // 如果设置该标记,则会进行trunc(round to zero) // ceil(round to +inf)以及floor(round to -inf)暂时没有支持 @@ -123,6 +122,9 @@ typedef uint64_t ObCastMode; #define CM_IS_STRICT_JSON(mode) ((CM_STRICT_JSON & (mode)) != 0) #define CM_IS_JSON_VALUE(mode) CM_IS_ERROR_ON_SCALE_OVER(mode) #define CM_IS_TO_COLUMN_CS_LEVEL(mode) ((CM_TO_COLUMN_CS_LEVEL & (mode)) != 0) +// for json type cast +#define CM_IS_SQL_AS_JSON_SCALAR(mode) ((CM_SQL_TO_JSON_SCALAR & (mode)) != 0) +#define CM_SET_SQL_AS_JSON_SCALAR(mode) (CM_SQL_TO_JSON_SCALAR | (mode)) // for geomerty type cast #define CM_IS_GEOMETRY_GEOMETRY(mode) ((((mode) >> 12) & 0x1F) == 0) #define CM_IS_GEOMETRY_POINT(mode) ((((mode) >> 12) & 0x1F) == 1) diff --git a/src/sql/engine/expr/ob_datum_cast.cpp b/src/sql/engine/expr/ob_datum_cast.cpp index 5fee214123..1d1bd32897 100644 --- a/src/sql/engine/expr/ob_datum_cast.cpp +++ b/src/sql/engine/expr/ob_datum_cast.cpp @@ -3649,12 +3649,16 @@ static int common_string_json(const ObExpr &expr, is_null_res = true; } else if (!is_oracle && (is_enumset_to_str + || (CM_IS_SQL_AS_JSON_SCALAR(expr.extra_) && ob_is_string_type(in_type)) || (CM_IS_IMPLICIT_CAST(expr.extra_) && !CM_IS_COLUMN_CONVERT(expr.extra_) && !CM_IS_JSON_VALUE(expr.extra_) && is_convert_jstr_type))) { // consistent with mysql: TINYTEXT, TEXT, MEDIUMTEXT, and LONGTEXT. We want to treat them like strings j_base = &j_string; + if ((CM_IS_SQL_AS_JSON_SCALAR(expr.extra_) && ob_is_string_type(in_type)) && j_text.compare("null") == 0) { + j_base = &j_null; + } } else if (is_oracle && (OB_ISNULL(j_text.ptr()) || j_text.length() == 0)) { j_base = &j_null; } else if (OB_FAIL(ObJsonParser::get_tree(&temp_allocator, j_text, j_tree, parse_flag))) { diff --git a/src/sql/engine/expr/ob_expr_json_pretty.cpp b/src/sql/engine/expr/ob_expr_json_pretty.cpp index 4dd8e9c58b..725416b951 100644 --- a/src/sql/engine/expr/ob_expr_json_pretty.cpp +++ b/src/sql/engine/expr/ob_expr_json_pretty.cpp @@ -45,6 +45,7 @@ int ObExprJsonPretty::calc_result_type1(ObExprResType &type, type.set_type(ObLongTextType); type.set_collation_type(CS_TYPE_UTF8MB4_BIN); type.set_collation_level(CS_LEVEL_IMPLICIT); + type.set_accuracy(ObAccuracy::DDL_DEFAULT_ACCURACY[ObLongTextType]); if (OB_FAIL(ObJsonExprHelper::is_valid_for_json(type1, 1, N_JSON_PRETTY))) { LOG_WARN("wrong type for json doc.", K(ret), K(type1.get_type())); diff --git a/src/sql/engine/expr/ob_expr_json_quote.cpp b/src/sql/engine/expr/ob_expr_json_quote.cpp index b76e31c1cc..f208f8f4ea 100644 --- a/src/sql/engine/expr/ob_expr_json_quote.cpp +++ b/src/sql/engine/expr/ob_expr_json_quote.cpp @@ -43,6 +43,7 @@ int ObExprJsonQuote::calc_result_type1(ObExprResType &type, type.set_type(ObLongTextType); type.set_collation_type(CS_TYPE_UTF8MB4_BIN); type.set_collation_level(CS_LEVEL_IMPLICIT); + type.set_accuracy(ObAccuracy::DDL_DEFAULT_ACCURACY[ObLongTextType]); if (type1.get_type() == ObNullType || type1.get_type() == ObDoubleType || type1.get_type() == ObIntType) { diff --git a/src/sql/engine/expr/ob_expr_json_unquote.cpp b/src/sql/engine/expr/ob_expr_json_unquote.cpp index f29cb23995..cc1a54c640 100644 --- a/src/sql/engine/expr/ob_expr_json_unquote.cpp +++ b/src/sql/engine/expr/ob_expr_json_unquote.cpp @@ -43,6 +43,7 @@ int ObExprJsonUnquote::calc_result_type1(ObExprResType &type, type.set_type(ObLongTextType); type.set_collation_type(CS_TYPE_UTF8MB4_BIN); type.set_collation_level(CS_LEVEL_IMPLICIT); + type.set_accuracy(ObAccuracy::DDL_DEFAULT_ACCURACY[ObLongTextType]); if (type1.get_type() == ObNullType || type1.get_type() == ObDoubleType || type1.get_type() == ObIntType) { diff --git a/src/sql/engine/expr/ob_expr_operator.cpp b/src/sql/engine/expr/ob_expr_operator.cpp index 2d126ee868..91647ff20a 100644 --- a/src/sql/engine/expr/ob_expr_operator.cpp +++ b/src/sql/engine/expr/ob_expr_operator.cpp @@ -1164,8 +1164,7 @@ int ObExprOperator::aggregate_result_type_for_merge( } else if (ob_is_extend(res_type)) { OZ (aggregate_extend_accuracy_for_merge(type, types, param_num)); } else if (ob_is_json(res_type)) { - type.set_collation_type(CS_TYPE_UTF8MB4_BIN); - type.set_collation_level(CS_LEVEL_IMPLICIT); + type.set_json(); } else if (ob_is_geometry(res_type)) { type.set_geometry(); type.set_length((ObAccuracy::DDL_DEFAULT_ACCURACY[ObGeometryType]).get_length()); diff --git a/src/sql/resolver/expr/ob_raw_expr_deduce_type.cpp b/src/sql/resolver/expr/ob_raw_expr_deduce_type.cpp index dd07de593d..72889b1801 100644 --- a/src/sql/resolver/expr/ob_raw_expr_deduce_type.cpp +++ b/src/sql/resolver/expr/ob_raw_expr_deduce_type.cpp @@ -3589,6 +3589,13 @@ int ObRawExprDeduceType::try_add_cast_expr(RawExprType &parent, ret = OB_ERR_INVALID_TYPE_FOR_OP; LOG_WARN("cast to lob type not allowed", K(ret)); } + + // for consistent with mysql, if const cast as json, should regard as scalar, don't need parse + if (ObStringTC == ori_tc && ObJsonTC == expect_tc + && IS_BASIC_CMP_OP(parent.get_expr_type())) { + uint64_t extra = new_expr->get_extra(); + new_expr->set_extra(CM_SET_SQL_AS_JSON_SCALAR(extra)); + } OZ(parent.replace_param_expr(child_idx, new_expr)); if (OB_FAIL(ret) && my_session_->is_varparams_sql_prepare()) { ret = OB_SUCCESS;