summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorVarun Gupta <varun.gupta@mariadb.com>2020-06-02 14:17:48 +0530
committerVarun Gupta <varun.gupta@mariadb.com>2020-06-02 17:43:45 +0530
commitd5e8b4d7f97c7a15be5d58b6f088c4c64787a385 (patch)
tree2c4c567936ec88012e66269d507ebc7b90e8f4ea /sql
parent6df2f2db11bf0a559db54e18315ad37e6a4d5573 (diff)
downloadmariadb-git-d5e8b4d7f97c7a15be5d58b6f088c4c64787a385.tar.gz
MDEV-22509: Server crashes in Field_inet6::store_inet6_null_with_warn / Field::maybe_null
For field with type INET, during EITS collection the min and max values are store in text representation in the statistical table. While retrieving the value from the statistical table, the value is stored back in the original field using binary form instead of text and this was resulting in the crash. Introduced 2 functions in the Field structure: 1) store_to_statistical_minmax_field 2) store_from_statistical_minmax_field
Diffstat (limited to 'sql')
-rw-r--r--sql/field.cc17
-rw-r--r--sql/field.h18
-rw-r--r--sql/sql_statistics.cc38
3 files changed, 57 insertions, 16 deletions
diff --git a/sql/field.cc b/sql/field.cc
index 7a2d67876e6..cbed034147d 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -1967,6 +1967,23 @@ int Field::store_timestamp_dec(const timeval &ts, uint dec)
return store_time_dec(Datetime(get_thd(), ts).get_mysql_time(), dec);
}
+
+int Field::store_to_statistical_minmax_field(Field *field, String *val)
+{
+ val_str(val);
+ size_t length= Well_formed_prefix(val->charset(), val->ptr(),
+ MY_MIN(val->length(), field->field_length)).length();
+ return field->store(val->ptr(), length, &my_charset_bin);
+}
+
+
+int Field::store_from_statistical_minmax_field(Field *stat_field, String *str)
+{
+ stat_field->val_str(str);
+ return store_text(str->ptr(), str->length(), &my_charset_bin);
+}
+
+
/**
Pack the field into a format suitable for storage and transfer.
diff --git a/sql/field.h b/sql/field.h
index bef73705f60..1bccff9991f 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -978,6 +978,24 @@ public:
return store(ls.str, (uint) ls.length, cs);
}
+ /*
+ @brief
+ Store minimum/maximum value of a column in the statistics table.
+ @param
+ field statistical table field
+ str value buffer
+ */
+ virtual int store_to_statistical_minmax_field(Field *field, String *str);
+
+ /*
+ @brief
+ Store minimum/maximum value of a column from the statistical table.
+ @param
+ field statistical table field
+ str value buffer
+ */
+ virtual int store_from_statistical_minmax_field(Field *field, String *str);
+
#ifdef HAVE_valgrind_or_MSAN
/**
Mark unused memory in the field as defined. Mainly used to ensure
diff --git a/sql/sql_statistics.cc b/sql/sql_statistics.cc
index f51f63020a3..0598698f7e5 100644
--- a/sql/sql_statistics.cc
+++ b/sql/sql_statistics.cc
@@ -1036,27 +1036,31 @@ public:
stat_field->set_notnull();
switch (i) {
case COLUMN_STAT_MIN_VALUE:
+ {
+ /*
+ TODO varun: After MDEV-22583 is fixed, add a function in Field_bit
+ and move this implementation there
+ */
if (table_field->type() == MYSQL_TYPE_BIT)
stat_field->store(table_field->collected_stats->min_value->val_int(),true);
else
{
- table_field->collected_stats->min_value->val_str(&val);
- size_t length= Well_formed_prefix(val.charset(), val.ptr(),
- MY_MIN(val.length(), stat_field->field_length)).length();
- stat_field->store(val.ptr(), length, &my_charset_bin);
+ Field *field= table_field->collected_stats->min_value;
+ field->store_to_statistical_minmax_field(stat_field, &val);
}
break;
+ }
case COLUMN_STAT_MAX_VALUE:
+ {
if (table_field->type() == MYSQL_TYPE_BIT)
stat_field->store(table_field->collected_stats->max_value->val_int(),true);
else
{
- table_field->collected_stats->max_value->val_str(&val);
- size_t length= Well_formed_prefix(val.charset(), val.ptr(),
- MY_MIN(val.length(), stat_field->field_length)).length();
- stat_field->store(val.ptr(), length, &my_charset_bin);
+ Field *field= table_field->collected_stats->max_value;
+ field->store_to_statistical_minmax_field(stat_field, &val);
}
break;
+ }
case COLUMN_STAT_NULLS_RATIO:
stat_field->store(table_field->collected_stats->get_nulls_ratio());
break;
@@ -1133,17 +1137,19 @@ public:
switch (i) {
case COLUMN_STAT_MIN_VALUE:
- table_field->read_stats->min_value->set_notnull();
- stat_field->val_str(&val);
- table_field->read_stats->min_value->store(val.ptr(), val.length(),
- &my_charset_bin);
+ {
+ Field *field= table_field->read_stats->min_value;
+ field->set_notnull();
+ field->store_from_statistical_minmax_field(stat_field, &val);
break;
+ }
case COLUMN_STAT_MAX_VALUE:
- table_field->read_stats->max_value->set_notnull();
- stat_field->val_str(&val);
- table_field->read_stats->max_value->store(val.ptr(), val.length(),
- &my_charset_bin);
+ {
+ Field *field= table_field->read_stats->max_value;
+ field->set_notnull();
+ field->store_from_statistical_minmax_field(stat_field, &val);
break;
+ }
case COLUMN_STAT_NULLS_RATIO:
table_field->read_stats->set_nulls_ratio(stat_field->val_real());
break;