summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikita Malyavin <nikitamalyavin@gmail.com>2021-06-22 18:30:53 +0300
committerNikita Malyavin <nikitamalyavin@gmail.com>2021-07-12 22:00:39 +0300
commit0f6a5b4390efeac19ff3ad6fd3a8dd32241b343c (patch)
tree6173a84980d947b4c3fed1bc7d7e85fb0d980d86
parent7d9ba57da4843c05a4d11e63159a961c4eb79a04 (diff)
downloadmariadb-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.inc30
-rw-r--r--mysql-test/suite/gcol/inc/gcol_view.inc17
-rw-r--r--mysql-test/suite/gcol/r/gcol_ins_upd_innodb.result27
-rw-r--r--mysql-test/suite/gcol/r/gcol_ins_upd_myisam.result27
-rw-r--r--mysql-test/suite/gcol/r/gcol_view_innodb.result12
-rw-r--r--mysql-test/suite/gcol/r/gcol_view_myisam.result12
-rw-r--r--sql/table.cc39
-rw-r--r--sql/table.h1
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);