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

Enforce the limit on the maximum number of fields

parent 1e8e4140
SET @old_instant=
(SELECT variable_value FROM information_schema.global_status
WHERE variable_name = 'innodb_instant_alter_column');
CREATE TABLE t(a INT PRIMARY KEY, b253 INT, c253 INT, d253 INT, e253 INT)
ENGINE=InnoDB;
INSERT INTO t VALUES(1,2,3,4,5);
SELECT * FROM t;
b0 d0 a c0 e0
NULL NULL 1 NULL NULL
ALTER TABLE t DROP b0, DROP c0, DROP d0, DROP e0,
ADD COLUMN b INT, ALGORITHM=INSTANT;
ERROR 0A000: ALGORITHM=INSTANT is not supported for this operation. Try ALGORITHM=INPLACE
ALTER TABLE t CHANGE COLUMN b0 b INT AFTER a, ALGORITHM=INSTANT;
ALTER TABLE t DROP e0, DROP c0, DROP d0, ALGORITHM=INSTANT;
SELECT * FROM t;
a b
1 NULL
ALTER TABLE t DROP COLUMN b, ALGORITHM=INSTANT;
ALTER TABLE t ADD COLUMN b INT, ALGORITHM=INSTANT;
ERROR 0A000: ALGORITHM=INSTANT is not supported for this operation. Try ALGORITHM=INPLACE
SELECT variable_value-@old_instant instants
FROM information_schema.global_status
WHERE variable_name = 'innodb_instant_alter_column';
instants
256
ALTER TABLE t ADD COLUMN b INT;
SELECT variable_value-@old_instant instants
FROM information_schema.global_status
WHERE variable_name = 'innodb_instant_alter_column';
instants
256
SELECT * FROM t;
a b
1 NULL
DROP TABLE t;
--source include/have_innodb.inc
SET @old_instant=
(SELECT variable_value FROM information_schema.global_status
WHERE variable_name = 'innodb_instant_alter_column');
CREATE TABLE t(a INT PRIMARY KEY, b INT, c INT, d INT, e INT)
ENGINE=InnoDB;
INSERT INTO t VALUES(1,2,3,4,5);
--disable_query_log
let $n=253;
while ($n) {
dec $n;
ALTER TABLE t DROP b, DROP c, DROP d, DROP e,
ADD COLUMN b INT FIRST, ADD COLUMN c INT, ADD COLUMN d INT AFTER b,
ADD COLUMN e INT AFTER c, ALGORITHM=INSTANT;
}
--enable_query_log
SELECT * FROM t;
--error ER_ALTER_OPERATION_NOT_SUPPORTED
ALTER TABLE t DROP b, DROP c, DROP d, DROP e,
ADD COLUMN b INT, ALGORITHM=INSTANT;
ALTER TABLE t CHANGE COLUMN b beta INT AFTER a, ALGORITHM=INSTANT;
ALTER TABLE t DROP e, DROP c, DROP d, ALGORITHM=INSTANT;
SELECT * FROM t;
ALTER TABLE t DROP COLUMN beta, ALGORITHM=INSTANT;
--error ER_ALTER_OPERATION_NOT_SUPPORTED
ALTER TABLE t ADD COLUMN b INT NOT NULL, ALGORITHM=INSTANT;
SELECT variable_value-@old_instant instants
FROM information_schema.global_status
WHERE variable_name = 'innodb_instant_alter_column';
ALTER TABLE t ADD COLUMN b INT NOT NULL;
SELECT variable_value-@old_instant instants
FROM information_schema.global_status
WHERE variable_name = 'innodb_instant_alter_column';
SELECT * FROM t;
DROP TABLE t;
......@@ -9462,12 +9462,14 @@ ha_innobase::change_active_index(
}
#endif
} else {
dtuple_set_n_fields(m_prebuilt->search_tuple,
m_prebuilt->index->n_fields);
ulint n_fields = dict_index_get_n_unique_in_tree(
m_prebuilt->index);
dtuple_set_n_fields(m_prebuilt->search_tuple, n_fields);
dict_index_copy_types(
m_prebuilt->search_tuple, m_prebuilt->index,
m_prebuilt->index->n_fields);
n_fields);
/* If it's FTS query and FTS_DOC_ID exists FTS_DOC_ID field is
always added to read_set. */
......
......@@ -883,14 +883,47 @@ 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 */
static
bool
instant_alter_column_possible(
const dict_table_t& ib_table,
const Alter_inplace_info* ha_alter_info,
const TABLE* table)
{
if (!ib_table.supports_instant()) {
return false;
}
#if 1 // MDEV-17459: adjust fts_fetch_doc_from_rec() and friends; remove this
if (ib_table.fts) {
return false;
}
#endif
const dict_index_t* index = ib_table.indexes.start;
if (ha_alter_info->handler_flags & ALTER_ADD_STORED_BASE_COLUMN) {
List_iterator_fast<Create_field> cf_it(
ha_alter_info->alter_info->create_list);
uint n_add = 0;
while (const Create_field* cf = cf_it++) {
n_add += !cf->field;
}
if (index->n_fields >= REC_MAX_N_USER_FIELDS + DATA_N_SYS_COLS
- n_add) {
return false;
}
}
#if 1 // MDEV-17468: fix bugs with indexed virtual columns & remove this
ut_ad(index->is_primary());
ut_ad(!index->has_virtual());
while ((index = index->indexes.next) != NULL) {
if (index->has_virtual()) {
ut_ad(ib_table.n_v_cols);
return false;
}
}
#endif
// Making table system-versioned instantly is not implemented yet.
if (ha_alter_info->handler_flags & ALTER_ADD_SYSTEM_VERSIONING) {
return false;
......@@ -1059,21 +1092,6 @@ innobase_fts_check_doc_id_col(
return(false);
}
#if 1 // MDEV-17468: fix bugs with indexed virtual columns & remove this
static bool has_virtual_index(const dict_table_t& table)
{
const dict_index_t* index = table.indexes.start;
ut_ad(!index->has_virtual());
while ((index = index->indexes.next) != NULL) {
if (index->has_virtual()) {
ut_ad(table.n_v_cols);
return true;
}
}
return false;
}
#endif
/** Check if InnoDB supports a particular alter table in-place
@param altered_table TABLE object for new version of table.
@param ha_alter_info Structure describing changes to be done
......@@ -1253,18 +1271,8 @@ ha_innobase::check_if_supported_inplace_alter(
DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
}
const bool supports_instant = m_prebuilt->table->supports_instant()
&& instant_alter_column_possible(ha_alter_info, table)
#if 1 // MDEV-17468: fix bugs with indexed virtual columns & remove this
&& !has_virtual_index(*m_prebuilt->table)
#endif
#if 1 // MDEV-17459: adjust fts_fetch_doc_from_rec() and friends; remove this
&& !m_prebuilt->table->fts
&& !innobase_fulltext_exist(altered_table)
&& !innobase_fulltext_exist(table)
#endif
;
const bool supports_instant = instant_alter_column_possible(
*m_prebuilt->table, ha_alter_info, table);
bool add_drop_v_cols = false;
/* If there is add or drop virtual columns, we will support operations
......@@ -5716,15 +5724,10 @@ prepare_inplace_alter_table_dict(
== !!new_clustered);
}
if (ctx->need_rebuild() && user_table->supports_instant()
&& instant_alter_column_possible(ha_alter_info, old_table)
#if 1 // MDEV-17468: fix bugs with indexed virtual columns & remove this
&& !has_virtual_index(*user_table)
#endif
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
&& !user_table->fts
&& !innobase_fulltext_exist(altered_table)
&& !innobase_fulltext_exist(old_table)
#endif
) {
for (uint a = 0; a < ctx->num_to_add_index; a++) {
......
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