Skip to content

Commit ccb1acb

Browse files
committed
MDEV-18035 Failing assertion on DELETE
instant_alter_column_possible(): Do not allow instant removal of NOT NULL attribute from a column that belongs to the key of the clustered index.
1 parent 2fe40a7 commit ccb1acb

File tree

3 files changed

+58
-8
lines changed

3 files changed

+58
-8
lines changed

mysql-test/suite/innodb/r/instant_alter.result

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -615,6 +615,11 @@ DROP TABLE t1;
615615
CREATE TABLE t1 (f1 VARCHAR(1), f2 VARCHAR(2)) ENGINE=InnoDB ROW_FORMAT=REDUNDANT;
616616
ALTER TABLE t1 MODIFY f2 VARCHAR (8) FIRST;
617617
DROP TABLE t1;
618+
CREATE TABLE t1 (a INT UNIQUE, b INT UNIQUE, PRIMARY KEY(a,b)) ENGINE=InnoDB ROW_FORMAT=REDUNDANT;
619+
ALTER TABLE t1 DROP PRIMARY KEY;
620+
ALTER TABLE t1 CHANGE COLUMN a a INT;
621+
DELETE FROM t1 WHERE a = NULL OR a IS NULL;
622+
DROP TABLE t1;
618623
CREATE TABLE t1
619624
(id INT PRIMARY KEY, c2 INT UNIQUE,
620625
c3 POINT NOT NULL DEFAULT ST_GeomFromText('POINT(3 4)'),
@@ -1176,6 +1181,11 @@ DROP TABLE t1;
11761181
CREATE TABLE t1 (f1 VARCHAR(1), f2 VARCHAR(2)) ENGINE=InnoDB ROW_FORMAT=COMPACT;
11771182
ALTER TABLE t1 MODIFY f2 VARCHAR (8) FIRST;
11781183
DROP TABLE t1;
1184+
CREATE TABLE t1 (a INT UNIQUE, b INT UNIQUE, PRIMARY KEY(a,b)) ENGINE=InnoDB ROW_FORMAT=COMPACT;
1185+
ALTER TABLE t1 DROP PRIMARY KEY;
1186+
ALTER TABLE t1 CHANGE COLUMN a a INT;
1187+
DELETE FROM t1 WHERE a = NULL OR a IS NULL;
1188+
DROP TABLE t1;
11791189
CREATE TABLE t1
11801190
(id INT PRIMARY KEY, c2 INT UNIQUE,
11811191
c3 POINT NOT NULL DEFAULT ST_GeomFromText('POINT(3 4)'),
@@ -1737,6 +1747,11 @@ DROP TABLE t1;
17371747
CREATE TABLE t1 (f1 VARCHAR(1), f2 VARCHAR(2)) ENGINE=InnoDB ROW_FORMAT=DYNAMIC;
17381748
ALTER TABLE t1 MODIFY f2 VARCHAR (8) FIRST;
17391749
DROP TABLE t1;
1750+
CREATE TABLE t1 (a INT UNIQUE, b INT UNIQUE, PRIMARY KEY(a,b)) ENGINE=InnoDB ROW_FORMAT=DYNAMIC;
1751+
ALTER TABLE t1 DROP PRIMARY KEY;
1752+
ALTER TABLE t1 CHANGE COLUMN a a INT;
1753+
DELETE FROM t1 WHERE a = NULL OR a IS NULL;
1754+
DROP TABLE t1;
17401755
disconnect analyze;
17411756
SELECT variable_value-@old_instant instants
17421757
FROM information_schema.global_status

mysql-test/suite/innodb/t/instant_alter.test

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -490,6 +490,13 @@ eval CREATE TABLE t1 (f1 VARCHAR(1), f2 VARCHAR(2)) $engine;
490490
ALTER TABLE t1 MODIFY f2 VARCHAR (8) FIRST;
491491
DROP TABLE t1;
492492

493+
# MDEV-18035 Failing assertion on DELETE
494+
eval CREATE TABLE t1 (a INT UNIQUE, b INT UNIQUE, PRIMARY KEY(a,b)) $engine;
495+
ALTER TABLE t1 DROP PRIMARY KEY;
496+
ALTER TABLE t1 CHANGE COLUMN a a INT;
497+
DELETE FROM t1 WHERE a = NULL OR a IS NULL;
498+
DROP TABLE t1;
499+
493500
dec $format;
494501
}
495502
disconnect analyze;

storage/innobase/handler/handler0alter.cc

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1372,13 +1372,15 @@ check_v_col_in_order(
13721372
/** Determine if an instant operation is possible for altering columns.
13731373
@param[in] ib_table InnoDB table definition
13741374
@param[in] ha_alter_info the ALTER TABLE operation
1375-
@param[in] table table definition before ALTER TABLE */
1375+
@param[in] table table definition before ALTER TABLE
1376+
@param[in] table table definition after ALTER TABLE */
13761377
static
13771378
bool
13781379
instant_alter_column_possible(
13791380
const dict_table_t& ib_table,
13801381
const Alter_inplace_info* ha_alter_info,
1381-
const TABLE* table)
1382+
const TABLE* table,
1383+
const TABLE* altered_table)
13821384
{
13831385
if (!ib_table.supports_instant()) {
13841386
return false;
@@ -1470,10 +1472,36 @@ instant_alter_column_possible(
14701472
return false;
14711473
}
14721474

1473-
if ((ha_alter_info->handler_flags
1474-
& ALTER_COLUMN_NULLABLE)
1475-
&& ib_table.not_redundant()) {
1476-
return false;
1475+
if (ha_alter_info->handler_flags & ALTER_COLUMN_NULLABLE) {
1476+
if (ib_table.not_redundant()) {
1477+
return false;
1478+
}
1479+
1480+
const dict_index_t* pk = ib_table.indexes.start;
1481+
Field** af = altered_table->field;
1482+
Field** const end = altered_table->field
1483+
+ altered_table->s->fields;
1484+
for (unsigned c = 0; af < end; af++) {
1485+
if (!(*af)->stored_in_db()) {
1486+
continue;
1487+
}
1488+
1489+
const dict_col_t* col = dict_table_get_nth_col(
1490+
&ib_table, c++);
1491+
1492+
if (!col->ord_part || col->is_nullable()
1493+
|| !(*af)->real_maybe_null()) {
1494+
continue;
1495+
}
1496+
1497+
/* The column would be changed from NOT NULL.
1498+
Ensure that it is not a clustered index key. */
1499+
for (auto i = pk->n_uniq; i--; ) {
1500+
if (pk->fields[i].col == col) {
1501+
return false;
1502+
}
1503+
}
1504+
}
14771505
}
14781506

14791507
return true;
@@ -1784,7 +1812,7 @@ ha_innobase::check_if_supported_inplace_alter(
17841812
}
17851813

17861814
const bool supports_instant = instant_alter_column_possible(
1787-
*m_prebuilt->table, ha_alter_info, table);
1815+
*m_prebuilt->table, ha_alter_info, table, altered_table);
17881816
bool add_drop_v_cols = false;
17891817

17901818
/* If there is add or drop virtual columns, we will support operations
@@ -6285,7 +6313,7 @@ prepare_inplace_alter_table_dict(
62856313
|| !ctx->new_table->persistent_autoinc);
62866314

62876315
if (ctx->need_rebuild() && instant_alter_column_possible(
6288-
*user_table, ha_alter_info, old_table)
6316+
*user_table, ha_alter_info, old_table, altered_table)
62896317
#if 1 // MDEV-17459: adjust fts_fetch_doc_from_rec() and friends; remove this
62906318
&& !innobase_fulltext_exist(altered_table)
62916319
#endif

0 commit comments

Comments
 (0)