diff --git a/src/pl/ob_pl_resolver.cpp b/src/pl/ob_pl_resolver.cpp index fe37cdac4..4fdd53cb9 100644 --- a/src/pl/ob_pl_resolver.cpp +++ b/src/pl/ob_pl_resolver.cpp @@ -10465,6 +10465,7 @@ int ObPLResolver::transform_subquery_expr(const ParseNode *node, } OX (subquery_expr->set_subquery_result_type(result_type)); + OX (subquery_expr->set_enum_set_values(expected_type->get_type_info())); OX (expr = subquery_expr); } else { ret = OB_ERR_UNEXPECTED; diff --git a/src/sql/code_generator/ob_expr_generator_impl.cpp b/src/sql/code_generator/ob_expr_generator_impl.cpp index b4bc04657..b848fa159 100644 --- a/src/sql/code_generator/ob_expr_generator_impl.cpp +++ b/src/sql/code_generator/ob_expr_generator_impl.cpp @@ -457,6 +457,7 @@ int ObExprGeneratorImpl::visit(ObPlQueryRefRawExpr &expr) OX (pl_subquery->set_stmt_type(expr.get_stmt_type())); OZ (pl_subquery->deep_copy_route_sql(expr.get_route_sql())); OX (pl_subquery->set_result_type(expr.get_subquery_result_type())); + OZ (pl_subquery->set_type_info(expr.get_enum_set_values())); if (OB_SUCC(ret) && expr.is_ignore_fail()) { pl_subquery->set_ignore_fail(); } diff --git a/src/sql/engine/expr/ob_pl_expr_subquery.cpp b/src/sql/engine/expr/ob_pl_expr_subquery.cpp index 9598d607f..c10b692be 100644 --- a/src/sql/engine/expr/ob_pl_expr_subquery.cpp +++ b/src/sql/engine/expr/ob_pl_expr_subquery.cpp @@ -31,7 +31,7 @@ namespace sql OB_SERIALIZE_MEMBER( (ObExprOpSubQueryInPl, ObFuncExprOperator), - id_, type_, route_sql_, result_type_, is_ignore_fail_, ps_sql_); + id_, type_, route_sql_, result_type_, is_ignore_fail_, ps_sql_, type_info_); ObExprOpSubQueryInPl::ObExprOpSubQueryInPl(common::ObIAllocator &alloc) @@ -44,10 +44,39 @@ ObExprOpSubQueryInPl::ObExprOpSubQueryInPl(common::ObIAllocator &alloc) route_sql_(ObString()), result_type_(), is_ignore_fail_(false), - allocator_(alloc) {} + allocator_(alloc), + type_info_() {} ObExprOpSubQueryInPl::~ObExprOpSubQueryInPl() {} +int ObExprOpSubQueryInPl::deep_copy_type_info(common::ObIArray& dst_type_info, + common::ObIAllocator &allocator, + const common::ObIArray& type_info) +{ + int ret = OB_SUCCESS; + if (OB_SUCC(ret)) { + dst_type_info.reset(); + for (int64_t i = 0; OB_SUCC(ret) && i < type_info.count(); ++i) { + const ObString &info = type_info.at(i); + if (OB_UNLIKELY(0 == info.length())) { + if (OB_FAIL(dst_type_info.push_back(ObString(0, NULL)))) { + LOG_WARN("fail to push back info", K(i), K(info), K(ret)); + } + } else { + char *buf = NULL; + if (OB_ISNULL(buf = static_cast(allocator.alloc(info.length())))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("fail to allocate memory", K(i), K(info), K(ret)); + } else if (FALSE_IT(MEMCPY(buf, info.ptr(), info.length()))) { + } else if (OB_FAIL(dst_type_info.push_back(ObString(info.length(), buf)))) { + LOG_WARN("fail to push back info", K(i), K(info), K(ret)); + } + } + } + } + return ret; +} + int ObExprOpSubQueryInPl::assign(const ObExprOperator &other) { int ret = OB_SUCCESS; @@ -64,6 +93,7 @@ int ObExprOpSubQueryInPl::assign(const ObExprOperator &other) OX (this->result_type_ = tmp_other->result_type_); OZ (deep_copy_route_sql(tmp_other->route_sql_)); OX (this->is_ignore_fail_ = tmp_other->is_ignore_fail_); + OZ (ObExprOpSubQueryInPl::deep_copy_type_info(type_info_, allocator_, tmp_other->type_info_)); } } return ret; @@ -233,7 +263,8 @@ int ObExprOpSubQueryInPl::eval_subquery(const ObExpr &expr, result, info->result_type_, conv_res, - info->is_ignore_fail_)); + info->is_ignore_fail_, + &info->type_info_)); if (OB_FAIL(ret)) { LOG_WARN("convert type error", K(ret)); } else { @@ -342,7 +373,8 @@ OB_DEF_SERIALIZE(ObExprPlSubQueryInfo) route_sql_, result_type_, is_ignore_fail_, - ps_sql_); + ps_sql_, + type_info_); return ret; } @@ -355,7 +387,8 @@ OB_DEF_DESERIALIZE(ObExprPlSubQueryInfo) route_sql_, result_type_, is_ignore_fail_, - ps_sql_); + ps_sql_, + type_info_); return ret; } @@ -368,10 +401,13 @@ OB_DEF_SERIALIZE_SIZE(ObExprPlSubQueryInfo) route_sql_, result_type_, is_ignore_fail_, - ps_sql_); + ps_sql_, + type_info_); return len; } + + int ObExprPlSubQueryInfo::deep_copy(common::ObIAllocator &allocator, const ObExprOperatorType type, ObIExprExtraInfo *&copied_info) const @@ -385,6 +421,7 @@ int ObExprPlSubQueryInfo::deep_copy(common::ObIAllocator &allocator, OZ(ob_write_string(allocator, route_sql_, other.route_sql_, true)); OZ(ob_write_string(allocator, ps_sql_, other.ps_sql_, true)); + OZ(ObExprOpSubQueryInPl::deep_copy_type_info(other.type_info_, allocator, type_info_)); return ret; } @@ -402,6 +439,7 @@ int ObExprPlSubQueryInfo::from_raw_expr(RE &raw_expr, ObIAllocator &alloc) OZ(ob_write_string(alloc, subquery_expr.get_route_sql(), route_sql_, true)); OZ(ob_write_string(alloc, subquery_expr.get_route_sql(), ps_sql_, true)); + OZ(ObExprOpSubQueryInPl::deep_copy_type_info(type_info_, alloc, subquery_expr.get_enum_set_values())); return ret; } diff --git a/src/sql/engine/expr/ob_pl_expr_subquery.h b/src/sql/engine/expr/ob_pl_expr_subquery.h index 73521eded..e64585473 100644 --- a/src/sql/engine/expr/ob_pl_expr_subquery.h +++ b/src/sql/engine/expr/ob_pl_expr_subquery.h @@ -34,7 +34,8 @@ public: type_(stmt::T_NONE), route_sql_(ObString()), result_type_(), - is_ignore_fail_(false) {} + is_ignore_fail_(false), + type_info_() {} virtual int deep_copy(common::ObIAllocator &allocator, const ObExprOperatorType type, @@ -50,6 +51,7 @@ public: common::ObString route_sql_; sql::ObExprResType result_type_; bool is_ignore_fail_; + common::ObSEArray type_info_; }; class ObExprOpSubQueryInPl : public ObFuncExprOperator @@ -69,6 +71,10 @@ public: ObFuncExprOperator::reset(); } + static int deep_copy_type_info(common::ObIArray& dst_type_info, + common::ObIAllocator &allocator, + const common::ObIArray& type_info); + virtual int assign(const ObExprOperator &other); int deep_copy_route_sql(const common::ObString &v) @@ -86,6 +92,11 @@ public: inline void set_result_type(ObExprResType type) { result_type_ = type; } inline void set_ignore_fail() { is_ignore_fail_ = true; } + int set_type_info(const common::ObIArray& type_info) + { + return deep_copy_type_info(type_info_, allocator_, type_info); + } + virtual int cg_expr(ObExprCGCtx &op_cg_ctx, const ObRawExpr &raw_expr, ObExpr &rt_expr) const override; @@ -105,6 +116,7 @@ private: ObExprResType result_type_; bool is_ignore_fail_; common::ObIAllocator &allocator_; + common::ObSEArray type_info_; private: DISALLOW_COPY_AND_ASSIGN(ObExprOpSubQueryInPl); diff --git a/src/sql/ob_spi.cpp b/src/sql/ob_spi.cpp index b2a4dae85..2e234937a 100644 --- a/src/sql/ob_spi.cpp +++ b/src/sql/ob_spi.cpp @@ -758,7 +758,8 @@ int ObSPIService::spi_convert(ObSQLSessionInfo &session, ObObj &src, const ObExprResType &dst_type, ObObj &dst, - bool ignore_fail) + bool ignore_fail, + const ObIArray *type_info) { int ret = OB_SUCCESS; ObCastMode cast_mode = CM_NONE; @@ -776,7 +777,7 @@ int ObSPIService::spi_convert(ObSQLSessionInfo &session, if (dst_type.is_null() || dst_type.is_unknown() || dst_type.is_ext()) { OX (dst = src); } else { - OZ (ObExprColumnConv::convert_with_null_check(dst, src, dst_type, is_strict, cast_ctx, NULL)); + OZ (ObExprColumnConv::convert_with_null_check(dst, src, dst_type, is_strict, cast_ctx, type_info)); } } return ret; diff --git a/src/sql/ob_spi.h b/src/sql/ob_spi.h index f9be7ce8f..477dd1d27 100644 --- a/src/sql/ob_spi.h +++ b/src/sql/ob_spi.h @@ -440,7 +440,9 @@ public: int64_t expr_idx, ObObjParam *result); static int spi_convert(ObSQLSessionInfo &session, ObIAllocator &allocator, - ObObj &src, const ObExprResType &result_type, ObObj &dst, bool ignore_fail = false); + ObObj &src, const ObExprResType &result_type, ObObj &dst, + bool ignore_fail = false, + const ObIArray *type_info = nullptr); static int spi_convert(ObSQLSessionInfo *session, ObIAllocator *allocator, ObObjParam &src, const ObExprResType &result_type, ObObjParam &result); static int spi_convert_objparam(pl::ObPLExecCtx *ctx, ObObjParam *src, const int64_t result_idx, ObObjParam *result, bool need_set); diff --git a/src/sql/resolver/expr/ob_raw_expr_util.cpp b/src/sql/resolver/expr/ob_raw_expr_util.cpp index 1062a598e..d60f92e9e 100644 --- a/src/sql/resolver/expr/ob_raw_expr_util.cpp +++ b/src/sql/resolver/expr/ob_raw_expr_util.cpp @@ -4898,7 +4898,8 @@ int ObRawExprUtils::create_type_to_str_expr(ObRawExprFactory &expr_factory, && !src_expr->is_sys_func_expr() && !src_expr->is_udf_expr() && !src_expr->is_win_func_expr() - && !(src_expr->is_op_expr() && ob_is_enum_or_set_type(src_expr->get_data_type())))) { + && !(src_expr->is_op_expr() && ob_is_enum_or_set_type(src_expr->get_data_type()))) + && src_expr->get_expr_type() != T_FUN_SUBQUERY) { ret = OB_INVALID_ARGUMENT; LOG_WARN("src_expr should be terminal expr or func expr", KPC(src_expr), K(ret)); } else if (FALSE_IT(data_type = src_expr->get_data_type())) {