diff --git a/src/sql/code_generator/ob_static_engine_cg.cpp b/src/sql/code_generator/ob_static_engine_cg.cpp index e917dc24b3..1bf974afa7 100644 --- a/src/sql/code_generator/ob_static_engine_cg.cpp +++ b/src/sql/code_generator/ob_static_engine_cg.cpp @@ -6050,6 +6050,8 @@ int ObStaticEngineCG::generate_spec(ObLogSelectInto &op, ObSelectIntoSpec &spec, LOG_WARN("fail to set line str", K(op.get_line_str()), K(ret)); } else if (OB_FAIL(spec.user_vars_.init(op.get_user_vars().count()))) { LOG_WARN("init fixed array failed", K(ret), K(op.get_user_vars().count())); + } else if (OB_FAIL(spec.select_exprs_.init(op.get_select_exprs().count()))) { + LOG_WARN("init fixed array failed", K(ret), K(op.get_select_exprs().count())); } else { ObString var; for (int64_t i = 0; OB_SUCC(ret) && i < op.get_user_vars().count(); ++i) { @@ -6060,6 +6062,18 @@ int ObStaticEngineCG::generate_spec(ObLogSelectInto &op, ObSelectIntoSpec &spec, LOG_WARN("fail to push back var", K(var), K(ret)); } } + for (int64_t i = 0; OB_SUCC(ret) && i < op.get_select_exprs().count(); ++i) { + ObExpr *rt_expr = nullptr; + const ObRawExpr* select_expr = op.get_select_exprs().at(i); + if (OB_ISNULL(select_expr)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpect null expr", K(ret)); + } else if (OB_FAIL(generate_rt_expr(*select_expr, rt_expr))) { + LOG_WARN("failed to generate rt expr", K(ret)); + } else if (OB_FAIL(spec.select_exprs_.push_back(rt_expr))) { + LOG_WARN("failed to push back expr", K(ret)); + } + } if (OB_SUCC(ret)) { spec.into_type_ = op.get_into_type(); spec.closed_cht_ = op.get_closed_cht(); diff --git a/src/sql/engine/basic/ob_select_into_op.cpp b/src/sql/engine/basic/ob_select_into_op.cpp index bd2fe6ad1a..3975fb7184 100644 --- a/src/sql/engine/basic/ob_select_into_op.cpp +++ b/src/sql/engine/basic/ob_select_into_op.cpp @@ -26,7 +26,7 @@ namespace sql { OB_SERIALIZE_MEMBER((ObSelectIntoSpec, ObOpSpec), into_type_, user_vars_, - outfile_name_, filed_str_, line_str_, closed_cht_, is_optional_); + outfile_name_, filed_str_, line_str_, closed_cht_, is_optional_, select_exprs_); int ObSelectIntoOp::inner_open() @@ -284,7 +284,10 @@ int ObSelectIntoOp::get_row_str(const int64_t buf_len, const ObObj &filed_str = filed_str_; char closed_cht = MY_SPEC.closed_cht_; bool is_optional = MY_SPEC.is_optional_; - const ObIArray &select_exprs = MY_SPEC.output_; + //before 4_1 use output + //after 4_1 use select exprs + const ObIArray &select_exprs = (MY_SPEC.select_exprs_.empty()) ? + MY_SPEC.output_ : MY_SPEC.select_exprs_; if (!is_first_row && line_str_.is_varying_len_char_type()) { // lines terminated by "a" ret = databuff_printf(buf, buf_len, pos, "%.*s", line_str_.get_varchar().length(), line_str_.get_varchar().ptr()); @@ -491,7 +494,10 @@ int ObSelectIntoOp::into_dumpfile() int ObSelectIntoOp::into_outfile() { int ret = OB_SUCCESS; - const ObIArray &select_exprs = MY_SPEC.output_; + //before 4_1 use output + //after 4_1 use select exprs + const ObIArray &select_exprs = (MY_SPEC.select_exprs_.empty()) ? + MY_SPEC.output_ : MY_SPEC.select_exprs_ ; if (select_exprs.count() != 1) { ret = OB_ERR_UNEXPECTED; LOG_WARN("invalid count of exprs in select into outfile", K(select_exprs.count()), K(ret)); @@ -518,7 +524,10 @@ int ObSelectIntoOp::into_outfile() int ObSelectIntoOp::into_outfile_batch(const ObBatchRows &brs) { int ret = OB_SUCCESS; - const ObIArray &select_exprs = MY_SPEC.output_; + //before 4_1 use output + //after 4_1 use select exprs + const ObIArray &select_exprs = (MY_SPEC.select_exprs_.empty()) ? + MY_SPEC.output_ : MY_SPEC.select_exprs_; if (select_exprs.count() != 1) { ret = OB_ERR_UNEXPECTED; LOG_WARN("invalid count of exprs in select into outfile", K(select_exprs.count()), K(ret)); @@ -548,7 +557,10 @@ int ObSelectIntoOp::into_outfile_batch(const ObBatchRows &brs) int ObSelectIntoOp::into_varlist() { int ret = OB_SUCCESS; - const ObIArray &select_exprs = MY_SPEC.output_; + //before 4_1 use output + //after 4_1 use select exprs + const ObIArray &select_exprs = (MY_SPEC.select_exprs_.empty()) ? + MY_SPEC.output_ : MY_SPEC.select_exprs_; const ObIArray &user_vars = MY_SPEC.user_vars_; if (select_exprs.count() != user_vars.count()) { ret = OB_ERR_COLUMN_SIZE; diff --git a/src/sql/engine/basic/ob_select_into_op.h b/src/sql/engine/basic/ob_select_into_op.h index 9055a8b633..37e27b8d6a 100644 --- a/src/sql/engine/basic/ob_select_into_op.h +++ b/src/sql/engine/basic/ob_select_into_op.h @@ -35,7 +35,8 @@ public: filed_str_(), line_str_(), closed_cht_(0), - is_optional_(false) + is_optional_(false), + select_exprs_(alloc) { } @@ -46,6 +47,7 @@ public: common::ObObj line_str_; char closed_cht_; bool is_optional_; + common::ObFixedArray select_exprs_; }; class ObSelectIntoOp : public ObOperator diff --git a/src/sql/optimizer/ob_log_plan.cpp b/src/sql/optimizer/ob_log_plan.cpp index e6c1dd0293..f05ab9d1d9 100644 --- a/src/sql/optimizer/ob_log_plan.cpp +++ b/src/sql/optimizer/ob_log_plan.cpp @@ -8606,10 +8606,28 @@ int ObLogPlan::allocate_select_into_as_top(ObLogicalOperator *&old_top) ret = OB_ALLOCATE_MEMORY_FAILED; LOG_ERROR("allocate memory for ObLogSelectInto failed", K(ret)); } else { - ObSelectIntoItem *into_item = stmt->get_select_into();; + ObSelectIntoItem *into_item = stmt->get_select_into(); + ObSEArray select_exprs; + ObRawExpr *to_outfile_expr = NULL; if (OB_ISNULL(into_item)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("into item is null", K(ret)); + } else if (OB_FAIL(stmt->get_select_exprs(select_exprs))) { + LOG_WARN("failed to get select exprs", K(ret)); + } else if (T_INTO_OUTFILE == into_item->into_type_ && + OB_FAIL(ObRawExprUtils::build_to_outfile_expr( + get_optimizer_context().get_expr_factory(), + get_optimizer_context().get_session_info(), + into_item, + select_exprs, + to_outfile_expr))) { + LOG_WARN("failed to build_to_outfile_expr", K(*into_item), K(ret)); + } else if (T_INTO_OUTFILE == into_item->into_type_ && + OB_FAIL(select_into->get_select_exprs().push_back(to_outfile_expr))) { + LOG_WARN("failed to add into outfile expr", K(ret)); + } else if (T_INTO_OUTFILE != into_item->into_type_ && + OB_FAIL(select_into->get_select_exprs().assign(select_exprs))) { + LOG_WARN("failed to get select exprs", K(ret)); } else { select_into->set_into_type(into_item->into_type_); select_into->set_outfile_name(into_item->outfile_name_); @@ -11496,6 +11514,19 @@ int ObLogPlan::adjust_final_plan_info(ObLogicalOperator *&op) } } + if (OB_SUCC(ret) && op->get_type() == LOG_SELECT_INTO && !op->is_plan_root() && + GET_MIN_CLUSTER_VERSION() < CLUSTER_VERSION_4_1_0_0) { + if (!op->get_stmt()->is_select_stmt()) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected stmt type", K(ret)); + } else { + const ObSelectStmt *sel_stmt = static_cast(op->get_stmt()); + if (OB_FAIL(sel_stmt->get_select_exprs(op->get_output_exprs()))) { + LOG_WARN("failed to get select exprs", K(ret)); + } + } + } + if (OB_SUCC(ret)) { if (op->is_plan_root() && OB_FAIL(op->set_plan_root_output_exprs())) { LOG_WARN("failed to add plan root exprs", K(ret)); diff --git a/src/sql/optimizer/ob_log_select_into.cpp b/src/sql/optimizer/ob_log_select_into.cpp index 02a4faf7e7..a264f894cf 100644 --- a/src/sql/optimizer/ob_log_select_into.cpp +++ b/src/sql/optimizer/ob_log_select_into.cpp @@ -60,19 +60,20 @@ int ObLogSelectInto::compute_plan_type() int ObLogSelectInto::get_op_exprs(ObIArray &all_exprs) { int ret = OB_SUCCESS; - const ObDMLStmt *stmt = NULL; - const ObSelectStmt *sel_stmt = NULL; - if (OB_ISNULL(get_plan()) || OB_ISNULL(stmt = get_plan()->get_stmt())) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("get unexpected null", K(ret)); - } else if (!stmt->is_select_stmt()) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("get unexpected stmt type", K(ret)); - } else if (OB_FALSE_IT(sel_stmt = static_cast(stmt))) { - } else if (OB_FAIL(sel_stmt->get_select_exprs(output_exprs_))) { - LOG_WARN("failed to get select exprs", K(ret)); + if (OB_FAIL(append(all_exprs, select_exprs_))) { + LOG_WARN("failed to push back select exprs", K(ret)); } else if (OB_FAIL(ObLogicalOperator::get_op_exprs(all_exprs))) { LOG_WARN("failed to get op exprs", K(ret)); } else { /*do nothing*/ } return ret; +} + +int ObLogSelectInto::inner_replace_op_exprs( + const ObIArray > &to_replace_exprs) +{ + int ret = OB_SUCCESS; + if (OB_FAIL(replace_exprs_action(to_replace_exprs, select_exprs_))) { + LOG_WARN("failed to replace select exprs", K(ret)); + } + return ret; } \ No newline at end of file diff --git a/src/sql/optimizer/ob_log_select_into.h b/src/sql/optimizer/ob_log_select_into.h index 9b8d16f5d0..5880a1a95c 100644 --- a/src/sql/optimizer/ob_log_select_into.h +++ b/src/sql/optimizer/ob_log_select_into.h @@ -97,14 +97,19 @@ public: { return closed_cht_; } + const common::ObIArray &get_select_exprs() const { return select_exprs_; } + common::ObIArray &get_select_exprs() { return select_exprs_; } virtual int est_cost() override; virtual int compute_plan_type() override; virtual int get_op_exprs(ObIArray &all_exprs) override; + virtual int inner_replace_op_exprs( + const common::ObIArray >&to_replace_exprs); private: ObItemType into_type_; common::ObObj outfile_name_; common::ObObj filed_str_; common::ObObj line_str_; + common::ObSEArray select_exprs_; common::ObSEArray user_vars_; char closed_cht_; bool is_optional_; diff --git a/src/sql/optimizer/ob_logical_operator.cpp b/src/sql/optimizer/ob_logical_operator.cpp index 09dcf605a6..23c1539caf 100644 --- a/src/sql/optimizer/ob_logical_operator.cpp +++ b/src/sql/optimizer/ob_logical_operator.cpp @@ -3045,7 +3045,8 @@ int ObLogicalOperator::adjust_plan_root_output_exprs() FALSE_IT(into_item = static_cast(stmt)->get_select_into())) { /*do nothing*/ } else if (NULL == get_parent()) { - if (NULL != into_item && T_INTO_OUTFILE == into_item->into_type_) { + if (NULL != into_item && T_INTO_OUTFILE == into_item->into_type_ && + GET_MIN_CLUSTER_VERSION() < CLUSTER_VERSION_4_1_0_0) { if (OB_FAIL(build_and_put_into_outfile_expr(into_item, output_exprs_))) { LOG_WARN("failed to add into outfile expr to ctx", K(ret)); } else {