diff options
-rw-r--r-- | plugin/type_inet/mysql-test/type_inet/type_inet6_stat_tables.result | 14 | ||||
-rw-r--r-- | plugin/type_inet/mysql-test/type_inet/type_inet6_stat_tables.test | 10 | ||||
-rw-r--r-- | sql/field.cc | 31 | ||||
-rw-r--r-- | sql/field.h | 22 | ||||
-rw-r--r-- | sql/sql_statistics.cc | 44 |
5 files changed, 95 insertions, 26 deletions
diff --git a/plugin/type_inet/mysql-test/type_inet/type_inet6_stat_tables.result b/plugin/type_inet/mysql-test/type_inet/type_inet6_stat_tables.result index 6d84d105c99..1cbedad1c3c 100644 --- a/plugin/type_inet/mysql-test/type_inet/type_inet6_stat_tables.result +++ b/plugin/type_inet/mysql-test/type_inet/type_inet6_stat_tables.result @@ -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 # diff --git a/plugin/type_inet/mysql-test/type_inet/type_inet6_stat_tables.test b/plugin/type_inet/mysql-test/type_inet/type_inet6_stat_tables.test index fb092db6bc4..063581b12f5 100644 --- a/plugin/type_inet/mysql-test/type_inet/type_inet6_stat_tables.test +++ b/plugin/type_inet/mysql-test/type_inet/type_inet6_stat_tables.test @@ -15,5 +15,15 @@ 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 # diff --git a/sql/field.cc b/sql/field.cc index 6234de43ec8..cfa67b0c5dc 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -1967,6 +1967,37 @@ 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); +} + + +int Field_bit::store_to_statistical_minmax_field(Field *field, String *str) +{ + longlong nr= val_int(); + return field->store(nr, TRUE); +} + + +int Field_bit::store_from_statistical_minmax_field(Field *stat_field, + String *str __attribute__((unused))) +{ + return store(stat_field->val_int(), TRUE); +} + + /** Pack the field into a format suitable for storage and transfer. diff --git a/sql/field.h b/sql/field.h index d709a84e0fe..358eb3939dc 100644 --- a/sql/field.h +++ b/sql/field.h @@ -977,6 +977,26 @@ public: DBUG_ASSERT(ls.length < UINT_MAX32); 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); + virtual double val_real()=0; virtual longlong val_int()=0; /* @@ -4946,6 +4966,8 @@ public: static_cast<uint16>((field_length & 7) | ((field_length / 8) << 8)), 2); } + int store_to_statistical_minmax_field(Field *fld, String *str) override; + int store_from_statistical_minmax_field(Field *fld, String *str) override; private: size_t do_last_null_byte() const override; diff --git a/sql/sql_statistics.cc b/sql/sql_statistics.cc index 55e8e52c052..2b171cba560 100644 --- a/sql/sql_statistics.cc +++ b/sql/sql_statistics.cc @@ -1037,27 +1037,17 @@ public: stat_field->set_notnull(); switch (i) { case COLUMN_STAT_MIN_VALUE: - 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; @@ -1134,17 +1124,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; |