From 22c8279a5b7033d45b419afbaf94a96226a5bf9d Mon Sep 17 00:00:00 2001 From: bit-dance <2634358021@qq.com> Date: Fri, 13 Dec 2024 05:14:41 +0000 Subject: [PATCH] [CP] [#2024101800104734653]Fix:can not find type by the mocked nested table type id --- src/pl/ob_pl.cpp | 9 ++- src/pl/ob_pl_compile.cpp | 7 +- src/pl/ob_pl_resolver.cpp | 93 ++++++++++++---------- src/pl/ob_pl_resolver.h | 4 +- src/pl/ob_pl_type.h | 20 +++++ src/sql/engine/cmd/ob_routine_executor.cpp | 2 +- src/sql/resolver/ob_resolver_utils.cpp | 2 +- 7 files changed, 87 insertions(+), 50 deletions(-) diff --git a/src/pl/ob_pl.cpp b/src/pl/ob_pl.cpp index 250171af2..b8b89d2d3 100644 --- a/src/pl/ob_pl.cpp +++ b/src/pl/ob_pl.cpp @@ -3569,7 +3569,8 @@ int ObPLExecState::check_routine_param_legal(ParamStore *params) } else if (!params->at(i).is_pl_extend()) { ret = OB_ERR_UNEXPECTED; LOG_WARN("real parameter is ext ptr, but extend type not set property", K(ret), K(params->at(i)), K(i)); - } else if (PL_OPAQUE_TYPE == params->at(i).get_meta().get_extend_type() || params->at(i).get_udt_id() != OB_INVALID_ID) { + } else if (PL_OPAQUE_TYPE == params->at(i).get_meta().get_extend_type() + || !is_mocked_anonymous_array_id(params->at(i).get_udt_id())) { if (params->at(i).get_udt_id() != dest_type.get_user_type_id()) { bool is_compatible = false; OZ (ObPLResolver::check_composite_compatible( @@ -3584,7 +3585,8 @@ int ObPLExecState::check_routine_param_legal(ParamStore *params) ObPLComposite *composite = reinterpret_cast(params->at(i).get_ext()); CK (OB_NOT_NULL(composite)); if (OB_FAIL(ret)) { - } else if (OB_INVALID_ID == composite->get_id()) { // anonymous collection, should check element composite. + } else if (is_mocked_anonymous_array_id(composite->get_id())) { + // anonymous collection, should check element composite. bool need_cast = false; if (!dest_type.is_collection_type()) { ret = OB_INVALID_ARGUMENT; @@ -3860,7 +3862,8 @@ do { \ get_params().at(i).set_is_ref_cursor_type(true); // last assignment statement could clear this flag get_params().at(i).set_extend( get_params().at(i).get_ext(), PL_REF_CURSOR_TYPE, get_params().at(i).get_val_len()); - } else if (pl_type.is_collection_type() && OB_INVALID_ID == params->at(i).get_udt_id()) { + } else if (pl_type.is_collection_type() + && (is_mocked_anonymous_array_id(params->at(i).get_udt_id()))) { ObPLComposite *composite = NULL; get_params().at(i) = params->at(i); get_params().at(i).set_udt_id(pl_type.get_user_type_id()); diff --git a/src/pl/ob_pl_compile.cpp b/src/pl/ob_pl_compile.cpp index 76f13ab3e..090ba45a6 100644 --- a/src/pl/ob_pl_compile.cpp +++ b/src/pl/ob_pl_compile.cpp @@ -100,7 +100,7 @@ int ObPLCompiler::init_anonymous_ast( func_ast.set_ret_type(pl_type); for (int64_t i = 0; OB_SUCC(ret) && OB_NOT_NULL(params) && i < params->count(); ++i) { - const ObObjParam param = params->at(i); + ObObjParam& param = const_cast(params->at(i)); if (param.is_pl_extend()) { #ifdef OB_BUILD_ORACLE_PL if (PL_REF_CURSOR_TYPE == param.get_meta().get_extend_type()) { @@ -109,7 +109,7 @@ int ObPLCompiler::init_anonymous_ast( pl_type.set_type_from(pl::PL_TYPE_SYS_REFCURSOR); } else #endif - if (param.get_udt_id() != OB_INVALID_ID) { + if (!is_mocked_anonymous_array_id(param.get_udt_id())) { const ObUserDefinedType *user_type = NULL; OZ (ObResolverUtils::get_user_type(&allocator, &session_info, @@ -140,9 +140,10 @@ int ObPLCompiler::init_anonymous_ast( } OX (nested_type->set_element_type(element_type)); OX (nested_type->set_user_type_id( - func_ast.get_user_type_table().generate_user_type_id(OB_INVALID_ID))); + func_ast.get_user_type_table().generate_user_type_id(OB_PL_MOCK_ANONYMOUS_ID))); OZ (func_ast.get_user_type_table().add_type(nested_type)); OZ (func_ast.get_user_type_table().add_external_type(nested_type)); + OX (param.set_udt_id(nested_type->get_user_type_id())); OX (pl_type = *nested_type); #endif } else { diff --git a/src/pl/ob_pl_resolver.cpp b/src/pl/ob_pl_resolver.cpp index b896f7c20..7211d11e5 100644 --- a/src/pl/ob_pl_resolver.cpp +++ b/src/pl/ob_pl_resolver.cpp @@ -6170,7 +6170,7 @@ int ObPLResolver::resolve_using(const ObStmtNodeTree *using_node, } else { bool legal_extend = false; if (ObExtendType == expr->get_result_type().get_type()) { - if (expr->get_result_type().get_udt_id() != OB_INVALID_ID) { + if (!is_mocked_anonymous_array_id(expr->get_result_type().get_udt_id())) { const ObUserDefinedType *user_type = NULL; CK (OB_NOT_NULL(current_block_)); OZ (current_block_->get_namespace().get_pl_data_type_by_id( @@ -7372,42 +7372,8 @@ int ObPLResolver::check_in_param_type_legal(const ObIRoutineParam *param_info, } else if (actually_type.is_obj_type() && ObNullType == actually_type.get_obj_type()) { // do nothing ... } else if (actually_type.is_composite_type() && expected_type.is_composite_type()) { - if (is_anonymous_array_type && expected_type.is_collection_type()) { // check anonymous array compatible - - const ObUserDefinedType *left_type = NULL; - const ObUserDefinedType *right_type = NULL; - const ObCollectionType *left_coll_type = NULL; - const ObCollectionType *right_coll_type = NULL; - - OZ (current_block_->get_namespace().get_pl_data_type_by_id(actually_type.get_user_type_id(), left_type)); - OZ (current_block_->get_namespace().get_pl_data_type_by_id(expected_type.get_user_type_id(), right_type)); - CK (OB_NOT_NULL(left_coll_type = static_cast(left_type))); - CK (OB_NOT_NULL(right_coll_type = static_cast(right_type))); - - if (OB_FAIL(ret)) { - } else if (left_coll_type->get_element_type().is_obj_type() ^ right_coll_type->get_element_type().is_obj_type()) { - is_legal = false; - LOG_WARN("uncompatible with anonymous array type", K(ret), KPC(left_coll_type), KPC(right_coll_type)); - } else if (left_coll_type->get_element_type().is_obj_type()) { - const ObDataType *left_basic_type = left_coll_type->get_element_type().get_data_type(); - const ObDataType *right_basic_type = right_coll_type->get_element_type().get_data_type(); - if (left_basic_type->get_obj_type() != right_basic_type->get_obj_type() - && !cast_supported(left_basic_type->get_obj_type(), - left_basic_type->get_collation_type(), - right_basic_type->get_obj_type(), - right_basic_type->get_collation_type())) { - is_legal = false; - LOG_WARN("uncompatible with anonymous array type", K(ret), KPC(left_coll_type), KPC(right_coll_type)); - } else { - // compatible with anonymous array type - } - } else if (left_coll_type->get_element_type().get_user_type_id() != right_coll_type->get_element_type().get_user_type_id()) { - OZ (check_composite_compatible(current_block_->get_namespace(), - left_coll_type->get_element_type().get_user_type_id(), - right_coll_type->get_element_type().get_user_type_id(), - is_legal)); - } + OZ (check_anonymous_array_compatible(actually_type.get_user_type_id(), expected_type.get_user_type_id(), is_legal)); } else if (actually_type.get_user_type_id() != expected_type.get_user_type_id()) { OZ (check_composite_compatible(current_block_->get_namespace(), actually_type.get_user_type_id(), @@ -10006,7 +9972,7 @@ int ObPLResolver::formalize_expr(ObRawExpr &expr, int ret = OB_SUCCESS; if (OB_SUCC(ret) && expr.get_result_type().is_ext() - && OB_INVALID_ID != expr.get_udt_id()) { + && !is_mocked_anonymous_array_id(expr.get_udt_id())) { int64_t size = 0; const ObUserDefinedType *user_type = NULL; OZ (ns.get_user_type(expr.get_udt_id(), user_type, NULL)); @@ -10178,10 +10144,14 @@ int ObPLResolver::resolve_expr(const ParseNode *node, && expected_type->get_user_type_id() != expr->get_result_type().get_udt_id() && expr->get_expr_type() != T_FUN_SYS_PDB_GET_RUNTIME_INFO) { bool is_compatible = false; - OZ (check_composite_compatible(current_block_->get_namespace(), - expr->get_result_type().get_udt_id(), - expected_type->get_user_type_id(), - is_compatible)); + if (is_mocked_anonymous_array_id(expr->get_result_type().get_udt_id())) { + OZ (check_anonymous_array_compatible(expr->get_result_type().get_udt_id(), expected_type->get_user_type_id(), is_compatible)); + } else { + OZ (check_composite_compatible(current_block_->get_namespace(), + expr->get_result_type().get_udt_id(), + expected_type->get_user_type_id(), + is_compatible)); + } if (OB_FAIL(ret)) { } else if (!is_compatible) { ret = OB_ERR_INVALID_TYPE_FOR_OP; @@ -10386,6 +10356,47 @@ int ObPLResolver::resolve_expr(const ParseNode *node, return ret; } +int ObPLResolver::check_anonymous_array_compatible (uint64_t actual_param_type_id, + uint64_t formal_param_type_id, + bool &is_compatible) +{ + int ret = OB_SUCCESS; + const ObUserDefinedType *left_type = NULL; + const ObUserDefinedType *right_type = NULL; + const ObCollectionType *left_coll_type = NULL; + const ObCollectionType *right_coll_type = NULL; + OZ (current_block_->get_namespace().get_pl_data_type_by_id(actual_param_type_id, left_type)); + OZ (current_block_->get_namespace().get_pl_data_type_by_id(formal_param_type_id, right_type)); + CK (OB_NOT_NULL(left_coll_type = static_cast(left_type))); + CK (OB_NOT_NULL(right_coll_type = static_cast(right_type))); + + if (OB_FAIL(ret)) { + } else if (left_coll_type->get_element_type().is_obj_type() ^ right_coll_type->get_element_type().is_obj_type()) { + is_compatible = false; + LOG_WARN("uncompatible with anonymous array type", K(ret), KPC(left_coll_type), KPC(right_coll_type)); + } else if (left_coll_type->get_element_type().is_obj_type()) { + const ObDataType *left_basic_type = left_coll_type->get_element_type().get_data_type(); + const ObDataType *right_basic_type = right_coll_type->get_element_type().get_data_type(); + if (left_basic_type->get_obj_type() != right_basic_type->get_obj_type() + && !cast_supported(left_basic_type->get_obj_type(), + left_basic_type->get_collation_type(), + right_basic_type->get_obj_type(), + right_basic_type->get_collation_type())) { + is_compatible = false; + LOG_WARN("uncompatible with anonymous array type", K(ret), KPC(left_coll_type), KPC(right_coll_type)); + } else { + is_compatible = true;// compatible with anonymous array type + } + } else if (left_coll_type->get_element_type().get_user_type_id() != right_coll_type->get_element_type().get_user_type_id()) { + OZ (check_composite_compatible(current_block_->get_namespace(), + left_coll_type->get_element_type().get_user_type_id(), + right_coll_type->get_element_type().get_user_type_id(), + is_compatible)); + } else { + is_compatible = true; // user_type_id equal + } + return ret; +} int ObPLResolver::transform_subquery_expr(const ParseNode *node, ObRawExpr *&expr, diff --git a/src/pl/ob_pl_resolver.h b/src/pl/ob_pl_resolver.h index 4f140c593..5892dbda0 100644 --- a/src/pl/ob_pl_resolver.h +++ b/src/pl/ob_pl_resolver.h @@ -525,7 +525,9 @@ public: static int check_composite_compatible(const ObUserDefinedType *actual_param_type, const ObUserDefinedType *formal_param_type, bool &is_compatible); - + int check_anonymous_array_compatible( uint64_t actual_param_type_id, + uint64_t formal_param_type_id, + bool &is_compatible); static int resolve_nocopy_params(const share::schema::ObIRoutineInfo *routine_info, sql::ObUDFInfo &udf_info); diff --git a/src/pl/ob_pl_type.h b/src/pl/ob_pl_type.h index 02ff8ed56..c008a91a4 100644 --- a/src/pl/ob_pl_type.h +++ b/src/pl/ob_pl_type.h @@ -31,6 +31,7 @@ #define ObCursorType ObIntType #define ObPtrType ObIntType +#define OB_PL_MOCK_ANONYMOUS_ID 0xFFFFFFFFFFFFFFFE #define IS_TYPE_FROM_TYPE_OR_ROWTYPE(type_from) \ (PL_TYPE_ATTR_ROWTYPE == type_from) || \ @@ -234,6 +235,25 @@ struct ObPLExternTypeInfo }; class ObPLEnumSetCtx; + +OB_INLINE bool is_mocked_anonymous_array_id(uint64_t udt_id) +{ + uint64_t mask = 0xFFFFFFFFFF000000; + uint64_t res = 0xFFFFFFFFFE000000; + // anonymous_array will use OB_PL_MOCK_ANONYMOUS_ID to generate a mocked id , + // OB_PL_MOCK_ANONYMOUS_ID = (uint64)OB_INVALID_ID - 1. + // Why do not use OB_INVALID_ID? Anonymous block has declare local nested type (this package_id is OB_INVALID_ID) + // use OB_INVALID_ID - 1 to identify this scenery. + // So the first 40 bits of mocked id in hex is: 0xFFFFFFFFFE + // We can use (mocked_id & mask) to get the first 40 bits and check if it is mocked. + return (udt_id & mask) == res || OB_INVALID_ID == udt_id; +} + +OB_INLINE bool is_invalid_or_mocked_package_id(uint64_t udt_id) +{ + return OB_INVALID_ID == extract_package_id(udt_id) || OB_PL_MOCK_ANONYMOUS_ID == extract_package_id(udt_id); +} + class ObPLDataType { public: diff --git a/src/sql/engine/cmd/ob_routine_executor.cpp b/src/sql/engine/cmd/ob_routine_executor.cpp index c55af1bd6..69a1bbc05 100644 --- a/src/sql/engine/cmd/ob_routine_executor.cpp +++ b/src/sql/engine/cmd/ob_routine_executor.cpp @@ -615,7 +615,7 @@ int ObAnonymousBlockExecutor::execute(ObExecContext &ctx, ObAnonymousBlockStmt & field.length_ = field.accuracy_.get_length(); if (value.is_ref_cursor_type()) { OZ (ob_write_string(ctx.get_allocator(), ObString("SYS_REFCURSOR"), field.type_name_)); - } else if (value.get_udt_id() != OB_INVALID_ID && extract_package_id(value.get_udt_id()) != OB_INVALID_ID) { + } else if (value.get_udt_id() != OB_INVALID_ID && !pl::is_invalid_or_mocked_package_id(value.get_udt_id())) { OZ (fill_field_with_udt_id(ctx, value.get_udt_id(), field)); } else if (value.is_pl_extend() && pl::PL_NESTED_TABLE_TYPE == value.get_meta().get_extend_type()) { diff --git a/src/sql/resolver/ob_resolver_utils.cpp b/src/sql/resolver/ob_resolver_utils.cpp index b65168905..74d56ef2c 100644 --- a/src/sql/resolver/ob_resolver_utils.cpp +++ b/src/sql/resolver/ob_resolver_utils.cpp @@ -1080,7 +1080,7 @@ int ObResolverUtils::check_type_match(const pl::ObPLResolveCtx &resolve_ctx, OX (match_info = (ObRoutineMatchInfo::MatchInfo(false, src_type, dst_type))); } else if (resolve_ctx.is_prepare_protocol_ && ObExtendType == src_type && - OB_INVALID_ID == src_type_id && + is_mocked_anonymous_array_id(src_type_id) && T_QUESTIONMARK == expr->get_expr_type()) { // 匿名数组 const ObConstRawExpr *const_expr = static_cast(expr); int64_t idx = const_expr->get_value().get_unknown();