mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 12:02:42 +01:00
Merge of fix for Bug#41660.
This commit is contained in:
commit
65a28caf4e
5 changed files with 89 additions and 20 deletions
|
@ -48,5 +48,40 @@ Got one of the listed errors
|
|||
SET SESSION debug=DEFAULT;
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# Bug#41660: Sort-index_merge for non-first join table may require
|
||||
# O(#scans) memory
|
||||
#
|
||||
CREATE TABLE t1 (a INT);
|
||||
INSERT INTO t1 VALUES (0), (1), (2), (3), (4), (5), (6), (7), (8), (9);
|
||||
CREATE TABLE t2 (a INT, b INT, filler CHAR(100), KEY(a), KEY(b));
|
||||
INSERT INTO t2 SELECT 1000, 1000, 'filler' FROM t1 A, t1 B, t1 C;
|
||||
INSERT INTO t2 VALUES (1, 1, 'data');
|
||||
# the example query uses LEFT JOIN only for the sake of being able to
|
||||
# demonstrate the issue with a very small dataset. (left outer join
|
||||
# disables the use of join buffering, so we get the second table
|
||||
# re-scanned for every record in the outer table. if we used inner join,
|
||||
# we would need to have thousands of records and/or more columns in both
|
||||
# tables so that the join buffer is filled and re-scans are triggered).
|
||||
SET SESSION debug = '+d,only_one_Unique_may_be_created';
|
||||
EXPLAIN
|
||||
SELECT * FROM t1 LEFT JOIN t2 ON ( t2.a < 10 OR t2.b < 10 );
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
x x x x x x x x x
|
||||
x x x x x x x x x Using sort_union(a,b); Using where
|
||||
SELECT * FROM t1 LEFT JOIN t2 ON ( t2.a < 10 OR t2.b < 10 );
|
||||
a a b filler
|
||||
0 1 1 data
|
||||
1 1 1 data
|
||||
2 1 1 data
|
||||
3 1 1 data
|
||||
4 1 1 data
|
||||
5 1 1 data
|
||||
6 1 1 data
|
||||
7 1 1 data
|
||||
8 1 1 data
|
||||
9 1 1 data
|
||||
SET SESSION debug = DEFAULT;
|
||||
DROP TABLE t1, t2;
|
||||
#
|
||||
# End of 5.1 tests
|
||||
#
|
||||
|
|
|
@ -45,7 +45,6 @@ SHOW CREATE TABLE t1;
|
|||
SELECT * FROM t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # Bug#42064: low memory crash when importing hex strings, in Item_hex_string::Item_hex_string
|
||||
--echo #
|
||||
|
@ -60,6 +59,36 @@ SET SESSION debug=DEFAULT;
|
|||
|
||||
DROP TABLE t1;
|
||||
|
||||
-- echo #
|
||||
-- echo # Bug#41660: Sort-index_merge for non-first join table may require
|
||||
-- echo # O(#scans) memory
|
||||
-- echo #
|
||||
|
||||
CREATE TABLE t1 (a INT);
|
||||
INSERT INTO t1 VALUES (0), (1), (2), (3), (4), (5), (6), (7), (8), (9);
|
||||
|
||||
CREATE TABLE t2 (a INT, b INT, filler CHAR(100), KEY(a), KEY(b));
|
||||
INSERT INTO t2 SELECT 1000, 1000, 'filler' FROM t1 A, t1 B, t1 C;
|
||||
INSERT INTO t2 VALUES (1, 1, 'data');
|
||||
|
||||
--echo # the example query uses LEFT JOIN only for the sake of being able to
|
||||
--echo # demonstrate the issue with a very small dataset. (left outer join
|
||||
--echo # disables the use of join buffering, so we get the second table
|
||||
--echo # re-scanned for every record in the outer table. if we used inner join,
|
||||
--echo # we would need to have thousands of records and/or more columns in both
|
||||
--echo # tables so that the join buffer is filled and re-scans are triggered).
|
||||
|
||||
SET SESSION debug = '+d,only_one_Unique_may_be_created';
|
||||
|
||||
--replace_column 1 x 2 x 3 x 4 x 5 x 6 x 7 x 8 x 9 x
|
||||
EXPLAIN
|
||||
SELECT * FROM t1 LEFT JOIN t2 ON ( t2.a < 10 OR t2.b < 10 );
|
||||
SELECT * FROM t1 LEFT JOIN t2 ON ( t2.a < 10 OR t2.b < 10 );
|
||||
|
||||
SET SESSION debug = DEFAULT;
|
||||
|
||||
DROP TABLE t1, t2;
|
||||
|
||||
--echo #
|
||||
--echo # End of 5.1 tests
|
||||
--echo #
|
||||
|
|
|
@ -1227,7 +1227,7 @@ QUICK_RANGE_SELECT::~QUICK_RANGE_SELECT()
|
|||
|
||||
QUICK_INDEX_MERGE_SELECT::QUICK_INDEX_MERGE_SELECT(THD *thd_param,
|
||||
TABLE *table)
|
||||
:pk_quick_select(NULL), thd(thd_param)
|
||||
:unique(NULL), pk_quick_select(NULL), thd(thd_param)
|
||||
{
|
||||
DBUG_ENTER("QUICK_INDEX_MERGE_SELECT::QUICK_INDEX_MERGE_SELECT");
|
||||
index= MAX_KEY;
|
||||
|
@ -1269,6 +1269,7 @@ QUICK_INDEX_MERGE_SELECT::~QUICK_INDEX_MERGE_SELECT()
|
|||
List_iterator_fast<QUICK_RANGE_SELECT> quick_it(quick_selects);
|
||||
QUICK_RANGE_SELECT* quick;
|
||||
DBUG_ENTER("QUICK_INDEX_MERGE_SELECT::~QUICK_INDEX_MERGE_SELECT");
|
||||
delete unique;
|
||||
quick_it.rewind();
|
||||
while ((quick= quick_it++))
|
||||
quick->file= NULL;
|
||||
|
@ -8342,7 +8343,6 @@ int QUICK_INDEX_MERGE_SELECT::read_keys_and_merge()
|
|||
List_iterator_fast<QUICK_RANGE_SELECT> cur_quick_it(quick_selects);
|
||||
QUICK_RANGE_SELECT* cur_quick;
|
||||
int result;
|
||||
Unique *unique;
|
||||
handler *file= head->file;
|
||||
DBUG_ENTER("QUICK_INDEX_MERGE_SELECT::read_keys_and_merge");
|
||||
|
||||
|
@ -8361,9 +8361,22 @@ int QUICK_INDEX_MERGE_SELECT::read_keys_and_merge()
|
|||
if (cur_quick->init() || cur_quick->reset())
|
||||
DBUG_RETURN(1);
|
||||
|
||||
unique= new Unique(refpos_order_cmp, (void *)file,
|
||||
file->ref_length,
|
||||
thd->variables.sortbuff_size);
|
||||
if (unique == NULL)
|
||||
{
|
||||
DBUG_EXECUTE_IF("index_merge_may_not_create_a_Unique", abort(); );
|
||||
DBUG_EXECUTE_IF("only_one_Unique_may_be_created",
|
||||
DBUG_SET("+d,index_merge_may_not_create_a_Unique"); );
|
||||
|
||||
unique= new Unique(refpos_order_cmp, (void *)file,
|
||||
file->ref_length,
|
||||
thd->variables.sortbuff_size);
|
||||
}
|
||||
else
|
||||
unique->reset();
|
||||
|
||||
DBUG_ASSERT(file->ref_length == unique->get_size());
|
||||
DBUG_ASSERT(thd->variables.sortbuff_size == unique->get_max_in_memory_size());
|
||||
|
||||
if (!unique)
|
||||
DBUG_RETURN(1);
|
||||
for (;;)
|
||||
|
@ -8378,10 +8391,7 @@ int QUICK_INDEX_MERGE_SELECT::read_keys_and_merge()
|
|||
if (cur_quick->file->inited != handler::NONE)
|
||||
cur_quick->file->ha_index_end();
|
||||
if (cur_quick->init() || cur_quick->reset())
|
||||
{
|
||||
delete unique;
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (result)
|
||||
|
@ -8389,17 +8399,13 @@ int QUICK_INDEX_MERGE_SELECT::read_keys_and_merge()
|
|||
if (result != HA_ERR_END_OF_FILE)
|
||||
{
|
||||
cur_quick->range_end();
|
||||
delete unique;
|
||||
DBUG_RETURN(result);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (thd->killed)
|
||||
{
|
||||
delete unique;
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
/* skip row if it will be retrieved by clustered PK scan */
|
||||
if (pk_quick_select && pk_quick_select->row_in_ranges())
|
||||
|
@ -8408,10 +8414,7 @@ int QUICK_INDEX_MERGE_SELECT::read_keys_and_merge()
|
|||
cur_quick->file->position(cur_quick->record);
|
||||
result= unique->unique_add((char*)cur_quick->file->ref);
|
||||
if (result)
|
||||
{
|
||||
delete unique;
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -8420,7 +8423,6 @@ int QUICK_INDEX_MERGE_SELECT::read_keys_and_merge()
|
|||
sequence.
|
||||
*/
|
||||
result= unique->get(head);
|
||||
delete unique;
|
||||
doing_pk_scan= FALSE;
|
||||
/* index_merge currently doesn't support "using index" at all */
|
||||
head->set_keyread(FALSE);
|
||||
|
@ -10496,7 +10498,7 @@ QUICK_GROUP_MIN_MAX_SELECT(TABLE *table, JOIN *join_arg, bool have_min_arg,
|
|||
ha_rows records_arg, uint key_infix_len_arg,
|
||||
uchar *key_infix_arg, MEM_ROOT *parent_alloc,
|
||||
bool is_index_scan_arg)
|
||||
:join(join_arg), index_info(index_info_arg),
|
||||
:file(table->file), join(join_arg), index_info(index_info_arg),
|
||||
group_prefix_len(group_prefix_len_arg),
|
||||
group_key_parts(group_key_parts_arg), have_min(have_min_arg),
|
||||
have_max(have_max_arg), have_agg_distinct(have_agg_distinct_arg),
|
||||
|
@ -10506,7 +10508,6 @@ QUICK_GROUP_MIN_MAX_SELECT(TABLE *table, JOIN *join_arg, bool have_min_arg,
|
|||
is_index_scan(is_index_scan_arg)
|
||||
{
|
||||
head= table;
|
||||
file= head->file;
|
||||
index= use_index;
|
||||
record= head->record[0];
|
||||
tmp_record= head->record[1];
|
||||
|
|
|
@ -514,6 +514,7 @@ public:
|
|||
|
||||
class QUICK_INDEX_MERGE_SELECT : public QUICK_SELECT_I
|
||||
{
|
||||
Unique *unique;
|
||||
public:
|
||||
QUICK_INDEX_MERGE_SELECT(THD *thd, TABLE *table);
|
||||
~QUICK_INDEX_MERGE_SELECT();
|
||||
|
@ -697,7 +698,7 @@ private:
|
|||
class QUICK_GROUP_MIN_MAX_SELECT : public QUICK_SELECT_I
|
||||
{
|
||||
private:
|
||||
handler *file; /* The handler used to get data. */
|
||||
handler * const file; /* The handler used to get data. */
|
||||
JOIN *join; /* Descriptor of the current query */
|
||||
KEY *index_info; /* The index chosen for data access */
|
||||
uchar *record; /* Buffer where the next record is returned. */
|
||||
|
|
|
@ -3291,6 +3291,9 @@ public:
|
|||
void reset();
|
||||
bool walk(tree_walk_action action, void *walk_action_arg);
|
||||
|
||||
uint get_size() const { return size; }
|
||||
ulonglong get_max_in_memory_size() const { return max_in_memory_size; }
|
||||
|
||||
friend int unique_write_to_file(uchar* key, element_count count, Unique *unique);
|
||||
friend int unique_write_to_ptrs(uchar* key, element_count count, Unique *unique);
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue