207 lines
7.4 KiB
C++
207 lines
7.4 KiB
C++
/**
|
|
* 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<const ObMergeStmt*>(stmt_);
|
|
const TableItem* target_table = NULL;
|
|
const TableItem* source_table = NULL;
|
|
const ObIArray<ObRawExpr*>& 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<ObRawExpr*>& 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<ObRawExpr*>& update_conds = merge_stmt.get_update_condition_exprs();
|
|
const ObIArray<ObRawExpr*>& 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<ObRawExpr*>& 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;
|
|
}
|