diff options
author | Alexander Barkov <bar@mariadb.com> | 2019-08-09 09:00:17 +0400 |
---|---|---|
committer | Alexander Barkov <bar@mariadb.com> | 2019-08-09 09:00:17 +0400 |
commit | 2dac1235150681433bdf6480e479e2f787b40f8b (patch) | |
tree | e40be99b51aaadb74917e7b02b80ab0525d54613 | |
parent | c3d67c17c150b06f79f2d4935933ebb6ecc4f644 (diff) | |
download | mariadb-git-2dac1235150681433bdf6480e479e2f787b40f8b.tar.gz |
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
-rw-r--r-- | sql/item_sum.cc | 64 | ||||
-rw-r--r-- | sql/item_sum.h | 3 | ||||
-rw-r--r-- | sql/item_windowfunc.cc | 38 | ||||
-rw-r--r-- | sql/item_windowfunc.h | 1 | ||||
-rw-r--r-- | sql/sql_type.cc | 80 | ||||
-rw-r--r-- | sql/sql_type.h | 20 |
6 files changed, 97 insertions, 109 deletions
diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 081db08e943..08ee190e96c 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -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() { DBUG_ASSERT(args[0]->field_type() == args[0]->real_item()->field_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); } diff --git a/sql/item_sum.h b/sql/item_sum.h index df37d0dbfa4..a3e10c25763 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -1044,6 +1044,9 @@ public: { } const Type_handler *type_handler() const { 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(); }; diff --git a/sql/item_windowfunc.cc b/sql/item_windowfunc.cc index 98474f62d4f..17c5740feda 100644 --- a/sql/item_windowfunc.cc +++ b/sql/item_windowfunc.cc @@ -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])) return TRUE; } - Type_std_attributes::set(args[0]); + for (uint i= 0; i < arg_count && !m_with_subquery; i++) m_with_subquery|= args[i]->with_subquery(); - Item *item2= args[0]->real_item(); - if (item2->type() == Item::FIELD_ITEM) - 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); + if (fix_length_and_dec()) + return true; - 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]); - /* MIN/MAX can return NULL for empty set indepedent of the used column */ - maybe_null= 1; result_field=0; - null_value=1; - if (fix_length_and_dec()) - return TRUE; if (check_sum_func(thd, ref)) return TRUE; @@ -397,6 +373,14 @@ bool Item_sum_hybrid_simple::fix_fields(THD *thd, Item **ref) 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() { value->store(args[0]); diff --git a/sql/item_windowfunc.h b/sql/item_windowfunc.h index 1432643dfc8..e6389c01832 100644 --- a/sql/item_windowfunc.h +++ b/sql/item_windowfunc.h @@ -307,6 +307,7 @@ class Item_sum_hybrid_simple : public Item_sum_hybrid bool add(); bool fix_fields(THD *, Item **); + bool fix_length_and_dec(); void setup_hybrid(THD *thd, Item *item); double val_real(); longlong val_int(); diff --git a/sql/sql_type.cc b/sql/sql_type.cc index 573d9721fc1..114e4cac367 100644 --- a/sql/sql_type.cc +++ b/sql/sql_type.cc @@ -365,7 +365,7 @@ Type_handler::blob_type_handler(const Item *item) /** 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 */ const Type_handler * @@ -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:: - 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, - &type_handler_longlong); + return func->fix_length_and_dec_numeric(&type_handler_longlong); } 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, - &type_handler_double); + (void) func->fix_length_and_dec_numeric(&type_handler_double); func->max_length= func->float_length(func->decimals); return false; } 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, - &type_handler_newdecimal); + return func->fix_length_and_dec_numeric(&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:: - 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]; - 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; + return func->fix_length_and_dec_string(); } @@ -3164,13 +3110,9 @@ bool Type_handler_string_result:: Traditional temporal types always preserve the type of the argument. */ 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]; - func->Type_std_attributes::set(item); - func->maybe_null= func->null_value= true; - func->set_handler(item->type_handler()); - return false; + return func->fix_length_and_dec_generic(); } diff --git a/sql/sql_type.h b/sql/sql_type.h index a7915ddc463..df4b99569c1 100644 --- a/sql/sql_type.h +++ b/sql/sql_type.h @@ -33,7 +33,7 @@ class Item; class Item_param; class Item_cache; class Item_func_or_sum; -class Item_sum_min_max; +class Item_sum_hybrid; class Item_sum_sum; class Item_sum_avg; class Item_sum_variance; @@ -1314,7 +1314,7 @@ public: Item_func_min_max *func, Item **items, 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_avg_fix_length_and_dec(Item_sum_avg *) const= 0; virtual @@ -1563,7 +1563,7 @@ public: DBUG_ASSERT(0); 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); return true; @@ -1742,10 +1742,6 @@ public: */ 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: String *print_item_value(THD *thd, Item *item, String *str) const; double Item_func_min_max_val_real(Item_func_min_max *) const; @@ -1796,7 +1792,7 @@ public: Item **items, uint nitems) const; bool Item_func_min_max_fix_attributes(THD *thd, Item_func_min_max *func, 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_avg_fix_length_and_dec(Item_sum_avg *) const; bool Item_sum_variance_fix_length_and_dec(Item_sum_variance *) const; @@ -1874,7 +1870,7 @@ public: Type_handler_hybrid_field_type *, Type_all_attributes *atrr, 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_avg_fix_length_and_dec(Item_sum_avg *) const; bool Item_sum_variance_fix_length_and_dec(Item_sum_variance *) const; @@ -2068,7 +2064,7 @@ public: Type_handler_hybrid_field_type *, Type_all_attributes *atrr, 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_avg_fix_length_and_dec(Item_sum_avg *) const; bool Item_sum_variance_fix_length_and_dec(Item_sum_variance *) const; @@ -2145,7 +2141,7 @@ public: const Item *outer) const; bool Item_func_min_max_fix_attributes(THD *thd, Item_func_min_max *func, 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_avg_fix_length_and_dec(Item_sum_avg *) const; bool Item_sum_variance_fix_length_and_dec(Item_sum_variance *) const; @@ -2258,7 +2254,7 @@ public: Type_handler_hybrid_field_type *, Type_all_attributes *atrr, 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_avg_fix_length_and_dec(Item_sum_avg *) const; bool Item_sum_variance_fix_length_and_dec(Item_sum_variance *) const; |