Commit d5e8b4d7 authored by Varun Gupta's avatar Varun Gupta

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
parent 6df2f2db
......@@ -13,5 +13,19 @@ test.t1 analyze status OK
INSERT INTO t1 VALUES ('3::3');
DROP TABLE t1;
#
# MDEV-22509: Server crashes in Field_inet6::store_inet6_null_with_warn / Field::maybe_null
#
CREATE TABLE t1 (a INT, b INET6 NOT NULL);
INSERT INTO t1 VALUES (1,'::'),(2,'::');
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
SELECT t1.a from t1;
a
1
2
DROP TABLE t1;
#
# End of 10.5 tests
#
......@@ -14,6 +14,16 @@ ANALYZE TABLE t1 PERSISTENT FOR ALL;
INSERT INTO t1 VALUES ('3::3');
DROP TABLE t1;
--echo #
--echo # MDEV-22509: Server crashes in Field_inet6::store_inet6_null_with_warn / Field::maybe_null
--echo #
CREATE TABLE t1 (a INT, b INET6 NOT NULL);
INSERT INTO t1 VALUES (1,'::'),(2,'::');
ANALYZE TABLE t1 PERSISTENT FOR ALL;
SELECT t1.a from t1;
DROP TABLE t1;
--echo #
--echo # End of 10.5 tests
--echo #
......@@ -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.
......
......@@ -978,6 +978,24 @@ class Field: public Value_source
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
......
......@@ -1036,27 +1036,31 @@ class Column_stat: public Stat_table
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 @@ class Column_stat: public Stat_table
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;
......
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