init push
This commit is contained in:
505
src/sql/engine/dml/ob_table_merge_op.cpp
Normal file
505
src/sql/engine/dml/ob_table_merge_op.cpp
Normal file
@ -0,0 +1,505 @@
|
||||
/**
|
||||
* 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_ENG
|
||||
#include "sql/engine/dml/ob_table_merge_op.h"
|
||||
#include "lib/utility/ob_unify_serialize.h"
|
||||
#include "share/ob_autoincrement_service.h"
|
||||
#include "sql/engine/ob_physical_plan_ctx.h"
|
||||
#include "sql/session/ob_sql_session_info.h"
|
||||
#include "storage/ob_partition_service.h"
|
||||
#include "sql/engine/ob_physical_plan.h"
|
||||
#include "common/sql_mode/ob_sql_mode_utils.h"
|
||||
#include "common/rowkey/ob_rowkey.h"
|
||||
#include "sql/engine/ob_physical_plan.h"
|
||||
#include "sql/engine/ob_exec_context.h"
|
||||
#include "sql/ob_sql_utils.h"
|
||||
|
||||
namespace oceanbase {
|
||||
using namespace common;
|
||||
using namespace share;
|
||||
using namespace sql;
|
||||
using storage::INSERT_RETURN_ONE_DUP;
|
||||
using storage::ObPartitionService;
|
||||
|
||||
namespace sql {
|
||||
|
||||
OB_SERIALIZE_MEMBER((ObTableMergeOpInput, ObTableModifyOpInput));
|
||||
|
||||
OB_SERIALIZE_MEMBER((ObTableMergeSpec, ObTableModifySpec), has_insert_clause_, has_update_clause_, delete_conds_,
|
||||
update_conds_, insert_conds_, rowkey_exprs_, delete_column_ids_, updated_column_ids_, updated_column_infos_,
|
||||
old_row_, new_row_);
|
||||
|
||||
ObTableMergeSpec::ObTableMergeSpec(common::ObIAllocator& alloc, const ObPhyOperatorType type)
|
||||
: ObTableModifySpec(alloc, type),
|
||||
has_insert_clause_(false),
|
||||
has_update_clause_(false),
|
||||
delete_conds_(alloc),
|
||||
update_conds_(alloc),
|
||||
insert_conds_(alloc),
|
||||
rowkey_exprs_(alloc),
|
||||
delete_column_ids_(alloc),
|
||||
updated_column_ids_(alloc),
|
||||
updated_column_infos_(alloc),
|
||||
old_row_(alloc),
|
||||
new_row_(alloc)
|
||||
{}
|
||||
|
||||
int ObTableMergeSpec::set_updated_column_info(
|
||||
int64_t array_index, uint64_t column_id, uint64_t project_index, bool auto_filled_timestamp)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ColumnContent column;
|
||||
column.projector_index_ = project_index;
|
||||
column.auto_filled_timestamp_ = auto_filled_timestamp;
|
||||
CK(array_index >= 0 && array_index < updated_column_ids_.count());
|
||||
CK(array_index >= 0 && array_index < updated_column_infos_.count());
|
||||
if (OB_SUCC(ret)) {
|
||||
updated_column_ids_.at(array_index) = column_id;
|
||||
updated_column_infos_.at(array_index) = column;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObTableMergeSpec::init_updated_column_count(common::ObIAllocator& allocator, int64_t count)
|
||||
{
|
||||
UNUSED(allocator);
|
||||
int ret = common::OB_SUCCESS;
|
||||
OZ(updated_column_infos_.prepare_allocate(count));
|
||||
OZ(updated_column_ids_.prepare_allocate(count));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
ObTableMergeOp::ObTableMergeOp(ObExecContext& ctx, const ObOpSpec& spec, ObOpInput* input)
|
||||
: ObTableModifyOp(ctx, spec, input),
|
||||
insert_row_(),
|
||||
insert_row_store_(ctx_.get_allocator(), ObModIds::OB_SQL_ROW_STORE, OB_SERVER_TENANT_ID, false),
|
||||
old_row_(),
|
||||
new_row_(),
|
||||
affected_rows_(0)
|
||||
{}
|
||||
|
||||
int ObTableMergeOp::inner_open()
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObPhysicalPlanCtx* plan_ctx = NULL;
|
||||
ObSQLSessionInfo* my_session = NULL;
|
||||
int64_t schema_version = 0;
|
||||
int64_t binlog_row_image = ObBinlogRowImage::FULL;
|
||||
if (OB_FAIL(ObTableModifyOp::inner_open())) {
|
||||
LOG_WARN("open child operator failed", K(ret));
|
||||
} else if (OB_ISNULL((plan_ctx = ctx_.get_physical_plan_ctx()))) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("get physical plan context failed", K(ret));
|
||||
} else if (OB_ISNULL((my_session = GET_MY_SESSION(ctx_)))) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("fail to get my session", K(ret));
|
||||
} else if (OB_FAIL(get_spec().plan_->get_base_table_version(MY_SPEC.index_tid_, schema_version))) {
|
||||
LOG_WARN("failed to get base table version", K(ret));
|
||||
} else if (OB_ISNULL(child_)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("invalid child op", K(ret), K(child_));
|
||||
} else if (OB_FAIL(my_session->get_binlog_row_image(binlog_row_image))) {
|
||||
LOG_WARN("fail to get binlog row image", K(ret));
|
||||
} else {
|
||||
dml_param_.timeout_ = plan_ctx->get_ps_timeout_timestamp();
|
||||
dml_param_.schema_version_ = schema_version;
|
||||
dml_param_.is_total_quantity_log_ = (ObBinlogRowImage::FULL == binlog_row_image);
|
||||
dml_param_.sql_mode_ = my_session->get_sql_mode();
|
||||
dml_param_.tz_info_ = TZ_INFO(my_session);
|
||||
dml_param_.table_param_ = &MY_SPEC.table_param_;
|
||||
dml_param_.tenant_schema_version_ = plan_ctx->get_tenant_schema_version();
|
||||
|
||||
if (MY_SPEC.gi_above_) {
|
||||
OZ(get_gi_task());
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
OZ(do_table_merge());
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObTableMergeOp::do_table_merge()
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObPhysicalPlanCtx* plan_ctx = NULL;
|
||||
ObSQLSessionInfo* my_session = NULL;
|
||||
ObPartitionKey* pkey;
|
||||
ObPartitionService* partition_service = NULL;
|
||||
ObTaskExecutorCtx* executor_ctx = NULL;
|
||||
if (iter_end_) {
|
||||
LOG_DEBUG("can't get gi task, iter end", K(iter_end_), K(MY_SPEC.id_));
|
||||
} else if (OB_FAIL(get_part_location(part_infos_))) {
|
||||
LOG_WARN("get part location failed", K(ret));
|
||||
} else if (part_infos_.count() != 1) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("the part info count is not right", K(ret), K(part_infos_.count()));
|
||||
} else if (OB_ISNULL(pkey = &part_infos_.at(0).partition_key_)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("the partition key is null", K(ret), K(pkey));
|
||||
} else if (OB_FAIL(set_autoinc_param_pkey(*pkey))) {
|
||||
LOG_WARN("set autoinc param pkey failed", K(pkey), K(ret));
|
||||
} else if (OB_ISNULL(plan_ctx = ctx_.get_physical_plan_ctx())) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("get physical plan context failed");
|
||||
} else if (OB_ISNULL(my_session = GET_MY_SESSION(ctx_))) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("fail to get my session", K(ret));
|
||||
} else if (OB_ISNULL(executor_ctx = GET_TASK_EXECUTOR_CTX(ctx_))) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("fail to get task executor ctx", K(ret));
|
||||
} else if (OB_ISNULL(partition_service = executor_ctx->get_partition_service())) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("fail to get partition service", K(ret));
|
||||
} else {
|
||||
if (OB_FAIL(set_autoinc_param_pkey(*pkey))) {
|
||||
LOG_WARN("set autoinc param pkey failed", K(pkey), K(ret));
|
||||
}
|
||||
// since inner open performes get_next_row, assgin opened_ as true
|
||||
opened_ = true;
|
||||
while (OB_SUCC(ret)) {
|
||||
bool is_match = false;
|
||||
clear_evaluated_flag();
|
||||
if (OB_FAIL(try_check_status())) {
|
||||
} else if (OB_FAIL(child_->get_next_row())) {
|
||||
if (OB_ITER_END != ret) {
|
||||
LOG_WARN("fail to get next row", K(ret));
|
||||
}
|
||||
} else if (OB_FAIL(check_is_match(is_match))) {
|
||||
LOG_WARN("failed to check is match", K(ret));
|
||||
} else if (is_match) { // execute update
|
||||
if (MY_SPEC.has_update_clause_ && OB_FAIL(process_update(partition_service, *pkey, dml_param_))) {
|
||||
LOG_WARN("fail to process update", K(ret));
|
||||
}
|
||||
} else { // execute insert
|
||||
if (MY_SPEC.has_insert_clause_ &&
|
||||
OB_FAIL(process_insert(partition_service, my_session->get_trans_desc(), dml_param_, *pkey))) {
|
||||
LOG_WARN("fail to insert row", K(ret));
|
||||
}
|
||||
}
|
||||
} // end while
|
||||
|
||||
if (OB_ITER_END == ret &&
|
||||
OB_FAIL(insert_all_rows(partition_service, my_session->get_trans_desc(), dml_param_, *pkey))) {
|
||||
if (OB_ITER_END != ret) {
|
||||
LOG_WARN("insert all rows failed", K(ret));
|
||||
}
|
||||
}
|
||||
|
||||
// deal with different ret
|
||||
if (OB_ITER_END != ret) {
|
||||
if (OB_TRY_LOCK_ROW_CONFLICT != ret && OB_TRANSACTION_SET_VIOLATION != ret) {
|
||||
LOG_WARN("failed to deal with merge into", K(ret));
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
}
|
||||
} else {
|
||||
ret = OB_SUCCESS;
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
plan_ctx->add_affected_rows(affected_rows_);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
int ObTableMergeOp::rescan()
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (!MY_SPEC.gi_above_) {
|
||||
ret = OB_NOT_SUPPORTED;
|
||||
LOG_WARN("table merge into rescan not supported", K(ret));
|
||||
} else if (OB_FAIL(ObTableModifyOp::rescan())) {
|
||||
LOG_WARN("rescan child operator failed", K(ret));
|
||||
} else {
|
||||
reset();
|
||||
if (OB_SUCC(ret)) {
|
||||
if (OB_FAIL(get_gi_task())) {
|
||||
LOG_WARN("get granule task failed", K(ret));
|
||||
} else if (OB_FAIL(do_table_merge())) {
|
||||
LOG_WARN("do table merge into failed", K(ret));
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObTableMergeOp::check_is_match(bool& is_match)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
const ObTableMergeSpec& spec = MY_SPEC;
|
||||
is_match = false;
|
||||
for (int64_t i = 0; OB_SUCC(ret) && !is_match && i < spec.rowkey_exprs_.count(); ++i) {
|
||||
ObDatum* datum = NULL;
|
||||
const ObExpr* e = spec.rowkey_exprs_.at(i);
|
||||
if (OB_ISNULL(e)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("expr is null", K(ret));
|
||||
} else if (e->eval(eval_ctx_, datum)) {
|
||||
LOG_WARN("failed to evaluate expression", K(ret));
|
||||
} else {
|
||||
is_match = !datum->is_null();
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObTableMergeOp::calc_delete_condition(const ObIArray<ObExpr*>& exprs, bool& is_true_cond)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (0 == exprs.count()) {
|
||||
is_true_cond = false;
|
||||
} else if (OB_FAIL(calc_condition(exprs, is_true_cond))) {
|
||||
LOG_WARN("fail to calc delete join condition", K(ret), K(exprs));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObTableMergeOp::calc_condition(const ObIArray<ObExpr*>& exprs, bool& is_true_cond)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObDatum* cmp_res = NULL;
|
||||
is_true_cond = true;
|
||||
ARRAY_FOREACH(exprs, i)
|
||||
{
|
||||
if (OB_FAIL(exprs.at(i)->eval(eval_ctx_, cmp_res))) {
|
||||
LOG_WARN("fail to calc other join condition", K(ret), K(*exprs.at(i)));
|
||||
} else if (cmp_res->is_null() || 0 == cmp_res->get_int()) {
|
||||
is_true_cond = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObTableMergeOp::process_insert(ObPartitionService* partition_service, const transaction::ObTransDesc& trans_desc,
|
||||
const storage::ObDMLBaseParam& dml_param, const common::ObPartitionKey& pkey)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
bool is_true_cond = false;
|
||||
int64_t cur_affected = 0;
|
||||
ObNewRowIterator* duplicated_rows = NULL;
|
||||
if (!MY_SPEC.has_insert_clause_) { // do nothing
|
||||
LOG_DEBUG("trace insert clause", K(ret));
|
||||
} else if (OB_FAIL(calc_condition(MY_SPEC.insert_conds_, is_true_cond))) {
|
||||
LOG_WARN("fail to calc condition", K(MY_SPEC.insert_conds_), K(ret));
|
||||
} else if (is_true_cond) {
|
||||
bool is_filtered = false;
|
||||
// in resolve phase, insert's check expression will be put in
|
||||
// check_constraint_exprs_'s second half
|
||||
int64_t cst_beg_idx = MY_SPEC.check_constraint_exprs_.count() / 2;
|
||||
int64_t cst_end_idx = MY_SPEC.check_constraint_exprs_.count();
|
||||
if (OB_FAIL(check_row_null(MY_SPEC.storage_row_output_, MY_SPEC.column_infos_))) {
|
||||
LOG_WARN("failed to check null", K(ret));
|
||||
} else if (OB_FAIL(
|
||||
filter_row_for_check_cst(MY_SPEC.check_constraint_exprs_, is_filtered, cst_beg_idx, cst_end_idx))) {
|
||||
LOG_WARN("failed to filter row for constraint", K(ret));
|
||||
} else if (is_filtered) {
|
||||
ret = OB_ERR_CHECK_CONSTRAINT_VIOLATED;
|
||||
LOG_WARN("row is filtered by check", K(ret));
|
||||
} else if (OB_FAIL(project_row(MY_SPEC.storage_row_output_, insert_row_))) {
|
||||
LOG_WARN("failed to project row", K(ret));
|
||||
} else if (OB_FAIL(partition_service->insert_row(trans_desc,
|
||||
dml_param,
|
||||
pkey,
|
||||
MY_SPEC.column_ids_,
|
||||
MY_SPEC.primary_key_ids_,
|
||||
insert_row_,
|
||||
INSERT_RETURN_ONE_DUP,
|
||||
cur_affected,
|
||||
duplicated_rows))) {
|
||||
if (OB_TRY_LOCK_ROW_CONFLICT != ret && OB_TRANSACTION_SET_VIOLATION != ret) {
|
||||
LOG_WARN("fail to insert row", K(pkey), K(MY_SPEC.column_ids_), K(ret));
|
||||
}
|
||||
LOG_DEBUG("trace insert clause", K(ret), K(affected_rows_));
|
||||
}
|
||||
|
||||
if (OB_SUCC(ret)) {
|
||||
affected_rows_ += cur_affected;
|
||||
}
|
||||
|
||||
if (OB_ERR_PRIMARY_KEY_DUPLICATE == ret) {
|
||||
if (OB_FAIL(insert_row_store_.add_row(insert_row_, false))) {
|
||||
LOG_WARN("add row to row store failed", K(ret), K(insert_row_));
|
||||
}
|
||||
}
|
||||
|
||||
if (nullptr != duplicated_rows) {
|
||||
(void)partition_service->revert_insert_iter(pkey, duplicated_rows);
|
||||
duplicated_rows = nullptr;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObTableMergeOp::insert_all_rows(ObPartitionService* partition_service, const transaction::ObTransDesc& trans_desc,
|
||||
const storage::ObDMLBaseParam& dml_param, const common::ObPartitionKey& pkey)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObRowStore::Iterator insert_row_iter;
|
||||
ObNewRow* insert_row = nullptr;
|
||||
int64_t cur_affected = 0;
|
||||
ObNewRowIterator* duplicated_rows = NULL;
|
||||
CK(OB_NOT_NULL(partition_service));
|
||||
insert_row_iter = insert_row_store_.begin();
|
||||
while (OB_SUCC(ret) && (OB_SUCC(insert_row_iter.get_next_row(insert_row, nullptr)))) {
|
||||
if (OB_FAIL(partition_service->insert_row(trans_desc,
|
||||
dml_param,
|
||||
pkey,
|
||||
MY_SPEC.column_ids_,
|
||||
MY_SPEC.primary_key_ids_,
|
||||
*insert_row,
|
||||
INSERT_RETURN_ONE_DUP,
|
||||
cur_affected,
|
||||
duplicated_rows))) {
|
||||
if (OB_TRY_LOCK_ROW_CONFLICT != ret && OB_TRANSACTION_SET_VIOLATION != ret) {
|
||||
LOG_WARN("fail to insert row", K(pkey), K(MY_SPEC.column_ids_), K(ret));
|
||||
}
|
||||
} else {
|
||||
affected_rows_ += cur_affected;
|
||||
}
|
||||
|
||||
if (nullptr != duplicated_rows) {
|
||||
(void)partition_service->revert_insert_iter(pkey, duplicated_rows);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObTableMergeOp::inner_close()
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (OB_FAIL(ObTableModifyOp::inner_close())) {
|
||||
LOG_WARN("fail to do inner close", K(ret));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObTableMergeOp::inner_get_next_row()
|
||||
{
|
||||
return OB_ITER_END;
|
||||
}
|
||||
|
||||
int ObTableMergeOp::process_update(
|
||||
ObPartitionService* partition_service, const ObPartitionKey& pkey, storage::ObDMLBaseParam& dml_param)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
bool need_update = false;
|
||||
bool need_delete = false;
|
||||
bool is_conflict = false;
|
||||
ObSQLSessionInfo* my_session = GET_MY_SESSION(ctx_);
|
||||
OZ(calc_condition(MY_SPEC.update_conds_, need_update));
|
||||
if (need_update) {
|
||||
OZ(generate_origin_row(is_conflict));
|
||||
OZ(calc_delete_condition(MY_SPEC.delete_conds_, need_delete));
|
||||
if (is_conflict) {
|
||||
ret = need_delete ? OB_ERR_SPECIFIED_ROW_NO_LONGER_EXISTS : OB_ERR_UPDATE_TWICE;
|
||||
} else {
|
||||
if (need_delete) {
|
||||
OZ(project_row(MY_SPEC.old_row_, old_row_));
|
||||
OZ(partition_service->delete_row(my_session->get_trans_desc(), dml_param, pkey, MY_SPEC.column_ids_, old_row_));
|
||||
OX(affected_rows_ += 1);
|
||||
} else {
|
||||
OZ(update_row(partition_service, pkey, dml_param));
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObTableMergeOp::generate_origin_row(bool& conflict)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
bool is_distinct = true;
|
||||
conflict = false;
|
||||
if (OB_FAIL(check_rowkey_whether_distinct(
|
||||
MY_SPEC.old_row_, MY_SPEC.primary_key_ids_.count(), T_HASH_DISTINCT, rowkey_dist_ctx_, is_distinct))) {
|
||||
LOG_WARN("faield to check whether row distinct", K(ret));
|
||||
} else if (!is_distinct) {
|
||||
conflict = true;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObTableMergeOp::update_row(
|
||||
ObPartitionService* partition_service, const ObPartitionKey& pkey, storage::ObDMLBaseParam& dml_param)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObSQLSessionInfo* my_session = GET_MY_SESSION(ctx_);
|
||||
ObNewRowIterator* duplicated_rows = NULL;
|
||||
int64_t cur_affected = 0;
|
||||
OV(OB_NOT_NULL(partition_service));
|
||||
OZ(check_row_null(MY_SPEC.new_row_, MY_SPEC.column_infos_));
|
||||
bool is_filtered = false;
|
||||
// In resolve phase, check constraint expression corresponding to
|
||||
// update subquery will be put in first half.
|
||||
int64_t cst_beg_idx = 0;
|
||||
int64_t cst_end_idx = MY_SPEC.check_constraint_exprs_.count() / 2;
|
||||
OZ(filter_row_for_check_cst(MY_SPEC.check_constraint_exprs_, is_filtered, cst_beg_idx, cst_end_idx));
|
||||
OV(!is_filtered, OB_ERR_CHECK_CONSTRAINT_VIOLATED);
|
||||
// do update.
|
||||
bool is_row_changed = false;
|
||||
OZ(check_updated_value(*this, MY_SPEC.updated_column_infos_, MY_SPEC.old_row_, MY_SPEC.new_row_, is_row_changed));
|
||||
|
||||
OZ(project_row(MY_SPEC.old_row_, old_row_));
|
||||
OZ(project_row(MY_SPEC.new_row_, new_row_));
|
||||
if (!is_row_changed) {
|
||||
OZ(lock_row(partition_service, pkey, dml_param));
|
||||
} else {
|
||||
OZ(partition_service->delete_row(my_session->get_trans_desc(), dml_param, pkey, MY_SPEC.column_ids_, old_row_));
|
||||
OZ(partition_service->insert_row(my_session->get_trans_desc(),
|
||||
dml_param,
|
||||
pkey,
|
||||
MY_SPEC.column_ids_,
|
||||
MY_SPEC.primary_key_ids_,
|
||||
new_row_,
|
||||
INSERT_RETURN_ONE_DUP,
|
||||
cur_affected,
|
||||
duplicated_rows));
|
||||
if (OB_ERR_PRIMARY_KEY_DUPLICATE == ret) {
|
||||
ret = OB_SUCCESS;
|
||||
OZ(insert_row_store_.add_row(new_row_, false));
|
||||
}
|
||||
if (nullptr != duplicated_rows) {
|
||||
(void)partition_service->revert_insert_iter(pkey, duplicated_rows);
|
||||
duplicated_rows = nullptr;
|
||||
}
|
||||
OX(affected_rows_ += 1);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObTableMergeOp::lock_row(
|
||||
ObPartitionService* partition_service, const ObPartitionKey& pkey, storage::ObDMLBaseParam& dml_param)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (OB_ISNULL((partition_service))) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("fail to get partition service", K(ret));
|
||||
} else {
|
||||
if (OB_SUCC(ret)) {
|
||||
if (OB_FAIL(ObTableModifyOp::lock_row(MY_SPEC.rowkey_exprs_, dml_param, pkey))) {
|
||||
if (OB_TRY_LOCK_ROW_CONFLICT != ret && OB_TRANSACTION_SET_VIOLATION != ret) {
|
||||
LOG_WARN("fail to lock row", K(ret));
|
||||
}
|
||||
} else {
|
||||
affected_rows_ += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // namespace sql
|
||||
} // namespace oceanbase
|
||||
Reference in New Issue
Block a user