MDEV-25872 InnoDB: Assertion failure in row_merge_read_clustered_index upon...

MDEV-25872 InnoDB: Assertion failure in row_merge_read_clustered_index upon ALTER on table with indexed virtual columns

- 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.
parent 8c7d8b71
...@@ -691,6 +691,8 @@ a b c ...@@ -691,6 +691,8 @@ a b c
1 127 0 1 127 0
SET STATEMENT sql_mode = 'NO_ENGINE_SUBSTITUTION' FOR SET STATEMENT sql_mode = 'NO_ENGINE_SUBSTITUTION' FOR
ALTER TABLE t ADD UNIQUE INDEX (c(1)); 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'; SELECT * FROM t WHERE c = '0';
a b c a b c
1 127 0 1 127 0
......
...@@ -266,3 +266,23 @@ CHECK TABLE t1; ...@@ -266,3 +266,23 @@ CHECK TABLE t1;
Table Op Msg_type Msg_text Table Op Msg_type Msg_text
test.t1 check status OK test.t1 check status OK
DROP TABLE t1; 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;
--source include/have_innodb.inc --source include/have_innodb.inc
--source include/have_sequence.inc
# Ensure that the history list length will actually be decremented by purge. # Ensure that the history list length will actually be decremented by purge.
SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency; SET @saved_frequency = @@GLOBAL.innodb_purge_rseg_truncate_frequency;
...@@ -281,3 +282,23 @@ ROLLBACK; ...@@ -281,3 +282,23 @@ ROLLBACK;
SELECT * FROM t1; SELECT * FROM t1;
CHECK TABLE t1; CHECK TABLE t1;
DROP 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;
...@@ -1041,7 +1041,9 @@ CREATE TABLE t1 (a INT NOT NULL DEFAULT 0) ENGINE=InnoDB; ...@@ -1041,7 +1041,9 @@ CREATE TABLE t1 (a INT NOT NULL DEFAULT 0) ENGINE=InnoDB;
iNSERT INTO t1 VALUES (10); 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); ALTER TABLE t1 ADD b DATE NOT NULL DEFAULT if(unix_timestamp()>1,TIMESTAMP'2001-01-01 10:20:30',0);
affected rows: 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; SELECT * FROM t1;
a b a b
10 2001-01-01 10 2001-01-01
...@@ -1050,7 +1052,9 @@ CREATE TABLE t1 (a INT NOT NULL DEFAULT 0) ENGINE=InnoDB; ...@@ -1050,7 +1052,9 @@ CREATE TABLE t1 (a INT NOT NULL DEFAULT 0) ENGINE=InnoDB;
iNSERT INTO t1 VALUES (10); 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); ALTER TABLE t1 ADD b TIME NOT NULL DEFAULT if(unix_timestamp()>1,TIMESTAMP'2001-01-01 10:20:30',0);
affected rows: 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; SELECT * FROM t1;
a b a b
10 10:20:30 10 10:20:30
......
...@@ -9680,9 +9680,17 @@ do_continue:; ...@@ -9680,9 +9680,17 @@ do_continue:;
if (use_inplace) if (use_inplace)
{ {
table->s->frm_image= &frm; 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, int res= mysql_inplace_alter_table(thd, table_list, table, altered_table,
&ha_alter_info, inplace_supported, &ha_alter_info, inplace_supported,
&target_mdl_request, &alter_ctx); &target_mdl_request, &alter_ctx);
thd->count_cuted_fields= save_count_cuted_fields;
my_free(const_cast<uchar*>(frm.str)); my_free(const_cast<uchar*>(frm.str));
if (res) if (res)
......
...@@ -524,7 +524,9 @@ row_merge_buf_add( ...@@ -524,7 +524,9 @@ row_merge_buf_add(
DBUG_ENTER("row_merge_buf_add"); DBUG_ENTER("row_merge_buf_add");
if (buf->n_tuples >= buf->max_tuples) { if (buf->n_tuples >= buf->max_tuples) {
DBUG_RETURN(0); error:
n_row_added = 0;
goto end;
} }
DBUG_EXECUTE_IF( DBUG_EXECUTE_IF(
...@@ -845,11 +847,6 @@ row_merge_buf_add( ...@@ -845,11 +847,6 @@ row_merge_buf_add(
if (vcol_storage.innobase_record) if (vcol_storage.innobase_record)
innobase_free_row_for_vcol(&vcol_storage); innobase_free_row_for_vcol(&vcol_storage);
DBUG_RETURN(n_row_added); DBUG_RETURN(n_row_added);
error:
if (vcol_storage.innobase_record)
innobase_free_row_for_vcol(&vcol_storage);
DBUG_RETURN(0);
} }
/*************************************************************//** /*************************************************************//**
...@@ -2569,15 +2566,17 @@ row_merge_read_clustered_index( ...@@ -2569,15 +2566,17 @@ row_merge_read_clustered_index(
&err, &v_heap, eval_table, trx)))) { &err, &v_heap, eval_table, trx)))) {
/* An empty buffer should have enough /* An empty buffer should have enough
room for at least one record. */ room for at least one record. */
ut_error; ut_ad(err == DB_COMPUTE_VALUE_FAILED
|| err == DB_OUT_OF_MEMORY
|| err == DB_TOO_BIG_RECORD);
} else if (err == DB_SUCCESS) {
file->n_rec += rows_added;
continue;
} }
if (err != DB_SUCCESS) { trx->error_key_num = i;
break; break;
} }
file->n_rec += rows_added;
}
} }
if (row == NULL) { if (row == NULL) {
......
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