Details
-
Task
-
Status: Closed (View Workflow)
-
Major
-
Resolution: Won't Do
Description
This task was canceled. See a comment below.
There is some code duplication in Item implementation.
class Item_str_func
|
{
|
double val_real()
|
{
|
int err_not_used;
|
char *end_not_used;
|
String *res;
|
res= val_str(&str_value);
|
return res ? my_strntod(res->charset(),(char*) res->ptr(),
|
res->length(), &end_not_used, &err_not_used) : 0.0;
|
}
|
};
|
class Item_func_group_concat
|
{
|
double val_real()
|
{
|
int error;
|
const char *end;
|
String *res;
|
if (!(res= val_str(&str_value)))
|
return 0.0;
|
end= res->ptr() + res->length();
|
return (my_strtod(res->ptr(), (char**) &end, &error));
|
}
|
};
|
class Item_func_udf_str
|
{
|
double val_real()
|
{
|
int err_not_used;
|
char *end_not_used;
|
String *res;
|
res= val_str(&str_value);
|
return res ? my_strntod(res->charset(),(char*) res->ptr(),
|
res->length(), &end_not_used, &err_not_used) : 0.0;
|
}
|
};
|
The same type of duplications happens with all other val_xxx() methods.
The same duplication happens in deriving Item_xxx from Type_handler_xxx:
class Item_sum_sum :public Item_sum_num,
|
public Type_handler_hybrid_field_type
|
{
|
...
|
enum_field_types field_type() const
|
{ return Type_handler_hybrid_field_type::field_type(); }
|
enum Item_result result_type () const
|
{ return Type_handler_hybrid_field_type::result_type(); }
|
enum Item_result cmp_type () const
|
{ return Type_handler_hybrid_field_type::cmp_type(); }
|
...
|
};
|
class Item_sum_hybrid :public Item_sum, public Type_handler_hybrid_field_type
|
{
|
...
|
enum Item_result result_type () const
|
{ return Type_handler_hybrid_field_type::result_type(); }
|
enum Item_result cmp_type () const
|
{ return Type_handler_hybrid_field_type::cmp_type(); }
|
enum enum_field_types field_type() const
|
{ return Type_handler_hybrid_field_type::field_type(); }
|
...
|
};
|
class Item_hybrid_func: public Item_func,
|
public Type_handler_hybrid_field_type
|
{
|
...
|
enum_field_types field_type() const
|
{ return Type_handler_hybrid_field_type::field_type(); }
|
enum Item_result result_type () const
|
{ return Type_handler_hybrid_field_type::result_type(); }
|
enum Item_result cmp_type () const
|
{ return Type_handler_hybrid_field_type::cmp_type(); }
|
...
|
};
|
Duplicate code can be avoided by using diamond-style inheritance, deriving Item from Type_handler virtually, so these methods are automatically assigned by just the class declaration.
Diamond style inheritance:
Top
|
/ \
|
Left Right
|
\ /
|
Bottom
|
Deriving from Top to Left and from Top to Right is done virtually. This is important to have only one copy of "Top" in "Bottom".
In our case:
- Top is Type_handler
- Left is the data type: Type_handler_str, Type_handler_longlong, Type_handler_double, etc.
- Right is the Item type: Item_func, Item_sum, Item_cache, etc.
- Bottom is the Item type with the data type: Item_func_str, Item_sum_int, Item_cache_real, etc.
Type_handler
/ \
Type_handler_longlong Item_func
\ /
Item_int_func
First, we inherit two different branches of Type_handler virtually (notice "public virtual"):
// The data type branch (string, double, int, decimal, date, time,datetime)
|
class Type_handler_str: public virtual Type_handler
|
{
|
// This class implements field_type(), cmp_type(), result_type()
|
// as well as conversion methods val_int(), val_decimal(), val_real(), get_date().
|
// Notice, it does not implement the native method val_str(). It's pure virtual here.
|
};
|
 |
// The Item type branch (Item_basic_constant, Item_cache, Item_func, Item_sum, Item_field, all the rest)
|
class Item: public Value_source,
|
public Type_std_attributes,
|
public virtual Type_handler
|
{
|
// This class implements the code that returns the native value.
|
// It does NOT implement field_type(), cmp_type(), return_type(), they are pure virtual. here.
|
// It does NOT implement non-native val_xxx(), get_date(). They are pure virtual here.
|
};
|
Now we join the two branches into a single object:
class Item_func_udf_str: public Item_udf_func, public Type_handler_str
|
{
|
// No needs to declare field_type(), result_type(), cmp_type().
|
// No needs to declare val_real(), val_int(), val_decimal(), get_date().
|
// They are derived automatically from Type_handler_str.
|
// This class leaves only one pure virtual method val_str(),
|
// and its children are responsible to implement it.
|
};
|
class Item_func_str: public Item_func, public Type_handler_str
|
{
|
// Same here.
|
};
|
class Item_func_group_concat: public Item_sum, public Type_handler_str
|
{
|
// Same here, but it does not have children and implements val_str() itself.
|
};
|
A similar example with Type_handler_hybrid_field_type
class Item_sum_sum :public Item_sum_num,
|
public Type_handler_hybrid_field_type
|
{
|
// No needs to declare field_type(), result_type(), cmp_type()
|
// They are automatically assigned from Type_handler_hybrid_field_type
|
}
|
Attachments
Issue Links
- blocks
-
MDEV-4912 Data type plugin API version 1
- Closed