8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-02-02 09:20:39 +01:00

This should fix #6778: Inconsistent cursor-driven deletion

This commit is contained in:
Dmitry Yemanov 2021-04-28 19:19:19 +03:00
parent f851cf78a2
commit 585ad1d1c5
3 changed files with 21 additions and 7 deletions

View File

@ -2594,9 +2594,6 @@ const StmtNode* EraseNode::erase(thread_db* tdbb, jrd_req* request, WhichTrigger
record_param* rpb = &request->req_rpb[stream];
jrd_rel* relation = rpb->rpb_relation;
if (rpb->rpb_number.isBof() || (!relation->rel_view_rse && !rpb->rpb_number.isValid()))
ERR_post(Arg::Gds(isc_no_cur_rec));
switch (request->req_operation)
{
case jrd_req::req_evaluate:
@ -2626,6 +2623,12 @@ const StmtNode* EraseNode::erase(thread_db* tdbb, jrd_req* request, WhichTrigger
request->req_operation = jrd_req::req_return;
RLCK_reserve_relation(tdbb, transaction, relation, true);
if (rpb->rpb_runtime_flags & RPB_just_deleted)
return parentStmt;
if (rpb->rpb_number.isBof() || (!relation->rel_view_rse && !rpb->rpb_number.isValid()))
ERR_post(Arg::Gds(isc_no_cur_rec));
if (forNode && forNode->isWriteLockMode(request))
{
forceWriteLock(tdbb, rpb, transaction);
@ -2672,6 +2675,7 @@ const StmtNode* EraseNode::erase(thread_db* tdbb, jrd_req* request, WhichTrigger
forNode->setWriteLockMode(request);
return parentStmt;
}
REPL_erase(tdbb, rpb, transaction);
}
@ -2698,6 +2702,7 @@ const StmtNode* EraseNode::erase(thread_db* tdbb, jrd_req* request, WhichTrigger
}
rpb->rpb_number.setValid(false);
rpb->rpb_runtime_flags |= RPB_just_deleted;
return parentStmt;
}
@ -6599,9 +6604,6 @@ const StmtNode* ModifyNode::modify(thread_db* tdbb, jrd_req* request, WhichTrigg
record_param* orgRpb = &request->req_rpb[orgStream];
jrd_rel* relation = orgRpb->rpb_relation;
if (orgRpb->rpb_number.isBof() || (!relation->rel_view_rse && !orgRpb->rpb_number.isValid()))
ERR_post(Arg::Gds(isc_no_cur_rec));
record_param* newRpb = &request->req_rpb[newStream];
switch (request->req_operation)
@ -6666,6 +6668,7 @@ const StmtNode* ModifyNode::modify(thread_db* tdbb, jrd_req* request, WhichTrigg
forNode->setWriteLockMode(request);
return parentStmt;
}
IDX_modify(tdbb, orgRpb, newRpb, transaction);
REPL_modify(tdbb, orgRpb, newRpb, transaction);
}
@ -6718,6 +6721,15 @@ const StmtNode* ModifyNode::modify(thread_db* tdbb, jrd_req* request, WhichTrigg
impure->sta_state = 0;
RLCK_reserve_relation(tdbb, transaction, relation, true);
if (orgRpb->rpb_runtime_flags & RPB_just_deleted)
{
request->req_operation = jrd_req::req_return;
return parentStmt;
}
if (orgRpb->rpb_number.isBof() || (!relation->rel_view_rse && !orgRpb->rpb_number.isValid()))
ERR_post(Arg::Gds(isc_no_cur_rec));
if (forNode && (marks & StmtNode::MARK_MERGE))
forNode->checkRecordUpdated(tdbb, request, orgRpb);

View File

@ -132,8 +132,10 @@ const USHORT RPB_refetch = 0x01; // re-fetch is required
const USHORT RPB_undo_data = 0x02; // data got from undo log
const USHORT RPB_undo_read = 0x04; // read was performed using the undo log
const USHORT RPB_undo_deleted = 0x08; // read was performed using the undo log, primary version is deleted
const USHORT RPB_just_deleted = 0x10; // record was just deleted by us
const USHORT RPB_UNDO_FLAGS = (RPB_undo_data | RPB_undo_read | RPB_undo_deleted);
const USHORT RPB_CLEAR_FLAGS = (RPB_UNDO_FLAGS | RPB_just_deleted);
const unsigned int MAX_DIFFERENCES = 1024; // Max length of generated Differences string
// between two records

View File

@ -741,7 +741,7 @@ bool VIO_chase_record_version(thread_db* tdbb, record_param* rpb,
// Take care about modifications performed by our own transaction
rpb->rpb_runtime_flags &= ~RPB_UNDO_FLAGS;
rpb->rpb_runtime_flags &= ~RPB_CLEAR_FLAGS;
int forceBack = 0;
if (rpb->rpb_stream_flags & RPB_s_unstable)