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:
parent
49279dae3d
commit
11b4fcf5b7
@ -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 !!!")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
|
Loading…
Reference in New Issue
Block a user