/** * Copyright (c) 2021 OceanBase * OceanBase CE is licensed under Mulan PubL v2. * You can use this software according to the terms and conditions of the Mulan PubL v2. * You may obtain a copy of Mulan PubL v2 at: * http://license.coscl.org.cn/MulanPubL-2.0 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. * See the Mulan PubL v2 for more details. */ #define USING_LOG_PREFIX SQL #include "ob_merge_stmt_printer.h" #include "sql/resolver/expr/ob_raw_expr_util.h" using namespace oceanbase::sql; using namespace oceanbase::common; void ObMergeStmtPrinter::init(char* buf, int64_t buf_len, int64_t* pos, ObMergeStmt* stmt) { ObDMLStmtPrinter::init(buf, buf_len, pos, stmt); } int ObMergeStmtPrinter::do_print() { int ret = OB_SUCCESS; if (OB_UNLIKELY(!is_inited_)) { ret = OB_NOT_INIT; LOG_WARN("not inited!", K(ret)); } else if (OB_ISNULL(stmt_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("stmt should not be NULL", K(ret)); } else { expr_printer_.init(buf_, buf_len_, pos_, print_params_); if (OB_FAIL(print())) { LOG_WARN("fail to print stmt", K(ret)); } } return ret; } // merge into target using source on match_condition update clause insert_clause int ObMergeStmtPrinter::print() { int ret = OB_SUCCESS; if (OB_ISNULL(stmt_) || OB_ISNULL(buf_) || OB_ISNULL(pos_) || OB_UNLIKELY(!stmt_->is_merge_stmt())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("stmt_ is NULL or buf_ is NULL or pos_ is NULL", K(ret), K(stmt_), K(buf_), K(pos_)); } else { const ObMergeStmt* merge_stmt = static_cast(stmt_); const TableItem* target_table = NULL; const TableItem* source_table = NULL; const ObIArray& match_conds = merge_stmt->get_match_condition_exprs(); if (OB_ISNULL(target_table = merge_stmt->get_table_item_by_id(merge_stmt->get_target_table_id())) || OB_ISNULL(source_table = merge_stmt->get_table_item_by_id(merge_stmt->get_source_table_id()))) { ret = OB_ERR_UNEXPECTED; LOG_WARN("target table or source table is null", K(ret), K(target_table), K(source_table)); } DATA_PRINTF("merge "); if (OB_SUCC(ret) && print_hint()) { LOG_WARN("failed to print hint", K(ret)); } DATA_PRINTF("into "); if (OB_SUCC(ret) && print_table(target_table)) { LOG_WARN("failed to print target table", K(ret)); } DATA_PRINTF(" using "); if (OB_SUCC(ret) && print_table(source_table)) { LOG_WARN("failed to print source table", K(ret)); } DATA_PRINTF(" on ( "); if (OB_SUCC(ret) && print_conds(match_conds)) { LOG_WARN("failed to print match conditions", K(ret)); } DATA_PRINTF(" )"); if (OB_SUCC(ret) && merge_stmt->has_update_clause()) { if (OB_FAIL(print_update_clause(*merge_stmt))) { LOG_WARN("failed to print update clause", K(ret)); } } if (OB_SUCC(ret) && merge_stmt->has_insert_clause()) { if (OB_FAIL(print_insert_clause(*merge_stmt))) { LOG_WARN("failed to print insert clause", K(ret)); } } } return ret; } int ObMergeStmtPrinter::print_conds(const ObIArray& conds) { int ret = OB_SUCCESS; for (int64_t i = 0; OB_SUCC(ret) && i < conds.count(); ++i) { if (OB_FAIL(expr_printer_.do_print(conds.at(i), T_NONE_SCOPE))) { LOG_WARN("failed to print match condition", K(ret)); } else if (i < conds.count() - 1) { DATA_PRINTF(" and "); } } return ret; } int ObMergeStmtPrinter::print_update_clause(const ObMergeStmt& merge_stmt) { int ret = OB_SUCCESS; bool first_assign = true; const ObIArray& update_conds = merge_stmt.get_update_condition_exprs(); const ObIArray& delete_conds = merge_stmt.get_delete_condition_exprs(); if (OB_UNLIKELY(merge_stmt.get_tables_assignments().empty())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("update clause does not have assignments", K(ret)); } DATA_PRINTF(" when matched then"); if (OB_SUCC(ret)) { // has update assign const ObTableAssignment& assigns = merge_stmt.get_tables_assignments().at(0); if (OB_UNLIKELY(assigns.assignments_.empty())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("stmt does not have column assign", K(ret)); } DATA_PRINTF(" update set "); for (int64_t i = 0; OB_SUCC(ret) && i < assigns.assignments_.count(); ++i) { const ObAssignment &assign = assigns.assignments_.at(i); ObColumnRefRawExpr *column = assign.column_expr_; ObRawExpr *value = assign.expr_; ObRawExpr *real_value = NULL; if (OB_ISNULL(column) || OB_ISNULL(value)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("invalid column assign", K(ret)); } else if (!assign.is_implicit_) { if (!first_assign) { DATA_PRINTF(", "); } else { first_assign = false; } if (OB_SUCC(ret)) { if (OB_FAIL(expr_printer_.do_print(column, T_UPDATE_SCOPE))) { LOG_WARN("failed to print assign target", K(ret)); } else { DATA_PRINTF(" = "); } } if (OB_SUCC(ret)) { if (OB_FAIL(ObRawExprUtils::erase_inner_added_exprs(value, real_value))) { LOG_WARN("failed to erase inner case expr", K(ret)); } else if (OB_FAIL(expr_printer_.do_print(real_value, T_UPDATE_SCOPE))) { LOG_WARN("failed to print assign value", K(ret)); } } } } } if (OB_SUCC(ret) && !update_conds.empty()) { DATA_PRINTF(" where "); if (OB_SUCC(ret) && print_conds(update_conds)) { LOG_WARN("failed to print update conditions", K(ret)); } } if (OB_SUCC(ret) && !delete_conds.empty()) { DATA_PRINTF(" delete where "); if (OB_SUCC(ret) && print_conds(delete_conds)) { LOG_WARN("failed to print conditions", K(ret)); } } return ret; } int ObMergeStmtPrinter::print_insert_clause(const ObMergeStmt& merge_stmt) { int ret = OB_SUCCESS; int64_t column_count = merge_stmt.get_values_desc().count(); int64_t value_count = merge_stmt.get_value_vectors().count(); ObArenaAllocator allocator("PrintMergeStmt"); const ObIArray& insert_conds = merge_stmt.get_insert_condition_exprs(); if (OB_UNLIKELY(column_count != value_count)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("column count does not equal with value count", K(ret), K(column_count), K(value_count)); } DATA_PRINTF(" when not matched then insert ("); for (int64_t i = 0; OB_SUCC(ret) && i < column_count; ++i) { const ObColumnRefRawExpr* column = merge_stmt.get_values_desc().at(i); if (OB_ISNULL(column)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("column is NULL", K(ret)); } else { ObString column_name = column->get_column_name(); CONVERT_CHARSET_FOR_RPINT(allocator, column_name); DATA_PRINTF(" %.*s %c", LEN_AND_PTR(column_name), (i < column_count - 1 ? ',' : ')')); } } DATA_PRINTF(" values ("); for (int64_t i = 0; OB_SUCC(ret) && i < value_count; ++i) { DATA_PRINTF(" "); if (OB_FAIL(expr_printer_.do_print(merge_stmt.get_value_vectors().at(i), T_INSERT_SCOPE))) { LOG_WARN("fail to print value expr", K(ret)); } DATA_PRINTF(" %c", i < value_count - 1 ? ',' : ')'); } if (OB_SUCC(ret) && !insert_conds.empty()) { DATA_PRINTF(" where "); if (OB_SUCC(ret) && print_conds(insert_conds)) { LOG_WARN("failed to print conditions", K(ret)); } } return ret; }