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

Improvement CORE-6032 - Add DPB properties for time zone bind and decfloat configuration.

This commit is contained in:
Adriano dos Santos Fernandes 2019-04-07 11:56:02 -03:00
parent eee0e0cb68
commit 2a9f8fa60b
19 changed files with 327 additions and 128 deletions

View File

@ -164,11 +164,16 @@ DECFLOAT (FB 4.0)
last digit in the result to be even), HALF_DOWN (to nearest, if equidistant - down),
DOWN (towards 0), FLOOR (towards -infinity), REROUND (up if digit to be rounded is
0 or 5, down in other cases). HALF_UP rounding is used by default.
The initial configuration may be specified with DPB isc_dpb_decfloat_round followed
by a string with its value (case does not matter).
SET DECFLOAT TRAPS TO <comma-separated traps list - may be empty> - controls which
exceptional conditions cause a trap. Valid traps are: Division_by_zero, Inexact,
Invalid_operation, Overflow and Underflow. By default traps are set to:
Division_by_zero, Invalid_operation, Overflow.
The initial configuration may be specified with DPB isc_dpb_decfloat_traps followed
by a comma-separated string with its value (case does not matter; using a single
optional space after commas).
SET DECFLOAT BIND <bind-type> - controls how are DECFLOAT values represented in outer
world (i.e. in messages or in XSQLDA). Valid binding types are: NATIVE (use IEEE754
@ -182,6 +187,8 @@ DECFLOAT (FB 4.0)
required precision but range of values is very limited). When using in a tool like
generic purporse GUI client choice of CHAR binding is OK in most cases. By default
NATIVE binding is used.
The initial configuration may be specified with DPB isc_dpb_decfloat_bind followed
by a string with its value (case does not matter).
5. The length of DECFLOAT literals are limited to 1024 characters. For longer values, you will
need to use the scientific notation. For example, the 0.0<1020 zeroes>11 cannot be used

View File

@ -169,6 +169,8 @@ Old clients may not understand the new data types, so it's possible to define th
The bind configuration is also applicable to input parameters.
The initial configuration of time zone bind may be specified with DPB `isc_dpb_time_zone_bind` followed by a string with its value (case does not matter).
#### Syntax
```

View File

@ -1920,6 +1920,10 @@ C --
PARAMETER (GDS__eds_input_prm_not_used = 335545253)
INTEGER*4 GDS__effective_user
PARAMETER (GDS__effective_user = 335545254)
INTEGER*4 GDS__time_zone_bind
PARAMETER (GDS__time_zone_bind = 335545255)
INTEGER*4 GDS__decfloat_bind
PARAMETER (GDS__decfloat_bind = 335545256)
INTEGER*4 GDS__gfix_db_name
PARAMETER (GDS__gfix_db_name = 335740929)
INTEGER*4 GDS__gfix_invalid_sw

View File

@ -1915,6 +1915,10 @@ const
gds_eds_input_prm_not_used = 335545253;
isc_effective_user = 335545254;
gds_effective_user = 335545254;
isc_time_zone_bind = 335545255;
gds_time_zone_bind = 335545255;
isc_decfloat_bind = 335545256;
gds_decfloat_bind = 335545256;
isc_gfix_db_name = 335740929;
gds_gfix_db_name = 335740929;
isc_gfix_invalid_sw = 335740930;

View File

@ -125,6 +125,11 @@
#define isc_dpb_map_attach 90
#define isc_dpb_session_time_zone 91
#define isc_dpb_set_db_replica 92
#define isc_dpb_time_zone_bind 93
#define isc_dpb_decfloat_bind 94
#define isc_dpb_decfloat_round 95
#define isc_dpb_decfloat_traps 96
/**************************************************/
/* clumplet tags used inside isc_dpb_address_path */

View File

@ -956,6 +956,8 @@ static const struct {
{"tra_snapshot_does_not_exist", 335545252},
{"eds_input_prm_not_used", 335545253},
{"effective_user", 335545254},
{"time_zone_bind", 335545255},
{"decfloat_bind", 335545256},
{"gfix_db_name", 335740929},
{"gfix_invalid_sw", 335740930},
{"gfix_incmp_sw", 335740932},

View File

@ -990,6 +990,8 @@ const ISC_STATUS isc_bad_repl_handle = 335545251L;
const ISC_STATUS isc_tra_snapshot_does_not_exist = 335545252L;
const ISC_STATUS isc_eds_input_prm_not_used = 335545253L;
const ISC_STATUS isc_effective_user = 335545254L;
const ISC_STATUS isc_time_zone_bind = 335545255L;
const ISC_STATUS isc_decfloat_bind = 335545256L;
const ISC_STATUS isc_gfix_db_name = 335740929L;
const ISC_STATUS isc_gfix_invalid_sw = 335740930L;
const ISC_STATUS isc_gfix_incmp_sw = 335740932L;
@ -1476,7 +1478,7 @@ const ISC_STATUS isc_trace_switch_user_only = 337182757L;
const ISC_STATUS isc_trace_switch_param_miss = 337182758L;
const ISC_STATUS isc_trace_param_act_notcompat = 337182759L;
const ISC_STATUS isc_trace_mandatory_switch_miss = 337182760L;
const ISC_STATUS isc_err_max = 1420;
const ISC_STATUS isc_err_max = 1422;
#else /* c definitions */
@ -2436,6 +2438,8 @@ const ISC_STATUS isc_err_max = 1420;
#define isc_tra_snapshot_does_not_exist 335545252L
#define isc_eds_input_prm_not_used 335545253L
#define isc_effective_user 335545254L
#define isc_time_zone_bind 335545255L
#define isc_decfloat_bind 335545256L
#define isc_gfix_db_name 335740929L
#define isc_gfix_invalid_sw 335740930L
#define isc_gfix_incmp_sw 335740932L
@ -2922,7 +2926,7 @@ const ISC_STATUS isc_err_max = 1420;
#define isc_trace_switch_param_miss 337182758L
#define isc_trace_param_act_notcompat 337182759L
#define isc_trace_mandatory_switch_miss 337182760L
#define isc_err_max 1420
#define isc_err_max 1422
#endif

View File

@ -959,6 +959,8 @@ Data source : @4"}, /* eds_statement */
{335545252, "Transaction's base snapshot number does not exist"}, /* tra_snapshot_does_not_exist */
{335545253, "Input parameter '@1' is not used in SQL query text"}, /* eds_input_prm_not_used */
{335545254, "Effective user is @1"}, /* effective_user */
{335545255, "Invalid time zone bind mode @1"}, /* time_zone_bind */
{335545256, "Invalid decfloat bind mode @1"}, /* decfloat_bind */
{335740929, "data base file name (@1) already given"}, /* gfix_db_name */
{335740930, "invalid switch @1"}, /* gfix_invalid_sw */
{335740932, "incompatible switch combination"}, /* gfix_incmp_sw */

View File

@ -955,6 +955,8 @@ static const struct {
{335545252, -901}, /* 932 tra_snapshot_does_not_exist */
{335545253, -901}, /* 933 eds_input_prm_not_used */
{335545254, -551}, /* 934 effective_user */
{335545255, -901}, /* 935 time_zone_bind */
{335545256, -901}, /* 936 decfloat_bind */
{335740929, -901}, /* 1 gfix_db_name */
{335740930, -901}, /* 2 gfix_invalid_sw */
{335740932, -901}, /* 4 gfix_incmp_sw */

View File

@ -955,6 +955,8 @@ static const struct {
{335545252, "0B000"}, // 932 tra_snapshot_does_not_exist
{335545253, "42000"}, // 933 eds_input_prm_not_used
{335545254, "28000"}, // 934 effective_user
{335545255, "42000"}, // 935 time_zone_bind
{335545256, "42000"}, // 936 decfloat_bind
{335740929, "00000"}, // 1 gfix_db_name
{335740930, "00000"}, // 2 gfix_invalid_sw
{335740932, "00000"}, // 4 gfix_incmp_sw

View File

@ -84,13 +84,13 @@ CommitNumber ActiveSnapshots::getSnapshotForVersion(CommitNumber version_cn)
// static method
Jrd::Attachment* Jrd::Attachment::create(Database* dbb)
Jrd::Attachment* Jrd::Attachment::create(Database* dbb, const InitialOptions* initialOptions)
{
MemoryPool* const pool = dbb->createPool();
try
{
Attachment* const attachment = FB_NEW_POOL(*pool) Attachment(pool, dbb);
Attachment* const attachment = FB_NEW_POOL(*pool) Attachment(pool, dbb, initialOptions);
pool->setStatsGroup(attachment->att_memory_stats);
return attachment;
}
@ -203,7 +203,7 @@ void Jrd::Attachment::backupStateReadUnLock(thread_db* tdbb)
}
Jrd::Attachment::Attachment(MemoryPool* pool, Database* dbb)
Jrd::Attachment::Attachment(MemoryPool* pool, Database* dbb, const InitialOptions* initialOptions)
: att_pool(pool),
att_memory_stats(&dbb->dbb_memory_stats),
att_database(dbb),
@ -253,6 +253,11 @@ Jrd::Attachment::Attachment(MemoryPool* pool, Database* dbb)
{
att_internal.grow(irq_MAX);
att_dyn_req.grow(drq_MAX);
if (initialOptions)
att_initial_options = *initialOptions;
att_initial_options.resetAttachment(this);
}
@ -492,13 +497,7 @@ void Jrd::Attachment::resetSession(thread_db* tdbb, jrd_tra** traHandle)
}
}
// reset DecFloat
att_dec_status = DecimalStatus::DEFAULT;
att_dec_binding = DecimalBinding::DEFAULT;
// reset time zone
att_timezone_bind = TimeZoneUtil::BIND_NATIVE;
att_current_timezone = att_original_timezone;
att_initial_options.resetAttachment(this);
// reset timeouts
setIdleTimeout(0);

View File

@ -150,6 +150,7 @@ const ULONG ATT_crypt_thread = 0x80000L; // Attachment from crypt thread
const ULONG ATT_NO_CLEANUP = (ATT_no_cleanup | ATT_notify_gc);
class Attachment;
class DatabaseOptions;
struct bid;
@ -349,8 +350,28 @@ public:
Firebird::Array<Firebird::MetaName> m_objects;
};
class InitialOptions
{
public:
static Attachment* create(Database* dbb);
InitialOptions(const DatabaseOptions& options);
InitialOptions()
{
}
public:
void resetAttachment(Attachment* attachment) const;
private:
Firebird::DecimalStatus decFloatStatus = Firebird::DecimalStatus::DEFAULT;
Firebird::DecimalBinding decFloatBinding = Firebird::DecimalBinding::DEFAULT;
Firebird::TimeZoneUtil::Bind timeZoneBind = Firebird::TimeZoneUtil::BIND_NATIVE;
USHORT originalTimeZone = Firebird::TimeZoneUtil::GMT_ZONE;
};
public:
static Attachment* create(Database* dbb, const InitialOptions* initialOptions);
static void destroy(Attachment* const attachment);
MemoryPool* const att_pool; // Memory pool
@ -572,7 +593,7 @@ public:
UserId* getUserId(const Firebird::MetaName &userName);
private:
Attachment(MemoryPool* pool, Database* dbb);
Attachment(MemoryPool* pool, Database* dbb, const InitialOptions* initialOptions);
~Attachment();
class IdleTimer FB_FINAL :
@ -608,6 +629,7 @@ private:
Firebird::RefPtr<IdleTimer> att_idle_timer;
Firebird::Array<JBatch*> att_batches;
InitialOptions att_initial_options; // Initial session options
};

View File

@ -922,7 +922,7 @@ namespace Jrd {
UserId user;
user.setUserName("Database Crypter");
Jrd::Attachment* const attachment = Jrd::Attachment::create(&dbb);
Jrd::Attachment* const attachment = Jrd::Attachment::create(&dbb, nullptr);
RefPtr<SysStableAttachment> sAtt(FB_NEW SysStableAttachment(attachment));
attachment->setStable(sAtt);
attachment->att_filename = dbb.dbb_filename;

View File

@ -2732,7 +2732,7 @@ void BufferControl::cache_reader(BufferControl* bcb)
// Dummy attachment needed for lock owner identification.
tdbb->setDatabase(dbb);
Jrd::Attachment* const attachment = Attachment::create(dbb);
Jrd::Attachment* const attachment = Attachment::create(dbb, nullptr);
tdbb->setAttachment(attachment);
attachment->att_filename = dbb->dbb_filename;
Jrd::ContextPoolHolder context(tdbb, bcb->bcb_bufferpool);
@ -2882,7 +2882,7 @@ void BufferControl::cache_writer(BufferControl* bcb)
UserId user;
user.setUserName("Cache Writer");
Jrd::Attachment* const attachment = Jrd::Attachment::create(dbb);
Jrd::Attachment* const attachment = Jrd::Attachment::create(dbb, nullptr);
RefPtr<SysStableAttachment> sAtt(FB_NEW SysStableAttachment(attachment));
attachment->setStable(sAtt);
attachment->att_filename = dbb->dbb_filename;

View File

@ -943,6 +943,8 @@ void Trigger::release(thread_db* tdbb)
statement = NULL;
}
namespace Jrd
{
// Option block for database parameter block
class DatabaseOptions
@ -1014,14 +1016,17 @@ public:
PathName dpb_org_filename;
string dpb_config;
string dpb_session_tz;
string dpb_time_zone_bind;
string dpb_decfloat_bind;
string dpb_decfloat_round;
string dpb_decfloat_traps;
public:
static const ULONG DPB_FLAGS_MASK = DBB_damaged;
DatabaseOptions()
{
memset(this, 0,
reinterpret_cast<char*>(&this->dpb_user_name) - reinterpret_cast<char*>(this));
memset(this, 0, reinterpret_cast<char*>(&this->dpb_user_name) - reinterpret_cast<char*>(this));
}
void get(const UCHAR*, USHORT, bool&);
@ -1057,6 +1062,124 @@ private:
}
};
Attachment::InitialOptions::InitialOptions(const DatabaseOptions& options)
{
if (options.dpb_time_zone_bind.hasData())
{
auto option = options.dpb_time_zone_bind;
option.lower();
if (option == "legacy")
timeZoneBind = TimeZoneUtil::BIND_LEGACY;
else if (option == "native")
timeZoneBind = TimeZoneUtil::BIND_NATIVE;
else
(Arg::Gds(isc_time_zone_bind) << option).raise();
}
if (options.dpb_decfloat_bind.hasData())
{
auto option = options.dpb_decfloat_bind;
option.lower();
if (option == "native")
decFloatBinding = DecimalBinding::DEFAULT;
else if (option == "char" || option == "character")
decFloatBinding = DecimalBinding(DecimalBinding::DEC_TEXT);
else if (option == "double" || option == "double precision")
decFloatBinding = DecimalBinding(DecimalBinding::DEC_DOUBLE);
else if (option == "bigint")
decFloatBinding = DecimalBinding(DecimalBinding::DEC_NUMERIC);
else if (option.substr(0, 7) == "bigint,")
{
const char* p = option.c_str() + 7;
while (*p == ' ')
++p;
const char* start = p;
int scale = 0;
while (*p >= '0' && *p <= '9')
{
scale = scale * 10 + (*p - '0');
++p;
}
if (*p != '\0' || p - start == 0 || p - start > 2 || scale > DecimalBinding::MAX_SCALE)
(Arg::Gds(isc_decfloat_bind) << option).raise();
decFloatBinding = DecimalBinding(DecimalBinding::DEC_NUMERIC, static_cast<SCHAR>(-scale));
}
else
(Arg::Gds(isc_decfloat_bind) << option).raise();
}
if (options.dpb_decfloat_round.hasData())
{
const DecFloatConstant* dfConst = DecFloatConstant::getByText(
options.dpb_decfloat_round.c_str(), FB_DEC_RoundModes, FB_DEC_RMODE_OFFSET);
if (!dfConst)
(Arg::Gds(isc_decfloat_round) << options.dpb_decfloat_round).raise();
decFloatStatus.roundingMode = dfConst->val;
}
if (options.dpb_decfloat_traps.hasData())
{
FB_SIZE_T pos = -1;
USHORT traps = 0;
do {
FB_SIZE_T start = pos + 1;
pos = options.dpb_decfloat_traps.find(',', start);
const auto trap = options.dpb_decfloat_traps.substr(start,
(pos == string::npos ? pos : pos - start));
const DecFloatConstant* dfConst = DecFloatConstant::getByText(
trap.c_str(), FB_DEC_IeeeTraps, FB_DEC_TRAPS_OFFSET);
if (!dfConst)
(Arg::Gds(isc_decfloat_trap) << trap).raise();
traps |= dfConst->val;
if (pos != string::npos)
{
const char* p = &options.dpb_decfloat_traps[pos + 1];
while (*p == ' ')
{
++p;
++pos;
}
}
} while (pos != string::npos);
decFloatStatus.decExtFlag = traps;
}
originalTimeZone = options.dpb_session_tz.isEmpty() ?
TimeZoneUtil::getSystemTimeZone() :
originalTimeZone = TimeZoneUtil::parse(
options.dpb_session_tz.c_str(), options.dpb_session_tz.length());
}
void Attachment::InitialOptions::resetAttachment(Attachment* attachment) const
{
// reset DecFloat options
attachment->att_dec_status = decFloatStatus;
attachment->att_dec_binding = decFloatBinding;
// reset time zone options
attachment->att_timezone_bind = timeZoneBind;
attachment->att_current_timezone = attachment->att_original_timezone = originalTimeZone;
}
} // namespace Jrd
/// trace manager support
class TraceFailedConnection :
@ -6839,6 +6962,22 @@ void DatabaseOptions::get(const UCHAR* dpb, USHORT dpb_length, bool& invalid_cli
dpb_replica_mode = (ReplicaMode) rdr.getInt();
break;
case isc_dpb_time_zone_bind:
rdr.getString(dpb_time_zone_bind);
break;
case isc_dpb_decfloat_bind:
rdr.getString(dpb_decfloat_bind);
break;
case isc_dpb_decfloat_round:
rdr.getString(dpb_decfloat_round);
break;
case isc_dpb_decfloat_traps:
rdr.getString(dpb_decfloat_traps);
break;
default:
break;
}
@ -7056,7 +7195,7 @@ static JAttachment* create_attachment(const PathName& alias_name,
RefDeb(DEB_AR_JATT, "jrd/create_attachment()");
fb_assert(dbb->locked());
Jrd::Attachment* attachment = NULL;
Attachment* attachment = NULL;
{ // scope
MutexLockGuard guard(newAttachmentMutex, FB_FUNCTION);
if (engineShutdown)
@ -7064,7 +7203,8 @@ static JAttachment* create_attachment(const PathName& alias_name,
status_exception::raise(Arg::Gds(isc_att_shutdown));
}
attachment = Jrd::Attachment::create(dbb);
Attachment::InitialOptions initialOptions(options);
attachment = Attachment::create(dbb, &initialOptions);
attachment->att_next = dbb->dbb_attachments;
dbb->dbb_attachments = attachment;
}

View File

@ -4712,7 +4712,7 @@ void Database::garbage_collector(Database* dbb)
UserId user;
user.setUserName("Garbage Collector");
Jrd::Attachment* const attachment = Jrd::Attachment::create(dbb);
Jrd::Attachment* const attachment = Jrd::Attachment::create(dbb, nullptr);
RefPtr<SysStableAttachment> sAtt(FB_NEW SysStableAttachment(attachment));
attachment->setStable(sAtt);
attachment->att_filename = dbb->dbb_filename;

View File

@ -1,7 +1,7 @@
/* MAX_NUMBER is the next number to be used, always one more than the highest message number. */
set bulk_insert INSERT INTO FACILITIES (LAST_CHANGE, FACILITY, FAC_CODE, MAX_NUMBER) VALUES (?, ?, ?, ?);
--
('2019-03-04 19:40:00', 'JRD', 0, 935)
('2019-04-06 20:14:00', 'JRD', 0, 937)
('2015-03-17 18:33:00', 'QLI', 1, 533)
('2018-03-17 12:00:00', 'GFIX', 3, 136)
('1996-11-07 13:39:40', 'GPRE', 4, 1)

View File

@ -1042,6 +1042,8 @@ Data source : @4', NULL, NULL)
('tra_snapshot_does_not_exist', NULL, 'tpc.cpp', NULL, 0, 932, NULL, 'Transaction''s base snapshot number does not exist', NULL, NULL);
('eds_input_prm_not_used', NULL, 'ExtDS.cpp', NULL, 0, 933, NULL, 'Input parameter ''@1'' is not used in SQL query text', NULL, NULL);
('effective_user', NULL, NULL, NULL, 0, 934, NULL, 'Effective user is @1', NULL, NULL);
('time_zone_bind', NULL, 'jrd.cpp', NULL, 0, 935, NULL, 'Invalid time zone bind mode @1', NULL, NULL);
('decfloat_bind', NULL, 'jrd.cpp', NULL, 0, 936, NULL, 'Invalid decfloat bind mode @1', NULL, NULL);
-- QLI
(NULL, NULL, NULL, NULL, 1, 0, NULL, 'expected type', NULL, NULL);
(NULL, NULL, NULL, NULL, 1, 1, NULL, 'bad block type', NULL, NULL);

View File

@ -941,6 +941,8 @@ set bulk_insert INSERT INTO SYSTEM_ERRORS (SQL_CODE, SQL_CLASS, SQL_SUBCLASS, FA
(-901, '0B', '000', 0, 932, 'tra_snapshot_does_not_exist', NULL, NULL)
(-901, '42', '000', 0, 933, 'eds_input_prm_not_used', NULL, NULL)
(-551, '28', '000', 0, 934, 'effective_user', NULL, 'ERROR')
(-901, '42', '000', 0, 935, 'time_zone_bind', NULL, NULL)
(-901, '42', '000', 0, 936, 'decfloat_bind', NULL, NULL)
-- GFIX
(-901, '00', '000', 3, 1, 'gfix_db_name', NULL, NULL)
(-901, '00', '000', 3, 2, 'gfix_invalid_sw', NULL, NULL)