Commit ad8266a5 authored by Roman Nozdrin's avatar Roman Nozdrin

MDEV-20732 MDB now correctly estimates a length of the FORMAT() result for

doubles in scientific notation with a big integer part.
parent 65358278
...@@ -225,9 +225,11 @@ DROP TABLE t1; ...@@ -225,9 +225,11 @@ DROP TABLE t1;
--echo # Bug#58371 Assertion failed: !s.uses_buffer_owned_by(this) with format string function --echo # Bug#58371 Assertion failed: !s.uses_buffer_owned_by(this) with format string function
--echo # --echo #
--disable_ps_protocol
SET NAMES latin1; SET NAMES latin1;
DO CONVERT(CAST(SUBSTRING_INDEX(FORMAT(1,'1111'), FORMAT('','Zpq'),1) DO CONVERT(CAST(SUBSTRING_INDEX(FORMAT(1,'1111'), FORMAT('','Zpq'),1)
AS BINARY(0)) USING utf8); AS BINARY(0)) USING utf8);
--enable_ps_protocol
--echo # --echo #
--echo # End of 5.1 tests --echo # End of 5.1 tests
--echo # --echo #
......
...@@ -1588,7 +1588,7 @@ CREATE TABLE t1 AS SELECT format(123,2,'no_NO'); ...@@ -1588,7 +1588,7 @@ CREATE TABLE t1 AS SELECT format(123,2,'no_NO');
SHOW CREATE TABLE t1; SHOW CREATE TABLE t1;
Table Create Table Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`format(123,2,'no_NO')` varchar(45) CHARACTER SET utf32 DEFAULT NULL `format(123,2,'no_NO')` varchar(17) CHARACTER SET utf32 DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1 ) ENGINE=MyISAM DEFAULT CHARSET=latin1
SELECT * FROM t1; SELECT * FROM t1;
format(123,2,'no_NO') format(123,2,'no_NO')
......
This diff is collapsed.
This diff is collapsed.
...@@ -745,7 +745,7 @@ t1 CREATE TABLE `t1` ( ...@@ -745,7 +745,7 @@ t1 CREATE TABLE `t1` (
`conv(130,16,10)` varchar(64) DEFAULT NULL, `conv(130,16,10)` varchar(64) DEFAULT NULL,
`hex(130)` varchar(6) DEFAULT NULL, `hex(130)` varchar(6) DEFAULT NULL,
`char(130)` varbinary(4) DEFAULT NULL, `char(130)` varbinary(4) DEFAULT NULL,
`format(130,10)` varchar(45) DEFAULT NULL, `format(130,10)` varchar(25) DEFAULT NULL,
`left(_latin2'a',1)` varchar(1) CHARACTER SET latin2 DEFAULT NULL, `left(_latin2'a',1)` varchar(1) CHARACTER SET latin2 DEFAULT NULL,
`right(_latin2'a',1)` varchar(1) CHARACTER SET latin2 DEFAULT NULL, `right(_latin2'a',1)` varchar(1) CHARACTER SET latin2 DEFAULT NULL,
`lcase(_latin2'a')` varchar(1) CHARACTER SET latin2 DEFAULT NULL, `lcase(_latin2'a')` varchar(1) CHARACTER SET latin2 DEFAULT NULL,
...@@ -2708,7 +2708,7 @@ create table t1(a float); ...@@ -2708,7 +2708,7 @@ create table t1(a float);
insert into t1 values (1.33); insert into t1 values (1.33);
select format(a, 2) from t1; select format(a, 2) from t1;
Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr
def format(a, 2) 253 57 4 Y 0 39 8 def format(a, 2) 253 4 4 Y 0 39 8
format(a, 2) format(a, 2)
1.33 1.33
drop table t1; drop table t1;
...@@ -3042,7 +3042,7 @@ CREATE TABLE t1 AS SELECT format(123,2,'no_NO'); ...@@ -3042,7 +3042,7 @@ CREATE TABLE t1 AS SELECT format(123,2,'no_NO');
SHOW CREATE TABLE t1; SHOW CREATE TABLE t1;
Table Create Table Table Create Table
t1 CREATE TABLE `t1` ( t1 CREATE TABLE `t1` (
`format(123,2,'no_NO')` varchar(45) DEFAULT NULL `format(123,2,'no_NO')` varchar(17) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1 ) ENGINE=MyISAM DEFAULT CHARSET=latin1
SELECT * FROM t1; SELECT * FROM t1;
format(123,2,'no_NO') format(123,2,'no_NO')
......
...@@ -2666,10 +2666,17 @@ const int FORMAT_MAX_DECIMALS= 30; ...@@ -2666,10 +2666,17 @@ const int FORMAT_MAX_DECIMALS= 30;
bool Item_func_format::fix_length_and_dec() bool Item_func_format::fix_length_and_dec()
{ {
uint32 char_length= args[0]->max_char_length(); uint32 char_length= args[0]->type_handler()->Item_decimal_notation_int_digits(args[0]);
uint32 max_sep_count= (char_length / 3) + (decimals ? 1 : 0) + /*sign*/1; 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()); 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) if (arg_count == 3)
locale= args[2]->basic_const_item() ? args[2]->locale_from_val_str() : NULL; locale= args[2]->basic_const_item() ? args[2]->locale_from_val_str() : NULL;
else else
......
...@@ -3490,7 +3490,6 @@ uint32 Type_handler_temporal_result::max_display_length(const Item *item) const ...@@ -3490,7 +3490,6 @@ uint32 Type_handler_temporal_result::max_display_length(const Item *item) const
return item->max_length; return item->max_length;
} }
uint32 Type_handler_string_result::max_display_length(const Item *item) const uint32 Type_handler_string_result::max_display_length(const Item *item) const
{ {
return item->max_length; return item->max_length;
...@@ -3515,6 +3514,50 @@ uint32 Type_handler_general_purpose_int::max_display_length(const Item *item) ...@@ -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(); 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;
}
/*************************************************************************/ /*************************************************************************/
......
...@@ -3488,6 +3488,7 @@ class Type_handler ...@@ -3488,6 +3488,7 @@ class Type_handler
SORT_FIELD_ATTR *attr) const= 0; SORT_FIELD_ATTR *attr) const= 0;
virtual uint32 max_display_length(const Item *item) 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 uint32 calc_pack_length(uint32 length) const= 0;
virtual void Item_update_null_value(Item *item) 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; virtual bool Item_save_in_value(THD *thd, Item *item, st_value *value) const= 0;
...@@ -4236,6 +4237,7 @@ class Type_handler_decimal_result: public Type_handler_numeric ...@@ -4236,6 +4237,7 @@ class Type_handler_decimal_result: public Type_handler_numeric
const Type_std_attributes *item, const Type_std_attributes *item,
SORT_FIELD_ATTR *attr) const; SORT_FIELD_ATTR *attr) const;
uint32 max_display_length(const Item *item) 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, Item *create_typecast_item(THD *thd, Item *item,
const Type_cast_attributes &attr) const; const Type_cast_attributes &attr) const;
bool Item_const_eq(const Item_const *a, const Item_const *b, bool Item_const_eq(const Item_const *a, const Item_const *b,
...@@ -4529,6 +4531,7 @@ class Type_handler_general_purpose_int: public Type_handler_int_result ...@@ -4529,6 +4531,7 @@ class Type_handler_general_purpose_int: public Type_handler_int_result
virtual const Type_limits_int * virtual const Type_limits_int *
type_limits_int_by_unsigned_flag(bool unsigned_flag) const= 0; type_limits_int_by_unsigned_flag(bool unsigned_flag) const= 0;
uint32 max_display_length(const Item *item) const; 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; bool Vers_history_point_resolve_unit(THD *thd, Vers_history_point *p) const;
}; };
...@@ -4554,6 +4557,7 @@ class Type_handler_temporal_result: public Type_handler ...@@ -4554,6 +4557,7 @@ class Type_handler_temporal_result: public Type_handler
const Type_all_attributes *attr, const Type_all_attributes *attr,
const st_value *value) const; const st_value *value) const;
uint32 max_display_length(const Item *item) 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, bool can_change_cond_ref_to_const(Item_bool_func2 *target,
Item *target_expr, Item *target_value, Item *target_expr, Item *target_value,
Item_bool_func2 *source, Item_bool_func2 *source,
...@@ -4638,6 +4642,11 @@ class Type_handler_string_result: public Type_handler ...@@ -4638,6 +4642,11 @@ class Type_handler_string_result: public Type_handler
const Schema_specification_st *schema) const Schema_specification_st *schema)
const; const;
uint32 max_display_length(const Item *item) 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 Item_const_eq(const Item_const *a, const Item_const *b,
bool binary_cmp) const; bool binary_cmp) const;
bool Item_eq_value(THD *thd, const Type_cmp_attributes *attr, bool Item_eq_value(THD *thd, const Type_cmp_attributes *attr,
...@@ -5024,6 +5033,7 @@ class Type_handler_year: public Type_handler_int_result ...@@ -5024,6 +5033,7 @@ class Type_handler_year: public Type_handler_int_result
return PROTOCOL_SEND_SHORT; return PROTOCOL_SEND_SHORT;
} }
uint32 max_display_length(const Item *item) const; 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; } uint32 calc_pack_length(uint32 length) const { return 1; }
bool Item_send(Item *item, Protocol *protocol, st_value *buf) const bool Item_send(Item *item, Protocol *protocol, st_value *buf) const
{ {
...@@ -5073,6 +5083,8 @@ class Type_handler_bit: public Type_handler_int_result ...@@ -5073,6 +5083,8 @@ class Type_handler_bit: public Type_handler_int_result
return PROTOCOL_SEND_STRING; return PROTOCOL_SEND_STRING;
} }
uint32 max_display_length(const Item *item) const; 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; } uint32 calc_pack_length(uint32 length) const { return length / 8; }
bool Item_send(Item *item, Protocol *protocol, st_value *buf) const bool Item_send(Item *item, Protocol *protocol, st_value *buf) const
{ {
...@@ -5175,6 +5187,7 @@ class Type_handler_double: public Type_handler_real_result ...@@ -5175,6 +5187,7 @@ class Type_handler_double: public Type_handler_real_result
} }
bool type_can_have_auto_increment_attribute() const { return true; } bool type_can_have_auto_increment_attribute() const { return true; }
uint32 max_display_length(const Item *item) const { return 53; } 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); } uint32 calc_pack_length(uint32 length) const { return sizeof(double); }
Item *create_typecast_item(THD *thd, Item *item, Item *create_typecast_item(THD *thd, Item *item,
const Type_cast_attributes &attr) const; const Type_cast_attributes &attr) 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