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) // (ISO/ANSI SQL:200n WG3:DRS-013 H2-2002-358 August, 2002)
// //
// If any datatype has a character type then : // 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) // (dtype_text, dtype_cstring, dtype_varying, dtype_blob sub_type TEXT)
// !! Currently engine cannot convert string to BLOB therefor BLOB isn't allowed. !! // !! Currently engine cannot convert string to BLOB therefor BLOB isn't allowed. !!
// - first character-set and collation are used as output descriptor. // - first character-set and collation are used as output descriptor.
// - if any type has datatype VARCHAR then output should be VARCHAR else // - if all types have datatype CHAR then output should be CHAR else
// CHAR and with the maximum length used from the given list. // VARCHAR and with the maximum length used from the given list.
// (dtype_text, dtype_cstring, dtype_varying)
// //
// If all of the datatypes are EXACT numeric then the output descriptor // If all of the datatypes are EXACT numeric then the output descriptor
// shall be EXACT numeric with the maximum scale and the maximum precision // 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; 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. 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 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_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. // Walk through arguments list.
DSQL_NOD *arg, *end, tnod; 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 : // numeric datatypes :
if (DTYPE_IS_NUMERIC(desc1.dsc_dtype)) { if (DTYPE_IS_NUMERIC(desc1.dsc_dtype)) {
any_numeric = true;
// Is there any approximate numeric? // Is there any approximate numeric?
if (DTYPE_IS_APPROX(desc1.dsc_dtype)) { if (DTYPE_IS_APPROX(desc1.dsc_dtype)) {
any_approx = true; any_approx = true;
@ -1246,16 +1247,16 @@ void MAKE_desc_from_list(DSC * desc, DSQL_NOD node, const TEXT* expression_name)
any_text = true; any_text = true;
} }
else { 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.. // Get max needed-length for not text types suchs as int64,timestamp etc..
//cnvlength = DSC_convert_to_text_length(desc1.dsc_dtype); USHORT cnvlength = DSC_convert_to_text_length(desc1.dsc_dtype);
//if (cnvlength > maxtextlength) { if (cnvlength > maxtextlength) {
// maxtextlength = cnvlength; maxtextlength = cnvlength;
//} }
all_text = false; all_text = false;
} }
if (DTYPE_IS_DATE(desc1.dsc_dtype)) { if (DTYPE_IS_DATE(desc1.dsc_dtype)) {
any_datetime = true;
if (desc1.dsc_dtype == dtype_sql_date) { if (desc1.dsc_dtype == dtype_sql_date) {
all_time = false; all_time = false;
all_timestamp = 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) { if (desc1.dsc_dtype == dtype_blob) {
any_blob = true;
if (desc1.dsc_sub_type = 1) { if (desc1.dsc_sub_type = 1) {
// TEXT BLOB // TEXT BLOB
if (!any_text) { if (!any_text_blob) {
// Save first characterset and collation // Save first characterset and collation
ttype = desc1.dsc_scale; ttype = desc1.dsc_scale;
} }
any_text = true; any_text_blob = true;
} }
} }
else { else {
@ -1299,8 +1301,12 @@ void MAKE_desc_from_list(DSC * desc, DSQL_NOD node, const TEXT* expression_name)
desc->dsc_flags = DSC_nullable; desc->dsc_flags = DSC_nullable;
// If all of the arguments are from type text use a text type. // If all of the arguments are from type text use a text type.
if (all_text) { // Firebird behaves a little bit different than standard here, because
if (any_varying) { // 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; desc->dsc_dtype = dtype_varying;
maxtextlength += sizeof(USHORT); 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. // datatypes aren't comparable.
// Let's try to give a usefull error message. // Let's try to give a usefull error message.
ERRD_post(gds_sqlerr, gds_arg_number, (SLONG) - 104, ERRD_post(gds_sqlerr, gds_arg_number, (SLONG) - 104,
gds_arg_gds, gds_dsql_command_err, gds_arg_gds, gds_dsql_datatypes_not_comparable,
gds_arg_gds, gds_dsql_no_relation_alias, gds_arg_string, "",
gds_arg_string, expression_name, 0); gds_arg_string, expression_name, 0);
// "Datatypes %sare not comparable in expression %s" // "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 { else {
*deepest_level = ldeepest_level; *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; aggregate = TRUE;
} }
else { else {