Commit 5aaee374 authored by Marko Mäkelä's avatar Marko Mäkelä

MDEV-17721: Corrupted data dictionary after instant DROP COLUMN

dict_index_t::clear_instant_alter(): Correctly sort the index fields
to correspond to the columns of the table.
parent 21a58840
...@@ -542,6 +542,11 @@ SELECT * FROM t1; ...@@ -542,6 +542,11 @@ SELECT * FROM t1;
b i v b i v
NULL 1 1 NULL 1 1
DROP TABLE t1; DROP TABLE t1;
CREATE TABLE t1 (ts TIMESTAMP) ENGINE=InnoDB ROW_FORMAT=REDUNDANT;
ALTER TABLE t1 ADD COLUMN f VARCHAR(8), ADD COLUMN dt DATETIME;
ALTER TABLE t1 ADD COLUMN b BIT, DROP COLUMN f, ADD COLUMN t TIME FIRST;
ALTER TABLE t1 ADD COLUMN ts2 TIMESTAMP;
DROP TABLE t1;
CREATE TABLE t1 CREATE TABLE t1
(id INT PRIMARY KEY, c2 INT UNIQUE, (id INT PRIMARY KEY, c2 INT UNIQUE,
c3 POINT NOT NULL DEFAULT ST_GeomFromText('POINT(3 4)'), c3 POINT NOT NULL DEFAULT ST_GeomFromText('POINT(3 4)'),
...@@ -1030,6 +1035,11 @@ SELECT * FROM t1; ...@@ -1030,6 +1035,11 @@ SELECT * FROM t1;
b i v b i v
NULL 1 1 NULL 1 1
DROP TABLE t1; DROP TABLE t1;
CREATE TABLE t1 (ts TIMESTAMP) ENGINE=InnoDB ROW_FORMAT=COMPACT;
ALTER TABLE t1 ADD COLUMN f VARCHAR(8), ADD COLUMN dt DATETIME;
ALTER TABLE t1 ADD COLUMN b BIT, DROP COLUMN f, ADD COLUMN t TIME FIRST;
ALTER TABLE t1 ADD COLUMN ts2 TIMESTAMP;
DROP TABLE t1;
CREATE TABLE t1 CREATE TABLE t1
(id INT PRIMARY KEY, c2 INT UNIQUE, (id INT PRIMARY KEY, c2 INT UNIQUE,
c3 POINT NOT NULL DEFAULT ST_GeomFromText('POINT(3 4)'), c3 POINT NOT NULL DEFAULT ST_GeomFromText('POINT(3 4)'),
...@@ -1518,10 +1528,15 @@ SELECT * FROM t1; ...@@ -1518,10 +1528,15 @@ SELECT * FROM t1;
b i v b i v
NULL 1 1 NULL 1 1
DROP TABLE t1; DROP TABLE t1;
CREATE TABLE t1 (ts TIMESTAMP) ENGINE=InnoDB ROW_FORMAT=DYNAMIC;
ALTER TABLE t1 ADD COLUMN f VARCHAR(8), ADD COLUMN dt DATETIME;
ALTER TABLE t1 ADD COLUMN b BIT, DROP COLUMN f, ADD COLUMN t TIME FIRST;
ALTER TABLE t1 ADD COLUMN ts2 TIMESTAMP;
DROP TABLE t1;
disconnect analyze; disconnect analyze;
SELECT variable_value-@old_instant instants SELECT variable_value-@old_instant instants
FROM information_schema.global_status FROM information_schema.global_status
WHERE variable_name = 'innodb_instant_alter_column'; WHERE variable_name = 'innodb_instant_alter_column';
instants instants
87 96
SET GLOBAL innodb_purge_rseg_truncate_frequency= @saved_frequency; SET GLOBAL innodb_purge_rseg_truncate_frequency= @saved_frequency;
...@@ -417,6 +417,13 @@ ALTER TABLE t1 ADD COLUMN v INT AS (i) VIRTUAL; ...@@ -417,6 +417,13 @@ ALTER TABLE t1 ADD COLUMN v INT AS (i) VIRTUAL;
SELECT * FROM t1; SELECT * FROM t1;
DROP TABLE t1; DROP TABLE t1;
# MDEV-17721 Corrupted data dictionary after instant DROP COLUMN
eval CREATE TABLE t1 (ts TIMESTAMP) $engine;
ALTER TABLE t1 ADD COLUMN f VARCHAR(8), ADD COLUMN dt DATETIME;
ALTER TABLE t1 ADD COLUMN b BIT, DROP COLUMN f, ADD COLUMN t TIME FIRST;
ALTER TABLE t1 ADD COLUMN ts2 TIMESTAMP;
DROP TABLE t1;
dec $format; dec $format;
} }
disconnect analyze; disconnect analyze;
......
...@@ -2149,39 +2149,26 @@ inline void dict_index_t::clear_instant_alter() ...@@ -2149,39 +2149,26 @@ inline void dict_index_t::clear_instant_alter()
DBUG_ASSERT(!fields[i].col->is_nullable()); DBUG_ASSERT(!fields[i].col->is_nullable());
} }
#endif #endif
dict_field_t* const begin = &fields[first_user_field()];
dict_field_t* end = &fields[n_fields]; dict_field_t* end = &fields[n_fields];
while (end[-1].col->is_dropped()) end--;
for (dict_field_t* d = &fields[first_user_field()]; d < end; d++) { for (dict_field_t* d = begin; d < end; d++) {
/* Move fields for dropped columns to the end. */ /* Move fields for dropped columns to the end. */
while (d->col->is_dropped()) { if (d->col->is_dropped()) {
if (d->col->is_nullable()) { if (d->col->is_nullable()) {
n_nullable--; n_nullable--;
} }
std::swap(*d, *--end); std::swap(*d, *--end);
if (d == end) {
goto done;
}
}
/* Ensure that the surviving fields are sorted by
ascending order of columns. */
const unsigned c = d->col->ind;
for (dict_field_t* s = d + 1; s < end; s++) {
if (s->col->ind < c) {
std::swap(*d, *s);
break;
}
} }
} }
done:
DBUG_ASSERT(&fields[n_fields - table->n_dropped()] == end); DBUG_ASSERT(&fields[n_fields - table->n_dropped()] == end);
n_core_fields = n_fields = n_def = end - fields; n_core_fields = n_fields = n_def = end - fields;
n_core_null_bytes = UT_BITS_IN_BYTES(n_nullable); n_core_null_bytes = UT_BITS_IN_BYTES(n_nullable);
std::sort(begin, end, [](const dict_field_t& a, const dict_field_t& b)
{ return a.col->ind < b.col->ind; });
table->instant = NULL; table->instant = NULL;
} }
......
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