Commit 273d8eb1 authored by Varun Gupta's avatar Varun Gupta

MDEV-20589: Server still crashes in Field::set_warning_truncated_wrong_value

The flag is_stat_field is not set for the min_value and max_value of field items
inside table share. This is a must requirement as we don't want to throw
warnings of truncation when we read values from the statistics table to the column
statistics of table share fields.
parent c471bfb3
...@@ -802,5 +802,28 @@ set use_stat_tables=@save_use_stat_tables; ...@@ -802,5 +802,28 @@ set use_stat_tables=@save_use_stat_tables;
set @@histogram_size= @save_histogram_size; set @@histogram_size= @save_histogram_size;
set @@optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivity; set @@optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivity;
drop table t1; drop table t1;
#
# MDEV-20589: Server still crashes in Field::set_warning_truncated_wrong_value
#
set names utf8;
create table t1 ( a varchar(255) character set utf8);
insert into t1 values (REPEAT('ӥ',255)), (REPEAT('ç',255));
set use_stat_tables='preferably';
analyze table t1 persistent for all;
Table Op Msg_type Msg_text
test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
set @save_sql_mode= @@sql_mode;
set sql_mode='ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';
update mysql.column_stats set min_value= REPEAT('ӥ',256) where db_name='test' and table_name='t1';
Warnings:
Warning 1265 Data truncated for column 'min_value' at row 1
set @@sql_mode= @save_sql_mode;
select length(a) from t1 where a=REPEAT('ӥ',255);
length(a)
510
set names latin1;
set @@use_stat_tables=@save_use_stat_tables;
drop table t1;
# please keep this at the last # please keep this at the last
set @@global.histogram_size=@save_histogram_size; set @@global.histogram_size=@save_histogram_size;
...@@ -829,6 +829,29 @@ set use_stat_tables=@save_use_stat_tables; ...@@ -829,6 +829,29 @@ set use_stat_tables=@save_use_stat_tables;
set @@histogram_size= @save_histogram_size; set @@histogram_size= @save_histogram_size;
set @@optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivity; set @@optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivity;
drop table t1; drop table t1;
#
# MDEV-20589: Server still crashes in Field::set_warning_truncated_wrong_value
#
set names utf8;
create table t1 ( a varchar(255) character set utf8);
insert into t1 values (REPEAT('ӥ',255)), (REPEAT('ç',255));
set use_stat_tables='preferably';
analyze table t1 persistent for all;
Table Op Msg_type Msg_text
test.t1 analyze status Engine-independent statistics collected
test.t1 analyze status OK
set @save_sql_mode= @@sql_mode;
set sql_mode='ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';
update mysql.column_stats set min_value= REPEAT('ӥ',256) where db_name='test' and table_name='t1';
Warnings:
Warning 1265 Data truncated for column 'min_value' at row 1
set @@sql_mode= @save_sql_mode;
select length(a) from t1 where a=REPEAT('ӥ',255);
length(a)
510
set names latin1;
set @@use_stat_tables=@save_use_stat_tables;
drop table t1;
# please keep this at the last # please keep this at the last
set @@global.histogram_size=@save_histogram_size; set @@global.histogram_size=@save_histogram_size;
set optimizer_switch=@save_optimizer_switch_for_stat_tables_test; set optimizer_switch=@save_optimizer_switch_for_stat_tables_test;
......
...@@ -546,5 +546,27 @@ set @@histogram_size= @save_histogram_size; ...@@ -546,5 +546,27 @@ set @@histogram_size= @save_histogram_size;
set @@optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivity; set @@optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivity;
drop table t1; drop table t1;
--echo #
--echo # MDEV-20589: Server still crashes in Field::set_warning_truncated_wrong_value
--echo #
set names utf8;
create table t1 ( a varchar(255) character set utf8);
insert into t1 values (REPEAT('ӥ',255)), (REPEAT('ç',255));
set use_stat_tables='preferably';
analyze table t1 persistent for all;
set @save_sql_mode= @@sql_mode;
set sql_mode='ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION';
update mysql.column_stats set min_value= REPEAT('ӥ',256) where db_name='test' and table_name='t1';
set @@sql_mode= @save_sql_mode;
select length(a) from t1 where a=REPEAT('ӥ',255);
set names latin1;
set @@use_stat_tables=@save_use_stat_tables;
drop table t1;
--echo # please keep this at the last --echo # please keep this at the last
set @@global.histogram_size=@save_histogram_size; set @@global.histogram_size=@save_histogram_size;
...@@ -2436,14 +2436,14 @@ Field *Field::clone(MEM_ROOT *root, TABLE *new_table) ...@@ -2436,14 +2436,14 @@ Field *Field::clone(MEM_ROOT *root, TABLE *new_table)
} }
Field *Field::clone(MEM_ROOT *root, TABLE *new_table, my_ptrdiff_t diff, Field *Field::clone(MEM_ROOT *root, TABLE *new_table, my_ptrdiff_t diff,
bool stat_flag) bool stat_flag)
{ {
Field *tmp; Field *tmp;
if ((tmp= (Field*) memdup_root(root,(char*) this,size_of()))) if ((tmp= (Field*) memdup_root(root,(char*) this,size_of())))
{ {
tmp->init(new_table); if (new_table)
tmp->init(new_table);
tmp->move_field_offset(diff); tmp->move_field_offset(diff);
} }
tmp->is_stat_field= stat_flag; tmp->is_stat_field= stat_flag;
...@@ -2451,16 +2451,6 @@ Field *Field::clone(MEM_ROOT *root, TABLE *new_table, my_ptrdiff_t diff, ...@@ -2451,16 +2451,6 @@ Field *Field::clone(MEM_ROOT *root, TABLE *new_table, my_ptrdiff_t diff,
} }
Field *Field::clone(MEM_ROOT *root, my_ptrdiff_t diff)
{
Field *tmp;
if ((tmp= (Field*) memdup_root(root,(char*) this,size_of())))
{
tmp->move_field_offset(diff);
}
return tmp;
}
int Field::set_default() int Field::set_default()
{ {
if (default_value) if (default_value)
......
...@@ -1220,7 +1220,6 @@ class Field: public Value_source ...@@ -1220,7 +1220,6 @@ class Field: public Value_source
Field *clone(MEM_ROOT *mem_root, TABLE *new_table); Field *clone(MEM_ROOT *mem_root, TABLE *new_table);
Field *clone(MEM_ROOT *mem_root, TABLE *new_table, my_ptrdiff_t diff, Field *clone(MEM_ROOT *mem_root, TABLE *new_table, my_ptrdiff_t diff,
bool stat_flag= FALSE); bool stat_flag= FALSE);
Field *clone(MEM_ROOT *mem_root, my_ptrdiff_t diff);
inline void move_field(uchar *ptr_arg,uchar *null_ptr_arg,uchar null_bit_arg) inline void move_field(uchar *ptr_arg,uchar *null_ptr_arg,uchar null_bit_arg)
{ {
ptr=ptr_arg; null_ptr=null_ptr_arg; null_bit=null_bit_arg; ptr=ptr_arg; null_ptr=null_ptr_arg; null_bit=null_bit_arg;
......
...@@ -1153,12 +1153,14 @@ class Column_stat: public Stat_table ...@@ -1153,12 +1153,14 @@ class Column_stat: public Stat_table
case COLUMN_STAT_MIN_VALUE: case COLUMN_STAT_MIN_VALUE:
table_field->read_stats->min_value->set_notnull(); table_field->read_stats->min_value->set_notnull();
stat_field->val_str(&val); stat_field->val_str(&val);
DBUG_ASSERT(table_field->read_stats->min_value->is_stat_field);
table_field->read_stats->min_value->store(val.ptr(), val.length(), table_field->read_stats->min_value->store(val.ptr(), val.length(),
&my_charset_bin); &my_charset_bin);
break; break;
case COLUMN_STAT_MAX_VALUE: case COLUMN_STAT_MAX_VALUE:
table_field->read_stats->max_value->set_notnull(); table_field->read_stats->max_value->set_notnull();
stat_field->val_str(&val); stat_field->val_str(&val);
DBUG_ASSERT(table_field->read_stats->min_value->is_stat_field);
table_field->read_stats->max_value->store(val.ptr(), val.length(), table_field->read_stats->max_value->store(val.ptr(), val.length(),
&my_charset_bin); &my_charset_bin);
break; break;
...@@ -2045,7 +2047,7 @@ void create_min_max_statistical_fields_for_table_share(THD *thd, ...@@ -2045,7 +2047,7 @@ void create_min_max_statistical_fields_for_table_share(THD *thd,
Field *fld; Field *fld;
Field *table_field= *field_ptr; Field *table_field= *field_ptr;
my_ptrdiff_t diff= record - table_share->default_values; my_ptrdiff_t diff= record - table_share->default_values;
if (!(fld= table_field->clone(&stats_cb->mem_root, diff))) if (!(fld= table_field->clone(&stats_cb->mem_root, NULL, diff, TRUE)))
continue; continue;
if (i == 0) if (i == 0)
table_field->read_stats->min_value= fld; table_field->read_stats->min_value= fld;
......
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