From 00c32f328ea0e5ecba40154f88964745f04aa18b Mon Sep 17 00:00:00 2001 From: xianyu-w <707512433@qq.com> Date: Mon, 9 Oct 2023 12:39:33 +0000 Subject: [PATCH] Fix core at multiset subquery --- src/sql/code_generator/ob_expr_generator_impl.cpp | 2 +- src/sql/engine/expr/ob_expr_cast.cpp | 2 +- src/sql/engine/expr/ob_expr_subquery_ref.cpp | 2 +- src/sql/optimizer/ob_join_order.cpp | 4 +--- src/sql/optimizer/ob_log_plan.cpp | 4 +--- src/sql/resolver/expr/ob_raw_expr.h | 1 + src/sql/resolver/expr/ob_raw_expr_deduce_type.cpp | 10 +++++----- src/sql/rewrite/ob_transform_pre_process.cpp | 4 ++-- src/sql/rewrite/ob_transform_subquery_coalesce.cpp | 3 +-- src/sql/rewrite/ob_transform_utils.cpp | 4 ++-- 10 files changed, 16 insertions(+), 20 deletions(-) diff --git a/src/sql/code_generator/ob_expr_generator_impl.cpp b/src/sql/code_generator/ob_expr_generator_impl.cpp index 9b38166e61..3c98e02c35 100644 --- a/src/sql/code_generator/ob_expr_generator_impl.cpp +++ b/src/sql/code_generator/ob_expr_generator_impl.cpp @@ -391,7 +391,7 @@ int ObExprGeneratorImpl::visit(ObQueryRefRawExpr &expr) "expr type", get_type_name(expr.get_expr_type())); } else { ObExprSubQueryRef *subquery_op = static_cast(op); - bool result_is_scalar = (expr.get_output_column() == 1 && !expr.is_set() && !expr.is_multiset()); + bool result_is_scalar = expr.is_scalar(); subquery_op->set_result_is_scalar(result_is_scalar); subquery_op->set_result_type(expr.get_result_type()); if (result_is_scalar) { diff --git a/src/sql/engine/expr/ob_expr_cast.cpp b/src/sql/engine/expr/ob_expr_cast.cpp index 30eeca9259..044e23a7f4 100644 --- a/src/sql/engine/expr/ob_expr_cast.cpp +++ b/src/sql/engine/expr/ob_expr_cast.cpp @@ -835,7 +835,7 @@ int ObExprCast::fill_element(const sql::ObExpr &expr, } else { const ObDatum &d = *subquery_datum; ObObj v, v2; - if (OB_FAIL(d.to_obj(v, expr.args_[0]->obj_meta_, expr.args_[0]->obj_datum_map_))) { + if (OB_FAIL(d.to_obj(v, subquery_row[0]->obj_meta_, subquery_row[0]->obj_datum_map_))) { LOG_WARN("failed to get obj", K(ret), K(d)); } else if (info->not_null_) { if (v.is_null()) { diff --git a/src/sql/engine/expr/ob_expr_subquery_ref.cpp b/src/sql/engine/expr/ob_expr_subquery_ref.cpp index e862c320f3..cb1548face 100644 --- a/src/sql/engine/expr/ob_expr_subquery_ref.cpp +++ b/src/sql/engine/expr/ob_expr_subquery_ref.cpp @@ -72,7 +72,7 @@ int ObExprSubQueryRef::ExtraInfo::init_cursor_info(ObIAllocator *allocator, LOG_WARN("fail to alloc memory", K(ret)); } else { cursor_info = new(buf) ExtraInfo(*allocator, type); - bool result_is_scalar = (expr.get_output_column() == 1 && !expr.is_set() && !expr.is_multiset()); + bool result_is_scalar = expr.is_scalar(); if (result_is_scalar) { cursor_info->scalar_result_type_ = expr.get_result_type(); } diff --git a/src/sql/optimizer/ob_join_order.cpp b/src/sql/optimizer/ob_join_order.cpp index fe46498002..1217c261e1 100644 --- a/src/sql/optimizer/ob_join_order.cpp +++ b/src/sql/optimizer/ob_join_order.cpp @@ -10736,9 +10736,7 @@ int ObJoinOrder::is_onetime_expr(const ObRelIds &ignore_relids,ObRawExpr* expr, LOG_WARN("failed to check subquery has ref assign user var", K(ret)); } else if (has_ref_assign_user_var) { is_valid = false; - } else if (expr->get_output_column() != 1 || - static_cast(expr)->is_set() || - static_cast(expr)->is_multiset()) { + } else if (!static_cast(expr)->is_scalar()) { is_valid = false; } } diff --git a/src/sql/optimizer/ob_log_plan.cpp b/src/sql/optimizer/ob_log_plan.cpp index 8abd12404c..18ada0b6c9 100644 --- a/src/sql/optimizer/ob_log_plan.cpp +++ b/src/sql/optimizer/ob_log_plan.cpp @@ -10106,9 +10106,7 @@ int ObLogPlan::extract_onetime_subquery(ObRawExpr *expr, LOG_WARN("failed to check subquery has ref assign user var", K(ret)); } else if (has_ref_assign_user_var) { is_valid = false; - } else if (expr->get_output_column() == 1 && - !static_cast(expr)->is_set() && - !static_cast(expr)->is_multiset() ) { + } else if (static_cast(expr)->is_scalar()) { if (OB_FAIL(onetime_list.push_back(expr))) { LOG_WARN("failed to push back candi onetime expr", K(ret)); } diff --git a/src/sql/resolver/expr/ob_raw_expr.h b/src/sql/resolver/expr/ob_raw_expr.h index a5d10e5129..66e9cd92d9 100644 --- a/src/sql/resolver/expr/ob_raw_expr.h +++ b/src/sql/resolver/expr/ob_raw_expr.h @@ -2363,6 +2363,7 @@ public: bool has_nl_param() const { return has_nl_param_; } void set_is_multiset(bool is_multiset) { is_multiset_ = is_multiset; } bool is_multiset() const {return is_multiset_; } + bool is_scalar() const { return !is_set_ && !is_multiset_ && get_output_column() == 1; } virtual void reset(); virtual bool inner_same_as(const ObRawExpr &expr, ObExprEqualCheckContext *check_context = NULL) const override; 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 0745c39341..6b9e09264b 100644 --- a/src/sql/resolver/expr/ob_raw_expr_deduce_type.cpp +++ b/src/sql/resolver/expr/ob_raw_expr_deduce_type.cpp @@ -92,7 +92,7 @@ int ObRawExprDeduceType::visit(ObQueryRefRawExpr &expr) int ret = OB_SUCCESS; if (expr.is_cursor()) { expr.set_data_type(ObExtendType); - } else if (((1 == expr.get_output_column()) && (!expr.is_set() || expr.is_multiset()))) { + } else if (expr.is_scalar()) { expr.set_result_type(expr.get_column_types().at(0)); if (ob_is_enumset_tc(expr.get_data_type())) { const ObSelectStmt *ref_stmt = expr.get_ref_stmt(); @@ -3258,10 +3258,9 @@ int ObRawExprDeduceType::add_implicit_cast(ObOpRawExpr &parent, parent.get_param_expr(child_idx) = child_ptr; } idx += ele_cnt; - } else if (((T_REF_QUERY == child_ptr->get_expr_type() - && !(static_cast(child_ptr)->is_cursor())) - && (static_cast(child_ptr)->get_output_column() > 1 - || static_cast(child_ptr)->is_set()))) { + } else if (T_REF_QUERY == child_ptr->get_expr_type() + && !static_cast(child_ptr)->is_cursor() + && !static_cast(child_ptr)->is_scalar()) { // subquery result not scalar (is row or set), add cast on subquery stmt's output ObQueryRefRawExpr *query_ref_expr = static_cast(child_ptr); const int64_t column_cnt = query_ref_expr->get_output_column(); @@ -3514,6 +3513,7 @@ int ObRawExprDeduceType::add_implicit_cast_for_subquery( // (select c1 from t1) + a int ret = OB_SUCCESS; CK(expr.get_output_column() > 1 || expr.is_set()); + CK(!expr.is_multiset_expr()); CK(expr.get_output_column() == input_types.count()); CK(NULL != expr.get_ref_stmt()); CK(expr.get_column_types().count() == expr.get_output_column() diff --git a/src/sql/rewrite/ob_transform_pre_process.cpp b/src/sql/rewrite/ob_transform_pre_process.cpp index bfd183a72a..089ce20bf7 100644 --- a/src/sql/rewrite/ob_transform_pre_process.cpp +++ b/src/sql/rewrite/ob_transform_pre_process.cpp @@ -9267,7 +9267,7 @@ int ObTransformPreProcess::add_constructor_to_multiset(ObDMLStmt &stmt, OB_UNLIKELY(OB_INVALID_ID == elem_udt_id)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected params", KPC(multiset_expr), K(elem_type)); - } else if (!multiset_stmt->is_set_stmt()) { + } else if (!multiset_stmt->is_set_stmt() && !multiset_stmt->is_distinct()) { // if multiset stmt is set stmt, create a view for it. // e.g. create type tbl_obj as table of obj // cast(multiset(select 1 as a from dual union select 2 as a from dual) as tbl_obj) @@ -9429,7 +9429,7 @@ int ObTransformPreProcess::add_column_conv_to_multiset(ObQueryRefRawExpr *multis ret = OB_ERR_INVALID_TYPE_FOR_OP; LOG_WARN("unexpected column count", K(ret), KPC(multiset_stmt), KPC(multiset_expr)); } else { - if (!multiset_stmt->is_set_stmt()) { + if (!multiset_stmt->is_set_stmt() && !multiset_stmt->is_distinct()) { // do nothing // if multiset stmt is set stmt, create a view for it. } else if (OB_FAIL(ObTransformUtils::create_stmt_with_generated_table(ctx_, multiset_stmt, new_stmt))) { diff --git a/src/sql/rewrite/ob_transform_subquery_coalesce.cpp b/src/sql/rewrite/ob_transform_subquery_coalesce.cpp index 8e686363cc..ffea8ea07f 100644 --- a/src/sql/rewrite/ob_transform_subquery_coalesce.cpp +++ b/src/sql/rewrite/ob_transform_subquery_coalesce.cpp @@ -1763,8 +1763,7 @@ int ObTransformSubqueryCoalesce::get_subquery_assign_exprs(ObIArray if (OB_ISNULL(query_ref_expr) || OB_ISNULL(stmt = query_ref_expr->get_ref_stmt())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpect null stmt", K(ret)); - } else if (query_ref_expr->is_set() || - 1 != query_ref_expr->get_output_column()) { + } else if (!query_ref_expr->is_scalar()) { //do nothing } else if (stmt->has_limit() || stmt->has_distinct() || stmt->is_set_stmt()) { //stmt can not coalesce,do nothing diff --git a/src/sql/rewrite/ob_transform_utils.cpp b/src/sql/rewrite/ob_transform_utils.cpp index 62dd1318a3..c73a7a90f4 100644 --- a/src/sql/rewrite/ob_transform_utils.cpp +++ b/src/sql/rewrite/ob_transform_utils.cpp @@ -3388,7 +3388,7 @@ int ObTransformUtils::classify_scalar_query_ref(ObRawExpr *expr, LOG_WARN("expr is null", K(ret)); } else if (expr->is_query_ref_expr()) { ObQueryRefRawExpr *query_ref = static_cast(expr); - if (query_ref->is_set() || query_ref->get_output_column() > 1) { + if (!query_ref->is_scalar()) { // if a query ref returns multi row or multi col, // we consider such query ref as a non-scalar one. if (OB_FAIL(add_var_to_array_no_dup(non_scalar_query_refs, expr))) { @@ -12745,7 +12745,7 @@ int ObTransformUtils::is_scalar_expr(ObRawExpr* expr, bool &is_scalar) is_scalar = false; } else if (expr->is_query_ref_expr()) { ObQueryRefRawExpr *query_ref = static_cast(expr); - is_scalar = (!query_ref->is_set()) && (query_ref->get_output_column() == 1); + is_scalar = query_ref->is_scalar(); } return ret; }