diff options
author | Nikita Malyavin <nikitamalyavin@gmail.com> | 2021-06-22 18:30:53 +0300 |
---|---|---|
committer | Nikita Malyavin <nikitamalyavin@gmail.com> | 2021-07-12 22:00:39 +0300 |
commit | 0f6a5b4390efeac19ff3ad6fd3a8dd32241b343c (patch) | |
tree | 6173a84980d947b4c3fed1bc7d7e85fb0d980d86 | |
parent | 7d9ba57da4843c05a4d11e63159a961c4eb79a04 (diff) | |
download | mariadb-git-0f6a5b4390efeac19ff3ad6fd3a8dd32241b343c.tar.gz |
[2/2] MDEV-18166 ASSERT_COLUMN_MARKED_FOR_READ failed on tables with vcols
Several different test cases were failing under the same reason: the
fields in a vcol expression were not marked during marking columns of a key
contatining virtual column for read.
Fix: make marking columns of a key for read a special case where
register_field_in_read_map() is done instead of plain bitmap_set_bit().
Some test cases are only reproducible in 10.4+, but the fix is applicable
to 10.2+
-rw-r--r-- | mysql-test/suite/gcol/inc/gcol_ins_upd.inc | 30 | ||||
-rw-r--r-- | mysql-test/suite/gcol/inc/gcol_view.inc | 17 | ||||
-rw-r--r-- | mysql-test/suite/gcol/r/gcol_ins_upd_innodb.result | 27 | ||||
-rw-r--r-- | mysql-test/suite/gcol/r/gcol_ins_upd_myisam.result | 27 | ||||
-rw-r--r-- | mysql-test/suite/gcol/r/gcol_view_innodb.result | 12 | ||||
-rw-r--r-- | mysql-test/suite/gcol/r/gcol_view_myisam.result | 12 | ||||
-rw-r--r-- | sql/table.cc | 39 | ||||
-rw-r--r-- | sql/table.h | 1 |
8 files changed, 152 insertions, 13 deletions
diff --git a/mysql-test/suite/gcol/inc/gcol_ins_upd.inc b/mysql-test/suite/gcol/inc/gcol_ins_upd.inc index 6bd7974f2af..4cfcf371fd7 100644 --- a/mysql-test/suite/gcol/inc/gcol_ins_upd.inc +++ b/mysql-test/suite/gcol/inc/gcol_ins_upd.inc @@ -629,4 +629,34 @@ DROP TABLE t1; --let $datadir= `SELECT @@datadir` --remove_file $datadir/test/load.data + +--echo # +--echo # MDEV-18166 ASSERT_COLUMN_MARKED_FOR_READ failed on tables with vcols +--echo # + +CREATE TABLE t1 ( + id INT NOT NULL AUTO_INCREMENT, + f ENUM('a','b','c'), + v ENUM('a','b','c') AS (f), + KEY(v,id) +) ENGINE=MyISAM; +INSERT INTO t1 (f) VALUES ('a'),('b'); +INSERT IGNORE INTO t1 SELECT * FROM t1; + +# Cleanup +DROP TABLE t1; + + +CREATE TABLE t1 ( + id INT NOT NULL AUTO_INCREMENT, + f ENUM('a','b','c'), + v ENUM('a','b','c') AS (f), + KEY(v,id) +) ENGINE=MyISAM; +INSERT INTO t1 (f) VALUES ('a'),('b'); +INSERT IGNORE INTO t1 SELECT * FROM t1; + +# Cleanup +DROP TABLE t1; + } diff --git a/mysql-test/suite/gcol/inc/gcol_view.inc b/mysql-test/suite/gcol/inc/gcol_view.inc index 5e5afcb5ab1..4aabd2429cd 100644 --- a/mysql-test/suite/gcol/inc/gcol_view.inc +++ b/mysql-test/suite/gcol/inc/gcol_view.inc @@ -250,3 +250,20 @@ DELETE FROM v1 ORDER BY b LIMIT 2; # Cleanup DROP VIEW v1; DROP TABLE t1; +CREATE TABLE t1 (d INT, v TINYINT AS (d)); +CREATE VIEW v1 AS SELECT * FROM t1; +INSERT INTO t1 (d) VALUES ('2004'),('1985') ; +DELETE FROM v1 ORDER BY v LIMIT 4; + +DROP VIEW v1; +DROP TABLE t1; + + +CREATE TABLE t1 (d VARCHAR(64), v VARCHAR(63) AS (d)); +CREATE VIEW v1 AS SELECT * FROM t1; +INSERT INTO t1 (d) VALUES ('2004-04-19 15:37:39.123'),('1985-12-24 10:15:08.456') ; +DELETE FROM v1 ORDER BY v LIMIT 4; + +DROP TABLE t1; +DROP VIEW v1; + diff --git a/mysql-test/suite/gcol/r/gcol_ins_upd_innodb.result b/mysql-test/suite/gcol/r/gcol_ins_upd_innodb.result index 99e47c2d168..1d85fc837dc 100644 --- a/mysql-test/suite/gcol/r/gcol_ins_upd_innodb.result +++ b/mysql-test/suite/gcol/r/gcol_ins_upd_innodb.result @@ -764,6 +764,33 @@ SELECT pk, b FROM t1 INTO OUTFILE 'load.data'; LOAD DATA INFILE 'load.data' REPLACE INTO TABLE t1 (pk, b); ERROR 22001: Data too long for column 'v' at row 1 DROP TABLE t1; +# +# MDEV-18166 ASSERT_COLUMN_MARKED_FOR_READ failed on tables with vcols +# +CREATE TABLE t1 ( +id INT NOT NULL AUTO_INCREMENT, +f ENUM('a','b','c'), +v ENUM('a','b','c') AS (f), +KEY(v,id) +) ENGINE=MyISAM; +INSERT INTO t1 (f) VALUES ('a'),('b'); +INSERT IGNORE INTO t1 SELECT * FROM t1; +Warnings: +Warning 1906 The value specified for generated column 'v' in table 't1' has been ignored +Warning 1906 The value specified for generated column 'v' in table 't1' has been ignored +DROP TABLE t1; +CREATE TABLE t1 ( +id INT NOT NULL AUTO_INCREMENT, +f ENUM('a','b','c'), +v ENUM('a','b','c') AS (f), +KEY(v,id) +) ENGINE=MyISAM; +INSERT INTO t1 (f) VALUES ('a'),('b'); +INSERT IGNORE INTO t1 SELECT * FROM t1; +Warnings: +Warning 1906 The value specified for generated column 'v' in table 't1' has been ignored +Warning 1906 The value specified for generated column 'v' in table 't1' has been ignored +DROP TABLE t1; DROP VIEW IF EXISTS v1,v2; DROP TABLE IF EXISTS t1,t2,t3; DROP PROCEDURE IF EXISTS p1; diff --git a/mysql-test/suite/gcol/r/gcol_ins_upd_myisam.result b/mysql-test/suite/gcol/r/gcol_ins_upd_myisam.result index ce57fc08ac2..e10b83cabf5 100644 --- a/mysql-test/suite/gcol/r/gcol_ins_upd_myisam.result +++ b/mysql-test/suite/gcol/r/gcol_ins_upd_myisam.result @@ -686,6 +686,33 @@ SELECT pk, b FROM t1 INTO OUTFILE 'load.data'; LOAD DATA INFILE 'load.data' REPLACE INTO TABLE t1 (pk, b); ERROR 22001: Data too long for column 'v' at row 1 DROP TABLE t1; +# +# MDEV-18166 ASSERT_COLUMN_MARKED_FOR_READ failed on tables with vcols +# +CREATE TABLE t1 ( +id INT NOT NULL AUTO_INCREMENT, +f ENUM('a','b','c'), +v ENUM('a','b','c') AS (f), +KEY(v,id) +) ENGINE=MyISAM; +INSERT INTO t1 (f) VALUES ('a'),('b'); +INSERT IGNORE INTO t1 SELECT * FROM t1; +Warnings: +Warning 1906 The value specified for generated column 'v' in table 't1' has been ignored +Warning 1906 The value specified for generated column 'v' in table 't1' has been ignored +DROP TABLE t1; +CREATE TABLE t1 ( +id INT NOT NULL AUTO_INCREMENT, +f ENUM('a','b','c'), +v ENUM('a','b','c') AS (f), +KEY(v,id) +) ENGINE=MyISAM; +INSERT INTO t1 (f) VALUES ('a'),('b'); +INSERT IGNORE INTO t1 SELECT * FROM t1; +Warnings: +Warning 1906 The value specified for generated column 'v' in table 't1' has been ignored +Warning 1906 The value specified for generated column 'v' in table 't1' has been ignored +DROP TABLE t1; DROP VIEW IF EXISTS v1,v2; DROP TABLE IF EXISTS t1,t2,t3; DROP PROCEDURE IF EXISTS p1; diff --git a/mysql-test/suite/gcol/r/gcol_view_innodb.result b/mysql-test/suite/gcol/r/gcol_view_innodb.result index 2690c60f634..59e299f9d8c 100644 --- a/mysql-test/suite/gcol/r/gcol_view_innodb.result +++ b/mysql-test/suite/gcol/r/gcol_view_innodb.result @@ -291,6 +291,18 @@ INSERT INTO t1 (a) VALUES ('foo'),('bar'); DELETE FROM v1 ORDER BY b LIMIT 2; DROP VIEW v1; DROP TABLE t1; +CREATE TABLE t1 (d INT, v TINYINT AS (d)); +CREATE VIEW v1 AS SELECT * FROM t1; +INSERT INTO t1 (d) VALUES ('2004'),('1985') ; +DELETE FROM v1 ORDER BY v LIMIT 4; +DROP VIEW v1; +DROP TABLE t1; +CREATE TABLE t1 (d VARCHAR(64), v VARCHAR(63) AS (d)); +CREATE VIEW v1 AS SELECT * FROM t1; +INSERT INTO t1 (d) VALUES ('2004-04-19 15:37:39.123'),('1985-12-24 10:15:08.456') ; +DELETE FROM v1 ORDER BY v LIMIT 4; +DROP TABLE t1; +DROP VIEW v1; DROP VIEW IF EXISTS v1,v2; DROP TABLE IF EXISTS t1,t2,t3; DROP PROCEDURE IF EXISTS p1; diff --git a/mysql-test/suite/gcol/r/gcol_view_myisam.result b/mysql-test/suite/gcol/r/gcol_view_myisam.result index b2856e36d13..17cc2135439 100644 --- a/mysql-test/suite/gcol/r/gcol_view_myisam.result +++ b/mysql-test/suite/gcol/r/gcol_view_myisam.result @@ -291,6 +291,18 @@ INSERT INTO t1 (a) VALUES ('foo'),('bar'); DELETE FROM v1 ORDER BY b LIMIT 2; DROP VIEW v1; DROP TABLE t1; +CREATE TABLE t1 (d INT, v TINYINT AS (d)); +CREATE VIEW v1 AS SELECT * FROM t1; +INSERT INTO t1 (d) VALUES ('2004'),('1985') ; +DELETE FROM v1 ORDER BY v LIMIT 4; +DROP VIEW v1; +DROP TABLE t1; +CREATE TABLE t1 (d VARCHAR(64), v VARCHAR(63) AS (d)); +CREATE VIEW v1 AS SELECT * FROM t1; +INSERT INTO t1 (d) VALUES ('2004-04-19 15:37:39.123'),('1985-12-24 10:15:08.456') ; +DELETE FROM v1 ORDER BY v LIMIT 4; +DROP TABLE t1; +DROP VIEW v1; DROP VIEW IF EXISTS v1,v2; DROP TABLE IF EXISTS t1,t2,t3; DROP PROCEDURE IF EXISTS p1; diff --git a/sql/table.cc b/sql/table.cc index 2666523f092..4afd2488ea1 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -6329,7 +6329,7 @@ void TABLE::prepare_for_position() if ((file->ha_table_flags() & HA_PRIMARY_KEY_IN_READ_INDEX) && s->primary_key < MAX_KEY) { - mark_columns_used_by_index_no_reset(s->primary_key, read_set); + mark_columns_used_by_index_for_read_no_reset(s->primary_key); /* signal change */ file->column_bitmaps_signal(); } @@ -6385,23 +6385,36 @@ void TABLE::restore_column_maps_after_keyread(MY_BITMAP *backup) DBUG_VOID_RETURN; } +static void mark_index_columns(TABLE *table, uint index, + MY_BITMAP *bitmap, bool read) +{ + KEY_PART_INFO *key_part= table->key_info[index].key_part; + uint key_parts= table->key_info[index].user_defined_key_parts; + for (uint k= 0; k < key_parts; k++) + if (read) + key_part[k].field->register_field_in_read_map(); + else + bitmap_set_bit(bitmap, key_part[k].fieldnr-1); + if (table->file->ha_table_flags() & HA_PRIMARY_KEY_IN_READ_INDEX && + table->s->primary_key != MAX_KEY && table->s->primary_key != index) + mark_index_columns(table, table->s->primary_key, bitmap, read); +} /* mark columns used by key, but don't reset other fields */ -void TABLE::mark_columns_used_by_index_no_reset(uint index, MY_BITMAP *bitmap) +inline void TABLE::mark_columns_used_by_index_no_reset(uint index, MY_BITMAP *bitmap) { - KEY_PART_INFO *key_part= key_info[index].key_part; - KEY_PART_INFO *key_part_end= (key_part + key_info[index].user_defined_key_parts); - for (;key_part != key_part_end; key_part++) - bitmap_set_bit(bitmap, key_part->fieldnr-1); - if (file->ha_table_flags() & HA_PRIMARY_KEY_IN_READ_INDEX && - s->primary_key != MAX_KEY && s->primary_key != index) - mark_columns_used_by_index_no_reset(s->primary_key, bitmap); + mark_index_columns(this, index, bitmap, false); } +inline void TABLE::mark_columns_used_by_index_for_read_no_reset(uint index) +{ + mark_index_columns(this, index, read_set, true); +} + /* Mark auto-increment fields as used fields in both read and write maps @@ -6420,7 +6433,7 @@ void TABLE::mark_auto_increment_column() bitmap_set_bit(read_set, found_next_number_field->field_index); bitmap_set_bit(write_set, found_next_number_field->field_index); if (s->next_number_keypart) - mark_columns_used_by_index_no_reset(s->next_number_index, read_set); + mark_columns_used_by_index_for_read_no_reset(s->next_number_index); file->column_bitmaps_signal(); } @@ -6476,7 +6489,7 @@ void TABLE::mark_columns_needed_for_delete() file->use_hidden_primary_key(); else { - mark_columns_used_by_index_no_reset(s->primary_key, read_set); + mark_columns_used_by_index_for_read_no_reset(s->primary_key); need_signal= true; } } @@ -6566,7 +6579,7 @@ void TABLE::mark_columns_needed_for_update() file->use_hidden_primary_key(); else { - mark_columns_used_by_index_no_reset(s->primary_key, read_set); + mark_columns_used_by_index_for_read_no_reset(s->primary_key); need_signal= true; } } @@ -6729,7 +6742,7 @@ void TABLE::mark_columns_per_binlog_row_image() We don't need to mark the primary key in the rpl_write_set as the binary log will include all columns read anyway. */ - mark_columns_used_by_index_no_reset(s->primary_key, read_set); + mark_columns_used_by_index_for_read_no_reset(s->primary_key); /* Only write columns that have changed */ rpl_write_set= write_set; break; diff --git a/sql/table.h b/sql/table.h index 69bd14b2834..7a5f4c6fe86 100644 --- a/sql/table.h +++ b/sql/table.h @@ -1423,6 +1423,7 @@ public: { return prepare_for_keyread(index, &tmp_set); } void mark_columns_used_by_index(uint index, MY_BITMAP *map); void mark_columns_used_by_index_no_reset(uint index, MY_BITMAP *map); + void mark_columns_used_by_index_for_read_no_reset(uint index); void restore_column_maps_after_keyread(MY_BITMAP *backup); void mark_auto_increment_column(void); void mark_columns_needed_for_update(void); |