Skip to content

Commit

Permalink
MDEV-20589: Server still crashes in Field::set_warning_truncated_wron…
Browse files Browse the repository at this point in the history
…g_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.
  • Loading branch information
Varun Gupta committed Sep 18, 2019
1 parent c471bfb commit 273d8eb
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 14 deletions.
23 changes: 23 additions & 0 deletions mysql-test/r/stat_tables.result
Original file line number Diff line number Diff line change
Expand Up @@ -802,5 +802,28 @@ set use_stat_tables=@save_use_stat_tables;
set @@histogram_size= @save_histogram_size;
set @@optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivity;
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
set @@global.histogram_size=@save_histogram_size;
23 changes: 23 additions & 0 deletions mysql-test/r/stat_tables_innodb.result
Original file line number Diff line number Diff line change
Expand Up @@ -829,6 +829,29 @@ set use_stat_tables=@save_use_stat_tables;
set @@histogram_size= @save_histogram_size;
set @@optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivity;
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
set @@global.histogram_size=@save_histogram_size;
set optimizer_switch=@save_optimizer_switch_for_stat_tables_test;
Expand Down
22 changes: 22 additions & 0 deletions mysql-test/t/stat_tables.test
Original file line number Diff line number Diff line change
Expand Up @@ -546,5 +546,27 @@ set @@histogram_size= @save_histogram_size;
set @@optimizer_use_condition_selectivity=@save_optimizer_use_condition_selectivity;
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
set @@global.histogram_size=@save_histogram_size;
14 changes: 2 additions & 12 deletions sql/field.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2436,31 +2436,21 @@ Field *Field::clone(MEM_ROOT *root, TABLE *new_table)
}



Field *Field::clone(MEM_ROOT *root, TABLE *new_table, my_ptrdiff_t diff,
bool stat_flag)
{
Field *tmp;
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->is_stat_field= stat_flag;
return tmp;
}


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()
{
if (default_value)
Expand Down
1 change: 0 additions & 1 deletion sql/field.h
Original file line number Diff line number Diff line change
Expand Up @@ -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, my_ptrdiff_t diff,
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)
{
ptr=ptr_arg; null_ptr=null_ptr_arg; null_bit=null_bit_arg;
Expand Down
4 changes: 3 additions & 1 deletion sql/sql_statistics.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1153,12 +1153,14 @@ class Column_stat: public Stat_table
case COLUMN_STAT_MIN_VALUE:
table_field->read_stats->min_value->set_notnull();
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(),
&my_charset_bin);
break;
case COLUMN_STAT_MAX_VALUE:
table_field->read_stats->max_value->set_notnull();
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(),
&my_charset_bin);
break;
Expand Down Expand Up @@ -2045,7 +2047,7 @@ void create_min_max_statistical_fields_for_table_share(THD *thd,
Field *fld;
Field *table_field= *field_ptr;
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;
if (i == 0)
table_field->read_stats->min_value= fld;
Expand Down

0 comments on commit 273d8eb

Please sign in to comment.