MDEV-20066 Wrong value on instantly added column after DELETE and UPDATE
row_upd_build_difference_binary(): Correctly handle the case where columns (or clustered index fields) have been added since the 'entry' was originally created. In this case, the update vector must replace any missing columns with the default values of the instantly added columns.
This commit is contained in:
parent
f42a23178e
commit
17336f6d30
@ -491,6 +491,29 @@ DELETE FROM t1;
|
||||
COMMIT;
|
||||
InnoDB 0 transactions not purged
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1(a INT PRIMARY KEY) ENGINE=InnoDB ROW_FORMAT=REDUNDANT;
|
||||
INSERT INTO t1 VALUES (7);
|
||||
ALTER TABLE t1 ADD COLUMN c INT NOT NULL DEFAULT 0;
|
||||
ALTER TABLE t1 ADD INDEX (c);
|
||||
BEGIN;
|
||||
DELETE FROM t1;
|
||||
INSERT INTO t1 VALUES (4,0),(7,77);
|
||||
COMMIT;
|
||||
BEGIN;
|
||||
DELETE FROM t1 WHERE a=7;
|
||||
UPDATE t1 SET a=7;
|
||||
COMMIT;
|
||||
SELECT * FROM t1 FORCE INDEX(PRIMARY);
|
||||
a c
|
||||
7 0
|
||||
SELECT * FROM t1 FORCE INDEX(c);
|
||||
a c
|
||||
7 0
|
||||
DELETE FROM t1;
|
||||
CHECK TABLE t1;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 check status OK
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1
|
||||
(id INT PRIMARY KEY, c2 INT UNIQUE,
|
||||
c3 POINT NOT NULL DEFAULT ST_GeomFromText('POINT(3 4)'),
|
||||
@ -927,6 +950,29 @@ DELETE FROM t1;
|
||||
COMMIT;
|
||||
InnoDB 0 transactions not purged
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1(a INT PRIMARY KEY) ENGINE=InnoDB ROW_FORMAT=COMPACT;
|
||||
INSERT INTO t1 VALUES (7);
|
||||
ALTER TABLE t1 ADD COLUMN c INT NOT NULL DEFAULT 0;
|
||||
ALTER TABLE t1 ADD INDEX (c);
|
||||
BEGIN;
|
||||
DELETE FROM t1;
|
||||
INSERT INTO t1 VALUES (4,0),(7,77);
|
||||
COMMIT;
|
||||
BEGIN;
|
||||
DELETE FROM t1 WHERE a=7;
|
||||
UPDATE t1 SET a=7;
|
||||
COMMIT;
|
||||
SELECT * FROM t1 FORCE INDEX(PRIMARY);
|
||||
a c
|
||||
7 0
|
||||
SELECT * FROM t1 FORCE INDEX(c);
|
||||
a c
|
||||
7 0
|
||||
DELETE FROM t1;
|
||||
CHECK TABLE t1;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 check status OK
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1
|
||||
(id INT PRIMARY KEY, c2 INT UNIQUE,
|
||||
c3 POINT NOT NULL DEFAULT ST_GeomFromText('POINT(3 4)'),
|
||||
@ -1363,10 +1409,33 @@ DELETE FROM t1;
|
||||
COMMIT;
|
||||
InnoDB 0 transactions not purged
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1(a INT PRIMARY KEY) ENGINE=InnoDB ROW_FORMAT=DYNAMIC;
|
||||
INSERT INTO t1 VALUES (7);
|
||||
ALTER TABLE t1 ADD COLUMN c INT NOT NULL DEFAULT 0;
|
||||
ALTER TABLE t1 ADD INDEX (c);
|
||||
BEGIN;
|
||||
DELETE FROM t1;
|
||||
INSERT INTO t1 VALUES (4,0),(7,77);
|
||||
COMMIT;
|
||||
BEGIN;
|
||||
DELETE FROM t1 WHERE a=7;
|
||||
UPDATE t1 SET a=7;
|
||||
COMMIT;
|
||||
SELECT * FROM t1 FORCE INDEX(PRIMARY);
|
||||
a c
|
||||
7 0
|
||||
SELECT * FROM t1 FORCE INDEX(c);
|
||||
a c
|
||||
7 0
|
||||
DELETE FROM t1;
|
||||
CHECK TABLE t1;
|
||||
Table Op Msg_type Msg_text
|
||||
test.t1 check status OK
|
||||
DROP TABLE t1;
|
||||
disconnect analyze;
|
||||
SELECT variable_value-@old_instant instants
|
||||
FROM information_schema.global_status
|
||||
WHERE variable_name = 'innodb_instant_alter_column';
|
||||
instants
|
||||
51
|
||||
54
|
||||
SET GLOBAL innodb_purge_rseg_truncate_frequency= @saved_frequency;
|
||||
|
@ -365,6 +365,30 @@ COMMIT;
|
||||
--source include/wait_all_purged.inc
|
||||
DROP TABLE t1;
|
||||
|
||||
#
|
||||
# MDEV-20066 Wrong value on instantly added column after DELETE and UPDATE
|
||||
#
|
||||
|
||||
eval CREATE TABLE t1(a INT PRIMARY KEY) $engine;
|
||||
INSERT INTO t1 VALUES (7);
|
||||
|
||||
ALTER TABLE t1 ADD COLUMN c INT NOT NULL DEFAULT 0;
|
||||
ALTER TABLE t1 ADD INDEX (c);
|
||||
|
||||
BEGIN;
|
||||
DELETE FROM t1;
|
||||
INSERT INTO t1 VALUES (4,0),(7,77);
|
||||
COMMIT;
|
||||
BEGIN;
|
||||
DELETE FROM t1 WHERE a=7;
|
||||
UPDATE t1 SET a=7;
|
||||
COMMIT;
|
||||
SELECT * FROM t1 FORCE INDEX(PRIMARY);
|
||||
SELECT * FROM t1 FORCE INDEX(c);
|
||||
DELETE FROM t1;
|
||||
CHECK TABLE t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
dec $format;
|
||||
}
|
||||
disconnect analyze;
|
||||
|
@ -1049,22 +1049,21 @@ row_upd_build_difference_binary(
|
||||
TABLE* mysql_table,
|
||||
dberr_t* error)
|
||||
{
|
||||
upd_field_t* upd_field;
|
||||
ulint len;
|
||||
upd_t* update;
|
||||
ulint n_diff;
|
||||
ulint trx_id_pos;
|
||||
ulint i;
|
||||
ulint offsets_[REC_OFFS_NORMAL_SIZE];
|
||||
ulint n_fld = dtuple_get_n_fields(entry);
|
||||
ulint n_v_fld = dtuple_get_n_v_fields(entry);
|
||||
const ulint n_v_fld = dtuple_get_n_v_fields(entry);
|
||||
rec_offs_init(offsets_);
|
||||
|
||||
/* This function is used only for a clustered index */
|
||||
ut_a(dict_index_is_clust(index));
|
||||
ut_ad(!index->table->skip_alter_undo);
|
||||
ut_ad(entry->n_fields <= index->n_fields);
|
||||
ut_ad(entry->n_fields >= index->n_core_fields);
|
||||
|
||||
update = upd_create(n_fld + n_v_fld, heap);
|
||||
update = upd_create(index->n_fields + n_v_fld, heap);
|
||||
|
||||
n_diff = 0;
|
||||
|
||||
@ -1079,7 +1078,7 @@ row_upd_build_difference_binary(
|
||||
ut_ad(rec_offs_validate(rec, index, offsets));
|
||||
}
|
||||
|
||||
for (i = 0; i < n_fld; i++) {
|
||||
for (ulint i = 0; i < entry->n_fields; i++) {
|
||||
const byte* data = rec_get_nth_cfield(rec, index, offsets, i,
|
||||
&len);
|
||||
const dfield_t* dfield = dtuple_get_nth_field(entry, i);
|
||||
@ -1101,17 +1100,22 @@ row_upd_build_difference_binary(
|
||||
if (!dfield_is_ext(dfield)
|
||||
!= !rec_offs_nth_extern(offsets, i)
|
||||
|| !dfield_data_is_binary_equal(dfield, len, data)) {
|
||||
|
||||
upd_field = upd_get_nth_field(update, n_diff);
|
||||
|
||||
dfield_copy(&(upd_field->new_val), dfield);
|
||||
|
||||
upd_field_set_field_no(upd_field, i, index);
|
||||
|
||||
n_diff++;
|
||||
upd_field_t* uf = upd_get_nth_field(update, n_diff++);
|
||||
dfield_copy(&uf->new_val, dfield);
|
||||
upd_field_set_field_no(uf, i, index);
|
||||
}
|
||||
}
|
||||
|
||||
for (ulint i = entry->n_fields; i < index->n_fields; i++) {
|
||||
upd_field_t* uf = upd_get_nth_field(update, n_diff++);
|
||||
const dict_col_t* col = dict_index_get_nth_col(index, i);
|
||||
/* upd_create() zero-initialized uf */
|
||||
uf->new_val.data = const_cast<byte*>(col->instant_value(&len));
|
||||
uf->new_val.len = static_cast<unsigned>(len);
|
||||
dict_col_copy_type(col, &uf->new_val.type);
|
||||
upd_field_set_field_no(uf, i, index);
|
||||
}
|
||||
|
||||
/* Check the virtual columns updates. Even if there is no non-virtual
|
||||
column (base columns) change, we will still need to build the
|
||||
indexed virtual column value so that undo log would log them (
|
||||
@ -1136,7 +1140,7 @@ row_upd_build_difference_binary(
|
||||
&mysql_table,
|
||||
&record, &vcol_storage);
|
||||
|
||||
for (i = 0; i < n_v_fld; i++) {
|
||||
for (ulint i = 0; i < n_v_fld; i++) {
|
||||
const dict_v_col_t* col
|
||||
= dict_table_get_nth_v_col(index->table, i);
|
||||
|
||||
@ -1164,24 +1168,16 @@ row_upd_build_difference_binary(
|
||||
entry, i);
|
||||
|
||||
if (!dfield_data_is_binary_equal(
|
||||
dfield, vfield->len,
|
||||
static_cast<byte*>(vfield->data))) {
|
||||
upd_field = upd_get_nth_field(update, n_diff);
|
||||
|
||||
upd_field->old_v_val = static_cast<dfield_t*>(
|
||||
mem_heap_alloc(
|
||||
heap,
|
||||
sizeof *upd_field->old_v_val));
|
||||
|
||||
dfield_copy(upd_field->old_v_val, vfield);
|
||||
|
||||
dfield_copy(&(upd_field->new_val), dfield);
|
||||
|
||||
upd_field_set_v_field_no(
|
||||
upd_field, i, index);
|
||||
|
||||
n_diff++;
|
||||
|
||||
dfield, vfield->len,
|
||||
static_cast<byte*>(vfield->data))) {
|
||||
upd_field_t* uf = upd_get_nth_field(update,
|
||||
n_diff++);
|
||||
uf->old_v_val = static_cast<dfield_t*>(
|
||||
mem_heap_alloc(heap,
|
||||
sizeof *uf->old_v_val));
|
||||
dfield_copy(uf->old_v_val, vfield);
|
||||
dfield_copy(&uf->new_val, dfield);
|
||||
upd_field_set_v_field_no(uf, i, index);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user