fix: fix the core and correctness error induced by foreign key and trigegr processing order refactor

This commit is contained in:
obdev
2023-03-14 10:10:52 +00:00
committed by ob-robot
parent 9b6784e77c
commit bbc80fb3d3
5 changed files with 66 additions and 30 deletions

View File

@ -974,7 +974,6 @@ int ObDMLService::update_row(const ObUpdCtDef &upd_ctdef,
LOG_WARN("check update new row tablet validity failed", K(ret));
} else if (OB_UNLIKELY(!upd_rtdef.is_row_changed_)) {
//old row is equal to new row, only need to lock row
ObChunkDatumStore::StoredRow* stored_row = nullptr;
if (OB_ISNULL(upd_rtdef.dlock_rtdef_)) {
ObIAllocator &allocator = dml_rtctx.get_exec_ctx().get_allocator();
if (OB_FAIL(init_das_lock_rtdef_for_update(dml_rtctx, upd_ctdef, upd_rtdef))) {
@ -990,8 +989,10 @@ int ObDMLService::update_row(const ObUpdCtDef &upd_ctdef,
old_tablet_loc,
dml_rtctx,
upd_ctdef.old_row_,
stored_row))) {
old_row))) {
LOG_WARN("write row to das op failed", K(ret), K(upd_ctdef), K(upd_rtdef));
} else {
new_row = old_row;
}
}
} else if (OB_UNLIKELY(old_tablet_loc != new_tablet_loc)) {
@ -2012,16 +2013,23 @@ int ObDMLService::get_nested_dup_table_ctx(const uint64_t table_id, DASDelCtxLi
int ObDMLService::handle_after_row_processing_batch(ObDMLModifyRowsList *dml_modify_rows)
{
int ret = OB_SUCCESS;
const ObDmlEventType t_insert = ObDmlEventType::DE_INSERTING;
const ObDmlEventType t_update = ObDmlEventType::DE_UPDATING;
const ObDmlEventType t_delete = ObDmlEventType::DE_DELETING;
ObDMLModifyRowsList::iterator row_iter = dml_modify_rows->begin();
for (; OB_SUCC(ret) && row_iter != dml_modify_rows->end(); row_iter++) {
ObDMLModifyRowNode &modify_row = *row_iter;
if (OB_ISNULL(modify_row.dml_op_) || OB_ISNULL(modify_row.dml_ctdef_) || OB_ISNULL(modify_row.dml_rtdef_)) {
if (OB_ISNULL(modify_row.full_row_) && OB_ISNULL(modify_row.new_row_) && OB_ISNULL(modify_row.old_row_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("invalid parameter for batch post row processing", K(ret));
} else if (OB_ISNULL(modify_row.dml_op_) || OB_ISNULL(modify_row.dml_ctdef_) || OB_ISNULL(modify_row.dml_rtdef_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("invalid parameter for batch post row processing", K(ret));
} else {
ObTableModifyOp &op = *modify_row.dml_op_;
const ObDMLBaseCtDef &dml_ctdef = *modify_row.dml_ctdef_;
ObDMLBaseRtDef &dml_rtdef = *modify_row.dml_rtdef_;
const ObDmlEventType dml_event = modify_row.dml_event_;
// process foreign key
if (OB_NOT_NULL(modify_row.full_row_) && OB_FAIL(modify_row.full_row_->to_expr(modify_row.dml_ctdef_->full_row_, op.get_eval_ctx()))) {
LOG_WARN("failed to covert stored full row to expr", K(ret));
@ -2029,15 +2037,18 @@ int ObDMLService::handle_after_row_processing_batch(ObDMLModifyRowsList *dml_mod
LOG_WARN("failed to covert stored old row to expr", K(ret));
} else if (OB_NOT_NULL(modify_row.new_row_) && OB_FAIL(modify_row.new_row_->to_expr(dml_ctdef.new_row_, op.get_eval_ctx()))) {
LOG_WARN("failed to covert stored new row to expr", K(ret));
} else if (OB_FAIL(ForeignKeyHandle::do_handle(op, dml_ctdef, dml_rtdef))) {
LOG_WARN("failed to handle foreign key constraints", K(ret));
} else {
if (t_update == dml_event) {
// for update op, Foreign key checks need to be performed only if the value has changed
if (reinterpret_cast<ObUpdRtDef &>(dml_rtdef).is_row_changed_ && OB_FAIL(ForeignKeyHandle::do_handle(op, dml_ctdef, dml_rtdef))) {
LOG_WARN("failed to handle foreign key constraints", K(ret));
}
} else if (OB_FAIL(ForeignKeyHandle::do_handle(op, dml_ctdef, dml_rtdef))) {
LOG_WARN("failed to handle foreign key constraints", K(ret));
}
}
// process after row trigger
const ObDmlEventType t_insert = ObDmlEventType::DE_INSERTING;
const ObDmlEventType t_update = ObDmlEventType::DE_UPDATING;
const ObDmlEventType t_delete = ObDmlEventType::DE_DELETING;
const ObDmlEventType dml_event = modify_row.dml_event_;
if (OB_SUCC(ret)) {
if (OB_SUCC(ret) && dml_ctdef.trig_ctdef_.all_tm_points_.has_after_row()) {
ObEvalCtx &eval_ctx = op.get_eval_ctx();
if (dml_event != t_insert && dml_event != t_update && dml_event != t_delete) {
ret = OB_ERR_UNEXPECTED;
@ -2060,18 +2071,20 @@ int ObDMLService::handle_after_row_processing_batch(ObDMLModifyRowsList *dml_mod
return ret;
}
int ObDMLService::handle_after_row_processing(ObDMLModifyRowsList *dml_modify_rows)
int ObDMLService::handle_after_row_processing_single(ObDMLModifyRowsList *dml_modify_rows)
{
int ret = OB_SUCCESS;
if (1 < dml_modify_rows->size()) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("the number of rows in the list is more than 1", K(ret), K(dml_modify_rows->size()));
} else if (1 == dml_modify_rows->size()) {
// for single-row processing, the expr defined in ctdef and trig parameters haven't been refreshed
// Therefore, there is no need to re-convert the rows to be modified into an expression and init trig parameters
ObDMLModifyRowsList::iterator row_iter = dml_modify_rows->begin();
// for single-row processing, the expr defined in ctdef and trig parameters haven't been refreshed
// case1: only one row added to the list of dml_modify_rows;
// case2: for multi table dml stmt, each table adds a row to the list;
// In these cases, there is no need to re-convert the rows to be modified into an expression and init trig parameters;
ObDMLModifyRowsList::iterator row_iter = dml_modify_rows->begin();
for (; OB_SUCC(ret) && row_iter != dml_modify_rows->end(); row_iter++) {
ObDMLModifyRowNode &modify_row = *row_iter;
if (OB_ISNULL(modify_row.dml_op_) || OB_ISNULL(modify_row.dml_ctdef_) || OB_ISNULL(modify_row.dml_rtdef_)) {
if (OB_ISNULL(modify_row.full_row_) && OB_ISNULL(modify_row.new_row_) && OB_ISNULL(modify_row.old_row_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("invalid parameter for batch post row processing", K(ret));
} else if (OB_ISNULL(modify_row.dml_op_) || OB_ISNULL(modify_row.dml_ctdef_) || OB_ISNULL(modify_row.dml_rtdef_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("invalid parameter for batch post row processing", K(ret));
} else {
@ -2085,14 +2098,38 @@ int ObDMLService::handle_after_row_processing(ObDMLModifyRowsList *dml_modify_ro
if (dml_event != t_insert && dml_event != t_update && dml_event != t_delete) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("invalid trigger event", K(ret));
} else if (OB_FAIL(ForeignKeyHandle::do_handle(op, dml_ctdef, dml_rtdef))) {
LOG_WARN("failed to handle foreign key constraints", K(ret));
} else if (OB_FAIL(TriggerHandle::do_handle_after_row(op, dml_ctdef.trig_ctdef_, dml_rtdef.trig_rtdef_, dml_event))) {
} else {
if (t_update == dml_event) {
// for update op, Foreign key checks need to be performed only if the value has changed
if (reinterpret_cast<ObUpdRtDef &>(dml_rtdef).is_row_changed_ && OB_FAIL(ForeignKeyHandle::do_handle(op, dml_ctdef, dml_rtdef))) {
LOG_WARN("failed to handle foreign key constraints", K(ret));
}
} else if (OB_FAIL(ForeignKeyHandle::do_handle(op, dml_ctdef, dml_rtdef))) {
LOG_WARN("failed to handle foreign key constraints", K(ret));
}
}
if (OB_SUCC(ret) && OB_FAIL(TriggerHandle::do_handle_after_row(op, dml_ctdef.trig_ctdef_, dml_rtdef.trig_rtdef_, dml_event))) {
LOG_WARN("failed to handle after trigger", K(ret));
}
}
}
return ret;
}
int ObDMLService::handle_after_row_processing(bool execute_single_row, ObDMLModifyRowsList *dml_modify_rows)
{
int ret = OB_SUCCESS;
if (1 > dml_modify_rows->size()) {
// after row processing list is empty, nothing to do
#ifndef NDEBUG
LOG_INFO("No row need to perform foreign key check or after row trigger");
#endif
} else if (execute_single_row) {
ret = handle_after_row_processing_single(dml_modify_rows);
} else {
ret = handle_after_row_processing_batch(dml_modify_rows);
}
return ret;
}
} // namespace sql
} // namespace oceanbase

View File

@ -227,8 +227,9 @@ public:
static int get_nested_dup_table_ctx(const uint64_t table_id,
DASDelCtxList& del_ctx_list,
SeRowkeyDistCtx* &rowkey_dist_ctx);
static int handle_after_row_processing(ObDMLModifyRowsList *dml_modify_rows);
static int handle_after_row_processing_single(ObDMLModifyRowsList *dml_modify_rows);
static int handle_after_row_processing_batch(ObDMLModifyRowsList *dml_modify_rows);
static int handle_after_row_processing(bool execute_single_row, ObDMLModifyRowsList *dml_modify_rows);
static int init_ob_rowkey( ObIAllocator &allocator, const int64_t rowkey_cnt, ObRowkey &table_rowkey);
private:
template <int N>

View File

@ -819,7 +819,7 @@ int ObTableInsertUpOp::do_insert_up()
LOG_WARN("fail to load all row", K(ret));
} else if (OB_FAIL(post_all_dml_das_task(dml_rtctx_, false))) {
LOG_WARN("fail to post all das task", K(ret));
} else if (!check_is_duplicated() && OB_FAIL(ObDMLService::handle_after_row_processing_batch(&dml_modify_rows_))) {
} else if (!check_is_duplicated() && OB_FAIL(ObDMLService::handle_after_row_processing(execute_single_row_, &dml_modify_rows_))) {
LOG_WARN("try insert is not duplicated, failed to process foreign key handle", K(ret));
} else if (!check_is_duplicated()) {
insert_rows_ += insert_rows;
@ -843,7 +843,7 @@ int ObTableInsertUpOp::do_insert_up()
LOG_WARN("do insert rows post process failed", K(ret));
} else if (OB_FAIL(post_all_dml_das_task(dml_rtctx_, false))) {
LOG_WARN("do insert rows post process failed", K(ret));
} else if (OB_FAIL(ObDMLService::handle_after_row_processing_batch(&dml_modify_rows_))) {
} else if (OB_FAIL(ObDMLService::handle_after_row_processing(execute_single_row_, &dml_modify_rows_))) {
LOG_WARN("try insert is duplicated, failed to process foreign key handle", K(ret));
}

View File

@ -1083,10 +1083,8 @@ int ObTableModifyOp::submit_all_dml_task()
LOG_WARN("execute all dml das task failed", K(ret));
} else if (OB_FAIL(dml_rtctx_.das_ref_.close_all_task())) {
LOG_WARN("close all das task failed", K(ret));
} else if (!execute_single_row_ && OB_FAIL(ObDMLService::handle_after_row_processing_batch(&get_dml_modify_row_list()))) {
} else if (OB_FAIL(ObDMLService::handle_after_row_processing(execute_single_row_, &get_dml_modify_row_list()))) {
LOG_WARN("perform batch foreign key constraints and after row trigger failed", K(ret));
} else if (execute_single_row_ && OB_FAIL(ObDMLService::handle_after_row_processing(&get_dml_modify_row_list()))) {
LOG_WARN("perform single row foreign key constraints and after row trigger failed", K(ret));
} else {
dml_modify_rows_.clear();
dml_rtctx_.reuse();

View File

@ -439,7 +439,7 @@ int ObTableReplaceOp::do_replace_into()
LOG_WARN("fail to load all row", K(ret));
} else if (OB_FAIL(post_all_dml_das_task())) {
LOG_WARN("fail to post all das task", K(ret));
} else if (!check_is_duplicated() && OB_FAIL(ObDMLService::handle_after_row_processing_batch(&dml_modify_rows_))) {
} else if (!check_is_duplicated() && OB_FAIL(ObDMLService::handle_after_row_processing(execute_single_row_, &dml_modify_rows_))) {
LOG_WARN("try insert is not duplicated, failed to process foreign key handle", K(ret));
} else if (!check_is_duplicated()) {
LOG_DEBUG("try insert is not duplicated", K(ret));
@ -460,7 +460,7 @@ int ObTableReplaceOp::do_replace_into()
LOG_WARN("fail to prepare final das task", K(ret));
} else if (OB_FAIL(post_all_dml_das_task())) {
LOG_WARN("do insert rows post process failed", K(ret));
} else if (OB_FAIL(ObDMLService::handle_after_row_processing_batch(&dml_modify_rows_))) {
} else if (OB_FAIL(ObDMLService::handle_after_row_processing(execute_single_row_, &dml_modify_rows_))) {
LOG_WARN("try insert is duplicated, failed to process foreign key handle", K(ret));
}