summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMonty <monty@mariadb.org>2017-12-12 15:04:29 +0200
committerMonty <monty@mariadb.org>2017-12-12 15:10:53 +0200
commitd4a4185451061d84ed6d3ead9ce77faac04c7151 (patch)
tree45ca10cc2f74efbb3d2b03db9d542ea98d949c6f
parent0edd395e8d791a3d78a1e882dc598843e521403e (diff)
downloadmariadb-git-d4a4185451061d84ed6d3ead9ce77faac04c7151.tar.gz
MDEV Assertion `partition_id == m_extra_cache_part_id' failed in ha_partition::late_extra_no_cache
The problem was that multi_range_read_info_const() called multi_range_key_create_key() which changed m_part_spec.start_part, while there was an activ table scan ongoing. Fixed by copying and restoring m_part_spec around multi_range_key_create_calls()
-rw-r--r--mysql-test/suite/parts/r/cache.result15
-rw-r--r--mysql-test/suite/parts/t/cache.test22
-rw-r--r--sql/ha_partition.cc11
3 files changed, 47 insertions, 1 deletions
diff --git a/mysql-test/suite/parts/r/cache.result b/mysql-test/suite/parts/r/cache.result
new file mode 100644
index 00000000000..fb40526f379
--- /dev/null
+++ b/mysql-test/suite/parts/r/cache.result
@@ -0,0 +1,15 @@
+CREATE TABLE t1 (f1 INT, f2 INT, f3 INT, f4 INT, KEY (f4),
+KEY (f1,f4,f3,f2)
+) PARTITION BY RANGE(f1) ( PARTITION p VALUES LESS THAN MAXVALUE );
+INSERT IGNORE INTO t1 VALUES
+(140,0,0,7),(143,92,NULL,0),(0,0,NULL,154),(NULL,255,117,197),(0,0,NULL,0),(60,0,0,1);
+CREATE TABLE t2 (f INT);
+INSERT INTO t2 VALUES (NULL),(35),(NULL),(2);
+SELECT * FROM t1, t2 WHERE f4 >= f;
+f1 f2 f3 f4 f
+0 0 NULL 154 2
+0 0 NULL 154 35
+140 0 0 7 2
+NULL 255 117 197 2
+NULL 255 117 197 35
+DROP TABLE t1, t2;
diff --git a/mysql-test/suite/parts/t/cache.test b/mysql-test/suite/parts/t/cache.test
new file mode 100644
index 00000000000..fcf2ba5d6b6
--- /dev/null
+++ b/mysql-test/suite/parts/t/cache.test
@@ -0,0 +1,22 @@
+#
+# Test cases related to row cache
+#
+
+# The server must support partitioning.
+--source include/have_partition.inc
+
+CREATE TABLE t1 (f1 INT, f2 INT, f3 INT, f4 INT, KEY (f4),
+ KEY (f1,f4,f3,f2)
+) PARTITION BY RANGE(f1) ( PARTITION p VALUES LESS THAN MAXVALUE );
+
+INSERT IGNORE INTO t1 VALUES
+(140,0,0,7),(143,92,NULL,0),(0,0,NULL,154),(NULL,255,117,197),(0,0,NULL,0),(60,0,0,1);
+
+CREATE TABLE t2 (f INT);
+INSERT INTO t2 VALUES (NULL),(35),(NULL),(2);
+
+--sorted_result
+SELECT * FROM t1, t2 WHERE f4 >= f;
+
+# Cleanup
+DROP TABLE t1, t2;
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc
index 2c0d313fd2b..e2d6bb1bdfe 100644
--- a/sql/ha_partition.cc
+++ b/sql/ha_partition.cc
@@ -5070,6 +5070,7 @@ int ha_partition::rnd_next(uchar *buf)
}
end:
+ DBUG_PRINT("exit", ("reset start_part"));
m_part_spec.start_part= NO_CURRENT_PART_ID;
end_dont_reset_start_part:
DBUG_RETURN(result);
@@ -6223,10 +6224,13 @@ ha_rows ha_partition::multi_range_read_info_const(uint keyno,
ha_rows rows= 0;
uint ret_mrr_mode= 0;
range_seq_t seq_it;
+ part_id_range save_part_spec;
DBUG_ENTER("ha_partition::multi_range_read_info_const");
DBUG_PRINT("enter", ("partition this: %p", this));
m_mrr_new_full_buffer_size= 0;
+ save_part_spec= m_part_spec;
+
seq_it= seq->init(seq_init_param, n_ranges, *mrr_mode);
if ((error= multi_range_key_create_key(seq, seq_it)))
{
@@ -6240,6 +6244,7 @@ ha_rows ha_partition::multi_range_read_info_const(uint keyno,
(probably running out of memory) and we need to fallback to
normal reads
*/
+ m_part_spec= save_part_spec;
DBUG_RETURN(HA_POS_ERROR);
}
m_part_seq_if.get_key_info=
@@ -6269,7 +6274,10 @@ ha_rows ha_partition::multi_range_read_info_const(uint keyno,
&m_mrr_buffer_size[i],
&tmp_mrr_mode, cost);
if (tmp_rows == HA_POS_ERROR)
+ {
+ m_part_spec= save_part_spec;
DBUG_RETURN(HA_POS_ERROR);
+ }
rows+= tmp_rows;
ret_mrr_mode|= tmp_mrr_mode;
m_mrr_new_full_buffer_size+= m_mrr_buffer_size[i];
@@ -6278,6 +6286,7 @@ ha_rows ha_partition::multi_range_read_info_const(uint keyno,
*mrr_mode= ret_mrr_mode;
calc_cost:
+ m_part_spec= save_part_spec;
cost->reset();
cost->avg_io_cost= 1;
if ((*mrr_mode & HA_MRR_INDEX_ONLY) && rows > 2)
@@ -8660,8 +8669,8 @@ int ha_partition::extra(enum ha_extra_function operation)
{
if (!m_myisam)
DBUG_RETURN(loop_extra(operation));
- break;
}
+ break;
/* Category 3), used by MyISAM handlers */
case HA_EXTRA_PREPARE_FOR_UPDATE: