summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexey Botchkov <holyfoot@askmonty.org>2019-11-01 09:39:43 +0400
committerAlexey Botchkov <holyfoot@askmonty.org>2019-11-01 09:39:43 +0400
commit6dce6aecebe6ef78a14cb5c5c5daa8a355551e40 (patch)
tree5634fcc0dd38530086186214895f8150e7e0c8ae
parent55b2281a5da38f66dca5e2180672f570c33676df (diff)
downloadmariadb-git-6dce6aecebe6ef78a14cb5c5c5daa8a355551e40.tar.gz
MDEV-18244 Server crashes in ha_innobase::update_thd / ... / ha_partition::update_next_auto_inc_val.
Partition table with the AUTO_INCREMENT column we ahve to check if the max value is properly loaded. So we need to open all tables in INSERT PARTITION statement if necessary. Also we need to check if some tables are pruned away and not count the max autoincrement in this case.
-rw-r--r--mysql-test/main/partition_innodb.result24
-rw-r--r--mysql-test/main/partition_innodb.test20
-rw-r--r--sql/ha_partition.cc24
-rw-r--r--sql/ha_partition.h13
4 files changed, 73 insertions, 8 deletions
diff --git a/mysql-test/main/partition_innodb.result b/mysql-test/main/partition_innodb.result
index f3d24347ff9..5c63fcfbbc9 100644
--- a/mysql-test/main/partition_innodb.result
+++ b/mysql-test/main/partition_innodb.result
@@ -1028,5 +1028,29 @@ COUNT(*)
2
DROP TABLE t1;
#
+# MDEV-18244 Server crashes in ha_innobase::update_thd / ... / ha_partition::update_next_auto_inc_val
+#
+CREATE TABLE t1 (a INT)
+ENGINE=InnoDB
+PARTITION BY RANGE (a) (
+PARTITION p0 VALUES LESS THAN (6),
+PARTITION pn VALUES LESS THAN MAXVALUE
+);
+INSERT INTO t1 VALUES (4),(5),(6);
+ALTER TABLE t1 MODIFY a INT AUTO_INCREMENT PRIMARY KEY;
+UPDATE t1 PARTITION (p0) SET a = 3 WHERE a = 5;
+INSERT INTO t1 PARTITION(p0) VALUES ();
+ERROR HY000: Found a row not matching the given partition set
+INSERT INTO t1 PARTITION(p0) VALUES (-1);
+INSERT INTO t1 VALUES ();
+SELECT * FROM t1;
+a
+-1
+1
+3
+4
+6
+DROP TABLE t1;
+#
# End of 10.3 tests
#
diff --git a/mysql-test/main/partition_innodb.test b/mysql-test/main/partition_innodb.test
index 629bc29e758..f7ce9b03a54 100644
--- a/mysql-test/main/partition_innodb.test
+++ b/mysql-test/main/partition_innodb.test
@@ -1106,5 +1106,25 @@ SELECT COUNT(*) FROM t1 WHERE x IS NULL AND y IS NULL AND z IS NULL;
DROP TABLE t1;
--echo #
+--echo # MDEV-18244 Server crashes in ha_innobase::update_thd / ... / ha_partition::update_next_auto_inc_val
+--echo #
+
+CREATE TABLE t1 (a INT)
+ ENGINE=InnoDB
+ PARTITION BY RANGE (a) (
+ PARTITION p0 VALUES LESS THAN (6),
+ PARTITION pn VALUES LESS THAN MAXVALUE
+ );
+INSERT INTO t1 VALUES (4),(5),(6);
+ALTER TABLE t1 MODIFY a INT AUTO_INCREMENT PRIMARY KEY;
+UPDATE t1 PARTITION (p0) SET a = 3 WHERE a = 5;
+--error ER_ROW_DOES_NOT_MATCH_GIVEN_PARTITION_SET
+INSERT INTO t1 PARTITION(p0) VALUES ();
+INSERT INTO t1 PARTITION(p0) VALUES (-1);
+INSERT INTO t1 VALUES ();
+SELECT * FROM t1;
+DROP TABLE t1;
+
+--echo #
--echo # End of 10.3 tests
--echo #
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc
index 5a78249644d..ccda01de6b7 100644
--- a/sql/ha_partition.cc
+++ b/sql/ha_partition.cc
@@ -3459,8 +3459,7 @@ bool ha_partition::init_partition_bitmaps()
/*
Open handler object
-
- SYNOPSIS
+SYNOPSIS
open()
name Full path of table name
mode Open mode flags
@@ -3586,6 +3585,7 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked)
}
else
{
+ check_insert_autoincrement();
if (unlikely((error= open_read_partitions(name_buff, sizeof(name_buff)))))
goto err_handler;
m_num_locks= m_file_sample->lock_count();
@@ -4472,11 +4472,8 @@ exit:
table->found_next_number_field->field_index))
{
update_next_auto_inc_val();
- /*
- The following call is safe as part_share->auto_inc_initialized
- (tested in the call) is guaranteed to be set for update statements.
- */
- set_auto_increment_if_higher(table->found_next_number_field);
+ if (part_share->auto_inc_initialized)
+ set_auto_increment_if_higher(table->found_next_number_field);
}
DBUG_RETURN(error);
}
@@ -8144,6 +8141,7 @@ int ha_partition::info(uint flag)
if (flag & HA_STATUS_AUTO)
{
bool auto_inc_is_first_in_idx= (table_share->next_number_keypart == 0);
+ bool all_parts_opened= true;
DBUG_PRINT("info", ("HA_STATUS_AUTO"));
if (!table->found_next_number_field)
stats.auto_increment_value= 0;
@@ -8174,6 +8172,15 @@ int ha_partition::info(uint flag)
("checking all partitions for auto_increment_value"));
do
{
+ if (!bitmap_is_set(&m_opened_partitions, (uint)(file_array - m_file)))
+ {
+ /*
+ Some partitions aren't opened.
+ So we can't calculate the autoincrement.
+ */
+ all_parts_opened= false;
+ break;
+ }
file= *file_array;
file->info(HA_STATUS_AUTO | no_lock_flag);
set_if_bigger(auto_increment_value,
@@ -8182,7 +8189,7 @@ int ha_partition::info(uint flag)
DBUG_ASSERT(auto_increment_value);
stats.auto_increment_value= auto_increment_value;
- if (auto_inc_is_first_in_idx)
+ if (all_parts_opened && auto_inc_is_first_in_idx)
{
set_if_bigger(part_share->next_auto_inc_val,
auto_increment_value);
@@ -8485,6 +8492,7 @@ int ha_partition::change_partitions_to_open(List<String> *partition_names)
return 0;
}
+ check_insert_autoincrement();
if (bitmap_cmp(&m_opened_partitions, &m_part_info->read_partitions) != 0)
return 0;
diff --git a/sql/ha_partition.h b/sql/ha_partition.h
index d48947822b9..1085eca72cc 100644
--- a/sql/ha_partition.h
+++ b/sql/ha_partition.h
@@ -1329,6 +1329,19 @@ private:
unlock_auto_increment();
}
+ void check_insert_autoincrement()
+ {
+ /*
+ If we INSERT into the table having the AUTO_INCREMENT column,
+ we have to read all partitions for the next autoincrement value
+ unless we already did it.
+ */
+ if (!part_share->auto_inc_initialized &&
+ ha_thd()->lex->sql_command == SQLCOM_INSERT &&
+ table->found_next_number_field)
+ bitmap_set_all(&m_part_info->read_partitions);
+ }
+
public:
/*