summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThirunarayanan Balathandayuthapani <thiru@mariadb.com>2021-06-10 15:38:14 +0530
committerThirunarayanan Balathandayuthapani <thiru@mariadb.com>2021-06-10 15:38:46 +0530
commitc5489d07655a968bcdfa29f064f2ed13f0abdf62 (patch)
tree7321270fc229fccc3aa7109f038bf9162fc3957d
parent396864c6b3d2cca9962f7eb58964f50ed6b612dc (diff)
downloadmariadb-git-bb-10.2-MDEV-25872.tar.gz
MDEV-25872 InnoDB: Assertion failure in row_merge_read_clustered_index upon ALTER on table with indexed virtual columnsbb-10.2-MDEV-25872
InnoDB fails to check DB_COMPUTE_VALUE_FAILED error in row_merge_read_clustered_index() and wrongly asserts that the buffer shouldn't be ran out of memory. Alter table should give warning when the column value is being truncated.
-rw-r--r--mysql-test/suite/gcol/r/gcol_keys_innodb.result2
-rw-r--r--mysql-test/suite/gcol/r/innodb_virtual_index.result20
-rw-r--r--mysql-test/suite/gcol/t/innodb_virtual_index.opt1
-rw-r--r--mysql-test/suite/gcol/t/innodb_virtual_index.test21
-rw-r--r--mysql-test/suite/innodb/r/innodb-alter.result8
-rw-r--r--sql/sql_table.cc8
-rw-r--r--storage/innobase/row/row0merge.cc17
7 files changed, 67 insertions, 10 deletions
diff --git a/mysql-test/suite/gcol/r/gcol_keys_innodb.result b/mysql-test/suite/gcol/r/gcol_keys_innodb.result
index 5a29c64bc20..37b350c0c32 100644
--- a/mysql-test/suite/gcol/r/gcol_keys_innodb.result
+++ b/mysql-test/suite/gcol/r/gcol_keys_innodb.result
@@ -691,6 +691,8 @@ a b c
1 127 0
SET STATEMENT sql_mode = 'NO_ENGINE_SUBSTITUTION' FOR
ALTER TABLE t ADD UNIQUE INDEX (c(1));
+Warnings:
+Warning 1264 Out of range value for column 'b' at row 1
SELECT * FROM t WHERE c = '0';
a b c
1 127 0
diff --git a/mysql-test/suite/gcol/r/innodb_virtual_index.result b/mysql-test/suite/gcol/r/innodb_virtual_index.result
index 20311a21136..ff339280e8a 100644
--- a/mysql-test/suite/gcol/r/innodb_virtual_index.result
+++ b/mysql-test/suite/gcol/r/innodb_virtual_index.result
@@ -266,3 +266,23 @@ CHECK TABLE t1;
Table Op Msg_type Msg_text
test.t1 check status OK
DROP TABLE t1;
+#
+# MDEV-25872 InnoDB: Assertion failure in row_merge_read_clustered_index
+# upon ALTER on table with indexed virtual columns
+#
+CREATE TABLE t1 (
+id BIGINT AUTO_INCREMENT PRIMARY KEY,
+a INT,
+va INT ZEROFILL AS (a) VIRTUAL,
+b TIMESTAMP,
+c CHAR(204),
+vc CHAR(8),
+KEY(vc,c(64),b,va)
+) ENGINE=InnoDB CHARACTER SET utf32;
+INSERT INTO t1 (id) SELECT NULL FROM seq_1_to_75;
+INSERT IGNORE INTO t1 (id, a) VALUES (NULL, -1);
+Warnings:
+Warning 1264 Out of range value for column 'va' at row 1
+ALTER TABLE t1 FORCE;
+ERROR 22003: Out of range value for column 'va' at row 1
+DROP TABLE t1;
diff --git a/mysql-test/suite/gcol/t/innodb_virtual_index.opt b/mysql-test/suite/gcol/t/innodb_virtual_index.opt
new file mode 100644
index 00000000000..c3f4a891cca
--- /dev/null
+++ b/mysql-test/suite/gcol/t/innodb_virtual_index.opt
@@ -0,0 +1 @@
+--innodb_sort_buffer_size=64k
diff --git a/mysql-test/suite/gcol/t/innodb_virtual_index.test b/mysql-test/suite/gcol/t/innodb_virtual_index.test
index 353841840dc..9e765ca104c 100644
--- a/mysql-test/suite/gcol/t/innodb_virtual_index.test
+++ b/mysql-test/suite/gcol/t/innodb_virtual_index.test
@@ -1,4 +1,5 @@
--source include/have_innodb.inc
+--source include/have_sequence.inc
# Ensure that the history list length will actually be decremented by purge.
SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency;
@@ -281,3 +282,23 @@ ROLLBACK;
SELECT * FROM t1;
CHECK TABLE t1;
DROP TABLE t1;
+
+--echo #
+--echo # MDEV-25872 InnoDB: Assertion failure in row_merge_read_clustered_index
+--echo # upon ALTER on table with indexed virtual columns
+--echo #
+
+CREATE TABLE t1 (
+ id BIGINT AUTO_INCREMENT PRIMARY KEY,
+ a INT,
+ va INT ZEROFILL AS (a) VIRTUAL,
+ b TIMESTAMP,
+ c CHAR(204),
+ vc CHAR(8),
+ KEY(vc,c(64),b,va)
+) ENGINE=InnoDB CHARACTER SET utf32;
+INSERT INTO t1 (id) SELECT NULL FROM seq_1_to_75;
+INSERT IGNORE INTO t1 (id, a) VALUES (NULL, -1);
+--error ER_WARN_DATA_OUT_OF_RANGE
+ALTER TABLE t1 FORCE;
+DROP TABLE t1;
diff --git a/mysql-test/suite/innodb/r/innodb-alter.result b/mysql-test/suite/innodb/r/innodb-alter.result
index 80cf14c1725..53e6c95af0f 100644
--- a/mysql-test/suite/innodb/r/innodb-alter.result
+++ b/mysql-test/suite/innodb/r/innodb-alter.result
@@ -1041,7 +1041,9 @@ CREATE TABLE t1 (a INT NOT NULL DEFAULT 0) ENGINE=InnoDB;
iNSERT INTO t1 VALUES (10);
ALTER TABLE t1 ADD b DATE NOT NULL DEFAULT if(unix_timestamp()>1,TIMESTAMP'2001-01-01 10:20:30',0);
affected rows: 0
-info: Records: 0 Duplicates: 0 Warnings: 0
+info: Records: 0 Duplicates: 0 Warnings: 1
+Warnings:
+Note 1265 Data truncated for column 'b' at row 1
SELECT * FROM t1;
a b
10 2001-01-01
@@ -1050,7 +1052,9 @@ CREATE TABLE t1 (a INT NOT NULL DEFAULT 0) ENGINE=InnoDB;
iNSERT INTO t1 VALUES (10);
ALTER TABLE t1 ADD b TIME NOT NULL DEFAULT if(unix_timestamp()>1,TIMESTAMP'2001-01-01 10:20:30',0);
affected rows: 0
-info: Records: 0 Duplicates: 0 Warnings: 0
+info: Records: 0 Duplicates: 0 Warnings: 1
+Warnings:
+Note 1265 Data truncated for column 'b' at row 1
SELECT * FROM t1;
a b
10 10:20:30
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 3a3a903bc35..9556cb9f136 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -9680,9 +9680,17 @@ do_continue:;
if (use_inplace)
{
table->s->frm_image= &frm;
+ enum_check_fields save_count_cuted_fields= thd->count_cuted_fields;
+ /*
+ Set the truncated column values of thd as warning for alter table.
+ */
+ thd->count_cuted_fields= CHECK_FIELD_WARN;
int res= mysql_inplace_alter_table(thd, table_list, table, altered_table,
&ha_alter_info, inplace_supported,
&target_mdl_request, &alter_ctx);
+
+ thd->count_cuted_fields= save_count_cuted_fields;
+
my_free(const_cast<uchar*>(frm.str));
if (res)
diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc
index e3b3f2c2762..b2091c162a9 100644
--- a/storage/innobase/row/row0merge.cc
+++ b/storage/innobase/row/row0merge.cc
@@ -2561,21 +2561,22 @@ write_buffers:
that the buffer has been written out
and emptied. */
- if (UNIV_UNLIKELY
- (!(rows_added = row_merge_buf_add(
+ rows_added = row_merge_buf_add(
buf, fts_index, old_table,
new_table, psort_info, row, ext,
- &doc_id, conv_heap,
- &err, &v_heap, eval_table, trx)))) {
- /* An empty buffer should have enough
- room for at least one record. */
- ut_error;
- }
+ &doc_id, conv_heap, &err, &v_heap,
+ eval_table, trx);
if (err != DB_SUCCESS) {
break;
}
+ if (rows_added == 0) {
+ /* An empty buffer should have enough
+ room for at least one record. */
+ ut_error;
+ }
+
file->n_rec += rows_added;
}
}