Skip to content

Commit ffb8250

Browse files
author
Sergey Glukhov
committed
Bug#28652733 ASSERTION FAILED: !TABLE || (!TABLE->READ_SET || BITMAP_IS_SET(TABLE->READ_SET,
1 parent 95d3ce9 commit ffb8250

File tree

2 files changed

+64
-18
lines changed

2 files changed

+64
-18
lines changed

sql/sql_join_buffer.cc

+30-15
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright (c) 2010, 2017, Oracle and/or its affiliates. All rights reserved.
1+
/* Copyright (c) 2010, 2019, Oracle and/or its affiliates. All rights reserved.
22
33
This program is free software; you can redistribute it and/or modify
44
it under the terms of the GNU General Public License as published by
@@ -566,8 +566,8 @@ void JOIN_CACHE::filter_virtual_gcol_base_cols()
566566
continue;
567567

568568
const uint index= tab->effective_index();
569-
if (index != MAX_KEY &&
570-
table->index_contains_some_virtual_gcol(index) &&
569+
const bool cov_index =
570+
index != MAX_KEY && table->index_contains_some_virtual_gcol(index) &&
571571
/*
572572
There are two cases:
573573
- If the table scan uses covering index scan, we can get the value
@@ -577,24 +577,38 @@ void JOIN_CACHE::filter_virtual_gcol_base_cols()
577577
After restore the base columns, the value of virtual generated
578578
columns can be calculated correctly.
579579
*/
580-
table->covering_keys.is_set(index))
580+
table->covering_keys.is_set(index);
581+
582+
if (!(cov_index || tab->dynamic_range())) continue;
583+
584+
/*
585+
Save of a copy of table->read_set in save_read_set so that it can be
586+
restored. tmp_set cannot be used as recipient for this as it's already
587+
used in other parts of JOIN_CACHE::init().
588+
*/
589+
auto bitbuf =
590+
(my_bitmap_map *)alloc_root(tab->table()->in_use->mem_root,
591+
table->s->column_bitmap_size);
592+
auto save_read_set = (MY_BITMAP *)alloc_root(tab->table()->in_use->mem_root,
593+
sizeof(MY_BITMAP));
594+
bitmap_init(save_read_set, bitbuf, table->s->fields, false);
595+
bitmap_copy(save_read_set, table->read_set);
596+
/*
597+
restore_virtual_gcol_base_cols() will need old bitmap so we save a
598+
reference to it.
599+
*/
600+
save_read_set_for_gcol.insert(std::make_pair(tab, save_read_set));
601+
if (cov_index)
581602
{
582-
DBUG_ASSERT(bitmap_is_clear_all(&table->tmp_set));
583-
// Keep table->read_set in tmp_set so that it can be restored
584-
bitmap_copy(&table->tmp_set, table->read_set);
585603
bitmap_clear_all(table->read_set);
586604
table->mark_columns_used_by_index_no_reset(index, table->read_set);
587605
if (table->s->primary_key != MAX_KEY)
588606
table->mark_columns_used_by_index_no_reset(table->s->primary_key,
589607
table->read_set);
590-
bitmap_intersect(table->read_set, &table->tmp_set);
608+
bitmap_intersect(table->read_set, save_read_set);
591609
}
592610
else if (tab->dynamic_range())
593611
{
594-
DBUG_ASSERT(bitmap_is_clear_all(&table->tmp_set));
595-
// Keep table->read_set in tmp_set so that it can be restored
596-
bitmap_copy(&table->tmp_set, table->read_set);
597-
598612
filter_gcol_for_dynamic_range_scan(tab);
599613
}
600614
}
@@ -614,10 +628,11 @@ void JOIN_CACHE::restore_virtual_gcol_base_cols()
614628
if (table->vfield == NULL)
615629
continue;
616630

617-
if (!bitmap_is_clear_all(&table->tmp_set))
631+
auto saved = save_read_set_for_gcol.find(tab);
632+
if (saved != save_read_set_for_gcol.end())
618633
{
619-
bitmap_copy(table->read_set, &table->tmp_set);
620-
bitmap_clear_all(&table->tmp_set);
634+
DBUG_ASSERT(!bitmap_is_clear_all(saved->second));
635+
bitmap_copy(table->read_set, saved->second);
621636
}
622637
}
623638
}

sql/sql_join_buffer.h

+34-3
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
#include "sql_executor.h"
55

6-
/* Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
6+
/* Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
77
88
This program is free software; you can redistribute it and/or modify
99
it under the terms of the GNU General Public License as published by
@@ -18,6 +18,10 @@
1818
along with this program; if not, write to the Free Software
1919
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
2020

21+
22+
#include "memroot_allocator.h"
23+
#include <unordered_map>
24+
2125
/** @file Join buffer classes */
2226

2327
/*
@@ -30,6 +34,25 @@
3034
#define CACHE_VARSTR1 3 /* short string value (length takes 1 byte) */
3135
#define CACHE_VARSTR2 4 /* long string value (length takes 2 bytes) */
3236

37+
38+
/**
39+
std::unordered_map, but allocated on a MEM_ROOT.
40+
*/
41+
template <class Key, class Value, class Hash = std::hash<Key>,
42+
class KeyEqual = std::equal_to<Key>>
43+
class memroot_unordered_map
44+
: public std::unordered_map<
45+
Key, Value, Hash, KeyEqual,
46+
Memroot_allocator<std::pair<const Key, Value>>> {
47+
public:
48+
memroot_unordered_map(MEM_ROOT *mem_root)
49+
: std::unordered_map<Key, Value, Hash, KeyEqual,
50+
Memroot_allocator<std::pair<const Key, Value>>>(
51+
/*bucket_count=*/10, Hash(), KeyEqual(),
52+
Memroot_allocator<std::pair<const Key, Value>>(mem_root)) {}
53+
};
54+
55+
3356
/*
3457
The CACHE_FIELD structure used to describe fields of records that
3558
are written into a join cache buffer from record buffers and backward.
@@ -98,6 +121,12 @@ class JOIN_CACHE :public QEP_operation
98121
/* Size of the offset of a field within a record in the cache */
99122
uint size_of_fld_ofs;
100123

124+
/**
125+
In init() there are several uses of TABLE::tmp_set, so one tmp_set isn't
126+
enough; this one is specific of generated column handling.
127+
*/
128+
memroot_unordered_map<QEP_TAB *, MY_BITMAP *> save_read_set_for_gcol;
129+
101130
protected:
102131

103132
/* 3 functions below actually do not use the hidden parameter 'this' */
@@ -460,8 +489,10 @@ class JOIN_CACHE :public QEP_operation
460489
linked.
461490
*/
462491
JOIN_CACHE(JOIN *j, QEP_TAB *qep_tab_arg, JOIN_CACHE *prev)
463-
: QEP_operation(qep_tab_arg), join(j), buff(NULL), prev_cache(prev),
464-
next_cache(NULL)
492+
: QEP_operation(qep_tab_arg),
493+
save_read_set_for_gcol(qep_tab_arg->table()->in_use->mem_root),
494+
join(j), buff(NULL), prev_cache(prev),
495+
next_cache(NULL)
465496
{
466497
if (prev_cache)
467498
prev_cache->next_cache= this;

0 commit comments

Comments
 (0)