summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <bell@sanja.is.com.ua>2004-09-26 17:26:32 +0300
committerunknown <bell@sanja.is.com.ua>2004-09-26 17:26:32 +0300
commit28ab42bb11dc47404b31a3442db44db88965f927 (patch)
treef3c155d866671b875d6c857896ebbe62553d938e
parent408b5ca5740fbbc41e67f7792969dcf19763547b (diff)
downloadmariadb-git-28ab42bb11dc47404b31a3442db44db88965f927.tar.gz
postreview fix
sql/field.cc: comments added sql/item.cc: comments added code made more clean
-rw-r--r--sql/field.cc11
-rw-r--r--sql/item.cc88
2 files changed, 66 insertions, 33 deletions
diff --git a/sql/field.cc b/sql/field.cc
index 5dd9886f82c..59d18dabcab 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -289,6 +289,17 @@ static Field::field_cast_enum *field_cast_array[]=
};
+/*
+ Check if field of given type can store a value of this field.
+
+ SYNOPSIS
+ type type for test
+
+ RETURN
+ 1 can
+ 0 can not
+*/
+
bool Field::field_cast_compatible(Field::field_cast_enum type)
{
DBUG_ASSERT(type != FIELD_CAST_STOP);
diff --git a/sql/item.cc b/sql/item.cc
index 4226f58e9a6..b0eb806cc7a 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -2504,62 +2504,84 @@ static Item_result type_convertor[4][4]=
{STRING_RESULT, REAL_RESULT, INT_RESULT, ROW_RESULT},
{ROW_RESULT, ROW_RESULT, ROW_RESULT, ROW_RESULT}};
+
+/*
+ Values of 'from' field can be stored in 'to' field.
+
+ SYNOPSIS
+ is_attr_compatible()
+ from Item which values should be saved
+ to Item where values should be saved
+
+ RETURN
+ 1 can be saved
+ 0 can not be saved
+*/
+
+inline bool is_attr_compatible(Item *from, Item *to)
+{
+ return ((to->max_length >= from->max_length) &&
+ (to->maybe_null || !from->maybe_null) &&
+ (to->result_type() != STRING_RESULT ||
+ from->result_type() != STRING_RESULT ||
+ my_charset_same(from->collation.collation,
+ to->collation.collation)));
+}
+
+
bool Item_type_holder::join_types(THD *thd, Item *item)
{
uint32 new_length= real_length(item);
- bool change_field= 0, skip_store_field= 0;
- Item_result new_type= type_convertor[item_type][item->result_type()];
+ bool use_new_field= 0, use_expression_type= 0;
+ Item_result new_result_type= type_convertor[item_type][item->result_type()];
/*
- we have both fields and field is not enum or set(different enums(sets)
- can't be joinned in one enum(set) field)
+ Check if both items point to fields: in this case we
+ can adjust column types of result table in the union smartly.
*/
if (field_example && item->type() == Item::FIELD_ITEM)
{
Field *field= ((Item_field *)item)->field;
- /* Can old example field store new data? */
- if ((change_field=
- !field->field_cast_compatible(field_example->field_cast_type())))
+ /* Can 'field_example' field store data of the column? */
+ if ((use_new_field=
+ (!field->field_cast_compatible(field_example->field_cast_type()) ||
+ !is_attr_compatible(item, this))))
{
/*
- if old field can't store value of 'worse' new field we will make
- decision about result field type based only on Item result type
+ The old field can't store value of the new field.
+ Check if the new field can store value of the old one.
*/
- if (!field_example->field_cast_compatible(field->field_cast_type()))
- skip_store_field= 1;
+ use_expression_type|=
+ (!field_example->field_cast_compatible(field->field_cast_type()) ||
+ !is_attr_compatible(this, item));
}
}
else if (field_example || item->type() == Item::FIELD_ITEM)
{
- /* expression can't be mixed with field */
- skip_store_field= 1;
+ /*
+ Expression types can't be mixed with field types, we have to use
+ expression types.
+ */
+ use_expression_type= 1;
}
- // size/type should be changed
- if (change_field ||
- skip_store_field ||
- (new_type != item_type) ||
- (max_length < new_length) ||
+ /* Check whether size/type of the result item should be changed */
+ if (use_new_field || use_expression_type ||
+ (new_result_type != item_type) || (new_length > max_length) ||
(!maybe_null && item->maybe_null) ||
- (item_type == STRING_RESULT && new_type == STRING_RESULT &&
+ (item_type == STRING_RESULT &&
!my_charset_same(collation.collation, item->collation.collation)))
{
- // new field has some parameters worse then current
- skip_store_field|= (change_field &&
- (max_length > new_length) ||
- (maybe_null && !item->maybe_null) ||
- (item_type == STRING_RESULT &&
- new_type == STRING_RESULT &&
- !my_charset_same(collation.collation,
- item->collation.collation)));
- /*
- It is safe assign pointer on field, because it will be used just after
- all JOIN::prepare calls and before any SELECT execution
- */
- if (skip_store_field || item->type() != Item::FIELD_ITEM)
+ if (use_expression_type || item->type() != Item::FIELD_ITEM)
field_example= 0;
else
+ {
+ /*
+ It is safe to assign a pointer to field here, because it will be used
+ before any table is closed.
+ */
field_example= ((Item_field*) item)->field;
+ }
const char *old_cs= collation.collation->name,
*old_derivation= collation.derivation_name();
@@ -2576,7 +2598,7 @@ bool Item_type_holder::join_types(THD *thd, Item *item)
max_length= max(max_length, new_length);
decimals= max(decimals, item->decimals);
maybe_null|= item->maybe_null;
- item_type= new_type;
+ item_type= new_result_type;
}
DBUG_ASSERT(item_type != ROW_RESULT);
return 0;