file: FirebirdPreparedStatement.cpp
method: FirebirdPreparedStatement::CreateStatement(...)
problem: if new transaction was started, and after that exception was thrown, transaction was not rolled back and statement was not added to statements list, and when database will closing, firebird exception will be thrown becouse there is opened transaction during database disconnection.
I resolve this problem, but I have not ability to test my changes in HEAD revision of svn. There is old version of this method with my patch:
FirebirdPreparedStatement* FirebirdPreparedStatement::CreateStatement(isc_db_handle pDatabase, isc_tr_handle pTransaction, const wxString& strSQL, const wxCSConv* conv)
{
wxArrayString Queries = ParseQueries(strSQL);
wxArrayString::iterator start = Queries.begin();
wxArrayString::iterator stop = Queries.end();
FirebirdPreparedStatement *pStatement = NULL;
if (Queries.size() < 1)
{
pStatement = new FirebirdPreparedStatement(pDatabase, pTransaction);
pStatement->SetEncoding(conv);
pStatement->SetErrorCode(DATABASE_LAYER_ERROR);
pStatement->SetErrorMessage(_("No SQL Statements found"));
#ifndef DONT_USE_DATABASE_LAYER_EXCEPTIONS
// If we're using exceptions, then assume that the calling program won't
// won't get the pStatement pointer back. So delete is now before
// throwing the exception
try
{
delete pStatement; //It's probably better to manually iterate over the list and close the statements, but for now just let close do it
}
catch (DatabaseLayerException& e)
{
}
DatabaseLayerException error(pStatement->GetErrorCode(), pStatement->GetErrorMessage());
throw error;
#endif
return pStatement;
}
// Start a new transaction if appropriate
bool startedNewTransaction = false;
if (pTransaction == NULL)
{
pTransaction = 0L;
ISC_STATUS_ARRAY status;
int nReturn = isc_start_transaction(status, &pTransaction, 1, &pDatabase, 0 /*tpb_length*/, NULL/*tpb*/);
pStatement = new FirebirdPreparedStatement(pDatabase, pTransaction);
pStatement->SetEncoding(conv);
if (nReturn != 0)
{
long nSqlCode = isc_sqlcode(status);
pStatement->SetErrorCode(FirebirdDatabaseLayer::TranslateErrorCode(nSqlCode));
pStatement->SetErrorMessage(FirebirdDatabaseLayer::TranslateErrorCodeToString(nSqlCode, status));
#ifndef DONT_USE_DATABASE_LAYER_EXCEPTIONS
// If we're using exceptions, then assume that the calling program won't
// won't get the pStatement pointer back. So delete is now before
// throwing the exception
try
{
delete pStatement; //It's probably better to manually iterate over the list and close the statements, but for now just let close do it
}
catch (DatabaseLayerException& e)
{
}
DatabaseLayerException error(pStatement->GetErrorCode(), pStatement->GetErrorMessage());
throw error;
#endif
return pStatement;
}
startedNewTransaction = true;
pStatement->SetManageTransaction(true);
}
else
{
pStatement = new FirebirdPreparedStatement(pDatabase, pTransaction);
pStatement->SetEncoding(conv);
pStatement->SetManageTransaction(false);
}
while (start != stop)
{
try
{
pStatement->AddPreparedStatement((*start));
}
catch(...)
{
if(startedNewTransaction)
try
{
ISC_STATUS_ARRAY status;
isc_rollback_transaction(status, &pTransaction);
}
catch(...){}
throw;
}
if (pStatement->GetErrorCode() != DATABASE_LAYER_OK)
{
// If we're using exceptions, then assume that the calling program won't
// won't get the pStatement pointer back. So delete is now before
// throwing the exception
#ifndef DONT_USE_DATABASE_LAYER_EXCEPTIONS
// Set the error code and message
DatabaseLayerException error(pStatement->GetErrorCode(), pStatement->GetErrorMessage());
if(startedNewTransaction)
try
{
ISC_STATUS_ARRAY status;
isc_rollback_transaction(status, &pTransaction);
}
catch(...){}
try
{
delete pStatement; //It's probably better to manually iterate over the list and close the statements, but for now just let close do it
}
catch (DatabaseLayerException& e)
{
}
// Pass on the error
throw error;
#endif
return pStatement;
}
start++;
}
// Success? Return the statement
return pStatement;
}
With best regards,
Evgeny Bevz.
Does this commit fix the issue for you: http://wxcode.svn.sourceforge.net/viewvc/wxcode/trunk/wxCode/components/databaselayer/src/FirebirdPreparedStatement.cpp?r1=903&r2=914