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

Fixup some issues with numeric & decimal datatypes

This commit is contained in:
AlexPeshkoff 2019-12-27 15:46:45 +03:00
parent cd78c265d3
commit a46a3df0fb
4 changed files with 19 additions and 10 deletions

View File

@ -24,6 +24,9 @@ When incomplete type definition is used (i.e. `CHAR` instead `CHAR(n)`) in left
will take place for all `CHAR` columns, not only default `CHAR(1)`. will take place for all `CHAR` columns, not only default `CHAR(1)`.
When incomplete type definiton is used in right side of the statement (TO part) firebird engine will define missing When incomplete type definiton is used in right side of the statement (TO part) firebird engine will define missing
details about that type automatically based on source column. details about that type automatically based on source column.
From this statement POV there is no difference between NUMERIC and DECIMAL datatypes. Changing bind of any NUMERIC
does not affect appropriate underlying integer type. On contrary, changing bind of integer datatype also affects
appropriate NUMERICs.
Special `TO` part format `LEGACY` is used when datatype, missing in previous FB version, should be represented in Special `TO` part format `LEGACY` is used when datatype, missing in previous FB version, should be represented in
a way, understandable by old client software (may be with some data losses). The following coercions are done for a way, understandable by old client software (may be with some data losses). The following coercions are done for

View File

@ -7449,7 +7449,7 @@ void LiteralNode::genNegZero(DsqlCompilerScratch* dsqlScratch, int prec)
GEN_descriptor(dsqlScratch, &desc, true); GEN_descriptor(dsqlScratch, &desc, true);
const USHORT len = static_cast<SSHORT>(s - buf); const USHORT len = static_cast<USHORT>(s - buf);
dsqlScratch->appendUShort(len); dsqlScratch->appendUShort(len);
if (len) if (len)
dsqlScratch->appendBytes(desc.dsc_address, len); dsqlScratch->appendBytes(desc.dsc_address, len);

View File

@ -199,6 +199,8 @@ ValueExprNode* MAKE_constant(const char* str, dsql_constant_type numeric_flag, S
{ {
literal->litDesc.dsc_dtype = numeric_flag == CONSTANT_DOUBLE ? dtype_double : literal->litDesc.dsc_dtype = numeric_flag == CONSTANT_DOUBLE ? dtype_double :
numeric_flag == CONSTANT_DECIMAL ? dtype_dec128 : dtype_int128; numeric_flag == CONSTANT_DECIMAL ? dtype_dec128 : dtype_int128;
if (numeric_flag == CONSTANT_NUM128)
literal->litDesc.dsc_sub_type = dsc_num_type_decimal;
literal->litDesc.dsc_scale = scale; literal->litDesc.dsc_scale = scale;
size_t l = strlen(str); size_t l = strlen(str);
if (l > MAX_SSHORT) if (l > MAX_SSHORT)

View File

@ -137,28 +137,25 @@ bool CoercionRule::operator==(const CoercionRule& rule) const
bool CoercionRule::match(const dsc* d) const bool CoercionRule::match(const dsc* d) const
{ {
bool found = false;
// check for exact match (taking flags into an account) // check for exact match (taking flags into an account)
if ((!found) && if ((d->dsc_dtype == fromDsc.dsc_dtype) &&
(d->dsc_dtype == fromDsc.dsc_dtype) &&
((d->dsc_length == fromDsc.dsc_length) || (!(fromMask & FLD_has_len))) && ((d->dsc_length == fromDsc.dsc_length) || (!(fromMask & FLD_has_len))) &&
((d->getCharSet() == fromDsc.getCharSet()) || (!(fromMask & FLD_has_chset))) && ((d->getCharSet() == fromDsc.getCharSet()) || (!(fromMask & FLD_has_chset))) &&
((d->getSubType() == fromDsc.getSubType()) || (!(fromMask & FLD_has_sub))) && ((d->getSubType() == fromDsc.getSubType()) || (!(fromMask & FLD_has_sub))) &&
((d->dsc_scale == fromDsc.dsc_scale) || (!(fromMask & FLD_has_scale)))) ((d->dsc_scale == fromDsc.dsc_scale) || (!(fromMask & FLD_has_scale))))
{ {
found = true; return true;
} }
// check for inexact datatype match when FLD_has_len is not set // check for inexact datatype match when FLD_has_len is not set
if ((!found) && (!(fromMask & FLD_has_len))) if (!(fromMask & FLD_has_len))
{ {
switch(fromDsc.dsc_dtype) switch(fromDsc.dsc_dtype)
{ {
case dtype_dec64: case dtype_dec64:
case dtype_dec128: case dtype_dec128:
if (d->dsc_dtype == dtype_dec64 || d->dsc_dtype == dtype_dec128) if (d->dsc_dtype == dtype_dec64 || d->dsc_dtype == dtype_dec128)
found = true; return true;
break; break;
case dtype_short: case dtype_short:
@ -166,12 +163,19 @@ bool CoercionRule::match(const dsc* d) const
case dtype_int64: case dtype_int64:
case dtype_int128: case dtype_int128:
if (d->isExact() && (fromMask & FLD_has_sub) && (d->dsc_sub_type != dsc_num_type_none)) if (d->isExact() && (fromMask & FLD_has_sub) && (d->dsc_sub_type != dsc_num_type_none))
found = true; return true;
break; break;
} }
} }
return found; // ignore minor decimal/numeric difference
if (fromDsc.isExact() && (fromMask & FLD_has_sub) &&
(fromDsc.dsc_dtype == d->dsc_dtype) && (d->dsc_sub_type != dsc_num_type_none))
{
return true;
}
return false;
} }
bool CoercionRule::coerce(dsc* d) const bool CoercionRule::coerce(dsc* d) const