diff options
author | Igor Babaev <igor@askmonty.org> | 2018-09-18 23:31:19 -0700 |
---|---|---|
committer | Igor Babaev <igor@askmonty.org> | 2018-09-18 23:31:19 -0700 |
commit | d3f01f64f0e0031dd684f0c700c84b58568276d3 (patch) | |
tree | 49e97cedce31c3ab8a06fee3eefea3456885d754 | |
parent | 809d8837ac6abd2b31a287927c978e41b0ddecf6 (diff) | |
download | mariadb-git-d3f01f64f0e0031dd684f0c700c84b58568276d3.tar.gz |
MDEV-16711 Crash in Field_blob::store() while reading statistics
for the small InnoDB table
This bug was introduced by the patch 6c414fcf89510215d6d3466eb9992d444eadae89.
The patch has not taken into account that some objects of the Field_* types
are created only for TABLE_SHARE and the field 'table' is set to NULL
for them. In particular such are objects created to store statistical
min/max values for columns.
-rw-r--r-- | mysql-test/r/stat_tables.result | 52 | ||||
-rw-r--r-- | mysql-test/r/stat_tables_innodb.result | 52 | ||||
-rw-r--r-- | mysql-test/t/stat_tables.test | 39 | ||||
-rw-r--r-- | sql/field.cc | 5 |
4 files changed, 101 insertions, 47 deletions
diff --git a/mysql-test/r/stat_tables.result b/mysql-test/r/stat_tables.result index 0ee0d698bcc..279c09ff44f 100644 --- a/mysql-test/r/stat_tables.result +++ b/mysql-test/r/stat_tables.result @@ -518,6 +518,34 @@ drop database db2; drop table t1; set use_stat_tables=@save_use_stat_tables; # +# MDEV-16757: manual addition of min/max statistics for BLOB +# +SET use_stat_tables= PREFERABLY; +CREATE TABLE t1 (pk INT PRIMARY KEY, t TEXT); +INSERT INTO t1 VALUES (1,'foo'),(2,'bar'); +ANALYZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze Warning Engine-independent statistics are not collected for column 't' +test.t1 analyze status OK +SELECT * FROM mysql.column_stats; +db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram +test t1 pk 1 2 0.0000 4.0000 1.0000 0 NULL NULL +DELETE FROM mysql.column_stats +WHERE db_name='test' AND table_name='t1' AND column_name='t'; +INSERT INTO mysql.column_stats VALUES +('test','t1','t','bar','foo', 0.0, 3.0, 1.0, 0, NULL, NULL); +SELECT * FROM mysql.column_stats; +db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram +test t1 pk 1 2 0.0000 4.0000 1.0000 0 NULL NULL +test t1 t bar foo 0.0000 3.0000 1.0000 0 NULL NULL +SELECT pk FROM t1; +pk +1 +2 +DROP TABLE t1; +set use_stat_tables=@save_use_stat_tables; +# # MDEV-16760: CREATE OR REPLACE TABLE after ANALYZE TABLE # SET use_stat_tables= PREFERABLY; @@ -543,30 +571,18 @@ db_name table_name column_name min_value max_value nulls_ratio avg_length avg_fr DROP TABLE t1; set use_stat_tables=@save_use_stat_tables; # -# MDEV-16757: manual addition of min/max statistics for BLOB +# MDEV-16711:CREATE OR REPLACE TABLE introducing BLOB column # SET use_stat_tables= PREFERABLY; -CREATE TABLE t1 (pk INT PRIMARY KEY, t TEXT); +CREATE TABLE t1 (pk INT PRIMARY KEY, t CHAR(60)); INSERT INTO t1 VALUES (1,'foo'),(2,'bar'); ANALYZE TABLE t1; Table Op Msg_type Msg_text test.t1 analyze status Engine-independent statistics collected -test.t1 analyze Warning Engine-independent statistics are not collected for column 't' test.t1 analyze status OK -SELECT * FROM mysql.column_stats; -db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram -test t1 pk 1 2 0.0000 4.0000 1.0000 0 NULL NULL -DELETE FROM mysql.column_stats -WHERE db_name='test' AND table_name='t1' AND column_name='t'; -INSERT INTO mysql.column_stats VALUES -('test','t1','t','bar','foo', 0.0, 3.0, 1.0, 0, NULL, NULL); -SELECT * FROM mysql.column_stats; -db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram -test t1 pk 1 2 0.0000 4.0000 1.0000 0 NULL NULL -test t1 t bar foo 0.0000 3.0000 1.0000 0 NULL NULL -SELECT pk FROM t1; -pk -1 -2 +CREATE OR REPLACE TABLE t1 (pk INT PRIMARY KEY, t TEXT); +SELECT MAX(pk) FROM t1; +MAX(pk) +NULL DROP TABLE t1; set use_stat_tables=@save_use_stat_tables; diff --git a/mysql-test/r/stat_tables_innodb.result b/mysql-test/r/stat_tables_innodb.result index b0319508ede..d551afdb282 100644 --- a/mysql-test/r/stat_tables_innodb.result +++ b/mysql-test/r/stat_tables_innodb.result @@ -545,6 +545,34 @@ drop database db2; drop table t1; set use_stat_tables=@save_use_stat_tables; # +# MDEV-16757: manual addition of min/max statistics for BLOB +# +SET use_stat_tables= PREFERABLY; +CREATE TABLE t1 (pk INT PRIMARY KEY, t TEXT); +INSERT INTO t1 VALUES (1,'foo'),(2,'bar'); +ANALYZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 analyze status Engine-independent statistics collected +test.t1 analyze Warning Engine-independent statistics are not collected for column 't' +test.t1 analyze status OK +SELECT * FROM mysql.column_stats; +db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram +test t1 pk 1 2 0.0000 4.0000 1.0000 0 NULL NULL +DELETE FROM mysql.column_stats +WHERE db_name='test' AND table_name='t1' AND column_name='t'; +INSERT INTO mysql.column_stats VALUES +('test','t1','t','bar','foo', 0.0, 3.0, 1.0, 0, NULL, NULL); +SELECT * FROM mysql.column_stats; +db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram +test t1 pk 1 2 0.0000 4.0000 1.0000 0 NULL NULL +test t1 t bar foo 0.0000 3.0000 1.0000 0 NULL NULL +SELECT pk FROM t1; +pk +1 +2 +DROP TABLE t1; +set use_stat_tables=@save_use_stat_tables; +# # MDEV-16760: CREATE OR REPLACE TABLE after ANALYZE TABLE # SET use_stat_tables= PREFERABLY; @@ -570,31 +598,19 @@ db_name table_name column_name min_value max_value nulls_ratio avg_length avg_fr DROP TABLE t1; set use_stat_tables=@save_use_stat_tables; # -# MDEV-16757: manual addition of min/max statistics for BLOB +# MDEV-16711:CREATE OR REPLACE TABLE introducing BLOB column # SET use_stat_tables= PREFERABLY; -CREATE TABLE t1 (pk INT PRIMARY KEY, t TEXT); +CREATE TABLE t1 (pk INT PRIMARY KEY, t CHAR(60)); INSERT INTO t1 VALUES (1,'foo'),(2,'bar'); ANALYZE TABLE t1; Table Op Msg_type Msg_text test.t1 analyze status Engine-independent statistics collected -test.t1 analyze Warning Engine-independent statistics are not collected for column 't' test.t1 analyze status OK -SELECT * FROM mysql.column_stats; -db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram -test t1 pk 1 2 0.0000 4.0000 1.0000 0 NULL NULL -DELETE FROM mysql.column_stats -WHERE db_name='test' AND table_name='t1' AND column_name='t'; -INSERT INTO mysql.column_stats VALUES -('test','t1','t','bar','foo', 0.0, 3.0, 1.0, 0, NULL, NULL); -SELECT * FROM mysql.column_stats; -db_name table_name column_name min_value max_value nulls_ratio avg_length avg_frequency hist_size hist_type histogram -test t1 pk 1 2 0.0000 4.0000 1.0000 0 NULL NULL -test t1 t bar foo 0.0000 3.0000 1.0000 0 NULL NULL -SELECT pk FROM t1; -pk -1 -2 +CREATE OR REPLACE TABLE t1 (pk INT PRIMARY KEY, t TEXT); +SELECT MAX(pk) FROM t1; +MAX(pk) +NULL DROP TABLE t1; set use_stat_tables=@save_use_stat_tables; 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 7660acf6e42..cfe9255891a 100644 --- a/mysql-test/t/stat_tables.test +++ b/mysql-test/t/stat_tables.test @@ -308,6 +308,30 @@ drop table t1; set use_stat_tables=@save_use_stat_tables; --echo # +--echo # MDEV-16757: manual addition of min/max statistics for BLOB +--echo # + +SET use_stat_tables= PREFERABLY; + +CREATE TABLE t1 (pk INT PRIMARY KEY, t TEXT); +INSERT INTO t1 VALUES (1,'foo'),(2,'bar'); +ANALYZE TABLE t1; +--sorted_result +SELECT * FROM mysql.column_stats; +DELETE FROM mysql.column_stats + WHERE db_name='test' AND table_name='t1' AND column_name='t'; +INSERT INTO mysql.column_stats VALUES + ('test','t1','t','bar','foo', 0.0, 3.0, 1.0, 0, NULL, NULL); +--sorted_result +SELECT * FROM mysql.column_stats; + +SELECT pk FROM t1; + +DROP TABLE t1; + +set use_stat_tables=@save_use_stat_tables; + +--echo # --echo # MDEV-16760: CREATE OR REPLACE TABLE after ANALYZE TABLE --echo # @@ -328,24 +352,17 @@ DROP TABLE t1; set use_stat_tables=@save_use_stat_tables; --echo # ---echo # MDEV-16757: manual addition of min/max statistics for BLOB +--echo # MDEV-16711:CREATE OR REPLACE TABLE introducing BLOB column --echo # SET use_stat_tables= PREFERABLY; -CREATE TABLE t1 (pk INT PRIMARY KEY, t TEXT); +CREATE TABLE t1 (pk INT PRIMARY KEY, t CHAR(60)); INSERT INTO t1 VALUES (1,'foo'),(2,'bar'); ANALYZE TABLE t1; ---sorted_result -SELECT * FROM mysql.column_stats; -DELETE FROM mysql.column_stats - WHERE db_name='test' AND table_name='t1' AND column_name='t'; -INSERT INTO mysql.column_stats VALUES - ('test','t1','t','bar','foo', 0.0, 3.0, 1.0, 0, NULL, NULL); ---sorted_result -SELECT * FROM mysql.column_stats; +CREATE OR REPLACE TABLE t1 (pk INT PRIMARY KEY, t TEXT); -SELECT pk FROM t1; +SELECT MAX(pk) FROM t1; DROP TABLE t1; diff --git a/sql/field.cc b/sql/field.cc index 50edec4a1db..f4717de7b35 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -7924,6 +7924,11 @@ int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs) return 0; } + /* + For min/max fields of statistical data 'table' is set to NULL. + It could not be otherwise as this data is shared by many instances + of the same base table. + */ if (table && table->blob_storage) // GROUP_CONCAT with ORDER BY | DISTINCT { DBUG_ASSERT(!f_is_hex_escape(flags)); |