From 2ff985ffddd4769c928f760a6bdb99b1da94435f Mon Sep 17 00:00:00 2001 From: obdev Date: Thu, 15 Dec 2022 10:37:54 +0000 Subject: [PATCH] Fix ps prepare stage type deduction failure --- src/sql/ob_sql.cpp | 1 + src/sql/optimizer/ob_optimizer_util.cpp | 25 ++++++++++++---- src/sql/plan_cache/ob_ps_cache.h | 18 ++++++++++++ .../resolver/expr/ob_raw_expr_deduce_type.cpp | 29 +++++++++++++++---- src/sql/session/ob_sql_session_info.cpp | 1 + src/sql/session/ob_sql_session_info.h | 3 ++ 6 files changed, 66 insertions(+), 11 deletions(-) diff --git a/src/sql/ob_sql.cpp b/src/sql/ob_sql.cpp index 1399b390a..3418c4750 100644 --- a/src/sql/ob_sql.cpp +++ b/src/sql/ob_sql.cpp @@ -922,6 +922,7 @@ int ObSql::do_real_prepare(const ObString &sql, context.is_dynamic_sql_ = !context.is_dynamic_sql_ ? !is_inner_sql : context.is_dynamic_sql_; bool is_from_pl = (NULL != context.secondary_namespace_ || result.is_simple_ps_protocol()); + ObPsPrepareStatusGuard ps_status_guard(session, is_from_pl); ObPlanCacheCtx pc_ctx(sql, true, /*is_ps_mode*/ allocator, context, ectx, session.get_effective_tenant_id()); ParamStore param_store( (ObWrapperAllocator(&allocator)) ); diff --git a/src/sql/optimizer/ob_optimizer_util.cpp b/src/sql/optimizer/ob_optimizer_util.cpp index e14b07cb8..7c73f4a46 100644 --- a/src/sql/optimizer/ob_optimizer_util.cpp +++ b/src/sql/optimizer/ob_optimizer_util.cpp @@ -5954,6 +5954,7 @@ int ObOptimizerUtil::try_add_cast_to_set_child_list(ObIAllocator *allocator, ObSEArray types; ObExprVersion dummy_op(*allocator); ObCollationType coll_type = CS_TYPE_INVALID; + bool skip_add_cast = false; if (lib::is_oracle_mode()) { /* * Oracle has more strict constraints for data types used in set operator @@ -5972,9 +5973,15 @@ int ObOptimizerUtil::try_add_cast_to_set_child_list(ObIAllocator *allocator, && (ob_is_oracle_temporal_type(right_type.get_type()))) || (left_type.is_urowid() && right_type.is_urowid()) || (left_type.is_lob() && right_type.is_lob() && !is_distinct))) { - ret = OB_ERR_EXP_NEED_SAME_DATATYPE; - LOG_WARN("expression must have same datatype as corresponding expression", K(ret), - K(i), K(left_type), K(right_type)); + if (session_info->is_ps_prepare_stage()) { + skip_add_cast = true; + LOG_WARN("ps prepare stage expression has different datatype", K(i), K(left_type), K(right_type)); + } else { + ret = OB_ERR_EXP_NEED_SAME_DATATYPE; + LOG_WARN("expression must have same datatype as corresponding expression", K(ret), + K(session_info->is_ps_prepare_stage()), K(right_type.is_varchar_or_char()), + K(i), K(left_type), K(right_type)); + } } else if (left_type.is_character_type() && right_type.is_character_type() && (left_type.is_varchar_or_char() != right_type.is_varchar_or_char())) { @@ -5998,7 +6005,7 @@ int ObOptimizerUtil::try_add_cast_to_set_child_list(ObIAllocator *allocator, } const ObLengthSemantics length_semantics = session_info->get_actual_nls_length_semantics(); if (OB_FAIL(ret)) { - } else if (to_left_type) { + } else if (to_left_type || skip_add_cast) { res_type = left_type; } else if (OB_FAIL(types.push_back(left_type)) || OB_FAIL(types.push_back(right_type))) { LOG_WARN("failed to push back", K(ret)); @@ -6006,9 +6013,15 @@ int ObOptimizerUtil::try_add_cast_to_set_child_list(ObIAllocator *allocator, LOG_WARN("failed to get collation connection", K(ret)); } else if (OB_FAIL(dummy_op.aggregate_result_type_for_merge(res_type, &types.at(0), 2, coll_type, is_oracle_mode(), length_semantics, session_info))) { - LOG_WARN("failed to aggregate result type for merge", K(ret)); + if (session_info->is_ps_prepare_stage()) { + skip_add_cast = true; + res_type = left_type; + LOG_WARN("failed to deduce type in ps prepare stage", K(types)); + } else { + LOG_WARN("failed to aggregate result type for merge", K(ret)); + } } - if (OB_FAIL(ret)) { + if (OB_FAIL(ret) || skip_add_cast) { } else if (ObMaxType == res_type.get_type()) { ret = OB_ERR_INVALID_TYPE_FOR_OP; LOG_WARN("column type incompatible", K(left_type), K(right_type)); diff --git a/src/sql/plan_cache/ob_ps_cache.h b/src/sql/plan_cache/ob_ps_cache.h index 3e366346e..7ba1937ae 100644 --- a/src/sql/plan_cache/ob_ps_cache.h +++ b/src/sql/plan_cache/ob_ps_cache.h @@ -32,6 +32,24 @@ using common::ObPsStmtId; namespace sql { +class ObPsPrepareStatusGuard final +{ +public: + explicit ObPsPrepareStatusGuard(ObSQLSessionInfo &session_info, bool is_from_pl) + : session_info_(session_info) + { + if (!is_from_pl) { + session_info_.set_is_ps_prepare_stage(true); + } + } + ~ObPsPrepareStatusGuard() + { + session_info_.set_is_ps_prepare_stage(false); + } +private: + ObSQLSessionInfo &session_info_; +}; + class ObPsCache { public: 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 8a682e38a..a6f600585 100644 --- a/src/sql/resolver/expr/ob_raw_expr_deduce_type.cpp +++ b/src/sql/resolver/expr/ob_raw_expr_deduce_type.cpp @@ -226,6 +226,11 @@ int ObRawExprDeduceType::calc_result_type_with_const_arg( break; } // end switch } + if (OB_FAIL(ret) && my_session_->is_ps_prepare_stage()) { + // the ps prepare stage does not do type deduction, and directly gives a default type. + result_type.set_null(); + ret = OB_SUCCESS; + } } #undef GET_TYPE_ARRAY return ret; @@ -396,6 +401,11 @@ int ObRawExprDeduceType::calc_result_type(ObNonTerminalRawExpr &expr, LOG_WARN("fail to calc result type with const arguments", K(ret)); } } + if (OB_FAIL(ret) && my_session_->is_ps_prepare_stage()) { + // the ps prepare stage does not do type deduction, and directly gives a default type. + result_type.set_null(); + ret = OB_SUCCESS; + } // check parameters can cast to expected type if (OB_SUCC(ret)) { const bool is_oracle_mode = lib::is_oracle_mode(); @@ -412,7 +422,8 @@ int ObRawExprDeduceType::calc_result_type(ObNonTerminalRawExpr &expr, LOG_WARN("PLS-00306: wrong number or types of arguments in call", K(ret)); } if (OB_FAIL(ret)) { - } else if (from != to && !cast_supported(from, from_cs_type, to, to_cs_type)) { + } else if (from != to && !cast_supported(from, from_cs_type, to, to_cs_type) + && !my_session_->is_ps_prepare_stage()) { ret = OB_ERR_INVALID_TYPE_FOR_OP; LOG_WARN("cast parameter to expected type not supported", K(ret), K(i), K(from), K(to)); } else if (is_oracle_mode && (ob_is_lob_locator(from) || ob_is_text_tc(from))) { @@ -1188,7 +1199,8 @@ int ObRawExprDeduceType::visit(ObAggFunRawExpr &expr) ? from_type : ObNumberType); if (from_type != to_type && !cast_supported(from_type, from_cs_type, - to_type, CS_TYPE_BINARY)) { + to_type, CS_TYPE_BINARY) + && !my_session_->is_ps_prepare_stage()) { ret = OB_ERR_INVALID_TYPE_FOR_OP; LOG_WARN("cast to expected type not supported", K(ret), K(from_type), K(to_type)); } else { @@ -1312,7 +1324,8 @@ int ObRawExprDeduceType::visit(ObAggFunRawExpr &expr) : (T_FUN_GROUP_PERCENTILE_DISC == expr.get_expr_type() ? from_cs_type : CS_TYPE_BINARY); if (from_type != to_type && !cast_supported(from_type, from_cs_type, - to_type, to_cs_type)) { + to_type, to_cs_type) + && !my_session_->is_ps_prepare_stage()) { ret = OB_ERR_INVALID_TYPE_FOR_OP; LOG_WARN("cast to expected type not supported", K(ret), K(from_type), K(to_type)); } else { @@ -1385,11 +1398,13 @@ int ObRawExprDeduceType::visit(ObAggFunRawExpr &expr) } } if (from_type1 != to_type && !cast_supported(from_type1, from_cs_type1, - to_type, to_cs_type)) { + to_type, to_cs_type) + && !my_session_->is_ps_prepare_stage()) { ret = OB_ERR_INVALID_TYPE_FOR_OP; LOG_WARN("cast to expected type not supported", K(ret), K(from_type1), K(to_type)); } else if (from_type2 != to_type && !cast_supported(from_type2, from_cs_type2, - to_type, to_cs_type)) { + to_type, to_cs_type) + && !my_session_->is_ps_prepare_stage()) { ret = OB_ERR_INVALID_TYPE_FOR_OP; LOG_WARN("cast to expected type not supported", K(ret), K(from_type2), K(to_type)); } else { @@ -2895,6 +2910,10 @@ int ObRawExprDeduceType::try_add_cast_expr(RawExprType &parent, LOG_WARN("cast to lob type not allowed", K(ret)); } OZ(parent.replace_param_expr(child_idx, new_expr)); + if (OB_FAIL(ret) && my_session_->is_ps_prepare_stage()) { + ret = OB_SUCCESS; + LOG_DEBUG("ps prepare phase ignores type deduce error"); + } } } return ret; diff --git a/src/sql/session/ob_sql_session_info.cpp b/src/sql/session/ob_sql_session_info.cpp index dd505cea7..52dce6161 100644 --- a/src/sql/session/ob_sql_session_info.cpp +++ b/src/sql/session/ob_sql_session_info.cpp @@ -168,6 +168,7 @@ ObSQLSessionInfo::ObSQLSessionInfo() : is_load_data_exec_session_(false), is_registered_to_deadlock_(false), pl_exact_err_msg_(), + is_ps_prepare_stage_(false), got_conn_res_(false), tx_level_temp_table_(false), mem_context_(nullptr), diff --git a/src/sql/session/ob_sql_session_info.h b/src/sql/session/ob_sql_session_info.h index 6f468e16a..9efda5e15 100644 --- a/src/sql/session/ob_sql_session_info.h +++ b/src/sql/session/ob_sql_session_info.h @@ -906,6 +906,8 @@ public: } bool is_registered_to_deadlock() const { return ATOMIC_LOAD(&is_registered_to_deadlock_); } void set_registered_to_deadlock(bool state) { ATOMIC_SET(&is_registered_to_deadlock_, state); } + bool is_ps_prepare_stage() const { return is_ps_prepare_stage_; } + void set_is_ps_prepare_stage(bool v) { is_ps_prepare_stage_ = v; } int get_tenant_audit_trail_type(ObAuditTrailType &at_type) { cached_tenant_config_info_.refresh(); @@ -1080,6 +1082,7 @@ private: // 记录session是否注册过死锁检测的信息 bool is_registered_to_deadlock_; ObSqlString pl_exact_err_msg_; + bool is_ps_prepare_stage_; // Record whether this session has got connection resource, which means it increased connections count. // It's used for on_user_disconnect. // No matter whether apply for resource successfully, a session will call on_user_disconnect when disconnect.