8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-24 06:43:03 +01:00

Fixed CORE-4670: Constraint violation error may be swallowed in some cases.

This commit is contained in:
dimitr 2015-01-26 10:42:35 +00:00
parent 09af5b862d
commit fbb4edcfd7

View File

@ -301,8 +301,6 @@ enum UdfError
};
static void handleUdfException(const Exception& ex);
static void reRaiseExceptionFromUdf(thread_db* tdbb);
static SSHORT blob_get_segment(blb*, UCHAR*, USHORT, USHORT*);
static void blob_put_segment(blb*, const UCHAR*, USHORT);
static SLONG blob_lseek(blb*, USHORT, SLONG);
@ -943,50 +941,6 @@ UserFunction* FUN_resolve(thread_db* tdbb, CompilerScratch* csb, UserFunction* f
}
static void handleUdfException(const Exception& ex)
{
/****************************************
*
* h a n d l e U d f E x c e p t i o n
*
****************************************
*
* Functional description
* When exception happens in UDF we have
* no better choice then store it in
* tdbb_status_vector and raise again
* on return from UDF.
*
****************************************/
thread_db* tdbb = JRD_get_thread_data();
fb_utils::init_status(tdbb->tdbb_status_vector);
ex.stuff_exception(tdbb->tdbb_status_vector);
}
static void reRaiseExceptionFromUdf(thread_db* tdbb)
{
/*************************************************
*
* r e R a i s e E x c e p t i o n F r o m U d f
*
*************************************************
*
* Functional description
* When exception happens in UDF we have
* no better choice then store it in
* tdbb_status_vector and raise again
* on return from UDF.
*
*************************************************/
ISC_STATUS* st = tdbb->tdbb_status_vector;
if (st[0] == 1 && st[1] != 0)
{
ERR_punt();
}
}
static SLONG blob_lseek(blb* blob, USHORT mode, SLONG offset)
{
/**************************************
@ -1000,18 +954,25 @@ static SLONG blob_lseek(blb* blob, USHORT mode, SLONG offset)
*
**************************************/
// As this is a call-back from a UDF, must put it under try/catch and reacquire the engine mutex
try
{
thread_db* tdbb = JRD_get_thread_data();
Database::SyncGuard dsGuard(tdbb->getDatabase());
return BLB_lseek(blob, mode, offset);
}
catch (const Exception& ex)
{
handleUdfException(ex);
return -1;
try
{
Database::SyncGuard dsGuard(tdbb->getDatabase());
return BLB_lseek(blob, mode, offset);
}
catch (const Exception& ex)
{
ex.stuff_exception(tdbb->tdbb_status_vector);
}
}
catch (const Exception&)
{} // no-op
return -1; // error
}
@ -1028,17 +989,23 @@ static void blob_put_segment(blb* blob, const UCHAR* buffer, USHORT length)
*
**************************************/
// As this is a call-back from a UDF, must put it under try/catch and reacquire the engine mutex
try
{
thread_db* tdbb = JRD_get_thread_data();
Database::SyncGuard dsGuard(tdbb->getDatabase());
BLB_put_segment(tdbb, blob, buffer, length);
}
catch (const Exception& ex)
{
handleUdfException(ex);
try
{
Database::SyncGuard dsGuard(tdbb->getDatabase());
BLB_put_segment(tdbb, blob, buffer, length);
}
catch (const Exception& ex)
{
ex.stuff_exception(tdbb->tdbb_status_vector);
}
}
catch (const Exception&)
{} // no-op
}
@ -1059,26 +1026,34 @@ static SSHORT blob_get_segment(blb* blob, UCHAR* buffer, USHORT length, USHORT*
*
**************************************/
// As this is a call-back from a UDF, must put it under try/catch and reacquire the engine mutex
try
{
thread_db* tdbb = JRD_get_thread_data();
Database::SyncGuard dsGuard(tdbb->getDatabase());
*return_length = BLB_get_segment(tdbb, blob, buffer, length);
try
{
Database::SyncGuard dsGuard(tdbb->getDatabase());
if (blob->blb_flags & BLB_eof)
return 0;
*return_length = BLB_get_segment(tdbb, blob, buffer, length);
if (blob->blb_fragment_size)
return -1;
if (blob->blb_flags & BLB_eof)
return 0;
return 1;
if (blob->blb_fragment_size)
return -1;
return 1;
}
catch (const Exception& ex)
{
ex.stuff_exception(tdbb->tdbb_status_vector);
}
}
catch (const Exception& ex)
{
handleUdfException(ex);
return 0;
}
{} // no-op
return 0; // error
}
@ -1188,8 +1163,7 @@ static void invoke(thread_db* tdbb,
SET_TDBB(tdbb);
Database* dbb = tdbb->getDatabase();
// Get ready to accept exceptions from API called from UDF
fb_utils::init_status(tdbb->tdbb_status_vector);
ThreadStatusGuard tempStatus(tdbb);
START_CHECK_FOR_EXCEPTIONS(function->fun_exception_message.c_str());
if (function->fun_return_arg)
@ -1361,7 +1335,11 @@ static void invoke(thread_db* tdbb,
}
END_CHECK_FOR_EXCEPTIONS(function->fun_exception_message.c_str());
reRaiseExceptionFromUdf(tdbb);
// When exception happens inside UDF we have no better choice than storing it in
// tdbb_status_vector and raising again on return from UDF
if (tempStatus[0] == isc_arg_gds && tempStatus[1] != FB_SUCCESS)
ERR_post(Arg::StatusVector(tempStatus));
}