summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/item_strfunc.cc13
-rw-r--r--sql/sql_type.cc45
-rw-r--r--sql/sql_type.h13
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;