diff --git a/mysql-test/suite/vcol/r/vcol_keys_innodb.result b/mysql-test/suite/vcol/r/vcol_keys_innodb.result index 398e447b819..41c5ffd748a 100644 --- a/mysql-test/suite/vcol/r/vcol_keys_innodb.result +++ b/mysql-test/suite/vcol/r/vcol_keys_innodb.result @@ -364,5 +364,21 @@ disconnect con1; connection default; drop table t; # +# MDEV-41667 InnoDB: Failing assertion: buf <= (byte*) +# original_upd_buff + buff_len +# +CREATE TABLE t1 (a INT PRIMARY KEY, b BIGINT NOT NULL , v1 BIGINT AS (b+1) VIRTUAL, KEY(v1), v2 BIGINT AS (b+2) VIRTUAL, KEY(v2), v3 BIGINT AS (b+3) VIRTUAL, KEY(v3), v4 BIGINT AS (b+4) VIRTUAL, KEY(v4), v5 BIGINT AS (b+5) VIRTUAL, KEY(v5), v6 BIGINT AS (b+6) VIRTUAL, KEY(v6), v7 BIGINT AS (b+7) VIRTUAL, KEY(v7), v8 BIGINT AS (b+8) VIRTUAL, KEY(v8), v9 BIGINT AS (b+9) VIRTUAL, KEY(v9), v10 BIGINT AS (b+10) VIRTUAL, KEY(v10), v11 BIGINT AS (b+11) VIRTUAL, KEY(v11), v12 BIGINT AS (b+12) VIRTUAL, KEY(v12), v13 BIGINT AS (b+13) VIRTUAL, KEY(v13), v14 BIGINT AS (b+14) VIRTUAL, KEY(v14), v15 BIGINT AS (b+15) VIRTUAL, KEY(v15), v16 BIGINT AS (b+16) VIRTUAL, KEY(v16), v17 BIGINT AS (b+17) VIRTUAL, KEY(v17), v18 BIGINT AS (b+18) VIRTUAL, KEY(v18), v19 BIGINT AS (b+19) VIRTUAL, KEY(v19), v20 BIGINT AS (b+20) VIRTUAL, KEY(v20), v21 BIGINT AS (b+21) VIRTUAL, KEY(v21), v22 BIGINT AS (b+22) VIRTUAL, KEY(v22), v23 BIGINT AS (b+23) VIRTUAL, KEY(v23), v24 BIGINT AS (b+24) VIRTUAL, KEY(v24), v25 BIGINT AS (b+25) VIRTUAL, KEY(v25), v26 BIGINT AS (b+26) VIRTUAL, KEY(v26), v27 BIGINT AS (b+27) VIRTUAL, KEY(v27), v28 BIGINT AS (b+28) VIRTUAL, KEY(v28), v29 BIGINT AS (b+29) VIRTUAL, KEY(v29), v30 BIGINT AS (b+30) VIRTUAL, KEY(v30), v31 BIGINT AS (b+31) VIRTUAL, KEY(v31), v32 BIGINT AS (b+32) VIRTUAL, KEY(v32)) ENGINE=InnoDB; +INSERT INTO t1 (a,b) VALUES (1,10),(2,20); +UPDATE t1 SET b=11 WHERE a=1; +UPDATE t1 SET b=b+100; +SELECT a, b, v1, v32 FROM t1; +a b v1 v32 +1 111 112 143 +2 120 121 152 +CHECK TABLE t1; +Table Op Msg_type Msg_text +test.t1 check status OK +DROP TABLE t1; +# # End of 10.11 tests # diff --git a/mysql-test/suite/vcol/t/vcol_keys_innodb.test b/mysql-test/suite/vcol/t/vcol_keys_innodb.test index 12750f8e48c..f12e6fc7b5d 100644 --- a/mysql-test/suite/vcol/t/vcol_keys_innodb.test +++ b/mysql-test/suite/vcol/t/vcol_keys_innodb.test @@ -197,6 +197,26 @@ disconnect con1; connection default; drop table t; +--echo # +--echo # MDEV-41667 InnoDB: Failing assertion: buf <= (byte*) +--echo # original_upd_buff + buff_len +--echo # +let $n= 32; +let $cols= ; +let $i= 1; +while ($i <= $n) +{ + let $cols= $cols, v$i BIGINT AS (b+$i) VIRTUAL, KEY(v$i); + inc $i; +} +eval CREATE TABLE t1 (a INT PRIMARY KEY, b BIGINT NOT NULL $cols) ENGINE=InnoDB; +INSERT INTO t1 (a,b) VALUES (1,10),(2,20); +UPDATE t1 SET b=11 WHERE a=1; +UPDATE t1 SET b=b+100; +SELECT a, b, v1, v32 FROM t1; +CHECK TABLE t1; +DROP TABLE t1; + --echo # --echo # End of 10.11 tests --echo # diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 338173c71e7..2f06c4adc80 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -8266,7 +8266,7 @@ calc_row_difference( const uchar* new_row, TABLE* table, uchar* upd_buff, - ulint buff_len, + size_t buff_len, row_prebuilt_t* prebuilt, ib_uint64_t& auto_inc) { @@ -8799,6 +8799,21 @@ ha_innobase::update_row( m_upd_buf_size = table->s->reclength + table->s->max_key_length + MAX_REF_PARTS * 3; + /* Reserve an extra packed value for every + virtual column. calc_row_difference() may retain + both new and old values for indexed virtual + columns, including columns indexed by an online + rebuild. + The buffer is reused, so its capacity must also + cover virtual columns that become indexed + after the initial allocation. */ + for (uint i = 0; i < table->s->fields; i++) { + Field *field = table->field[i]; + if (!field->stored_in_db()) { + m_upd_buf_size += field->pack_length(); + } + } + m_upd_buf = reinterpret_cast( my_malloc(PSI_INSTRUMENT_ME, m_upd_buf_size, diff --git a/storage/innobase/handler/ha_innodb.h b/storage/innobase/handler/ha_innodb.h index c6d3ffa8c3f..bea4a15ce0f 100644 --- a/storage/innobase/handler/ha_innodb.h +++ b/storage/innobase/handler/ha_innodb.h @@ -518,7 +518,7 @@ protected: uchar* m_upd_buf; /** the size of upd_buf in bytes */ - ulint m_upd_buf_size; + size_t m_upd_buf_size; /** Flags that specificy the handler instance (table) capability. */ Table_flags m_int_table_flags;