Commit 0f6a5b43 authored by Nikita Malyavin's avatar Nikita Malyavin

[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+
parent 7d9ba57d
......@@ -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;
}
......@@ -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;
......@@ -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;
......
......@@ -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;
......
......@@ -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;
......
......@@ -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;
......
......@@ -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;
......
......@@ -1423,6 +1423,7 @@ struct TABLE
{ 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);
......
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