From 78662489b862ad87ec68a9e18f48b001fdbd7bb7 Mon Sep 17 00:00:00 2001 From: obdev Date: Mon, 6 Feb 2023 13:34:20 +0800 Subject: [PATCH] [to #47144085] fix pkg/subprogram cursor with default parameter --- src/pl/ob_pl_package_state.cpp | 9 +- src/pl/ob_pl_resolver.cpp | 17 ++- .../engine/expr/ob_expr_get_package_var.cpp | 8 +- src/sql/ob_spi.cpp | 128 ++++++++++++++---- src/sql/ob_spi.h | 16 +++ .../cmd/ob_call_procedure_resolver.cpp | 2 +- 6 files changed, 141 insertions(+), 39 deletions(-) diff --git a/src/pl/ob_pl_package_state.cpp b/src/pl/ob_pl_package_state.cpp index cb6b8d1337..f00a4a70e4 100644 --- a/src/pl/ob_pl_package_state.cpp +++ b/src/pl/ob_pl_package_state.cpp @@ -52,7 +52,9 @@ bool ObPackageStateVersion::operator ==(const ObPackageStateVersion &other) { bool b_ret = true; if (package_version_ != other.package_version_ - || package_body_version_ != other.package_body_version_) { + || (package_body_version_ != OB_INVALID_VERSION + && other.package_body_version_ != OB_INVALID_VERSION + && package_body_version_ != other.package_body_version_)) { b_ret = false; } return b_ret; @@ -179,6 +181,7 @@ void ObPLPackageState::reset(ObSQLSessionInfo *session_info) types_.reset(); vars_.reset(); inner_allocator_.reset(); + cursor_allocator_.reset(); } int ObPLPackageState::set_package_var_val(const int64_t var_idx, const ObObj &value) @@ -197,6 +200,10 @@ int ObPLPackageState::set_package_var_val(const int64_t var_idx, const ObObj &va LOG_WARN("failed to alloc memory for pacakge var", K(ret), K(buf)); } OZ (vars_.at(var_idx).deep_copy(value, buf, value.get_deep_copy_size(), pos)); + } else if (value.is_pl_extend()) { + ObObj copy; + OZ (ObUserDefinedType::deep_copy_obj(inner_allocator_, value, copy)); + OX (vars_.at(var_idx) = copy); } else { vars_.at(var_idx) = value; } diff --git a/src/pl/ob_pl_resolver.cpp b/src/pl/ob_pl_resolver.cpp index 10dd3eb03d..3d1da6cad3 100644 --- a/src/pl/ob_pl_resolver.cpp +++ b/src/pl/ob_pl_resolver.cpp @@ -5995,7 +5995,7 @@ int ObPLResolver::resolve_cparams(ObIArray &exprs, ObConstRawExpr *default_expr = NULL; OZ (ObRawExprUtils::build_const_int_expr(expr_factory_, ObIntType, 0, default_expr)); CK (OB_NOT_NULL(default_expr)); - OZ(default_expr->add_flag(IS_PL_MOCK_DEFAULT_EXPR)); + OZ (default_expr->add_flag(IS_PL_MOCK_DEFAULT_EXPR)); OZ (func.add_expr(default_expr)); OZ (resolve_cparam_without_assign(default_expr, i, func, params, expr_idx)); } @@ -6005,9 +6005,14 @@ int ObPLResolver::resolve_cparams(ObIArray &exprs, int64_t default_idx = static_cast(formal_param)->get_default(); if (OB_UNLIKELY(-1 == default_idx)) { ret = OB_ERR_SP_WRONG_ARG_NUM; - LOG_WARN("actual param expr is null", K(formal_param), K(ret)); + LOG_WARN("actual param expr is null", KPC(formal_param), KPC(static_cast(formal_param)), K(ret)); } else { - OX (expr_idx.at(i) = default_idx); + ObConstRawExpr *default_expr = NULL; + OZ (ObRawExprUtils::build_const_int_expr(expr_factory_, ObIntType, default_idx, default_expr)); + CK (OB_NOT_NULL(default_expr)); + OZ (default_expr->add_flag(IS_PL_MOCK_DEFAULT_EXPR)); + OZ (func.add_expr(default_expr)); + OZ (resolve_cparam_without_assign(default_expr, i, func, params, expr_idx)); } } else { ret = OB_ERR_UNEXPECTED; @@ -6795,8 +6800,10 @@ int ObPLResolver::resolve_cursor_actual_params( OZ (iparams.push_back(const_cast(var))); } else if (cursor->get_routine_id() != stmt->get_namespace()->get_routine_id()) { // not package cursor, not local cursor, must be subprogram cursor. - OZ (stmt->get_namespace()->get_cursor_var( - cursor->get_package_id(), cursor->get_routine_id(), cursor->get_index(), var)); + OZ (stmt->get_namespace()->get_subprogram_var(cursor->get_package_id(), + cursor->get_routine_id(), + params_list.at(i), + var)); CK (OB_NOT_NULL(var)); OZ (iparams.push_back(const_cast(var))); } else { diff --git a/src/sql/engine/expr/ob_expr_get_package_var.cpp b/src/sql/engine/expr/ob_expr_get_package_var.cpp index 915d425a69..bd9c8f0bac 100644 --- a/src/sql/engine/expr/ob_expr_get_package_var.cpp +++ b/src/sql/engine/expr/ob_expr_get_package_var.cpp @@ -130,18 +130,18 @@ int ObExprGetPackageVar::eval_get_package_var(const ObExpr &expr, } else if (package_id->is_null() || var_idx->is_null() || result_type->is_null() - || spec_version->is_null() - || body_version->is_null()) { + || spec_version->is_null()) { res.set_null(); } else { ObObj res_obj; OZ(calc(res_obj, package_id->get_uint(), spec_version->get_int(), - body_version->get_int(), + body_version->is_null() ? OB_INVALID_VERSION : body_version->get_int(), var_idx->get_int(), &ctx.exec_ctx_, - ctx.exec_ctx_.get_my_session())); + ctx.exec_ctx_.get_my_session()), + KPC(package_id), KPC(spec_version), KPC(body_version), KPC(var_idx)); if (OB_SUCC(ret)) { if (ob_is_string_tc(res_obj.get_type())) { ObString res_str; diff --git a/src/sql/ob_spi.cpp b/src/sql/ob_spi.cpp index cbd0c29aa4..c1639dc798 100644 --- a/src/sql/ob_spi.cpp +++ b/src/sql/ob_spi.cpp @@ -868,6 +868,41 @@ int ObSPIService::spi_calc_expr(ObPLExecCtx *ctx, return ret; } +int ObSPIService::spi_calc_subprogram_expr(ObPLExecCtx *ctx, + uint64_t package_id, + uint64_t routine_id, + int64_t expr_idx, + ObObjParam *result) +{ + int ret = OB_SUCCESS; + ObExecContext *exec_ctx = NULL; + ObSQLSessionInfo *session_info = NULL; + ObPLExecState *state = NULL; + ObSqlExpression *expr = NULL; + CK (OB_NOT_NULL(exec_ctx = ctx->exec_ctx_)); + CK (OB_NOT_NULL(session_info = exec_ctx->get_my_session())); + OZ (ObPLContext::get_exec_state_from_local(*session_info, package_id, routine_id, state)); + CK (OB_NOT_NULL(state)); + CK (OB_NOT_NULL(exec_ctx = state->get_exec_ctx().exec_ctx_)); + CK (OB_NOT_NULL(expr = state->get_function().get_default_expr(expr_idx))); + if (OB_SUCC(ret)) { + ExecCtxBak exec_ctx_bak; + OX (exec_ctx_bak.backup(*exec_ctx)); + OX (exec_ctx->set_physical_plan_ctx(&(state->get_physical_plan_ctx()))); + if (OB_SUCC(ret) && state->get_function().get_expr_op_size() > 0) { + OZ (exec_ctx->init_expr_op(state->get_function().get_expr_op_size())); + } + OZ (state->get_function().get_frame_info().pre_alloc_exec_memory(*exec_ctx)); + OZ (spi_calc_expr(&(state->get_exec_ctx()), expr, OB_INVALID_ID, result), KPC(expr)); + if (state->get_function().get_expr_op_size() > 0) { + exec_ctx->reset_expr_op(); + exec_ctx->get_allocator().free(exec_ctx->get_expr_op_ctx_store()); + } + exec_ctx_bak.restore(*exec_ctx); + } + return ret; +} + int ObSPIService::spi_calc_package_expr(ObPLExecCtx *ctx, uint64_t package_id, int64_t expr_idx, @@ -3040,6 +3075,68 @@ int ObSPIService::dbms_dynamic_open(ObPLExecCtx *pl_ctx, return ret; } +int ObSPIService::prepare_cursor_parameters(ObPLExecCtx *ctx, + ObSQLSessionInfo &session_info, + uint64_t package_id, + uint64_t routine_id, + ObCusorDeclareLoc loc, + const int64_t *formal_param_idxs, + const ObSqlExpression **actual_param_exprs, + int64_t cursor_param_count) +{ + int ret = OB_SUCCESS; + + ObObjParam dummy_result; + + for (int64_t i = 0; OB_SUCC(ret) && i < cursor_param_count; ++i) { + + CK (OB_NOT_NULL(actual_param_exprs[i])); + OX (dummy_result.reset()); + OX (dummy_result.ObObj::reset()); + OZ (spi_calc_expr(ctx, actual_param_exprs[i], OB_INVALID_INDEX, &dummy_result), + K(i), K(cursor_param_count), KPC(actual_param_exprs[i]), K(dummy_result)); + + if (OB_SUCC(ret) && dummy_result.is_pl_mock_default_param()) { + ObSqlExpression *actual_param_expr = NULL; + if (DECL_PKG == loc) { + OZ (spi_calc_package_expr(ctx, package_id, dummy_result.get_int(), &dummy_result)); + } else { + OZ (spi_calc_subprogram_expr(ctx, package_id, routine_id, dummy_result.get_int(), &dummy_result)); + } + } + + if (OB_FAIL(ret)) { + } else if (DECL_PKG == loc) { + OZ (spi_set_package_variable(ctx, package_id, formal_param_idxs[i], dummy_result)); + } else if (DECL_SUBPROG == loc) { + OZ (ObPLContext::set_subprogram_var_from_local( + session_info, package_id, routine_id, formal_param_idxs[i], dummy_result)); + } else { + int64_t result_idx = formal_param_idxs[i]; + CK (DECL_LOCAL == loc); + CK (result_idx >= 0 && result_idx < ctx->params_->count()); + if (OB_SUCC(ret)) { + ObObjParam ¶m = ctx->params_->at(result_idx); + bool is_ref_cursor = param.is_ref_cursor_type(); + if (!dummy_result.is_ext()) { + dummy_result.ObObj::set_scale(param.get_meta().get_scale()); + dummy_result.set_accuracy(ctx->params_->at(result_idx).get_accuracy()); + param = dummy_result; + param.set_is_ref_cursor_type(is_ref_cursor); + param.set_param_meta(); + } else if (!is_ref_cursor) { + int64_t orig_udt_id = ctx->params_->at(result_idx).get_udt_id(); + ctx->params_->at(result_idx) = dummy_result; + ctx->params_->at(result_idx).set_udt_id(orig_udt_id); + ctx->params_->at(result_idx).set_param_meta(); + } + } + } + } + + return ret; +} + int ObSPIService::spi_cursor_open(ObPLExecCtx *ctx, const char *sql, const char *ps_sql, @@ -3070,13 +3167,8 @@ int ObSPIService::spi_cursor_open(ObPLExecCtx *ctx, LOG_WARN("Argument passed in is NULL", K(ctx), K(sql), K(ps_sql), K(type), K(sql_param_exprs), K(sql_param_count), K(ret)); } else if (OB_FAIL(spi_get_cursor_info(ctx, package_id, routine_id, cursor_index, cursor, cursor_var, loc))) { LOG_WARN("failed to get cursor info", K(ret), K(cursor_index)); - // } else if (OB_ISNULL(cursor)) { - // } else if (!cursor_var.is_ext()) { - // ret = OB_INVALID_ARGUMENT; - // LOG_WARN("cursor var in is null", K(ret)); } else if (OB_FAIL(cursor_open_check(ctx, package_id, routine_id, cursor_index, cursor, cursor_var, loc))) { - // ret = OB_INVALID_ARGUMENT; LOG_WARN("cursor info not init", K(ret), K(cursor)); } else if (cursor->isopen()) { ret = OB_ER_SP_CURSOR_ALREADY_OPEN; @@ -3100,29 +3192,9 @@ int ObSPIService::spi_cursor_open(ObPLExecCtx *ctx, LOG_WARN("cursor params in not valid", K(cursor_param_count), K(formal_param_idxs), K(actual_param_exprs), K(ret)); } else { - ObObjParam dummy_result; - for (int64_t i = 0; OB_SUCC(ret) && i < cursor_param_count; ++i) { - CK (OB_NOT_NULL(actual_param_exprs[i])); - OX (dummy_result.reset()); - OX (dummy_result.ObObj::reset()); - OZ (spi_calc_expr( - ctx, - actual_param_exprs[i], - DECL_LOCAL == loc ? formal_param_idxs[i] : OB_INVALID_INDEX, - &dummy_result), - i, cursor_param_count, *actual_param_exprs[i], dummy_result); - if (OB_SUCC(ret)) { - if (DECL_PKG == loc) { - OZ (spi_set_package_variable(ctx, package_id, formal_param_idxs[i], dummy_result)); - } else if (DECL_SUBPROG == loc) { - OZ (ObPLContext::set_subprogram_var_from_local(*session_info, - package_id, - routine_id, - formal_param_idxs[i], - dummy_result)); - } else { /* do nothing */ } - } - } + OZ (prepare_cursor_parameters( + ctx, *session_info, package_id, + routine_id, loc, formal_param_idxs, actual_param_exprs, cursor_param_count)); } if (OB_SUCC(ret) && DECL_SUBPROG == loc) { diff --git a/src/sql/ob_spi.h b/src/sql/ob_spi.h index a4ae41879a..6462586197 100644 --- a/src/sql/ob_spi.h +++ b/src/sql/ob_spi.h @@ -319,6 +319,13 @@ public: const ObSqlExpression *expr, const int64_t result_idx, ObObjParam *result); + + static int spi_calc_subprogram_expr(pl::ObPLExecCtx *ctx, + uint64_t package_id, + uint64_t routine_id, + int64_t expr_idx, + ObObjParam *result); + static int spi_calc_package_expr(pl::ObPLExecCtx *ctx, uint64_t package_id, int64_t expr_idx, @@ -945,6 +952,15 @@ private: const ObSqlExpression &expr, ObIArray &src_array, ObIArray &dst_array); + + static int prepare_cursor_parameters(pl::ObPLExecCtx *ctx, + ObSQLSessionInfo &session_info, + uint64_t package_id, + uint64_t routine_id, + ObCusorDeclareLoc loc, + const int64_t *formal_param_idxs, + const ObSqlExpression **actual_param_exprs, + int64_t cursor_param_count); }; } diff --git a/src/sql/resolver/cmd/ob_call_procedure_resolver.cpp b/src/sql/resolver/cmd/ob_call_procedure_resolver.cpp index 669b58be22..c952eafe40 100644 --- a/src/sql/resolver/cmd/ob_call_procedure_resolver.cpp +++ b/src/sql/resolver/cmd/ob_call_procedure_resolver.cpp @@ -99,7 +99,7 @@ int ObCallProcedureResolver::resolve_cparams(const ParseNode *params_node, OZ (ObRawExprUtils::build_const_int_expr( *(params_.expr_factory_), ObIntType, 0, default_expr)); CK (OB_NOT_NULL(default_expr)); - OZ(default_expr->add_flag(IS_PL_MOCK_DEFAULT_EXPR)); + OZ (default_expr->add_flag(IS_PL_MOCK_DEFAULT_EXPR)); OX (params.at(i) = default_expr); } } -- GitLab