summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugene Kosov <eugene.kosov@mariadb.com>2022-02-01 17:40:35 +0600
committerEugene Kosov <eugene.kosov@mariadb.com>2022-02-03 01:47:46 +0600
commitab2414a6ceb376a8c03569a7d63d747ff215afdc (patch)
tree480eef426165743644b741e2ca0099896c00b5aa
parent12cad0c3468d734e041d4ef0cd5a26d2a28606fc (diff)
downloadmariadb-git-bb-10.4-MDEV-26294-instant-alter-charset.tar.gz
-rw-r--r--mysql-test/suite/innodb/t/1.test48
-rw-r--r--storage/innobase/include/row0merge.h3
-rw-r--r--storage/innobase/rem/rem0rec.cc6
-rw-r--r--storage/innobase/row/row0ftsort.cc2
-rw-r--r--storage/innobase/row/row0log.cc20
-rw-r--r--storage/innobase/row/row0merge.cc38
6 files changed, 107 insertions, 10 deletions
diff --git a/mysql-test/suite/innodb/t/1.test b/mysql-test/suite/innodb/t/1.test
new file mode 100644
index 00000000000..c974b88a02f
--- /dev/null
+++ b/mysql-test/suite/innodb/t/1.test
@@ -0,0 +1,48 @@
+--source include/have_innodb.inc
+
+# CREATE TABLE t1 (
+# id INT PRIMARY KEY,
+# msg VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_bin,
+# UNIQUE(msg)
+# ) ENGINE=INNODB;
+
+# INSERT INTO t1 VALUES (1, 'aaa');
+# INSERT INTO t1 VALUES (2, 'AAA');
+
+# # --error ER_DUP_ENTRY
+# # ALTER TABLE t1 MODIFY msg VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci, ALGORITHM=COPY;
+# --error ER_DUP_ENTRY
+# ALTER TABLE t1 MODIFY msg VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci, ALGORITHM=NOCOPY;
+
+# # ALTER TABLE t1 MODIFY msg VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci, FORCE, ALGORITHM=INPLACE;
+
+# DROP TABLE t1;
+
+
+CREATE TABLE t1 (
+ id INT PRIMARY KEY,
+ msg VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_bin,
+ UNIQUE(msg)
+) ENGINE=INNODB;
+
+INSERT INTO t1 VALUES (1, 'aaa');
+
+SET DEBUG_SYNC = 'RESET';
+SET DEBUG_SYNC = 'row_log_apply_before SIGNAL before_apply WAIT_FOR go_ahead';
+--send
+ALTER TABLE t1 MODIFY msg VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci, ALGORITHM=NOCOPY;
+
+connect (con1,localhost,root,,);
+connection con1;
+
+SET DEBUG_SYNC = 'now WAIT_FOR before_apply';
+INSERT INTO t1 VALUES (2, 'AAA');
+SET DEBUG_SYNC = 'now SIGNAL go_ahead';
+SET DEBUG_SYNC = 'RESET';
+
+connection default;
+
+--error ER_DUP_ENTRY
+reap;
+
+DROP TABLE t1;
diff --git a/storage/innobase/include/row0merge.h b/storage/innobase/include/row0merge.h
index 3252af0062b..c8ee7430205 100644
--- a/storage/innobase/include/row0merge.h
+++ b/storage/innobase/include/row0merge.h
@@ -94,6 +94,7 @@ struct row_merge_buf_t {
mtuple_t* tuples; /*!< array of data tuples */
mtuple_t* tmp_tuples; /*!< temporary copy of tuples,
for sorting */
+ unsigned* prtype_list;
};
/** Information about temporary files used in merge sort */
@@ -431,7 +432,7 @@ Allocate a sort buffer.
row_merge_buf_t*
row_merge_buf_create(
/*=================*/
- dict_index_t* index) /*!< in: secondary index */
+ dict_index_t* index, const TABLE *mariadb_table) /*!< in: secondary index */
MY_ATTRIBUTE((warn_unused_result, nonnull, malloc));
/*********************************************************************//**
diff --git a/storage/innobase/rem/rem0rec.cc b/storage/innobase/rem/rem0rec.cc
index 08682304410..bcc683449f2 100644
--- a/storage/innobase/rem/rem0rec.cc
+++ b/storage/innobase/rem/rem0rec.cc
@@ -1198,9 +1198,9 @@ rec_get_converted_size_comp_prefix_low(
field->col, &dfield->type));
}
} else {
- ut_ad(field->col->is_dropped()
- || dict_col_type_assert_equal(field->col,
- &dfield->type));
+ // ut_ad(field->col->is_dropped()
+ // || dict_col_type_assert_equal(field->col,
+ // &dfield->type));
}
#endif
diff --git a/storage/innobase/row/row0ftsort.cc b/storage/innobase/row/row0ftsort.cc
index 8d1dbad22cb..707945786cd 100644
--- a/storage/innobase/row/row0ftsort.cc
+++ b/storage/innobase/row/row0ftsort.cc
@@ -245,7 +245,7 @@ row_fts_psort_info_init(
}
psort_info[j].merge_buf[i] = row_merge_buf_create(
- dup->index);
+ dup->index, dup->table);
if (row_merge_file_create(psort_info[j].merge_file[i],
path) == OS_FILE_CLOSED) {
diff --git a/storage/innobase/row/row0log.cc b/storage/innobase/row/row0log.cc
index c0396c33cc4..6040b690c8e 100644
--- a/storage/innobase/row/row0log.cc
+++ b/storage/innobase/row/row0log.cc
@@ -3652,6 +3652,26 @@ corrupted:
indexes, which never contain off-page columns. */
ut_ad(dtuple_get_n_ext(entry) == 0);
+ for (unsigned i = 0; i < index->n_fields; i++) {
+ if (index->fields[i].col->mtype != DATA_VARMYSQL) {
+ continue;
+ }
+
+ auto *field_name = static_cast<const char*>(index->fields[i].name);
+
+ for (uint j = 0; j < dup->table->s->fields; j++) {
+ if (!strcmp(field_name, dup->table->field[j]->field_name.str)) {
+ ut_ad(dup->table->field[j]->type() == MYSQL_TYPE_VARCHAR);
+ auto *field = static_cast<Field_varstring*>(dup->table->field[j]);
+ uint cs_number= field->charset()->number;
+ entry->fields[i].type.prtype &= ~((uint) CHAR_COLL_MASK << 16);
+ entry->fields[i].type.prtype |= cs_number << 16;
+ break;
+ }
+
+ }
+ }
+
row_log_apply_op_low(index, dup, error, offsets_heap,
has_index_lock, op, trx_id, entry);
return(mrec);
diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc
index a81e47edaf5..2f5777b188b 100644
--- a/storage/innobase/row/row0merge.cc
+++ b/storage/innobase/row/row0merge.cc
@@ -338,7 +338,7 @@ row_merge_buf_create_low(
dict_index_t* index, /*!< in: secondary index */
ulint max_tuples, /*!< in: maximum number of
data tuples */
- ulint buf_size) /*!< in: size of the buffer,
+ ulint buf_size, const TABLE* mariadb_table) /*!< in: size of the buffer,
in bytes */
{
row_merge_buf_t* buf;
@@ -354,6 +354,29 @@ row_merge_buf_create_low(
buf->tuples = static_cast<mtuple_t*>(
ut_malloc_nokey(2 * max_tuples * sizeof *buf->tuples));
buf->tmp_tuples = buf->tuples + max_tuples;
+ buf->prtype_list = static_cast<unsigned*>(mem_heap_zalloc(heap,
+ sizeof(unsigned) * index->n_fields));
+
+ for (unsigned i = 0; i< index->n_fields; i++) {
+ if (index->fields[i].col->mtype != DATA_VARMYSQL) {
+ continue;
+ }
+
+ auto *field_name = static_cast<const char*>(
+ index->fields[i].name);
+
+ for (uint j = 0; j < mariadb_table->s->fields; j++) {
+ Field* field = mariadb_table->field[j];
+ if (!strcmp(field_name, field->field_name.str)) {
+ ut_ad(field->type() == MYSQL_TYPE_VARCHAR);
+ uint cs_number = field->charset()->number;
+ auto& prtype = buf->prtype_list[i];
+ prtype = index->fields[i].col->prtype;
+ prtype &= ~((uint) CHAR_COLL_MASK << 16);
+ prtype |= cs_number << 16;
+ }
+ }
+ }
return(buf);
}
@@ -364,7 +387,7 @@ Allocate a sort buffer.
row_merge_buf_t*
row_merge_buf_create(
/*=================*/
- dict_index_t* index) /*!< in: secondary index */
+ dict_index_t* index, const TABLE *mariadb_table) /*!< in: secondary index */
{
row_merge_buf_t* buf;
ulint max_tuples;
@@ -379,7 +402,8 @@ row_merge_buf_create(
heap = mem_heap_create(buf_size);
- buf = row_merge_buf_create_low(heap, index, max_tuples, buf_size);
+ buf = row_merge_buf_create_low(heap, index, max_tuples, buf_size,
+ mariadb_table);
return(buf);
}
@@ -709,6 +733,10 @@ error:
ut_ad(index->table->not_redundant());
}
}
+
+ if (buf->prtype_list[i]) {
+ field->type.prtype = buf->prtype_list[i];
+ }
}
len = dfield_get_len(field);
@@ -1778,7 +1806,7 @@ row_merge_read_clustered_index(
fts_index = index[i];
- merge_buf[i] = row_merge_buf_create(fts_sort_idx);
+ merge_buf[i] = row_merge_buf_create(fts_sort_idx, table);
add_doc_id = DICT_TF2_FLAG_IS_SET(
new_table, DICT_TF2_FTS_ADD_DOC_ID);
@@ -1801,7 +1829,7 @@ row_merge_read_clustered_index(
num_spatial++;
}
- merge_buf[i] = row_merge_buf_create(index[i]);
+ merge_buf[i] = row_merge_buf_create(index[i], table);
}
}