From a3b0891c86e9f1e28222263d56cde7b3fc4a0e42 Mon Sep 17 00:00:00 2001 From: obdev Date: Wed, 27 Sep 2023 06:10:09 +0000 Subject: [PATCH] [to #52406314] fix serval PL/SQL bugs --- src/pl/ob_pl.cpp | 26 ++++++---- src/pl/ob_pl_resolver.cpp | 46 +++++++++++++---- src/pl/ob_pl_stmt.cpp | 3 +- .../ob_pl_user_defined_agg_function.cpp | 2 +- src/sql/ob_spi.cpp | 2 +- .../ddl/ob_create_routine_resolver.cpp | 50 +++++++++++++++++-- src/sql/resolver/expr/ob_raw_expr_printer.cpp | 13 +++-- .../expr/ob_raw_expr_resolver_impl.cpp | 16 ++++-- 8 files changed, 121 insertions(+), 37 deletions(-) diff --git a/src/pl/ob_pl.cpp b/src/pl/ob_pl.cpp index b73c1e3f49..4a35ef03b9 100644 --- a/src/pl/ob_pl.cpp +++ b/src/pl/ob_pl.cpp @@ -2851,7 +2851,12 @@ int ObPLExecState::init_complex_obj(ObIAllocator &allocator, } else if (real_pl_type->is_udt_type()) { ObPLUDTNS ns(*schema_guard); OZ (ns.init_complex_obj(allocator, *real_pl_type, obj, false)); - } else if (real_pl_type->is_package_type() || real_pl_type->is_rowtype_type()) { + } else if (OB_NOT_NULL(session->get_pl_context()) + && OB_NOT_NULL(session->get_pl_context()->get_current_ctx())) { + pl::ObPLINS *ns = session->get_pl_context()->get_current_ctx(); + CK (OB_NOT_NULL(ns)); + OZ (ns->init_complex_obj(allocator, *real_pl_type, obj, false)); + } else { ObPLResolveCtx ns(allocator, *session, *schema_guard, @@ -2859,11 +2864,6 @@ int ObPLExecState::init_complex_obj(ObIAllocator &allocator, *sql_proxy, false); OZ (ns.init_complex_obj(allocator, *real_pl_type, obj, false)); - } else if (OB_NOT_NULL(session->get_pl_context()) - && OB_NOT_NULL(session->get_pl_context()->get_current_ctx())) { - pl::ObPLINS *ns = session->get_pl_context()->get_current_ctx(); - CK (OB_NOT_NULL(ns)); - OZ (ns->init_complex_obj(allocator, *real_pl_type, obj, false)); } OX (obj.set_udt_id(real_pl_type->get_user_type_id())); return ret; @@ -3232,11 +3232,17 @@ do { \ *get_allocator())); OX (get_params().at(i) = tmp); } else { + // same type, we already check this on resolve stage, here directly assign value to symbol. + get_params().at(i) = params->at(i); if (get_params().at(i).is_ref_cursor_type()) { - get_params().at(i) = params->at(i); get_params().at(i).set_is_ref_cursor_type(true); - } else { - get_params().at(i) = params->at(i); + } else if (pl_type.is_collection_type() && OB_INVALID_ID == params->at(i).get_udt_id()) { + ObPLComposite *composite = NULL; + get_params().at(i).set_udt_id(pl_type.get_user_type_id()); + composite = reinterpret_cast(params->at(i).get_ext()); + if (OB_NOT_NULL(composite) && composite->is_collection() && OB_INVALID_ID == composite->get_id()) { + composite->set_id(pl_type.get_user_type_id()); + } } } } @@ -4302,7 +4308,7 @@ int ObPLINS::get_size(ObPLTypeSize type, const ObUserDefinedType *user_type = NULL; CK (pl_type.is_composite_type()); OZ (get_user_type(pl_type.get_user_type_id(), user_type, allocator)); - CK (OB_NOT_NULL(user_type)); + OV (OB_NOT_NULL(user_type), OB_ERR_UNEXPECTED, K(pl_type)); OZ (user_type->get_size(*this, type, size)); return ret; } diff --git a/src/pl/ob_pl_resolver.cpp b/src/pl/ob_pl_resolver.cpp index 263c34e97e..e58ae16598 100644 --- a/src/pl/ob_pl_resolver.cpp +++ b/src/pl/ob_pl_resolver.cpp @@ -4455,12 +4455,18 @@ int ObPLResolver::resolve_cursor_for_loop( OX (stmt->set_cursor_index(cursor_index)); //解析实参 - OZ (resolve_cursor_actual_params( - (T_FUN_SYS == cursor_node->type_ && cursor_node->num_child_ > 1) - ? cursor_node->children_[1] : NULL, - stmt, - func)); - + if (OB_SUCC(ret)) { + const ObStmtNodeTree *param_node = NULL; + if (T_FUN_SYS == cursor_node->type_ && cursor_node->num_child_ > 1) { + param_node = cursor_node->children_[1]; + } else if (T_OBJ_ACCESS_REF == cursor_node->type_ + && cursor_node->children_[1] != NULL + && T_FUN_SYS == cursor_node->children_[1]->children_[0]->type_ + && cursor_node->children_[1]->children_[0]->num_child_ > 1) { + param_node = cursor_node->children_[1]->children_[0]->children_[1]; + } + OZ (resolve_cursor_actual_params(param_node, stmt, func)); + } if (OB_SUCC(ret)) { const ObPLVar *var = NULL; const ObPLCursor *cursor = stmt->get_cursor(); @@ -11133,7 +11139,7 @@ int ObPLResolver::resolve_object_construct(const sql::ObQualifiedName &q_name, } else { // do nothing } - if (OB_SUCC(ret)) { + if (OB_SUCC(ret) && OB_NOT_NULL(uinfo.ref_expr_) && uinfo.ref_expr_->get_udf_id() == OB_INVALID_ID) { SMART_VAR(ObPLFunctionAST, dummy_ast, resolve_ctx_.allocator_) { ObSEArray access_idxs; OZ (resolve_udf_info(uinfo, access_idxs, dummy_ast)); @@ -15160,11 +15166,26 @@ int ObPLResolver::resolve_cursor(ObPLCompileUnitAST &func, OZ (resolve_ctx_.schema_guard_.get_package_info( tenant_id, database_id, package_name, PACKAGE_TYPE, compatible_mode, package_info)); if (OB_SUCC(ret) - && OB_ISNULL(package_info) && db_name.case_compare(OB_SYS_DATABASE_NAME)) { + && OB_ISNULL(package_info) && 0 == db_name.case_compare(OB_SYS_DATABASE_NAME)) { OZ (resolve_ctx_.schema_guard_.get_package_info( OB_SYS_TENANT_ID, OB_SYS_DATABASE_ID, package_name, PACKAGE_TYPE, compatible_mode, package_info)); } + if (OB_SUCC(ret) && OB_ISNULL(package_info)) { + ObSchemaChecker checker; + ObSEArray syn_id_array; + ObString new_package_name; + OZ (checker.init(resolve_ctx_.schema_guard_)); + OZ (checker.get_obj_info_recursively_with_synonym( + tenant_id, database_id, package_name, database_id, new_package_name, syn_id_array, true)); + OZ (resolve_ctx_.schema_guard_.get_package_info( + tenant_id, database_id, new_package_name, PACKAGE_TYPE, compatible_mode, package_info)); + if (OB_SUCC(ret) + && OB_ISNULL(package_info) && OB_SYS_DATABASE_ID == database_id) { + OZ (resolve_ctx_.schema_guard_.get_package_info( + OB_SYS_TENANT_ID, OB_SYS_DATABASE_ID, new_package_name, PACKAGE_TYPE, compatible_mode, package_info)); + } + } if (OB_SUCC(ret) && OB_ISNULL(package_info)) { ret = OB_ERR_PACKAGE_DOSE_NOT_EXIST; LOG_WARN("package not exist", K(ret), K(package_name), K(db_name)); @@ -15244,10 +15265,15 @@ int ObPLResolver::resolve_cursor( ObString package_name; ObString cursor_name; const ObStmtNodeTree *package_node = parse_tree->children_[0]; - CK (T_OBJ_ACCESS_REF == parse_tree->children_[1]->type_); const ObStmtNodeTree *cursor_node = parse_tree->children_[1]->children_[0]; package_name.assign_ptr(package_node->str_value_, static_cast(package_node->str_len_)); - cursor_name.assign_ptr(cursor_node->str_value_, static_cast(cursor_node->str_len_)); + if (T_FUN_SYS == cursor_node->type_ + && OB_NOT_NULL(cursor_node->children_[0]) + && T_IDENT == cursor_node->children_[0]->type_) { + cursor_name.assign_ptr(cursor_node->children_[0]->str_value_, static_cast(cursor_node->children_[0]->str_len_)); + } else { + cursor_name.assign_ptr(cursor_node->str_value_, static_cast(cursor_node->str_len_)); + } db_name = resolve_ctx_.session_info_.get_database_name(); if (OB_FAIL(ret)) { } else if (package_name.empty()) { diff --git a/src/pl/ob_pl_stmt.cpp b/src/pl/ob_pl_stmt.cpp index 673936cbc0..103ef2742d 100644 --- a/src/pl/ob_pl_stmt.cpp +++ b/src/pl/ob_pl_stmt.cpp @@ -766,8 +766,7 @@ int ObPLRoutineTable::make_routine_ast(ObIAllocator &allocator, OZ (routine_ast->add_dependency_object(ret_param->get_obj_version())); } OX (routine_ast->set_ret_type(ret_param->get_type())); - CK (ret_param->get_type().is_valid_type()); - if (OB_SUCC(ret) && ret_param->get_type().is_obj_type()) { + if (OB_SUCC(ret) && ret_param->get_type().is_valid_type() && ret_param->get_type().is_obj_type()) { CK (OB_NOT_NULL(ret_param->get_type().get_data_type())); if (OB_SUCC(ret) && ob_is_enum_or_set_type(ret_param->get_type().get_data_type()->get_obj_type())) { diff --git a/src/sql/engine/user_defined_function/ob_pl_user_defined_agg_function.cpp b/src/sql/engine/user_defined_function/ob_pl_user_defined_agg_function.cpp index 891d6c048d..622fd928b4 100644 --- a/src/sql/engine/user_defined_function/ob_pl_user_defined_agg_function.cpp +++ b/src/sql/engine/user_defined_function/ob_pl_user_defined_agg_function.cpp @@ -94,7 +94,7 @@ int ObPlAggUdfFunction::get_package_routine_info(const ObString &routine_name, routine_infos))) { LOG_WARN("failed to get package routine infos", K(ret)); } else if (OB_FAIL(pick_routine(routine_infos, base_routine_info, param_type))) { - LOG_WARN("get unexpected error", K(routine_infos), K(base_routine_info), K(ret)); + LOG_WARN("get unexpected error", K(routine_infos), K(base_routine_info), K(ret), K(type_id_), K(routine_name), K(routine_type)); } else if (OB_ISNULL(base_routine_info) || OB_ISNULL(routine_info = static_cast(base_routine_info))) { ret = OB_ERR_UNEXPECTED; diff --git a/src/sql/ob_spi.cpp b/src/sql/ob_spi.cpp index d7eb9c118d..700fd5b7b6 100644 --- a/src/sql/ob_spi.cpp +++ b/src/sql/ob_spi.cpp @@ -5844,7 +5844,7 @@ int ObSPIService::spi_copy_ref_cursor(ObPLExecCtx *ctx, if (OB_NOT_NULL(src_cursor) && src_cursor->isopen()) { LOG_DEBUG("copy ref cursor, src ref count: ", K(src_cursor->get_ref_count())); need_inc_ref_cnt = (0 == src_cursor->get_ref_count() && src_cursor->get_is_returning()); - CK (0 < src_cursor->get_ref_count() || need_inc_ref_cnt); + OV (0 < src_cursor->get_ref_count() || need_inc_ref_cnt, OB_ERR_UNEXPECTED, KPC(src_cursor), K(need_inc_ref_cnt)); // 到了这里先把returning状态重置,ref count先不加,等赋值成功再加 OX (src_cursor->set_is_returning(false)); } diff --git a/src/sql/resolver/ddl/ob_create_routine_resolver.cpp b/src/sql/resolver/ddl/ob_create_routine_resolver.cpp index ea6a90f2f0..fb6b459a55 100644 --- a/src/sql/resolver/ddl/ob_create_routine_resolver.cpp +++ b/src/sql/resolver/ddl/ob_create_routine_resolver.cpp @@ -780,7 +780,7 @@ int ObCreateRoutineResolver::resolve_aggregate_body( const ParseNode *parse_node, ObRoutineInfo &routine_info) { int ret = OB_SUCCESS; - ObString db_name, type_name; + ObString db_name, type_name, real_db_name; const share::schema::ObUDTTypeInfo *udt_info = NULL; CK (OB_NOT_NULL(parse_node), OB_NOT_NULL(session_info_)); @@ -790,16 +790,56 @@ int ObCreateRoutineResolver::resolve_aggregate_body( CK (OB_NOT_NULL(parse_node->children_[0])); OZ (ObResolverUtils::resolve_sp_name( - *session_info_, *(parse_node->children_[0]), db_name, type_name)); + *session_info_, *(parse_node->children_[0]), db_name, type_name, false)); + + if (OB_SUCC(ret)) { + if (db_name.empty()) { + if (session_info_->get_database_name().empty() || OB_INVALID_ID == session_info_->get_database_id()) { + ret = OB_ERR_NO_DB_SELECTED; + LOG_USER_ERROR(OB_ERR_NO_DB_SELECTED); + LOG_WARN("No Database Selected", K(ret)); + } else { + real_db_name = session_info_->get_database_name(); + } + } else { + real_db_name = db_name; + } + } + OZ (schema_checker_->get_udt_info( - session_info_->get_effective_tenant_id(), db_name, type_name, udt_info)); + session_info_->get_effective_tenant_id(), real_db_name, type_name, udt_info)); if (OB_ISNULL(udt_info) // try sys udt - && (db_name.case_compare(OB_ORA_SYS_SCHEMA_NAME) - || db_name.case_compare(OB_SYS_DATABASE_NAME))) { + && (0 == real_db_name.case_compare(OB_ORA_SYS_SCHEMA_NAME) + || 0 == real_db_name.case_compare(OB_SYS_DATABASE_NAME))) { OZ (schema_checker_->get_udt_info( OB_SYS_TENANT_ID, OB_SYS_DATABASE_NAME, type_name, udt_info)); } + if (OB_ISNULL(udt_info) && ret != OB_ERR_NO_DB_SELECTED) { // try synonym + uint64_t tenant_id = session_info_->get_effective_tenant_id(); + uint64_t database_id = session_info_->get_database_id(); + ObSEArray syn_id_array; + if (!db_name.empty() // try database name synonym + && (OB_FAIL(schema_checker_->get_database_id(tenant_id, db_name, database_id)) + || OB_INVALID_ID == database_id)) { + database_id = session_info_->get_database_id(); + OZ (schema_checker_->get_obj_info_recursively_with_synonym( + tenant_id, database_id, db_name, database_id, db_name, syn_id_array, true)); + OZ (schema_checker_->get_udt_info(tenant_id, db_name, type_name, udt_info)); + } else { // try type name synonym + OZ (schema_checker_->get_obj_info_recursively_with_synonym( + tenant_id, database_id, type_name, database_id, type_name, syn_id_array, true)); + if (database_id != session_info_->get_database_id()) { + const share::schema::ObDatabaseSchema *database_schema = NULL; + OZ (schema_checker_->get_database_schema(tenant_id, database_id, database_schema)); + CK (OB_NOT_NULL(database_schema)); + OX (real_db_name = database_schema->get_database_name_str()); + } + OZ (schema_checker_->get_udt_info(tenant_id, real_db_name, type_name, udt_info)); + } + } + + if (OB_SUCC(ret) && OB_ISNULL(udt_info)) { ret = OB_ERR_SP_UNDECLARED_VAR; LOG_WARN("PLS-00201: identifier type_name must be declared", diff --git a/src/sql/resolver/expr/ob_raw_expr_printer.cpp b/src/sql/resolver/expr/ob_raw_expr_printer.cpp index 0b20fd0e02..b7d4569033 100644 --- a/src/sql/resolver/expr/ob_raw_expr_printer.cpp +++ b/src/sql/resolver/expr/ob_raw_expr_printer.cpp @@ -709,11 +709,18 @@ int ObRawExprPrinter::print(ObOpRawExpr *expr) case T_OBJ_ACCESS_REF: { ObObjAccessRawExpr *obj_access_expr = static_cast(expr); bool parent_is_table = false; - for (int64_t i = 0; OB_SUCC(ret) && i < obj_access_expr->get_orig_access_idxs().count(); ++i) { - pl::ObObjAccessIdx ¤t_idx = obj_access_expr->get_orig_access_idxs().at(i); + ObIArray &access_idxs = obj_access_expr->get_orig_access_idxs(); + int64_t start = access_idxs.count() - 1; + for (;start > 0; --start) { + if (OB_NOT_NULL(access_idxs.at(start).get_sysfunc_)) { + break; + } + } + for (int64_t i = start; OB_SUCC(ret) && i < access_idxs.count(); ++i) { + pl::ObObjAccessIdx ¤t_idx = access_idxs.at(i); if (parent_is_table) { DATA_PRINTF("("); - } else if (i > 0) { + } else if (i > start) { DATA_PRINTF("."); } if (OB_NOT_NULL(current_idx.get_sysfunc_)) { diff --git a/src/sql/resolver/expr/ob_raw_expr_resolver_impl.cpp b/src/sql/resolver/expr/ob_raw_expr_resolver_impl.cpp index 6ba90a3b55..0c8d5c76de 100644 --- a/src/sql/resolver/expr/ob_raw_expr_resolver_impl.cpp +++ b/src/sql/resolver/expr/ob_raw_expr_resolver_impl.cpp @@ -2573,11 +2573,17 @@ int ObRawExprResolverImpl::process_datatype_or_questionmark(const ParseNode &nod CK (OB_NOT_NULL(var = symbol_table->get_symbol(val.get_unknown()))); if (OB_SUCC(ret)) { if (0 == var->get_name().case_compare(pl::ObPLResolver::ANONYMOUS_ARG)) { - CK (OB_NOT_NULL(var->get_type().get_meta_type())); - CK (OB_NOT_NULL(var->get_type().get_data_type())); - OX (c_expr->set_meta_type(*var->get_type().get_meta_type())); - OX (c_expr->set_expr_obj_meta(*var->get_type().get_meta_type())); - OX (c_expr->set_accuracy(var->get_type().get_data_type()->get_accuracy())); + if (OB_NOT_NULL(var->get_type().get_meta_type())) { + CK (OB_NOT_NULL(var->get_type().get_data_type())); + OX (c_expr->set_meta_type(*var->get_type().get_meta_type())); + OX (c_expr->set_expr_obj_meta(*var->get_type().get_meta_type())); + OX (c_expr->set_accuracy(var->get_type().get_data_type()->get_accuracy())); + } else { + ObObjMeta meta; + OX (meta.set_type(ObExtendType)); + OX (c_expr->set_meta_type(meta)); + OX (c_expr->set_udt_id(var->get_type().get_user_type_id())); + } } } }