Skip to content

Commit 58b91e8

Browse files
author
Sergey Glukhov
committed
Bug#28652733 ASSERTION FAILED: !TABLE || (!TABLE->READ_SET || BITMAP_IS_SET(TABLE->READ_SET,
1 parent 3e8c32a commit 58b91e8

File tree

2 files changed

+48
-15
lines changed

2 files changed

+48
-15
lines changed

sql/sql_join_buffer.cc

+41-15
Original file line numberDiff line numberDiff line change
@@ -559,14 +559,16 @@ static void filter_gcol_for_dynamic_range_scan(QEP_TAB *const tab)
559559

560560
void JOIN_CACHE::filter_virtual_gcol_base_cols()
561561
{
562+
DBUG_ASSERT(save_read_set_for_gcol.size() == 0);
562563
for (QEP_TAB *tab= qep_tab - tables; tab < qep_tab; tab++)
563564
{
564565
TABLE *table= tab->table();
565566
if (table->vfield == NULL)
566567
continue;
567568

568569
const uint index= tab->effective_index();
569-
if (index != MAX_KEY && table->index_contains_some_virtual_gcol(index) &&
570+
const bool cov_index =
571+
index != MAX_KEY && table->index_contains_some_virtual_gcol(index) &&
570572
/*
571573
There are two cases:
572574
- If the table scan uses covering index scan, we can get the value
@@ -576,24 +578,40 @@ void JOIN_CACHE::filter_virtual_gcol_base_cols()
576578
After restore the base columns, the value of virtual generated
577579
columns can be calculated correctly.
578580
*/
579-
table->covering_keys.is_set(index))
581+
table->covering_keys.is_set(index);
582+
583+
if (!(cov_index || tab->dynamic_range())) continue;
584+
585+
/*
586+
Save of a copy of table->read_set in save_read_set so that it can be
587+
restored. tmp_set cannot be used as recipient for this as it's already
588+
used in other parts of JOIN_CACHE::init().
589+
*/
590+
my_bitmap_map *bitbuf =
591+
(my_bitmap_map *)alloc_root(tab->table()->in_use->mem_root,
592+
table->s->column_bitmap_size);
593+
MY_BITMAP *save_read_set =
594+
(MY_BITMAP *)alloc_root(tab->table()->in_use->mem_root,
595+
sizeof(MY_BITMAP));
596+
bitmap_init(save_read_set, bitbuf, table->s->fields, false);
597+
bitmap_copy(save_read_set, table->read_set);
598+
/*
599+
restore_virtual_gcol_base_cols() will need old bitmap so we save a
600+
reference to it.
601+
*/
602+
save_read_set_for_gcol.push_back(save_read_set);
603+
604+
if (cov_index)
580605
{
581-
DBUG_ASSERT(bitmap_is_clear_all(&table->tmp_set));
582-
// Keep table->read_set in tmp_set so that it can be restored
583-
bitmap_copy(&table->tmp_set, table->read_set);
584606
bitmap_clear_all(table->read_set);
585607
table->mark_columns_used_by_index_no_reset(index, table->read_set);
586608
if (table->s->primary_key != MAX_KEY)
587609
table->mark_columns_used_by_index_no_reset(table->s->primary_key,
588610
table->read_set);
589-
bitmap_intersect(table->read_set, &table->tmp_set);
611+
bitmap_intersect(table->read_set, save_read_set);
590612
}
591613
else if (tab->dynamic_range())
592614
{
593-
DBUG_ASSERT(bitmap_is_clear_all(&table->tmp_set));
594-
// Keep table->read_set in tmp_set so that it can be restored
595-
bitmap_copy(&table->tmp_set, table->read_set);
596-
597615
filter_gcol_for_dynamic_range_scan(tab);
598616
}
599617
}
@@ -607,18 +625,26 @@ void JOIN_CACHE::filter_virtual_gcol_base_cols()
607625

608626
void JOIN_CACHE::restore_virtual_gcol_base_cols()
609627
{
628+
MY_BITMAP **save_read_set= save_read_set_for_gcol.begin();
629+
610630
for (QEP_TAB *tab= qep_tab - tables; tab < qep_tab; tab++)
611631
{
612632
TABLE *table= tab->table();
613633
if (table->vfield == NULL)
614634
continue;
615635

616-
if (!bitmap_is_clear_all(&table->tmp_set))
617-
{
618-
bitmap_copy(table->read_set, &table->tmp_set);
619-
bitmap_clear_all(&table->tmp_set);
620-
}
636+
const uint index= tab->effective_index();
637+
const bool cov_index =
638+
(index != MAX_KEY && table->index_contains_some_virtual_gcol(index) &&
639+
table->covering_keys.is_set(index));
640+
641+
if (!(cov_index || tab->dynamic_range())) continue;
642+
643+
DBUG_ASSERT(!bitmap_is_clear_all(*save_read_set));
644+
bitmap_copy(table->read_set, *save_read_set);
645+
save_read_set++;
621646
}
647+
DBUG_ASSERT(save_read_set == save_read_set_for_gcol.end());
622648
}
623649

624650
/*

sql/sql_join_buffer.h

+7
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#define SQL_JOIN_CACHE_INCLUDED
33

44
#include "sql_executor.h"
5+
#include "mem_root_array.h"
56

67
/* Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
78
@@ -99,6 +100,11 @@ class JOIN_CACHE :public QEP_operation
99100
uint size_of_rec_len;
100101
/* Size of the offset of a field within a record in the cache */
101102
uint size_of_fld_ofs;
103+
/**
104+
In init() there are several uses of TABLE::tmp_set, so one tmp_set isn't
105+
enough; this one is specific of generated column handling.
106+
*/
107+
Mem_root_array<MY_BITMAP*, true> save_read_set_for_gcol;
102108

103109
protected:
104110

@@ -463,6 +469,7 @@ class JOIN_CACHE :public QEP_operation
463469
*/
464470
JOIN_CACHE(JOIN *j, QEP_TAB *qep_tab_arg, JOIN_CACHE *prev)
465471
: QEP_operation(qep_tab_arg),
472+
save_read_set_for_gcol(qep_tab_arg->table()->in_use->mem_root),
466473
join(j), buff(NULL), prev_cache(prev),
467474
next_cache(NULL)
468475
{

0 commit comments

Comments
 (0)