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

Control which exceptions in decfloat (underflow, division by zero, etc.) trap SQL statement

This commit is contained in:
AlexPeshkoff 2017-03-07 20:45:11 +03:00
parent 57af009fd8
commit 14906afe06
5 changed files with 144 additions and 29 deletions

View File

@ -870,6 +870,16 @@ dnl if 64-bit mode, then archive tool, ar, needs -X64 option
[AC_LANG_PROGRAM(,[[int lp64 = __64BIT__; ]])],
[AR_OPTIONS=-X64],)
fi
XE_SAVE_ENV()
CXXFLAGS="$CXXFLAGS -std=c++11"
AC_CACHE_CHECK([whether the C++ compiler understands noexcept], [ac_cv_cxx_noexcept], [
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[int f(int x) noexcept { return x + 1; }]], [[]])],
[ac_cv_cxx_noexcept=yes], [ac_cv_cxx_noexcept=no])])
XE_RESTORE_ENV()
if test "$ac_cv_cxx_noexcept" = yes; then
AC_DEFINE([HAS_NOEXCEPT], [1], [Define if the C++ compiler understands noexcept.])
fi
AC_LANG_POP(C++)
dnl Check for functions

View File

@ -7972,49 +7972,100 @@ void SetRoleNode::execute(thread_db* tdbb, dsql_req* request) const
namespace
{
struct RoundMode
struct TextCode
{
const char* name;
USHORT val;
};
#define FB_RMODE(x) { STRINGIZE(x), x }
//#define FB_TEXTCODE(x) { STRINGIZE(x), x }
#define FB_TEXTCODE(x) { #x, x }
const RoundMode roundModes[] = {
FB_RMODE(DEC_ROUND_CEILING),
FB_RMODE(DEC_ROUND_UP),
FB_RMODE(DEC_ROUND_HALF_UP),
FB_RMODE(DEC_ROUND_HALF_EVEN),
FB_RMODE(DEC_ROUND_HALF_DOWN),
FB_RMODE(DEC_ROUND_DOWN),
FB_RMODE(DEC_ROUND_FLOOR),
const TextCode roundModes[] = {
FB_TEXTCODE(DEC_ROUND_CEILING),
FB_TEXTCODE(DEC_ROUND_UP),
FB_TEXTCODE(DEC_ROUND_HALF_UP),
FB_TEXTCODE(DEC_ROUND_HALF_EVEN),
FB_TEXTCODE(DEC_ROUND_HALF_DOWN),
FB_TEXTCODE(DEC_ROUND_DOWN),
FB_TEXTCODE(DEC_ROUND_FLOOR),
{ "DEC_ROUND_REROUND", DEC_ROUND_05UP },
{ NULL, 0 }
};
#undef FB_RMODE
//DEC_ROUND_
//0123456789
const unsigned FB_RMODE_OFFSET = 10;
const TextCode ieeeTraps[] = {
FB_TEXTCODE(DEC_IEEE_754_Division_by_zero),
FB_TEXTCODE(DEC_IEEE_754_Inexact),
FB_TEXTCODE(DEC_IEEE_754_Invalid_operation),
FB_TEXTCODE(DEC_IEEE_754_Overflow),
FB_TEXTCODE(DEC_IEEE_754_Underflow),
{ NULL, 0 }
};
//DEC_IEEE_754_
//0123456789012
const unsigned FB_TRAPS_OFFSET = 13;
#undef FB_TEXTCODE
const TextCode* getCodeByText(const MetaName& text, const TextCode* textCode, unsigned offset)
{
NoCaseString name(text.c_str(), text.length());
for (const TextCode* tc = textCode; tc->name; ++tc)
{
if (name == &tc->name[offset])
return tc;
}
void SetRoundNode::execute(thread_db* tdbb, dsql_req* request) const
return nullptr;
}
}
//--------------------
SetRoundNode::SetRoundNode(MemoryPool& pool, Firebird::MetaName* name)
: SessionManagementNode(pool)
{
fb_assert(name);
const TextCode* mode = getCodeByText(*name, roundModes, FB_RMODE_OFFSET);
if (!mode)
(Arg::Gds(isc_random) << "Invalid round mode for decfloat").raise();
rndMode = mode->val;
}
void SetRoundNode::execute(thread_db* tdbb, dsql_req* /*request*/) const
{
SET_TDBB(tdbb);
Attachment* const attachment = tdbb->getAttachment();
for (const RoundMode* r = roundModes; r->name; ++r)
{
if (rndName == &r->name[FB_RMODE_OFFSET])
{
attachment->att_dec_status.roundingMode = r->val;
return;
}
attachment->att_dec_status.roundingMode = rndMode;
}
(Arg::Gds(isc_random) << "Invalid round mode for decfloat").raise();
//--------------------
void SetTrapsNode::trap(Firebird::MetaName* name)
{
fb_assert(name);
const TextCode* trap = getCodeByText(*name, ieeeTraps, FB_TRAPS_OFFSET);
if (!trap)
(Arg::Gds(isc_random) << "Invalid decfloat trap").raise();
traps |= trap->val;
}
void SetTrapsNode::execute(thread_db* tdbb, dsql_req* /*request*/) const
{
SET_TDBB(tdbb);
Attachment* const attachment = tdbb->getAttachment();
attachment->att_dec_status.decExtFlag = traps;
}

View File

@ -1584,9 +1584,31 @@ public:
class SetRoundNode : public SessionManagementNode
{
public:
SetRoundNode(MemoryPool& pool, Firebird::MetaName* name)
SetRoundNode(MemoryPool& pool, Firebird::MetaName* name);
public:
virtual Firebird::string internalPrint(NodePrinter& printer) const
{
SessionManagementNode::internalPrint(printer);
NODE_PRINT(printer, rndMode);
return "SetRoundNode";
}
virtual void execute(thread_db* tdbb, dsql_req* request) const;
public:
USHORT rndMode;
};
class SetTrapsNode : public SessionManagementNode
{
public:
SetTrapsNode(MemoryPool& pool)
: SessionManagementNode(pool),
rndName(pool, *name)
traps(0u)
{
}
@ -1595,15 +1617,17 @@ public:
{
SessionManagementNode::internalPrint(printer);
NODE_PRINT(printer, rndName);
NODE_PRINT(printer, traps);
return "SetRoundNode";
return "SetTrapsNode";
}
virtual void execute(thread_db* tdbb, dsql_req* request) const;
void trap(Firebird::MetaName* name);
public:
Firebird::MetaName rndName;
USHORT traps;
};

View File

@ -611,6 +611,7 @@ using namespace Firebird;
%token <metaNamePtr> SQL
%token <metaNamePtr> SYSTEM
%token <metaNamePtr> TIES
%token <metaNamePtr> TRAPS
%token <metaNamePtr> UNBOUNDED
%token <metaNamePtr> VARBINARY
%token <metaNamePtr> WINDOW
@ -756,8 +757,9 @@ using namespace Firebird;
Jrd::MappingNode* mappingNode;
Jrd::MappingNode::OP mappingOp;
Jrd::SetRoleNode* setRoleNode;
Jrd::SetRoundNode* setRoundNode;
Jrd::CreateAlterRoleNode* createAlterRoleNode;
Jrd::SetRoundNode* setRoundNode;
Jrd::SetTrapsNode* setTrapsNode;
}
%include types.y
@ -816,7 +818,7 @@ tra_statement
%type <mngNode> mng_statement
mng_statement
: set_round { $$ = $1; }
// | set_traps { $$ = $1; }
| set_traps { $$ = $1; }
| set_role { $$ = $1; }
;
@ -5024,6 +5026,32 @@ set_round
{ $$ = newNode<SetRoundNode>($4); }
;
%type <setTrapsNode> set_traps
set_traps
: SET DECFLOAT TRAPS TO
{ $$ = newNode<SetTrapsNode>(); }
traps_list_opt($5)
{ $$ = $5; }
;
%type traps_list_opt(<setTrapsNode>)
traps_list_opt($setTrapsNode)
: // nothing
| traps_list($setTrapsNode)
;
%type traps_list(<setTrapsNode>)
traps_list($setTrapsNode)
: trap($setTrapsNode)
| traps_list ',' trap($setTrapsNode)
;
%type trap(<setTrapsNode>)
trap($setTrapsNode)
: valid_symbol_name
{ $setTrapsNode->trap($1); }
;
%type tran_option_list_opt(<setTransactionNode>)
tran_option_list_opt($setTransactionNode)
: // nothing
@ -8280,6 +8308,7 @@ non_reserved_word
| SQL
| SYSTEM
| TIES
| TRAPS
;
%%

View File

@ -440,6 +440,7 @@ static const TOK tokens[] =
{TOK_TO, "TO", false},
{TOK_TRAILING, "TRAILING", false},
{TOK_TRANSACTION, "TRANSACTION", true},
{TOK_TRAPS, "TRAPS", true},
{TOK_TRIGGER, "TRIGGER", false},
{TOK_TRIM, "TRIM", false},
{TOK_TRUE, "TRUE", false},