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

1) Make COALESCE/CASE output descriptor more SQL-standard.

Exception is that we allow mixing datatypes with (var)char (except blob), because all datatypes are convertable to character-type and because this functionallity was available from 1st day COALESCE is introduced inside Firebird.
2) Fix bug with expressions without fields inside aggregate-functions.
Example :
  SELECT
    (SELECT Count(1) FROM RDB$DATABASE)
  FROM
    RDB$RELATIONS
This commit is contained in:
arnobrinkman 2003-08-25 23:35:30 +00:00
parent 49279dae3d
commit 11b4fcf5b7
2 changed files with 26 additions and 20 deletions

View File

@ -1111,13 +1111,12 @@ void MAKE_desc_from_list(DSC * desc, DSQL_NOD node, const TEXT* expression_name)
// (ISO/ANSI SQL:200n WG3:DRS-013 H2-2002-358 August, 2002)
//
// If any datatype has a character type then :
// - all types should be a character type else throw a error.
// - the output will always be a character type except unconvertable types.
// (dtype_text, dtype_cstring, dtype_varying, dtype_blob sub_type TEXT)
// !! Currently engine cannot convert string to BLOB therefor BLOB isn't allowed. !!
// - first character-set and collation are used as output descriptor.
// - if any type has datatype VARCHAR then output should be VARCHAR else
// CHAR and with the maximum length used from the given list.
// (dtype_text, dtype_cstring, dtype_varying)
// - if all types have datatype CHAR then output should be CHAR else
// VARCHAR and with the maximum length used from the given list.
//
// If all of the datatypes are EXACT numeric then the output descriptor
// shall be EXACT numeric with the maximum scale and the maximum precision
@ -1146,9 +1145,10 @@ void MAKE_desc_from_list(DSC * desc, DSQL_NOD node, const TEXT* expression_name)
USHORT max_length = 0, max_dtype_length = 0, maxtextlength = 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_approx = false, all_blob = true;
bool all_numeric = true, any_numeric = false, any_approx = false;
bool all_text = true, any_text = false, any_varying = false;
bool all_date = true, all_time = true, all_timestamp = true;
bool all_date = true, all_time = true, all_timestamp = true, any_datetime = false;
bool all_blob = true, any_blob = false, any_text_blob = false;
// Walk through arguments list.
DSQL_NOD *arg, *end, tnod;
@ -1185,6 +1185,7 @@ void MAKE_desc_from_list(DSC * desc, DSQL_NOD node, const TEXT* expression_name)
// numeric datatypes :
if (DTYPE_IS_NUMERIC(desc1.dsc_dtype)) {
any_numeric = true;
// Is there any approximate numeric?
if (DTYPE_IS_APPROX(desc1.dsc_dtype)) {
any_approx = true;
@ -1246,16 +1247,16 @@ void MAKE_desc_from_list(DSC * desc, DSQL_NOD node, const TEXT* expression_name)
any_text = true;
}
else {
// Code below isn't used anymore, but could be helpfull in the future.
// Get max needed-length for not text types suchs as int64,timestamp etc..
//cnvlength = DSC_convert_to_text_length(desc1.dsc_dtype);
//if (cnvlength > maxtextlength) {
// maxtextlength = cnvlength;
//}
USHORT cnvlength = DSC_convert_to_text_length(desc1.dsc_dtype);
if (cnvlength > maxtextlength) {
maxtextlength = cnvlength;
}
all_text = false;
}
if (DTYPE_IS_DATE(desc1.dsc_dtype)) {
any_datetime = true;
if (desc1.dsc_dtype == dtype_sql_date) {
all_time = false;
all_timestamp = false;
@ -1276,13 +1277,14 @@ void MAKE_desc_from_list(DSC * desc, DSQL_NOD node, const TEXT* expression_name)
}
if (desc1.dsc_dtype == dtype_blob) {
any_blob = true;
if (desc1.dsc_sub_type = 1) {
// TEXT BLOB
if (!any_text) {
if (!any_text_blob) {
// Save first characterset and collation
ttype = desc1.dsc_scale;
}
any_text = true;
any_text_blob = true;
}
}
else {
@ -1299,8 +1301,12 @@ void MAKE_desc_from_list(DSC * desc, DSQL_NOD node, const TEXT* expression_name)
desc->dsc_flags = DSC_nullable;
// If all of the arguments are from type text use a text type.
if (all_text) {
if (any_varying) {
// Firebird behaves a little bit different than standard here, because
// any datatype (except BLOB) can be converted to a character-type we
// allow to use numeric and datetime types together with a
// character-type, but output will always be varying !
if (all_text || (any_text && (any_numeric || any_datetime))) {
if (any_varying || (any_text && (any_numeric || any_datetime))) {
desc->dsc_dtype = dtype_varying;
maxtextlength += sizeof(USHORT);
}
@ -1364,12 +1370,10 @@ void MAKE_desc_from_list(DSC * desc, DSQL_NOD node, const TEXT* expression_name)
// datatypes aren't comparable.
// Let's try to give a usefull error message.
ERRD_post(gds_sqlerr, gds_arg_number, (SLONG) - 104,
gds_arg_gds, gds_dsql_command_err,
gds_arg_gds, gds_dsql_no_relation_alias,
gds_arg_gds, gds_dsql_datatypes_not_comparable,
gds_arg_string, "",
gds_arg_string, expression_name, 0);
// "Datatypes %sare not comparable in expression %s"
#pragma FB_COMPILER_MESSAGE("TODO: AB: Don't forget to change to new error message !!!")
}

View File

@ -1557,7 +1557,9 @@ static BOOLEAN aggregate_found2(DSQL_REQ request, DSQL_NOD node, USHORT * curren
else {
*deepest_level = ldeepest_level;
}
if ((ldeepest_level == 0) || (ldeepest_level == request->req_scope_level)) {
// If the deepest_value is the same as the current scope_level
// this an aggregate that belongs to the current context.
if (*deepest_level == request->req_scope_level) {
aggregate = TRUE;
}
else {