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

Fix problems with NUMERIC and DECIMAL datatypes in MAKE_desc_from_list() for Dialect 1.

This affects CASE, COALESCE and the auto-union cast.
This commit is contained in:
arnobrinkman 2004-06-19 21:29:50 +00:00
parent 3e9da0e48d
commit ffd4d94124
2 changed files with 71 additions and 7 deletions

View File

@ -1177,10 +1177,11 @@ void MAKE_desc_from_list(dsc* desc, dsql_nod* node, const TEXT* expression_name)
// Initialize values.
UCHAR max_dtype = 0;
SCHAR max_scale = 0;
USHORT max_length = 0, max_dtype_length = 0, maxtextlength = 0;
USHORT max_length = 0, max_dtype_length = 0, maxtextlength = 0, max_significant_digits = 0;
SSHORT max_sub_type = 0, first_sub_type, ttype = ttype_ascii; // default type if all nodes are nod_null.
bool firstarg = true, all_same_sub_type = true;
bool all_numeric = true, any_numeric = false, any_approx = false;
SSHORT max_numeric_sub_type = 0;
bool firstarg = true, all_same_sub_type = true, all_equal = true;
bool all_numeric = true, any_numeric = false, any_approx = false, any_float = false;
bool all_text = true, any_text = false, any_varying = false;
bool all_date = true, all_time = true, all_timestamp = true, any_datetime = false;
bool all_blob = true, any_blob = false, any_text_blob = false;
@ -1217,6 +1218,15 @@ void MAKE_desc_from_list(dsc* desc, dsql_nod* node, const TEXT* expression_name)
max_dtype = desc1.dsc_dtype;
firstarg = false;
}
else {
if (all_equal) {
all_equal =
(max_dtype == desc1.dsc_dtype) &&
(max_scale == desc1.dsc_scale) &&
(max_length == desc1.dsc_length) &&
(max_sub_type == desc1.dsc_sub_type);
}
}
// numeric datatypes :
if (DTYPE_IS_NUMERIC(desc1.dsc_dtype)) {
@ -1224,6 +1234,15 @@ void MAKE_desc_from_list(dsc* desc, dsql_nod* node, const TEXT* expression_name)
// Is there any approximate numeric?
if (DTYPE_IS_APPROX(desc1.dsc_dtype)) {
any_approx = true;
// Dialect 1 NUMERIC and DECIMAL are stored as sub-types
// 1 and 2 from float types dtype_real, dtype_double
if (!any_float) {
any_float = (desc1.dsc_sub_type == 0);
}
}
//
if (desc1.dsc_sub_type > max_numeric_sub_type) {
max_numeric_sub_type = desc1.dsc_sub_type;
}
}
else {
@ -1238,6 +1257,10 @@ void MAKE_desc_from_list(dsc* desc, dsql_nod* node, const TEXT* expression_name)
if (desc1.dsc_length > max_length) {
max_length = desc1.dsc_length;
}
// Get max significant bits
if (type_significant_bits[desc1.dsc_dtype] > max_significant_digits) {
max_significant_digits = type_significant_bits[desc1.dsc_dtype];
}
// Get max dtype and sub_type
if (desc1.dsc_dtype > max_dtype) {
max_dtype = desc1.dsc_dtype;
@ -1357,6 +1380,16 @@ void MAKE_desc_from_list(dsc* desc, dsql_nod* node, const TEXT* expression_name)
}
desc->dsc_flags = DSC_nullable;
// If all the datatypes we've seen are exactly the same, we're done
if (all_equal) {
desc->dsc_dtype = max_dtype;
desc->dsc_length = max_length;
desc->dsc_scale = max_scale;
desc->dsc_sub_type = max_sub_type;
return;
}
// If all of the arguments are from type text use a text type.
// Firebird behaves a little bit different than standard here, because
// any datatype (except BLOB) can be converted to a character-type we
@ -1378,7 +1411,7 @@ void MAKE_desc_from_list(dsc* desc, dsql_nod* node, const TEXT* expression_name)
else if (all_numeric) {
// If all of the arguments are a numeric datatype.
if (any_approx) {
if (max_length <= type_lengths[dtype_real]) {
if (max_significant_digits <= type_significant_bits[dtype_real]) {
desc->dsc_dtype = dtype_real;
desc->dsc_length = type_lengths[desc->dsc_dtype];
}
@ -1386,13 +1419,19 @@ void MAKE_desc_from_list(dsc* desc, dsql_nod* node, const TEXT* expression_name)
desc->dsc_dtype = dtype_double;
desc->dsc_length = type_lengths[desc->dsc_dtype];
}
desc->dsc_scale = 0;
desc->dsc_sub_type = 0;
if (any_float) {
desc->dsc_scale = 0;
desc->dsc_sub_type = 0;
}
else {
desc->dsc_scale = max_scale;
desc->dsc_sub_type = max_numeric_sub_type;
}
}
else {
desc->dsc_dtype = max_dtype;
desc->dsc_length = max_dtype_length;
desc->dsc_sub_type = max_sub_type;
desc->dsc_sub_type = max_numeric_sub_type;
desc->dsc_scale = max_scale;
}
return;

View File

@ -126,5 +126,30 @@ static const USHORT type_lengths[DTYPE_TYPE_MAX] = {
sizeof(SINT64) /* dtype_int64 */
};
// float, double are numbers from IEEE floating-point standard (IEEE 754)
static const USHORT type_significant_bits[DTYPE_TYPE_MAX] = {
0,
0, /* dtype_text */
0, /* dtype_cstring */
0, /* dtype_varying */
0, /* unused */
0, /* unused */
0, /* dtype_packed */
sizeof(SCHAR) * 8, /* dtype_byte */
sizeof(SSHORT) * 8, /* dtype_short */
sizeof(SLONG) * 8, /* dtype_long */
sizeof(ISC_QUAD) * 8, /* dtype_quad */
23, /* dtype_real, 23 sign. bits = 7 sign. digits */
52, /* dtype_double, 52 sign. bits = 15 sign. digits */
52, /* dtype_d_float, 52 sign. bits = 15 sign. digits */
sizeof(GDS_DATE) * 8, /* dtype_sql_date */
sizeof(GDS_TIME) * 8, /* dtype_sql_time */
sizeof(GDS_TIMESTAMP) * 8, /* dtype_timestamp */
sizeof(ISC_QUAD) * 8, /* dtype_blob */
sizeof(ISC_QUAD) * 8, /* dtype_array */
sizeof(SINT64) * 8 /* dtype_int64 */
};
#endif /* JRD_ALIGN_H */