diff options
Diffstat (limited to 'sql')
-rw-r--r-- | sql/item_strfunc.cc | 13 | ||||
-rw-r--r-- | sql/sql_type.cc | 45 | ||||
-rw-r--r-- | sql/sql_type.h | 13 |
3 files changed, 67 insertions, 4 deletions
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index f571521b982..32f05a815db 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -2666,10 +2666,17 @@ const int FORMAT_MAX_DECIMALS= 30; bool Item_func_format::fix_length_and_dec() { - uint32 char_length= args[0]->max_char_length(); - uint32 max_sep_count= (char_length / 3) + (decimals ? 1 : 0) + /*sign*/1; + uint32 char_length= args[0]->type_handler()->Item_decimal_notation_int_digits(args[0]); + uint dec= FORMAT_MAX_DECIMALS; + if (args[1]->const_item() && !args[1]->is_expensive()) + { + Longlong_hybrid tmp= args[1]->to_longlong_hybrid(); + if (!args[1]->null_value) + dec= tmp.to_uint(FORMAT_MAX_DECIMALS); + } + uint32 max_sep_count= (char_length / 3) + (dec ? 1 : 0) + /*sign*/1; collation.set(default_charset()); - fix_char_length(char_length + max_sep_count + decimals); + fix_char_length(char_length + max_sep_count + dec); if (arg_count == 3) locale= args[2]->basic_const_item() ? args[2]->locale_from_val_str() : NULL; else diff --git a/sql/sql_type.cc b/sql/sql_type.cc index 8b382773f7a..31b85c2e858 100644 --- a/sql/sql_type.cc +++ b/sql/sql_type.cc @@ -3490,7 +3490,6 @@ uint32 Type_handler_temporal_result::max_display_length(const Item *item) const return item->max_length; } - uint32 Type_handler_string_result::max_display_length(const Item *item) const { return item->max_length; @@ -3515,6 +3514,50 @@ uint32 Type_handler_general_purpose_int::max_display_length(const Item *item) return type_limits_int_by_unsigned_flag(item->unsigned_flag)->char_length(); } +/*************************************************************************/ + +uint32 +Type_handler_decimal_result::Item_decimal_notation_int_digits(const Item *item) + const +{ + return item->decimal_int_part(); +} + + +uint32 +Type_handler_temporal_result::Item_decimal_notation_int_digits(const Item *item) + const +{ + return item->decimal_int_part(); +} + + +uint32 +Type_handler_bit::Item_decimal_notation_int_digits(const Item *item) + const +{ + return Bit_decimal_notation_int_digits(item); +} + + +uint32 +Type_handler_general_purpose_int::Item_decimal_notation_int_digits( + const Item *item) const +{ + return type_limits_int_by_unsigned_flag(item->unsigned_flag)->precision(); +} + +/*************************************************************************/ + +/* + Decimal to binary digits ratio converges to log2(10) thus using 3 as + a divisor. +*/ +uint32 +Type_handler_bit::Bit_decimal_notation_int_digits(const Item *item) +{ + return item->max_length/3+1; +} /*************************************************************************/ diff --git a/sql/sql_type.h b/sql/sql_type.h index 0d6f7901480..0dd82f3dfaf 100644 --- a/sql/sql_type.h +++ b/sql/sql_type.h @@ -3488,6 +3488,7 @@ public: SORT_FIELD_ATTR *attr) const= 0; virtual uint32 max_display_length(const Item *item) const= 0; + virtual uint32 Item_decimal_notation_int_digits(const Item *item) const { return 0; } virtual uint32 calc_pack_length(uint32 length) const= 0; virtual void Item_update_null_value(Item *item) const= 0; virtual bool Item_save_in_value(THD *thd, Item *item, st_value *value) const= 0; @@ -4236,6 +4237,7 @@ public: const Type_std_attributes *item, SORT_FIELD_ATTR *attr) const; uint32 max_display_length(const Item *item) const; + uint32 Item_decimal_notation_int_digits(const Item *item) const; Item *create_typecast_item(THD *thd, Item *item, const Type_cast_attributes &attr) const; bool Item_const_eq(const Item_const *a, const Item_const *b, @@ -4529,6 +4531,7 @@ public: virtual const Type_limits_int * type_limits_int_by_unsigned_flag(bool unsigned_flag) const= 0; uint32 max_display_length(const Item *item) const; + uint32 Item_decimal_notation_int_digits(const Item *item) const; bool Vers_history_point_resolve_unit(THD *thd, Vers_history_point *p) const; }; @@ -4554,6 +4557,7 @@ public: const Type_all_attributes *attr, const st_value *value) const; uint32 max_display_length(const Item *item) const; + uint32 Item_decimal_notation_int_digits(const Item *item) const; bool can_change_cond_ref_to_const(Item_bool_func2 *target, Item *target_expr, Item *target_value, Item_bool_func2 *source, @@ -4638,6 +4642,11 @@ public: const Schema_specification_st *schema) const; uint32 max_display_length(const Item *item) const; +/* + The next method returns 309 for long stringified doubles in scientific + notation, e.g. FORMAT('1e308', 2). +*/ + uint32 Item_decimal_notation_int_digits(const Item *item) const { return 309; } bool Item_const_eq(const Item_const *a, const Item_const *b, bool binary_cmp) const; bool Item_eq_value(THD *thd, const Type_cmp_attributes *attr, @@ -5024,6 +5033,7 @@ public: return PROTOCOL_SEND_SHORT; } uint32 max_display_length(const Item *item) const; + uint32 Item_decimal_notation_int_digits(const Item *item) const { return 4; }; uint32 calc_pack_length(uint32 length) const { return 1; } bool Item_send(Item *item, Protocol *protocol, st_value *buf) const { @@ -5073,6 +5083,8 @@ public: return PROTOCOL_SEND_STRING; } uint32 max_display_length(const Item *item) const; + uint32 Item_decimal_notation_int_digits(const Item *item) const; + static uint32 Bit_decimal_notation_int_digits(const Item *item); uint32 calc_pack_length(uint32 length) const { return length / 8; } bool Item_send(Item *item, Protocol *protocol, st_value *buf) const { @@ -5175,6 +5187,7 @@ public: } bool type_can_have_auto_increment_attribute() const { return true; } uint32 max_display_length(const Item *item) const { return 53; } + uint32 Item_decimal_notation_int_digits(const Item *item) const { return 309; } uint32 calc_pack_length(uint32 length) const { return sizeof(double); } Item *create_typecast_item(THD *thd, Item *item, const Type_cast_attributes &attr) const; |