summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/suite/innodb/r/instant_alter.result15
-rw-r--r--mysql-test/suite/innodb/t/instant_alter.test7
-rw-r--r--storage/innobase/handler/handler0alter.cc44
3 files changed, 58 insertions, 8 deletions
diff --git a/mysql-test/suite/innodb/r/instant_alter.result b/mysql-test/suite/innodb/r/instant_alter.result
index 07160ff91dd..19a59dfa171 100644
--- a/mysql-test/suite/innodb/r/instant_alter.result
+++ b/mysql-test/suite/innodb/r/instant_alter.result
@@ -615,6 +615,11 @@ DROP TABLE t1;
CREATE TABLE t1 (f1 VARCHAR(1), f2 VARCHAR(2)) ENGINE=InnoDB ROW_FORMAT=REDUNDANT;
ALTER TABLE t1 MODIFY f2 VARCHAR (8) FIRST;
DROP TABLE t1;
+CREATE TABLE t1 (a INT UNIQUE, b INT UNIQUE, PRIMARY KEY(a,b)) ENGINE=InnoDB ROW_FORMAT=REDUNDANT;
+ALTER TABLE t1 DROP PRIMARY KEY;
+ALTER TABLE t1 CHANGE COLUMN a a INT;
+DELETE FROM t1 WHERE a = NULL OR a IS NULL;
+DROP TABLE t1;
CREATE TABLE t1
(id INT PRIMARY KEY, c2 INT UNIQUE,
c3 POINT NOT NULL DEFAULT ST_GeomFromText('POINT(3 4)'),
@@ -1176,6 +1181,11 @@ DROP TABLE t1;
CREATE TABLE t1 (f1 VARCHAR(1), f2 VARCHAR(2)) ENGINE=InnoDB ROW_FORMAT=COMPACT;
ALTER TABLE t1 MODIFY f2 VARCHAR (8) FIRST;
DROP TABLE t1;
+CREATE TABLE t1 (a INT UNIQUE, b INT UNIQUE, PRIMARY KEY(a,b)) ENGINE=InnoDB ROW_FORMAT=COMPACT;
+ALTER TABLE t1 DROP PRIMARY KEY;
+ALTER TABLE t1 CHANGE COLUMN a a INT;
+DELETE FROM t1 WHERE a = NULL OR a IS NULL;
+DROP TABLE t1;
CREATE TABLE t1
(id INT PRIMARY KEY, c2 INT UNIQUE,
c3 POINT NOT NULL DEFAULT ST_GeomFromText('POINT(3 4)'),
@@ -1737,6 +1747,11 @@ DROP TABLE t1;
CREATE TABLE t1 (f1 VARCHAR(1), f2 VARCHAR(2)) ENGINE=InnoDB ROW_FORMAT=DYNAMIC;
ALTER TABLE t1 MODIFY f2 VARCHAR (8) FIRST;
DROP TABLE t1;
+CREATE TABLE t1 (a INT UNIQUE, b INT UNIQUE, PRIMARY KEY(a,b)) ENGINE=InnoDB ROW_FORMAT=DYNAMIC;
+ALTER TABLE t1 DROP PRIMARY KEY;
+ALTER TABLE t1 CHANGE COLUMN a a INT;
+DELETE FROM t1 WHERE a = NULL OR a IS NULL;
+DROP TABLE t1;
disconnect analyze;
SELECT variable_value-@old_instant instants
FROM information_schema.global_status
diff --git a/mysql-test/suite/innodb/t/instant_alter.test b/mysql-test/suite/innodb/t/instant_alter.test
index db2915479ce..a65f994f238 100644
--- a/mysql-test/suite/innodb/t/instant_alter.test
+++ b/mysql-test/suite/innodb/t/instant_alter.test
@@ -490,6 +490,13 @@ eval CREATE TABLE t1 (f1 VARCHAR(1), f2 VARCHAR(2)) $engine;
ALTER TABLE t1 MODIFY f2 VARCHAR (8) FIRST;
DROP TABLE t1;
+# MDEV-18035 Failing assertion on DELETE
+eval CREATE TABLE t1 (a INT UNIQUE, b INT UNIQUE, PRIMARY KEY(a,b)) $engine;
+ALTER TABLE t1 DROP PRIMARY KEY;
+ALTER TABLE t1 CHANGE COLUMN a a INT;
+DELETE FROM t1 WHERE a = NULL OR a IS NULL;
+DROP TABLE t1;
+
dec $format;
}
disconnect analyze;
diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc
index 4d9eb00995e..5be9e2d7303 100644
--- a/storage/innobase/handler/handler0alter.cc
+++ b/storage/innobase/handler/handler0alter.cc
@@ -1372,13 +1372,15 @@ check_v_col_in_order(
/** Determine if an instant operation is possible for altering columns.
@param[in] ib_table InnoDB table definition
@param[in] ha_alter_info the ALTER TABLE operation
-@param[in] table table definition before ALTER TABLE */
+@param[in] table table definition before ALTER TABLE
+@param[in] table table definition after ALTER TABLE */
static
bool
instant_alter_column_possible(
const dict_table_t& ib_table,
const Alter_inplace_info* ha_alter_info,
- const TABLE* table)
+ const TABLE* table,
+ const TABLE* altered_table)
{
if (!ib_table.supports_instant()) {
return false;
@@ -1470,10 +1472,36 @@ instant_alter_column_possible(
return false;
}
- if ((ha_alter_info->handler_flags
- & ALTER_COLUMN_NULLABLE)
- && ib_table.not_redundant()) {
- return false;
+ if (ha_alter_info->handler_flags & ALTER_COLUMN_NULLABLE) {
+ if (ib_table.not_redundant()) {
+ return false;
+ }
+
+ const dict_index_t* pk = ib_table.indexes.start;
+ Field** af = altered_table->field;
+ Field** const end = altered_table->field
+ + altered_table->s->fields;
+ for (unsigned c = 0; af < end; af++) {
+ if (!(*af)->stored_in_db()) {
+ continue;
+ }
+
+ const dict_col_t* col = dict_table_get_nth_col(
+ &ib_table, c++);
+
+ if (!col->ord_part || col->is_nullable()
+ || !(*af)->real_maybe_null()) {
+ continue;
+ }
+
+ /* The column would be changed from NOT NULL.
+ Ensure that it is not a clustered index key. */
+ for (auto i = pk->n_uniq; i--; ) {
+ if (pk->fields[i].col == col) {
+ return false;
+ }
+ }
+ }
}
return true;
@@ -1784,7 +1812,7 @@ ha_innobase::check_if_supported_inplace_alter(
}
const bool supports_instant = instant_alter_column_possible(
- *m_prebuilt->table, ha_alter_info, table);
+ *m_prebuilt->table, ha_alter_info, table, altered_table);
bool add_drop_v_cols = false;
/* If there is add or drop virtual columns, we will support operations
@@ -6285,7 +6313,7 @@ new_clustered_failed:
|| !ctx->new_table->persistent_autoinc);
if (ctx->need_rebuild() && instant_alter_column_possible(
- *user_table, ha_alter_info, old_table)
+ *user_table, ha_alter_info, old_table, altered_table)
#if 1 // MDEV-17459: adjust fts_fetch_doc_from_rec() and friends; remove this
&& !innobase_fulltext_exist(altered_table)
#endif