Commit dc6ad597 authored by Marko Mäkelä's avatar Marko Mäkelä

MDEV-17901 Crash after instant DROP COLUMN of AUTO_INCREMENT column

We failed to reset the dict_table_t::persistent_autoinc after
instantly dropping an AUTO_INCREMENT column, causing a bogus
call to row_parse_int() on a subsequent insert.
parent 8dc460b8
......@@ -565,6 +565,19 @@ ALTER TABLE t1 DROP f2, ADD COLUMN f4 INT;
ALTER TABLE t1 DROP f4;
ALTER TABLE t1 DROP f1;
DROP TABLE t1;
CREATE TABLE t1 (id INT NOT NULL AUTO_INCREMENT, f INT, KEY(id)) ENGINE=InnoDB ROW_FORMAT=REDUNDANT;
ALTER TABLE t1 DROP COLUMN id;
INSERT INTO t1 () VALUES (),();
SELECT * FROM t1;
f
NULL
NULL
ALTER TABLE t1 ADD COLUMN id INT NOT NULL AUTO_INCREMENT FIRST, ADD KEY(id);
SELECT * FROM t1;
id f
1 NULL
2 NULL
DROP TABLE t1;
CREATE TABLE t1
(id INT PRIMARY KEY, c2 INT UNIQUE,
c3 POINT NOT NULL DEFAULT ST_GeomFromText('POINT(3 4)'),
......@@ -1076,6 +1089,19 @@ ALTER TABLE t1 DROP f2, ADD COLUMN f4 INT;
ALTER TABLE t1 DROP f4;
ALTER TABLE t1 DROP f1;
DROP TABLE t1;
CREATE TABLE t1 (id INT NOT NULL AUTO_INCREMENT, f INT, KEY(id)) ENGINE=InnoDB ROW_FORMAT=COMPACT;
ALTER TABLE t1 DROP COLUMN id;
INSERT INTO t1 () VALUES (),();
SELECT * FROM t1;
f
NULL
NULL
ALTER TABLE t1 ADD COLUMN id INT NOT NULL AUTO_INCREMENT FIRST, ADD KEY(id);
SELECT * FROM t1;
id f
1 NULL
2 NULL
DROP TABLE t1;
CREATE TABLE t1
(id INT PRIMARY KEY, c2 INT UNIQUE,
c3 POINT NOT NULL DEFAULT ST_GeomFromText('POINT(3 4)'),
......@@ -1587,10 +1613,23 @@ ALTER TABLE t1 DROP f2, ADD COLUMN f4 INT;
ALTER TABLE t1 DROP f4;
ALTER TABLE t1 DROP f1;
DROP TABLE t1;
CREATE TABLE t1 (id INT NOT NULL AUTO_INCREMENT, f INT, KEY(id)) ENGINE=InnoDB ROW_FORMAT=DYNAMIC;
ALTER TABLE t1 DROP COLUMN id;
INSERT INTO t1 () VALUES (),();
SELECT * FROM t1;
f
NULL
NULL
ALTER TABLE t1 ADD COLUMN id INT NOT NULL AUTO_INCREMENT FIRST, ADD KEY(id);
SELECT * FROM t1;
id f
1 NULL
2 NULL
DROP TABLE t1;
disconnect analyze;
SELECT variable_value-@old_instant instants
FROM information_schema.global_status
WHERE variable_name = 'innodb_instant_alter_column';
instants
111
114
SET GLOBAL innodb_purge_rseg_truncate_frequency= @saved_frequency;
......@@ -437,6 +437,16 @@ ALTER TABLE t1 DROP f4;
ALTER TABLE t1 DROP f1;
DROP TABLE t1;
# MDEV-17901 Crash after instant DROP COLUMN of AUTO_INCREMENT column
eval CREATE TABLE t1 (id INT NOT NULL AUTO_INCREMENT, f INT, KEY(id)) $engine;
ALTER TABLE t1 DROP COLUMN id;
INSERT INTO t1 () VALUES (),();
SELECT * FROM t1;
# Adding AUTO_INCREMENT column will always require rebuild.
ALTER TABLE t1 ADD COLUMN id INT NOT NULL AUTO_INCREMENT FIRST, ADD KEY(id);
SELECT * FROM t1;
DROP TABLE t1;
dec $format;
}
disconnect analyze;
......
......@@ -173,6 +173,8 @@ inline void dict_table_t::prepare_instant(const dict_table_t& old,
DBUG_ASSERT(old.n_cols == old.n_def);
DBUG_ASSERT(n_cols == n_def);
DBUG_ASSERT(old.supports_instant());
DBUG_ASSERT(!persistent_autoinc
|| persistent_autoinc == old.persistent_autoinc);
/* supports_instant() does not necessarily hold here,
in case ROW_FORMAT=COMPRESSED according to the
MariaDB data dictionary, and ALTER_OPTIONS was not set.
......@@ -431,6 +433,8 @@ inline void dict_table_t::instant_column(const dict_table_t& table,
DBUG_ASSERT(n_v_def == n_v_cols);
DBUG_ASSERT(table.n_v_def == table.n_v_cols);
DBUG_ASSERT(table.n_cols + table.n_dropped() >= n_cols + n_dropped());
DBUG_ASSERT(!table.persistent_autoinc
|| persistent_autoinc == table.persistent_autoinc);
ut_ad(mutex_own(&dict_sys->mutex));
{
......@@ -6202,6 +6206,9 @@ prepare_inplace_alter_table_dict(
== !!new_clustered);
}
DBUG_ASSERT(!ctx->need_rebuild()
|| !ctx->new_table->persistent_autoinc);
if (ctx->need_rebuild() && instant_alter_column_possible(
*user_table, ha_alter_info, old_table)
#if 1 // MDEV-17459: adjust fts_fetch_doc_from_rec() and friends; remove this
......@@ -6330,6 +6337,11 @@ prepare_inplace_alter_table_dict(
ctx->new_table, i),
FTS_DOC_ID_COL_NAME)));
if (altered_table->found_next_number_field) {
ctx->new_table->persistent_autoinc
= ctx->old_table->persistent_autoinc;
}
ctx->prepare_instant();
}
......@@ -6462,7 +6474,6 @@ prepare_inplace_alter_table_dict(
ut_ad(new_clust_index->n_core_null_bytes
== UT_BITS_IN_BYTES(new_clust_index->n_nullable));
DBUG_ASSERT(!ctx->new_table->persistent_autoinc);
if (const Field* ai = altered_table->found_next_number_field) {
const unsigned col_no = innodb_col_no(ai);
......@@ -10142,8 +10153,8 @@ commit_cache_norebuild(
}
if (ha_alter_info->handler_flags & ALTER_DROP_STORED_COLUMN) {
dict_index_t* index = dict_table_get_first_index(
ctx->new_table);
const dict_index_t* index = ctx->new_table->indexes.start;
for (const dict_field_t* f = index->fields,
* const end = f + index->n_fields;
f != end; f++) {
......@@ -10156,6 +10167,14 @@ commit_cache_norebuild(
f->fixed_len);
}
}
DBUG_ASSERT(!ctx->instant_table->persistent_autoinc
|| ctx->new_table->persistent_autoinc
== ctx->instant_table->persistent_autoinc);
if (!ctx->instant_table->persistent_autoinc) {
ctx->new_table->persistent_autoinc = 0;
}
}
}
......
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