summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVarun Gupta <varun.gupta@mariadb.com>2019-09-18 01:59:29 +0530
committerVarun Gupta <varun.gupta@mariadb.com>2019-09-18 15:06:02 +0530
commit273d8eb12c40a6dcd05a8148bdfba3f1fd96e764 (patch)
tree4d67cbf15ce5cc7fac333cac019f70eb4afb3916
parentc471bfb34e970075d8649247ab088b19a097eaf4 (diff)
downloadmariadb-git-273d8eb12c40a6dcd05a8148bdfba3f1fd96e764.tar.gz
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.
-rw-r--r--mysql-test/r/stat_tables.result23
-rw-r--r--mysql-test/r/stat_tables_innodb.result23
-rw-r--r--mysql-test/t/stat_tables.test22
-rw-r--r--sql/field.cc14
-rw-r--r--sql/field.h1
-rw-r--r--sql/sql_statistics.cc4
6 files changed, 73 insertions, 14 deletions
diff --git a/mysql-test/r/stat_tables.result b/mysql-test/r/stat_tables.result
index c47a47cea31..bb3a0a80f7e 100644
--- a/mysql-test/r/stat_tables.result
+++ b/mysql-test/r/stat_tables.result
@@ -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;
diff --git a/mysql-test/r/stat_tables_innodb.result b/mysql-test/r/stat_tables_innodb.result
index dcfdb55f9c9..a436efb5fea 100644
--- a/mysql-test/r/stat_tables_innodb.result
+++ b/mysql-test/r/stat_tables_innodb.result
@@ -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;
diff --git a/mysql-test/t/stat_tables.test b/mysql-test/t/stat_tables.test
index 880e6378ca5..4c21e21ea70 100644
--- a/mysql-test/t/stat_tables.test
+++ b/mysql-test/t/stat_tables.test
@@ -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;
diff --git a/sql/field.cc b/sql/field.cc
index 2b1ba0e1372..fd4cd8d5c54 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -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,
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;
@@ -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()
{
if (default_value)
diff --git a/sql/field.h b/sql/field.h
index 19a716cfd5d..3f027868c3c 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -1220,7 +1220,6 @@ public:
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;
diff --git a/sql/sql_statistics.cc b/sql/sql_statistics.cc
index 26032d8d535..578d3fac641 100644
--- a/sql/sql_statistics.cc
+++ b/sql/sql_statistics.cc
@@ -1153,12 +1153,14 @@ public:
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;
@@ -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;