Commit 10a081a0 authored by bell@sanja.is.com.ua's avatar bell@sanja.is.com.ua

postreview fix

parent 6df58cc9
...@@ -289,6 +289,17 @@ static Field::field_cast_enum *field_cast_array[]= ...@@ -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) bool Field::field_cast_compatible(Field::field_cast_enum type)
{ {
DBUG_ASSERT(type != FIELD_CAST_STOP); DBUG_ASSERT(type != FIELD_CAST_STOP);
......
...@@ -2504,62 +2504,84 @@ static Item_result type_convertor[4][4]= ...@@ -2504,62 +2504,84 @@ static Item_result type_convertor[4][4]=
{STRING_RESULT, REAL_RESULT, INT_RESULT, ROW_RESULT}, {STRING_RESULT, REAL_RESULT, INT_RESULT, ROW_RESULT},
{ROW_RESULT, ROW_RESULT, ROW_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) bool Item_type_holder::join_types(THD *thd, Item *item)
{ {
uint32 new_length= real_length(item); uint32 new_length= real_length(item);
bool change_field= 0, skip_store_field= 0; bool use_new_field= 0, use_expression_type= 0;
Item_result new_type= type_convertor[item_type][item->result_type()]; 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) Check if both items point to fields: in this case we
can't be joinned in one enum(set) field) can adjust column types of result table in the union smartly.
*/ */
if (field_example && item->type() == Item::FIELD_ITEM) if (field_example && item->type() == Item::FIELD_ITEM)
{ {
Field *field= ((Item_field *)item)->field; Field *field= ((Item_field *)item)->field;
/* Can old example field store new data? */ /* Can 'field_example' field store data of the column? */
if ((change_field= if ((use_new_field=
!field->field_cast_compatible(field_example->field_cast_type()))) (!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 The old field can't store value of the new field.
decision about result field type based only on Item result type Check if the new field can store value of the old one.
*/ */
if (!field_example->field_cast_compatible(field->field_cast_type())) use_expression_type|=
skip_store_field= 1; (!field_example->field_cast_compatible(field->field_cast_type()) ||
!is_attr_compatible(this, item));
} }
} }
else if (field_example || item->type() == Item::FIELD_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 /* Check whether size/type of the result item should be changed */
if (change_field || if (use_new_field || use_expression_type ||
skip_store_field || (new_result_type != item_type) || (new_length > max_length) ||
(new_type != item_type) ||
(max_length < new_length) ||
(!maybe_null && item->maybe_null) || (!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))) !my_charset_same(collation.collation, item->collation.collation)))
{ {
// new field has some parameters worse then current if (use_expression_type || item->type() != Item::FIELD_ITEM)
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)
field_example= 0; field_example= 0;
else 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; field_example= ((Item_field*) item)->field;
}
const char *old_cs= collation.collation->name, const char *old_cs= collation.collation->name,
*old_derivation= collation.derivation_name(); *old_derivation= collation.derivation_name();
...@@ -2576,7 +2598,7 @@ bool Item_type_holder::join_types(THD *thd, Item *item) ...@@ -2576,7 +2598,7 @@ bool Item_type_holder::join_types(THD *thd, Item *item)
max_length= max(max_length, new_length); max_length= max(max_length, new_length);
decimals= max(decimals, item->decimals); decimals= max(decimals, item->decimals);
maybe_null|= item->maybe_null; maybe_null|= item->maybe_null;
item_type= new_type; item_type= new_result_type;
} }
DBUG_ASSERT(item_type != ROW_RESULT); DBUG_ASSERT(item_type != ROW_RESULT);
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment