mirror of
https://github.com/FirebirdSQL/firebird.git
synced 2025-01-23 06:43:04 +01:00
Fixed bug CORE-5681 : AV when external statement is executed and local transaction is rolled back
This commit is contained in:
parent
40897c40de
commit
860f179712
@ -365,8 +365,24 @@ Transaction* Connection::createTransaction()
|
|||||||
return tran;
|
return tran;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Connection::deleteTransaction(Transaction* tran)
|
void Connection::deleteTransaction(thread_db* tdbb, Transaction* tran)
|
||||||
{
|
{
|
||||||
|
// Close all active statements in tran context avoiding commit of already
|
||||||
|
// deleted transaction
|
||||||
|
Statement** stmt_ptr = m_statements.begin();
|
||||||
|
while (stmt_ptr < m_statements.end())
|
||||||
|
{
|
||||||
|
Statement* stmt = *stmt_ptr;
|
||||||
|
if (stmt->getTransaction() == tran)
|
||||||
|
{
|
||||||
|
if (stmt->isActive())
|
||||||
|
stmt->close(tdbb, true);
|
||||||
|
}
|
||||||
|
// close() above could destroy statement and remove it from m_statements
|
||||||
|
if (stmt_ptr < m_statements.end() && *stmt_ptr == stmt)
|
||||||
|
stmt_ptr++;
|
||||||
|
}
|
||||||
|
|
||||||
FB_SIZE_T pos;
|
FB_SIZE_T pos;
|
||||||
if (m_transactions.find(tran, pos))
|
if (m_transactions.find(tran, pos))
|
||||||
{
|
{
|
||||||
@ -378,7 +394,7 @@ void Connection::deleteTransaction(Transaction* tran)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!m_used_stmts && m_transactions.getCount() == 0 && !m_deleting)
|
if (!m_used_stmts && m_transactions.getCount() == 0 && !m_deleting)
|
||||||
m_provider.releaseConnection(JRD_get_thread_data(), *this);
|
m_provider.releaseConnection(tdbb, *this);
|
||||||
}
|
}
|
||||||
|
|
||||||
Statement* Connection::createStatement(const string& sql)
|
Statement* Connection::createStatement(const string& sql)
|
||||||
@ -657,7 +673,7 @@ void Transaction::commit(thread_db* tdbb, bool retain)
|
|||||||
if (!retain)
|
if (!retain)
|
||||||
{
|
{
|
||||||
detachFromJrdTran();
|
detachFromJrdTran();
|
||||||
m_connection.deleteTransaction(this);
|
m_connection.deleteTransaction(tdbb, this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -670,7 +686,7 @@ void Transaction::rollback(thread_db* tdbb, bool retain)
|
|||||||
if (!retain)
|
if (!retain)
|
||||||
{
|
{
|
||||||
detachFromJrdTran();
|
detachFromJrdTran();
|
||||||
m_connection.deleteTransaction(this);
|
m_connection.deleteTransaction(tdbb, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status->getState() & IStatus::STATE_ERRORS) {
|
if (status->getState() & IStatus::STATE_ERRORS) {
|
||||||
@ -710,7 +726,7 @@ Transaction* Transaction::getTransaction(thread_db* tdbb, Connection* conn, TraS
|
|||||||
}
|
}
|
||||||
catch (const Exception&)
|
catch (const Exception&)
|
||||||
{
|
{
|
||||||
conn->deleteTransaction(ext_tran);
|
conn->deleteTransaction(tdbb, ext_tran);
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -913,7 +929,7 @@ bool Statement::fetch(thread_db* tdbb, const ValueListNode* out_params)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Statement::close(thread_db* tdbb)
|
void Statement::close(thread_db* tdbb, bool invalidTran)
|
||||||
{
|
{
|
||||||
// we must stuff exception if and only if this is the first time it occurs
|
// we must stuff exception if and only if this is the first time it occurs
|
||||||
// once we stuff exception we must punt
|
// once we stuff exception we must punt
|
||||||
@ -942,6 +958,9 @@ void Statement::close(thread_db* tdbb)
|
|||||||
unBindFromRequest();
|
unBindFromRequest();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (invalidTran)
|
||||||
|
m_transaction = NULL;
|
||||||
|
|
||||||
if (m_transaction && m_transaction->getScope() == traAutonomous)
|
if (m_transaction && m_transaction->getScope() == traAutonomous)
|
||||||
{
|
{
|
||||||
bool commitFailed = false;
|
bool commitFailed = false;
|
||||||
|
@ -201,7 +201,7 @@ public:
|
|||||||
// transaction into m_transactions array and delete not needed transaction
|
// transaction into m_transactions array and delete not needed transaction
|
||||||
// immediately (as we didn't pool transactions)
|
// immediately (as we didn't pool transactions)
|
||||||
Transaction* createTransaction();
|
Transaction* createTransaction();
|
||||||
void deleteTransaction(Transaction* tran);
|
void deleteTransaction(Jrd::thread_db* tdbb, Transaction* tran);
|
||||||
|
|
||||||
// Statements management within connection scope : put newly created
|
// Statements management within connection scope : put newly created
|
||||||
// statement into m_statements array, but don't delete freed statement
|
// statement into m_statements array, but don't delete freed statement
|
||||||
@ -325,7 +325,7 @@ public:
|
|||||||
void open(Jrd::thread_db* tdbb, Transaction* tran,
|
void open(Jrd::thread_db* tdbb, Transaction* tran,
|
||||||
const Firebird::MetaName* const* in_names, const Jrd::ValueListNode* in_params, bool singleton);
|
const Firebird::MetaName* const* in_names, const Jrd::ValueListNode* in_params, bool singleton);
|
||||||
bool fetch(Jrd::thread_db* tdbb, const Jrd::ValueListNode* out_params);
|
bool fetch(Jrd::thread_db* tdbb, const Jrd::ValueListNode* out_params);
|
||||||
void close(Jrd::thread_db* tdbb);
|
void close(Jrd::thread_db* tdbb, bool invalidTran = false);
|
||||||
void deallocate(Jrd::thread_db* tdbb);
|
void deallocate(Jrd::thread_db* tdbb);
|
||||||
|
|
||||||
const Firebird::string& getSql() const { return m_sql; }
|
const Firebird::string& getSql() const { return m_sql; }
|
||||||
|
Loading…
Reference in New Issue
Block a user