Commit 2dac1235 authored by Alexander Barkov's avatar Alexander Barkov

A cleanup for `MDEV-20273 Add class Item_sum_min_max` - removing duplicate code

Reusing the MIN()/MAX() fix_length_and_dec() related code for window functions
- FIRST_VALUE()
- LAST_VALUE()
- NTH_VALUE()
- LEAD()
- LAG
parent c3d67c17
...@@ -1184,11 +1184,73 @@ Item_sum_min_max::fix_fields(THD *thd, Item **ref) ...@@ -1184,11 +1184,73 @@ Item_sum_min_max::fix_fields(THD *thd, Item **ref)
} }
bool Item_sum_hybrid::fix_length_and_dec_generic()
{
Item *item= arguments()[0];
Type_std_attributes::set(item);
set_handler(item->type_handler());
return false;
}
/**
MAX/MIN for the traditional numeric types preserve the exact data type
from Fields, but do not preserve the exact type from Items:
MAX(float_field) -> FLOAT
MAX(smallint_field) -> LONGLONG
MAX(COALESCE(float_field)) -> DOUBLE
MAX(COALESCE(smallint_field)) -> LONGLONG
QQ: Items should probably be fixed to preserve the exact type.
*/
bool Item_sum_hybrid::fix_length_and_dec_numeric(const Type_handler *handler)
{
Item *item= arguments()[0];
Item *item2= item->real_item();
Type_std_attributes::set(item);
if (item2->type() == Item::FIELD_ITEM)
set_handler(item2->type_handler());
else
set_handler(handler);
return false;
}
/**
MAX(str_field) converts ENUM/SET to CHAR, and preserve all other types
for Fields.
QQ: This works differently from UNION, which preserve the exact data
type for ENUM/SET if the joined ENUM/SET fields are equally defined.
Perhaps should be fixed.
MAX(str_item) chooses the best suitable string type.
*/
bool Item_sum_hybrid::fix_length_and_dec_string()
{
Item *item= arguments()[0];
Item *item2= item->real_item();
Type_std_attributes::set(item);
if (item2->type() == Item::FIELD_ITEM)
{
// Fields: convert ENUM/SET to CHAR, preserve the type otherwise.
set_handler(item->type_handler());
}
else
{
// Items: choose VARCHAR/BLOB/MEDIUMBLOB/LONGBLOB, depending on length.
set_handler(type_handler_varchar.
type_handler_adjusted_to_max_octet_length(max_length,
collation.collation));
}
return false;
}
bool Item_sum_min_max::fix_length_and_dec() bool Item_sum_min_max::fix_length_and_dec()
{ {
DBUG_ASSERT(args[0]->field_type() == args[0]->real_item()->field_type()); DBUG_ASSERT(args[0]->field_type() == args[0]->real_item()->field_type());
DBUG_ASSERT(args[0]->result_type() == args[0]->real_item()->result_type()); DBUG_ASSERT(args[0]->result_type() == args[0]->real_item()->result_type());
return args[0]->type_handler()->Item_sum_min_max_fix_length_and_dec(this); /* MIN/MAX can return NULL for empty set indepedent of the used column */
maybe_null= null_value= true;
return args[0]->type_handler()->Item_sum_hybrid_fix_length_and_dec(this);
} }
......
...@@ -1044,6 +1044,9 @@ class Item_sum_hybrid: public Item_sum, ...@@ -1044,6 +1044,9 @@ class Item_sum_hybrid: public Item_sum,
{ } { }
const Type_handler *type_handler() const const Type_handler *type_handler() const
{ return Type_handler_hybrid_field_type::type_handler(); } { return Type_handler_hybrid_field_type::type_handler(); }
bool fix_length_and_dec_generic();
bool fix_length_and_dec_numeric(const Type_handler *h);
bool fix_length_and_dec_string();
}; };
......
...@@ -353,39 +353,15 @@ bool Item_sum_hybrid_simple::fix_fields(THD *thd, Item **ref) ...@@ -353,39 +353,15 @@ bool Item_sum_hybrid_simple::fix_fields(THD *thd, Item **ref)
if (args[i]->fix_fields_if_needed_for_scalar(thd, &args[i])) if (args[i]->fix_fields_if_needed_for_scalar(thd, &args[i]))
return TRUE; return TRUE;
} }
Type_std_attributes::set(args[0]);
for (uint i= 0; i < arg_count && !m_with_subquery; i++) for (uint i= 0; i < arg_count && !m_with_subquery; i++)
m_with_subquery|= args[i]->with_subquery(); m_with_subquery|= args[i]->with_subquery();
Item *item2= args[0]->real_item(); if (fix_length_and_dec())
if (item2->type() == Item::FIELD_ITEM) return true;
set_handler(item2->type_handler());
else if (args[0]->cmp_type() == TIME_RESULT)
set_handler(item2->type_handler());
else
set_handler_by_result_type(item2->result_type(),
max_length, collation.collation);
switch (result_type()) {
case INT_RESULT:
case DECIMAL_RESULT:
case STRING_RESULT:
break;
case REAL_RESULT:
max_length= float_length(decimals);
break;
case ROW_RESULT:
case TIME_RESULT:
DBUG_ASSERT(0); // XXX(cvicentiu) Should this never happen?
return TRUE;
};
setup_hybrid(thd, args[0]); setup_hybrid(thd, args[0]);
/* MIN/MAX can return NULL for empty set indepedent of the used column */
maybe_null= 1;
result_field=0; result_field=0;
null_value=1;
if (fix_length_and_dec())
return TRUE;
if (check_sum_func(thd, ref)) if (check_sum_func(thd, ref))
return TRUE; return TRUE;
...@@ -397,6 +373,14 @@ bool Item_sum_hybrid_simple::fix_fields(THD *thd, Item **ref) ...@@ -397,6 +373,14 @@ bool Item_sum_hybrid_simple::fix_fields(THD *thd, Item **ref)
return FALSE; return FALSE;
} }
bool Item_sum_hybrid_simple::fix_length_and_dec()
{
maybe_null= null_value= true;
return args[0]->type_handler()->Item_sum_hybrid_fix_length_and_dec(this);
}
bool Item_sum_hybrid_simple::add() bool Item_sum_hybrid_simple::add()
{ {
value->store(args[0]); value->store(args[0]);
......
...@@ -307,6 +307,7 @@ class Item_sum_hybrid_simple : public Item_sum_hybrid ...@@ -307,6 +307,7 @@ class Item_sum_hybrid_simple : public Item_sum_hybrid
bool add(); bool add();
bool fix_fields(THD *, Item **); bool fix_fields(THD *, Item **);
bool fix_length_and_dec();
void setup_hybrid(THD *thd, Item *item); void setup_hybrid(THD *thd, Item *item);
double val_real(); double val_real();
longlong val_int(); longlong val_int();
......
...@@ -365,7 +365,7 @@ Type_handler::blob_type_handler(const Item *item) ...@@ -365,7 +365,7 @@ Type_handler::blob_type_handler(const Item *item)
/** /**
This method is used by: This method is used by:
- Item_sum_min_max, e.g. MAX(item), MIN(item). - Item_sum_hybrid, e.g. MAX(item), MIN(item).
- Item_func_set_user_var - Item_func_set_user_var
*/ */
const Type_handler * const Type_handler *
...@@ -3076,87 +3076,33 @@ bool Type_handler_real_result:: ...@@ -3076,87 +3076,33 @@ bool Type_handler_real_result::
/*************************************************************************/ /*************************************************************************/
/**
MAX/MIN for the traditional numeric types preserve the exact data type
from Fields, but do not preserve the exact type from Items:
MAX(float_field) -> FLOAT
MAX(smallint_field) -> LONGLONG
MAX(COALESCE(float_field)) -> DOUBLE
MAX(COALESCE(smallint_field)) -> LONGLONG
QQ: Items should probably be fixed to preserve the exact type.
*/
bool Type_handler_numeric::
Item_sum_min_max_fix_length_and_dec_numeric(Item_sum_min_max *func,
const Type_handler *handler)
const
{
Item *item= func->arguments()[0];
Item *item2= item->real_item();
func->Type_std_attributes::set(item);
/* MIN/MAX can return NULL for empty set indepedent of the used column */
func->maybe_null= func->null_value= true;
if (item2->type() == Item::FIELD_ITEM)
func->set_handler(item2->type_handler());
else
func->set_handler(handler);
return false;
}
bool Type_handler_int_result:: bool Type_handler_int_result::
Item_sum_min_max_fix_length_and_dec(Item_sum_min_max *func) const Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *func) const
{ {
return Item_sum_min_max_fix_length_and_dec_numeric(func, return func->fix_length_and_dec_numeric(&type_handler_longlong);
&type_handler_longlong);
} }
bool Type_handler_real_result:: bool Type_handler_real_result::
Item_sum_min_max_fix_length_and_dec(Item_sum_min_max *func) const Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *func) const
{ {
(void) Item_sum_min_max_fix_length_and_dec_numeric(func, (void) func->fix_length_and_dec_numeric(&type_handler_double);
&type_handler_double);
func->max_length= func->float_length(func->decimals); func->max_length= func->float_length(func->decimals);
return false; return false;
} }
bool Type_handler_decimal_result:: bool Type_handler_decimal_result::
Item_sum_min_max_fix_length_and_dec(Item_sum_min_max *func) const Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *func) const
{ {
return Item_sum_min_max_fix_length_and_dec_numeric(func, return func->fix_length_and_dec_numeric(&type_handler_newdecimal);
&type_handler_newdecimal);
} }
/**
MAX(str_field) converts ENUM/SET to CHAR, and preserve all other types
for Fields.
QQ: This works differently from UNION, which preserve the exact data
type for ENUM/SET if the joined ENUM/SET fields are equally defined.
Perhaps should be fixed.
MAX(str_item) chooses the best suitable string type.
*/
bool Type_handler_string_result:: bool Type_handler_string_result::
Item_sum_min_max_fix_length_and_dec(Item_sum_min_max *func) const Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *func) const
{ {
Item *item= func->arguments()[0]; return func->fix_length_and_dec_string();
Item *item2= item->real_item();
func->Type_std_attributes::set(item);
func->maybe_null= func->null_value= true;
if (item2->type() == Item::FIELD_ITEM)
{
// Fields: convert ENUM/SET to CHAR, preserve the type otherwise.
func->set_handler(item->type_handler());
}
else
{
// Items: choose VARCHAR/BLOB/MEDIUMBLOB/LONGBLOB, depending on length.
func->set_handler(type_handler_varchar.
type_handler_adjusted_to_max_octet_length(func->max_length,
func->collation.collation));
}
return false;
} }
...@@ -3164,13 +3110,9 @@ bool Type_handler_string_result:: ...@@ -3164,13 +3110,9 @@ bool Type_handler_string_result::
Traditional temporal types always preserve the type of the argument. Traditional temporal types always preserve the type of the argument.
*/ */
bool Type_handler_temporal_result:: bool Type_handler_temporal_result::
Item_sum_min_max_fix_length_and_dec(Item_sum_min_max *func) const Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *func) const
{ {
Item *item= func->arguments()[0]; return func->fix_length_and_dec_generic();
func->Type_std_attributes::set(item);
func->maybe_null= func->null_value= true;
func->set_handler(item->type_handler());
return false;
} }
......
...@@ -33,7 +33,7 @@ class Item; ...@@ -33,7 +33,7 @@ class Item;
class Item_param; class Item_param;
class Item_cache; class Item_cache;
class Item_func_or_sum; class Item_func_or_sum;
class Item_sum_min_max; class Item_sum_hybrid;
class Item_sum_sum; class Item_sum_sum;
class Item_sum_avg; class Item_sum_avg;
class Item_sum_variance; class Item_sum_variance;
...@@ -1314,7 +1314,7 @@ class Type_handler ...@@ -1314,7 +1314,7 @@ class Type_handler
Item_func_min_max *func, Item_func_min_max *func,
Item **items, Item **items,
uint nitems) const; uint nitems) const;
virtual bool Item_sum_min_max_fix_length_and_dec(Item_sum_min_max *) const= 0; virtual bool Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *) const= 0;
virtual bool Item_sum_sum_fix_length_and_dec(Item_sum_sum *) const= 0; virtual bool Item_sum_sum_fix_length_and_dec(Item_sum_sum *) const= 0;
virtual bool Item_sum_avg_fix_length_and_dec(Item_sum_avg *) const= 0; virtual bool Item_sum_avg_fix_length_and_dec(Item_sum_avg *) const= 0;
virtual virtual
...@@ -1563,7 +1563,7 @@ class Type_handler_row: public Type_handler ...@@ -1563,7 +1563,7 @@ class Type_handler_row: public Type_handler
DBUG_ASSERT(0); DBUG_ASSERT(0);
return true; return true;
} }
bool Item_sum_min_max_fix_length_and_dec(Item_sum_min_max *func) const bool Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *func) const
{ {
DBUG_ASSERT(0); DBUG_ASSERT(0);
return true; return true;
...@@ -1742,10 +1742,6 @@ class Type_handler_row: public Type_handler ...@@ -1742,10 +1742,6 @@ class Type_handler_row: public Type_handler
*/ */
class Type_handler_numeric: public Type_handler class Type_handler_numeric: public Type_handler
{ {
protected:
bool Item_sum_min_max_fix_length_and_dec_numeric(Item_sum_min_max *func,
const Type_handler *handler)
const;
public: public:
String *print_item_value(THD *thd, Item *item, String *str) const; String *print_item_value(THD *thd, Item *item, String *str) const;
double Item_func_min_max_val_real(Item_func_min_max *) const; double Item_func_min_max_val_real(Item_func_min_max *) const;
...@@ -1796,7 +1792,7 @@ class Type_handler_real_result: public Type_handler_numeric ...@@ -1796,7 +1792,7 @@ class Type_handler_real_result: public Type_handler_numeric
Item **items, uint nitems) const; Item **items, uint nitems) const;
bool Item_func_min_max_fix_attributes(THD *thd, Item_func_min_max *func, bool Item_func_min_max_fix_attributes(THD *thd, Item_func_min_max *func,
Item **items, uint nitems) const; Item **items, uint nitems) const;
bool Item_sum_min_max_fix_length_and_dec(Item_sum_min_max *func) const; bool Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *func) const;
bool Item_sum_sum_fix_length_and_dec(Item_sum_sum *) const; bool Item_sum_sum_fix_length_and_dec(Item_sum_sum *) const;
bool Item_sum_avg_fix_length_and_dec(Item_sum_avg *) const; bool Item_sum_avg_fix_length_and_dec(Item_sum_avg *) const;
bool Item_sum_variance_fix_length_and_dec(Item_sum_variance *) const; bool Item_sum_variance_fix_length_and_dec(Item_sum_variance *) const;
...@@ -1874,7 +1870,7 @@ class Type_handler_decimal_result: public Type_handler_numeric ...@@ -1874,7 +1870,7 @@ class Type_handler_decimal_result: public Type_handler_numeric
Type_handler_hybrid_field_type *, Type_handler_hybrid_field_type *,
Type_all_attributes *atrr, Type_all_attributes *atrr,
Item **items, uint nitems) const; Item **items, uint nitems) const;
bool Item_sum_min_max_fix_length_and_dec(Item_sum_min_max *func) const; bool Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *func) const;
bool Item_sum_sum_fix_length_and_dec(Item_sum_sum *) const; bool Item_sum_sum_fix_length_and_dec(Item_sum_sum *) const;
bool Item_sum_avg_fix_length_and_dec(Item_sum_avg *) const; bool Item_sum_avg_fix_length_and_dec(Item_sum_avg *) const;
bool Item_sum_variance_fix_length_and_dec(Item_sum_variance *) const; bool Item_sum_variance_fix_length_and_dec(Item_sum_variance *) const;
...@@ -2068,7 +2064,7 @@ class Type_handler_int_result: public Type_handler_numeric ...@@ -2068,7 +2064,7 @@ class Type_handler_int_result: public Type_handler_numeric
Type_handler_hybrid_field_type *, Type_handler_hybrid_field_type *,
Type_all_attributes *atrr, Type_all_attributes *atrr,
Item **items, uint nitems) const; Item **items, uint nitems) const;
bool Item_sum_min_max_fix_length_and_dec(Item_sum_min_max *func) const; bool Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *func) const;
bool Item_sum_sum_fix_length_and_dec(Item_sum_sum *) const; bool Item_sum_sum_fix_length_and_dec(Item_sum_sum *) const;
bool Item_sum_avg_fix_length_and_dec(Item_sum_avg *) const; bool Item_sum_avg_fix_length_and_dec(Item_sum_avg *) const;
bool Item_sum_variance_fix_length_and_dec(Item_sum_variance *) const; bool Item_sum_variance_fix_length_and_dec(Item_sum_variance *) const;
...@@ -2145,7 +2141,7 @@ class Type_handler_temporal_result: public Type_handler ...@@ -2145,7 +2141,7 @@ class Type_handler_temporal_result: public Type_handler
const Item *outer) const; const Item *outer) const;
bool Item_func_min_max_fix_attributes(THD *thd, Item_func_min_max *func, bool Item_func_min_max_fix_attributes(THD *thd, Item_func_min_max *func,
Item **items, uint nitems) const; Item **items, uint nitems) const;
bool Item_sum_min_max_fix_length_and_dec(Item_sum_min_max *func) const; bool Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *func) const;
bool Item_sum_sum_fix_length_and_dec(Item_sum_sum *) const; bool Item_sum_sum_fix_length_and_dec(Item_sum_sum *) const;
bool Item_sum_avg_fix_length_and_dec(Item_sum_avg *) const; bool Item_sum_avg_fix_length_and_dec(Item_sum_avg *) const;
bool Item_sum_variance_fix_length_and_dec(Item_sum_variance *) const; bool Item_sum_variance_fix_length_and_dec(Item_sum_variance *) const;
...@@ -2258,7 +2254,7 @@ class Type_handler_string_result: public Type_handler ...@@ -2258,7 +2254,7 @@ class Type_handler_string_result: public Type_handler
Type_handler_hybrid_field_type *, Type_handler_hybrid_field_type *,
Type_all_attributes *atrr, Type_all_attributes *atrr,
Item **items, uint nitems) const; Item **items, uint nitems) const;
bool Item_sum_min_max_fix_length_and_dec(Item_sum_min_max *func) const; bool Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *func) const;
bool Item_sum_sum_fix_length_and_dec(Item_sum_sum *) const; bool Item_sum_sum_fix_length_and_dec(Item_sum_sum *) const;
bool Item_sum_avg_fix_length_and_dec(Item_sum_avg *) const; bool Item_sum_avg_fix_length_and_dec(Item_sum_avg *) const;
bool Item_sum_variance_fix_length_and_dec(Item_sum_variance *) const; bool Item_sum_variance_fix_length_and_dec(Item_sum_variance *) const;
......
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