summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksey Midenkov <midenok@gmail.com>2019-05-11 17:27:23 +0300
committerAleksey Midenkov <midenok@gmail.com>2019-10-10 00:20:34 +0300
commita92f3146d22cb3b290228c0e66eb1ea6c7b7c373 (patch)
tree012598feb31ab78c15501db3a17f7919945131d4
parent647a38818a44012c22128e0e1cad96739aa8a5c2 (diff)
downloadmariadb-git-a92f3146d22cb3b290228c0e66eb1ea6c7b7c373.tar.gz
MDEV-19406 Assertion on updating view of join with versioned table
TABLE::mark_columns_needed_for_update(): use_all_columns() assigns pointer of all_set into read_set and write_set, but this is not good since all_set is changed later by TABLE::mark_columns_used_by_index_no_reset(). Do column_bitmaps_signal() whenever we change read_set/write_set.
-rw-r--r--mysql-test/suite/versioning/r/update.result11
-rw-r--r--mysql-test/suite/versioning/t/update.test15
-rw-r--r--sql/log_event.cc2
-rw-r--r--sql/sql_insert.cc1
-rw-r--r--sql/table.cc32
5 files changed, 51 insertions, 10 deletions
diff --git a/mysql-test/suite/versioning/r/update.result b/mysql-test/suite/versioning/r/update.result
index af263a63fae..eaa8549b38a 100644
--- a/mysql-test/suite/versioning/r/update.result
+++ b/mysql-test/suite/versioning/r/update.result
@@ -265,3 +265,14 @@ ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
disconnect con1;
connection default;
drop table t1;
+#
+# MDEV-19406 Assertion on updating view of join with versioned table
+#
+create or replace table t1 (pk int primary key, a date, b int, index(b)) engine=innodb with system versioning;
+create or replace table t2 (c int);
+create or replace view v as select * from t1 join t2;
+insert into t1 (pk) values (1);
+update t1 set a= '2012-12-12';
+update v set a= '2000-01-01' order by b limit 1;
+drop view v;
+drop table t1, t2;
diff --git a/mysql-test/suite/versioning/t/update.test b/mysql-test/suite/versioning/t/update.test
index a9550564a15..e41c7d15995 100644
--- a/mysql-test/suite/versioning/t/update.test
+++ b/mysql-test/suite/versioning/t/update.test
@@ -177,4 +177,19 @@ connection default;
reap;
drop table t1;
+--echo #
+--echo # MDEV-19406 Assertion on updating view of join with versioned table
+--echo #
+--disable_warnings
+create or replace table t1 (pk int primary key, a date, b int, index(b)) engine=innodb with system versioning;
+create or replace table t2 (c int);
+create or replace view v as select * from t1 join t2;
+
+insert into t1 (pk) values (1);
+update t1 set a= '2012-12-12';
+update v set a= '2000-01-01' order by b limit 1; # point of failure
+drop view v;
+drop table t1, t2;
+--enable_warnings
+
source suite/versioning/common_finish.inc;
diff --git a/sql/log_event.cc b/sql/log_event.cc
index dc7203fc94f..78111e86f20 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -13450,6 +13450,7 @@ Rows_log_event::write_row(rpl_group_info *rgi,
{
ulong sec_part;
bitmap_set_bit(table->read_set, table->vers_start_field()->field_index);
+ table->file->column_bitmaps_signal();
// Check whether a row came from unversioned table and fix vers fields.
if (table->vers_start_field()->get_timestamp(&sec_part) == 0 && sec_part == 0)
table->vers_update_fields();
@@ -14010,6 +14011,7 @@ int Rows_log_event::find_row(rpl_group_info *rgi)
table->vers_end_field()->set_max();
m_vers_from_plain= true;
}
+ table->file->column_bitmaps_signal();
}
DBUG_PRINT("info",("looking for the following record"));
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 7913ea2b2ec..dc8ee19b1e1 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -1945,6 +1945,7 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
if (table->versioned(VERS_TRX_ID))
{
bitmap_set_bit(table->write_set, table->vers_start_field()->field_index);
+ table->file->column_bitmaps_signal();
table->vers_start_field()->store(0, false);
}
if (unlikely(error= table->file->ha_update_row(table->record[1],
diff --git a/sql/table.cc b/sql/table.cc
index e2b2a5ec273..34523767eb4 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -6510,15 +6510,16 @@ void TABLE::mark_columns_needed_for_delete()
}
}
- if (need_signal)
- file->column_bitmaps_signal();
-
if (s->versioned)
{
bitmap_set_bit(read_set, s->vers_start_field()->field_index);
bitmap_set_bit(read_set, s->vers_end_field()->field_index);
bitmap_set_bit(write_set, s->vers_end_field()->field_index);
+ need_signal= true;
}
+
+ if (need_signal)
+ file->column_bitmaps_signal();
}
@@ -6531,7 +6532,7 @@ void TABLE::mark_columns_needed_for_delete()
updated columns to be read.
If this is no the case, we do like in the delete case and mark
- if neeed, either the primary key column or all columns to be read.
+ if needed, either the primary key column or all columns to be read.
(see mark_columns_needed_for_delete() for details)
If the engine has HA_REQUIRES_KEY_COLUMNS_FOR_DELETE, we will
@@ -6595,14 +6596,18 @@ void TABLE::mark_columns_needed_for_update()
need_signal= true;
}
}
- /*
- For System Versioning we have to read all columns since we will store
- a copy of previous row with modified Sys_end column back to a table.
- */
if (s->versioned)
{
- // We will copy old columns to a new row.
- use_all_columns();
+ /*
+ For System Versioning we have to read all columns since we store
+ a copy of previous row with modified row_end back to a table.
+
+ Without write_set versioning.rpl,row is unstable until MDEV-16370 is
+ applied.
+ */
+ bitmap_union(read_set, &s->all_set);
+ bitmap_union(write_set, &s->all_set);
+ need_signal= true;
}
if (check_constraints)
{
@@ -7991,7 +7996,10 @@ void TABLE::vers_update_fields()
if (versioned(VERS_TIMESTAMP))
{
if (!vers_write)
+ {
+ file->column_bitmaps_signal();
return;
+ }
if (vers_start_field()->store_timestamp(in_use->query_start(),
in_use->query_start_sec_part()))
DBUG_ASSERT(0);
@@ -7999,11 +8007,15 @@ void TABLE::vers_update_fields()
else
{
if (!vers_write)
+ {
+ file->column_bitmaps_signal();
return;
+ }
}
vers_end_field()->set_max();
bitmap_set_bit(read_set, vers_end_field()->field_index);
+ file->column_bitmaps_signal();
}