Commit c4097382 authored by unknown's avatar unknown

Automatic merge.

parents b1a177e4 1e6bd6b4
No related merge requests found
set @save_optimizer_switch=@@optimizer_switch;
drop table if exists t1, t2;
#
# LP BUG#608744
#
set @save_optimizer_switch=@@optimizer_switch;
set @@optimizer_switch="materialization=on,semijoin=off,partial_match_rowid_merge=on,partial_match_table_scan=off";
create table t1 (a1 char(1), a2 char(1));
insert into t1 values (NULL, 'b');
......@@ -11,7 +11,6 @@ insert into t2 values ('a','b'), ('c', 'd');
select * from t1 where (a1, a2) NOT IN (select b1, b2 from t2);
a1 a2
drop table t1,t2;
set @@optimizer_switch=@save_optimizer_switch;
#
# LP BUG#601156
#
......@@ -21,7 +20,6 @@ INSERT INTO t1 VALUES (4,NULL);
CREATE TABLE t2 (b1 int DEFAULT NULL, b2 int DEFAULT NULL);
INSERT INTO t2 VALUES (6,NULL);
INSERT INTO t2 VALUES (NULL,0);
set @save_optimizer_switch=@@optimizer_switch;
set @@optimizer_switch='materialization=on,semijoin=off,partial_match_rowid_merge=on,partial_match_table_scan=on';
EXPLAIN EXTENDED
SELECT * FROM (SELECT * FROM t1 WHERE a1 NOT IN (SELECT b2 FROM t2)) table1;
......@@ -31,11 +29,9 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
Warnings:
Note 1003 select `test`.`t1`.`a1` AS `a1`,`test`.`t1`.`a2` AS `a2` from `test`.`t1` where (not(<in_optimizer>(`test`.`t1`.`a1`,`test`.`t1`.`a1` in ( <materialize> (select `test`.`t2`.`b2` from `test`.`t2` ), <primary_index_lookup>(`test`.`t1`.`a1` in <temporary table> on distinct_key where ((`test`.`t1`.`a1` = `<subquery3>`.`b2`)))))))
DROP TABLE t1, t2;
set @@optimizer_switch=@save_optimizer_switch;
#
# LP BUG#613009 Crash in Ordered_key::get_field_idx
#
set @save_optimizer_switch=@@optimizer_switch;
set @@optimizer_switch='materialization=on,semijoin=off,partial_match_rowid_merge=on,partial_match_table_scan=off';
create table t1 (a1 char(3) DEFAULT NULL, a2 char(3) DEFAULT NULL);
insert into t1 values (NULL, 'a21'), (NULL, 'a22');
......@@ -46,7 +42,6 @@ id select_type table type possible_keys key key_len ref rows Extra
select * from t1 where (a1, a2) not in (select a1, a2 from t1);
a1 a2
drop table t1;
set @@optimizer_switch=@save_optimizer_switch;
#
# LP BUG#680058 void Ordered_key::add_key(rownum_t):
# Assertion `key_buff_elements && cur_key_idx < key_buff_elements' failed
......@@ -55,10 +50,99 @@ create table t1 (f1 char(1), f2 char(1));
insert into t1 values ('t', '0'), ('0', 't');
create table t2 (f3 char(1), f4 char(1));
insert into t2 values ('t', NULL), ('t', NULL), ('d', 'y');
set @save_optimizer_switch=@@optimizer_switch;
SET @@optimizer_switch='materialization=on,partial_match_rowid_merge=on,partial_match_table_scan=off,semijoin=off';
set @@optimizer_switch='materialization=on,partial_match_rowid_merge=on,partial_match_table_scan=off,semijoin=off';
select * from t1 where (f1, f2) not in (select * from t2);
f1 f2
0 t
set @@optimizer_switch=@save_optimizer_switch;
drop table t1, t2;
#
# LP BUG#809245 Second assertion `bit < (map)->n_bits' with partial_match_merge
#
CREATE TABLE t1 (d varchar(32)) ;
INSERT INTO t1 VALUES ('r');
CREATE TABLE t2 ( a int, c varchar(32)) ;
INSERT INTO t2 VALUES (5,'r');
CREATE TABLE t3 ( a int NOT NULL , d varchar(32)) ;
INSERT INTO t3 VALUES (10,'g');
set @@optimizer_switch='materialization=on,partial_match_rowid_merge=on,partial_match_table_scan=off,in_to_exists=off';
EXPLAIN SELECT *
FROM t1
WHERE (t1.d , t1.d) NOT IN (
SELECT t3.d , t2.c
FROM t3 LEFT JOIN t2 ON t3.a = t2.a);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 system NULL NULL NULL NULL 1
2 SUBQUERY t3 system NULL NULL NULL NULL 1
2 SUBQUERY t2 system NULL NULL NULL NULL 1
SELECT *
FROM t1
WHERE (t1.d , t1.d) NOT IN (
SELECT t3.d , t2.c
FROM t3 LEFT JOIN t2 ON t3.a = t2.a);
d
r
set @@optimizer_switch='materialization=off,in_to_exists=on';
EXPLAIN SELECT *
FROM t1
WHERE (t1.d , t1.d) NOT IN (
SELECT t3.d , t2.c
FROM t3 LEFT JOIN t2 ON t3.a = t2.a);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 system NULL NULL NULL NULL 1
2 DEPENDENT SUBQUERY t3 system NULL NULL NULL NULL 1
2 DEPENDENT SUBQUERY t2 system NULL NULL NULL NULL 1
SELECT *
FROM t1
WHERE (t1.d , t1.d) NOT IN (
SELECT t3.d , t2.c
FROM t3 LEFT JOIN t2 ON t3.a = t2.a);
d
r
drop table t1, t2, t3;
#
# LP BUG#809266 Diverging results with partial_match_rowid_merge=on
#
CREATE TABLE t1 (c int) ;
INSERT INTO t1 VALUES (0),(0);
CREATE TABLE t2 (a int, b int) ;
INSERT INTO t2 VALUES (6,3), (9,NULL);
set @@optimizer_switch='materialization=on,partial_match_rowid_merge=on,partial_match_table_scan=off,in_to_exists=off';
EXPLAIN
SELECT * FROM t1 WHERE (6, 4 ) NOT IN (SELECT b, a FROM t2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2
2 SUBQUERY t2 ALL NULL NULL NULL NULL 2
SELECT * FROM t1 WHERE (6, 4 ) NOT IN (SELECT b, a FROM t2);
c
0
0
EXPLAIN
SELECT * FROM t1 WHERE (6, 4 ) NOT IN (SELECT a, b FROM t2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2
2 SUBQUERY t2 ALL NULL NULL NULL NULL 2
SELECT * FROM t1 WHERE (6, 4 ) NOT IN (SELECT a, b FROM t2);
c
0
0
set @@optimizer_switch='materialization=off,in_to_exists=on';
EXPLAIN
SELECT * FROM t1 WHERE (6, 4 ) NOT IN (SELECT b, a FROM t2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2
2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
SELECT * FROM t1 WHERE (6, 4 ) NOT IN (SELECT b, a FROM t2);
c
0
0
EXPLAIN
SELECT * FROM t1 WHERE (6, 4 ) NOT IN (SELECT a, b FROM t2);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2
2 DEPENDENT SUBQUERY t2 ALL NULL NULL NULL NULL 2 Using where
SELECT * FROM t1 WHERE (6, 4 ) NOT IN (SELECT a, b FROM t2);
c
0
0
drop table t1, t2;
set @@optimizer_switch=@save_optimizer_switch;
......@@ -3,6 +3,8 @@
# MWL#68: Subquery optimization: Efficient NOT IN execution with NULLs
#
set @save_optimizer_switch=@@optimizer_switch;
--disable_warnings
drop table if exists t1, t2;
--enable_warnings
......@@ -10,7 +12,6 @@ drop table if exists t1, t2;
--echo #
--echo # LP BUG#608744
--echo #
set @save_optimizer_switch=@@optimizer_switch;
set @@optimizer_switch="materialization=on,semijoin=off,partial_match_rowid_merge=on,partial_match_table_scan=off";
create table t1 (a1 char(1), a2 char(1));
insert into t1 values (NULL, 'b');
......@@ -18,7 +19,6 @@ create table t2 (b1 char(1), b2 char(2));
insert into t2 values ('a','b'), ('c', 'd');
select * from t1 where (a1, a2) NOT IN (select b1, b2 from t2);
drop table t1,t2;
set @@optimizer_switch=@save_optimizer_switch;
--echo #
......@@ -32,20 +32,17 @@ CREATE TABLE t2 (b1 int DEFAULT NULL, b2 int DEFAULT NULL);
INSERT INTO t2 VALUES (6,NULL);
INSERT INTO t2 VALUES (NULL,0);
set @save_optimizer_switch=@@optimizer_switch;
set @@optimizer_switch='materialization=on,semijoin=off,partial_match_rowid_merge=on,partial_match_table_scan=on';
EXPLAIN EXTENDED
SELECT * FROM (SELECT * FROM t1 WHERE a1 NOT IN (SELECT b2 FROM t2)) table1;
DROP TABLE t1, t2;
set @@optimizer_switch=@save_optimizer_switch;
--echo #
--echo # LP BUG#613009 Crash in Ordered_key::get_field_idx
--echo #
set @save_optimizer_switch=@@optimizer_switch;
set @@optimizer_switch='materialization=on,semijoin=off,partial_match_rowid_merge=on,partial_match_table_scan=off';
create table t1 (a1 char(3) DEFAULT NULL, a2 char(3) DEFAULT NULL);
......@@ -53,7 +50,6 @@ insert into t1 values (NULL, 'a21'), (NULL, 'a22');
explain select * from t1 where (a1, a2) not in (select a1, a2 from t1);
select * from t1 where (a1, a2) not in (select a1, a2 from t1);
drop table t1;
set @@optimizer_switch=@save_optimizer_switch;
--echo #
--echo # LP BUG#680058 void Ordered_key::add_key(rownum_t):
......@@ -65,8 +61,84 @@ insert into t1 values ('t', '0'), ('0', 't');
create table t2 (f3 char(1), f4 char(1));
insert into t2 values ('t', NULL), ('t', NULL), ('d', 'y');
set @save_optimizer_switch=@@optimizer_switch;
SET @@optimizer_switch='materialization=on,partial_match_rowid_merge=on,partial_match_table_scan=off,semijoin=off';
set @@optimizer_switch='materialization=on,partial_match_rowid_merge=on,partial_match_table_scan=off,semijoin=off';
select * from t1 where (f1, f2) not in (select * from t2);
set @@optimizer_switch=@save_optimizer_switch;
drop table t1, t2;
--echo #
--echo # LP BUG#809245 Second assertion `bit < (map)->n_bits' with partial_match_merge
--echo #
CREATE TABLE t1 (d varchar(32)) ;
INSERT INTO t1 VALUES ('r');
CREATE TABLE t2 ( a int, c varchar(32)) ;
INSERT INTO t2 VALUES (5,'r');
CREATE TABLE t3 ( a int NOT NULL , d varchar(32)) ;
INSERT INTO t3 VALUES (10,'g');
set @@optimizer_switch='materialization=on,partial_match_rowid_merge=on,partial_match_table_scan=off,in_to_exists=off';
EXPLAIN SELECT *
FROM t1
WHERE (t1.d , t1.d) NOT IN (
SELECT t3.d , t2.c
FROM t3 LEFT JOIN t2 ON t3.a = t2.a);
SELECT *
FROM t1
WHERE (t1.d , t1.d) NOT IN (
SELECT t3.d , t2.c
FROM t3 LEFT JOIN t2 ON t3.a = t2.a);
set @@optimizer_switch='materialization=off,in_to_exists=on';
EXPLAIN SELECT *
FROM t1
WHERE (t1.d , t1.d) NOT IN (
SELECT t3.d , t2.c
FROM t3 LEFT JOIN t2 ON t3.a = t2.a);
SELECT *
FROM t1
WHERE (t1.d , t1.d) NOT IN (
SELECT t3.d , t2.c
FROM t3 LEFT JOIN t2 ON t3.a = t2.a);
drop table t1, t2, t3;
--echo #
--echo # LP BUG#809266 Diverging results with partial_match_rowid_merge=on
--echo #
CREATE TABLE t1 (c int) ;
INSERT INTO t1 VALUES (0),(0);
CREATE TABLE t2 (a int, b int) ;
INSERT INTO t2 VALUES (6,3), (9,NULL);
set @@optimizer_switch='materialization=on,partial_match_rowid_merge=on,partial_match_table_scan=off,in_to_exists=off';
EXPLAIN
SELECT * FROM t1 WHERE (6, 4 ) NOT IN (SELECT b, a FROM t2);
SELECT * FROM t1 WHERE (6, 4 ) NOT IN (SELECT b, a FROM t2);
EXPLAIN
SELECT * FROM t1 WHERE (6, 4 ) NOT IN (SELECT a, b FROM t2);
SELECT * FROM t1 WHERE (6, 4 ) NOT IN (SELECT a, b FROM t2);
set @@optimizer_switch='materialization=off,in_to_exists=on';
EXPLAIN
SELECT * FROM t1 WHERE (6, 4 ) NOT IN (SELECT b, a FROM t2);
SELECT * FROM t1 WHERE (6, 4 ) NOT IN (SELECT b, a FROM t2);
EXPLAIN
SELECT * FROM t1 WHERE (6, 4 ) NOT IN (SELECT a, b FROM t2);
SELECT * FROM t1 WHERE (6, 4 ) NOT IN (SELECT a, b FROM t2);
drop table t1, t2;
set @@optimizer_switch=@save_optimizer_switch;
......@@ -3864,8 +3864,7 @@ subselect_hash_sj_engine::get_strategy_using_data()
bitmap_set_bit(&non_null_key_parts, i);
--count_partial_match_columns;
}
if (result_sink->get_null_count_of_col(i) ==
tmp_table->file->stats.records)
if (result_sink->get_null_count_of_col(i) == tmp_table->file->stats.records)
++count_null_only_columns;
}
......@@ -4573,29 +4572,36 @@ int subselect_hash_sj_engine::exec()
if (strategy == PARTIAL_MATCH)
{
uint count_pm_keys; /* Total number of keys needed for partial matching. */
MY_BITMAP *nn_key_parts; /* The key parts of the only non-NULL index. */
uint covering_null_row_width;
MY_BITMAP *nn_key_parts= NULL; /* Key parts of the only non-NULL index. */
uint count_non_null_columns= 0; /* Number of columns in nn_key_parts. */
bool has_covering_null_row;
bool has_covering_null_columns;
select_materialize_with_stats *result_sink=
(select_materialize_with_stats *) result;
uint field_count= tmp_table->s->fields;
nn_key_parts= (count_partial_match_columns < tmp_table->s->fields) ?
&non_null_key_parts : NULL;
if (result_sink->get_max_nulls_in_row() ==
tmp_table->s->fields -
(nn_key_parts ? bitmap_bits_set(nn_key_parts) : 0))
covering_null_row_width= result_sink->get_max_nulls_in_row();
else
covering_null_row_width= 0;
if (count_partial_match_columns < field_count)
{
nn_key_parts= &non_null_key_parts;
count_non_null_columns= bitmap_bits_set(nn_key_parts);
}
has_covering_null_row= (result_sink->get_max_nulls_in_row() == field_count);
has_covering_null_columns= (count_non_null_columns +
count_null_only_columns == field_count);
if (covering_null_row_width)
count_pm_keys= nn_key_parts ? 1 : 0;
if (has_covering_null_row)
{
DBUG_ASSERT(count_partial_match_columns = field_count);
count_pm_keys= 0;
}
else if (has_covering_null_columns)
count_pm_keys= 1;
else
count_pm_keys= count_partial_match_columns - count_null_only_columns +
(nn_key_parts ? 1 : 0);
(nn_key_parts ? 1 : 0);
choose_partial_match_strategy(test(nn_key_parts),
test(covering_null_row_width),
has_covering_null_row,
&partial_match_key_parts);
DBUG_ASSERT(strategy == PARTIAL_MATCH_MERGE ||
strategy == PARTIAL_MATCH_SCAN);
......@@ -4605,7 +4611,8 @@ int subselect_hash_sj_engine::exec()
new subselect_rowid_merge_engine(thd, (subselect_uniquesubquery_engine*)
lookup_engine, tmp_table,
count_pm_keys,
covering_null_row_width,
has_covering_null_row,
has_covering_null_columns,
item, result,
semi_join_conds->argument_list());
if (!pm_engine ||
......@@ -4630,7 +4637,8 @@ int subselect_hash_sj_engine::exec()
lookup_engine, tmp_table,
item, result,
semi_join_conds->argument_list(),
covering_null_row_width)))
has_covering_null_row,
has_covering_null_columns)))
{
/* This is an irrecoverable error. */
res= 1;
......@@ -5066,11 +5074,13 @@ subselect_partial_match_engine::subselect_partial_match_engine(
TABLE *tmp_table_arg, Item_subselect *item_arg,
select_result_interceptor *result_arg,
List<Item> *equi_join_conds_arg,
uint covering_null_row_width_arg)
bool has_covering_null_row_arg,
bool has_covering_null_columns_arg)
:subselect_engine(thd_arg, item_arg, result_arg),
tmp_table(tmp_table_arg), lookup_engine(engine_arg),
equi_join_conds(equi_join_conds_arg),
covering_null_row_width(covering_null_row_width_arg)
has_covering_null_row(has_covering_null_row_arg),
has_covering_null_columns(has_covering_null_columns_arg)
{}
......@@ -5108,7 +5118,7 @@ int subselect_partial_match_engine::exec()
}
}
if (covering_null_row_width == tmp_table->s->fields)
if (has_covering_null_row)
{
/*
If there is a NULL-only row that coveres all columns the result of IN
......@@ -5172,7 +5182,6 @@ void subselect_partial_match_engine::print(String *str,
/*
@param non_null_key_parts
@param partial_match_key_parts A union of all single-column NULL key parts.
@param count_partial_match_columns Number of NULL keyparts (set bits above).
@retval FALSE the engine was initialized successfully
@retval TRUE there was some (memory allocation) error during initialization,
......@@ -5193,20 +5202,26 @@ subselect_rowid_merge_engine::init(MY_BITMAP *non_null_key_parts,
Item_in_subselect *item_in= (Item_in_subselect*) item;
int error;
if (keys_count == 0)
if (merge_keys_count == 0)
{
DBUG_ASSERT(bitmap_bits_set(partial_match_key_parts) == 0 ||
has_covering_null_row);
/* There is nothing to initialize, we will only do regular lookups. */
return FALSE;
}
DBUG_ASSERT(!covering_null_row_width || (covering_null_row_width &&
keys_count == 1 &&
non_null_key_parts));
/*
If all nullable columns contain only NULLs, there must be one index
over all non-null columns.
*/
DBUG_ASSERT(!has_covering_null_columns ||
(has_covering_null_columns &&
merge_keys_count == 1 && non_null_key_parts));
/*
Allocate buffers to hold the merged keys and the mapping between rowids and
row numbers.
*/
if (!(merge_keys= (Ordered_key**) thd->alloc(keys_count *
if (!(merge_keys= (Ordered_key**) thd->alloc(merge_keys_count *
sizeof(Ordered_key*))) ||
!(row_num_to_rowid= (uchar*) my_malloc((size_t)(row_count * rowid_length),
MYF(MY_WME))))
......@@ -5225,15 +5240,13 @@ subselect_rowid_merge_engine::init(MY_BITMAP *non_null_key_parts,
}
/*
If there is a covering NULL row, the only key that is needed is the
only non-NULL key that is already created above. We create keys on
NULL-able columns only if there is no covering NULL row.
If all nullable columns contain NULLs, the only key that is needed is the
only non-NULL key that is already created above.
*/
if (!covering_null_row_width)
if (!has_covering_null_columns)
{
if (bitmap_init_memroot(&matching_keys, keys_count, thd->mem_root) ||
bitmap_init_memroot(&matching_outer_cols, keys_count, thd->mem_root) ||
bitmap_init_memroot(&null_only_columns, keys_count, thd->mem_root))
if (bitmap_init_memroot(&matching_keys, merge_keys_count, thd->mem_root) ||
bitmap_init_memroot(&matching_outer_cols, merge_keys_count, thd->mem_root))
return TRUE;
/*
......@@ -5242,31 +5255,25 @@ subselect_rowid_merge_engine::init(MY_BITMAP *non_null_key_parts,
*/
for (uint i= 0; i < partial_match_key_parts->n_bits; i++)
{
if (!bitmap_is_set(partial_match_key_parts, i))
/* Skip columns that have no NULLs, or contain only NULLs. */
if (!bitmap_is_set(partial_match_key_parts, i) ||
result_sink->get_null_count_of_col(i) == row_count)
continue;
if (result_sink->get_null_count_of_col(i) == row_count)
{
bitmap_set_bit(&null_only_columns, cur_keyid);
continue;
}
else
{
merge_keys[cur_keyid]= new Ordered_key(
merge_keys[cur_keyid]= new Ordered_key(
cur_keyid, tmp_table,
item_in->left_expr->element_index(i),
result_sink->get_null_count_of_col(i),
result_sink->get_min_null_of_col(i),
result_sink->get_max_null_of_col(i),
row_num_to_rowid);
if (merge_keys[cur_keyid]->init(i))
return TRUE;
merge_keys[cur_keyid]->first();
}
if (merge_keys[cur_keyid]->init(i))
return TRUE;
merge_keys[cur_keyid]->first();
++cur_keyid;
}
}
DBUG_ASSERT(cur_keyid == keys_count);
DBUG_ASSERT(cur_keyid == merge_keys_count);
/* Populate the indexes with data from the temporary table. */
if (tmp_table->file->ha_rnd_init_with_error(1))
......@@ -5307,7 +5314,7 @@ subselect_rowid_merge_engine::init(MY_BITMAP *non_null_key_parts,
non_null_key->add_key(cur_rownum);
}
for (uint i= (non_null_key ? 1 : 0); i < keys_count; i++)
for (uint i= (non_null_key ? 1 : 0); i < merge_keys_count; i++)
{
/*
Check if the first and only indexed column contains NULL in the curent
......@@ -5324,14 +5331,14 @@ subselect_rowid_merge_engine::init(MY_BITMAP *non_null_key_parts,
tmp_table->file->ha_rnd_end();
/* Sort all the keys by their NULL selectivity. */
my_qsort(merge_keys, keys_count, sizeof(Ordered_key*),
my_qsort(merge_keys, merge_keys_count, sizeof(Ordered_key*),
(qsort_cmp) cmp_keys_by_null_selectivity);
/* Sort the keys in each of the indexes. */
for (uint i= 0; i < keys_count; i++)
for (uint i= 0; i < merge_keys_count; i++)
merge_keys[i]->sort_keys();
if (init_queue(&pq, keys_count, 0, FALSE,
if (init_queue(&pq, merge_keys_count, 0, FALSE,
subselect_rowid_merge_engine::cmp_keys_by_cur_rownum, NULL,
0, 0))
return TRUE;
......@@ -5343,10 +5350,10 @@ subselect_rowid_merge_engine::init(MY_BITMAP *non_null_key_parts,
subselect_rowid_merge_engine::~subselect_rowid_merge_engine()
{
/* None of the resources below is allocated if there are no ordered keys. */
if (keys_count)
if (merge_keys_count)
{
my_free((char*) row_num_to_rowid, MYF(0));
for (uint i= 0; i < keys_count; i++)
for (uint i= 0; i < merge_keys_count; i++)
delete merge_keys[i];
delete_queue(&pq);
if (tmp_table->file->inited == handler::RND)
......@@ -5404,6 +5411,10 @@ subselect_rowid_merge_engine::cmp_keys_by_cur_rownum(void *arg,
Check if certain table row contains a NULL in all columns for which there is
no match in the corresponding value index.
@note
There is no need to check the columns that contain only NULLs, because
those are guaranteed to match.
@retval TRUE if a NULL row exists
@retval FALSE otherwise
*/
......@@ -5411,16 +5422,14 @@ subselect_rowid_merge_engine::cmp_keys_by_cur_rownum(void *arg,
bool subselect_rowid_merge_engine::test_null_row(rownum_t row_num)
{
Ordered_key *cur_key;
uint cur_id;
for (uint i = 0; i < keys_count; i++)
for (uint i = 0; i < merge_keys_count; i++)
{
cur_key= merge_keys[i];
cur_id= cur_key->get_keyid();
if (bitmap_is_set(&matching_keys, cur_id))
if (bitmap_is_set(&matching_keys, cur_key->get_keyid()))
{
/*
The key 'i' (with id 'cur_keyid') already matches a value in row 'row_num',
thus we skip it as it can't possibly match a NULL.
The key 'i' (with id 'cur_keyid') already matches a value in row
'row_num', thus we skip it as it can't possibly match a NULL.
*/
continue;
}
......@@ -5465,11 +5474,10 @@ bool subselect_rowid_merge_engine::partial_match()
}
/*
If there is a NULL (sub)row that covers all NULL-able columns,
then there is a guranteed partial match, and we don't need to search
for the matching row.
*/
if (covering_null_row_width)
If all nullable columns contain only NULLs, then there is a guranteed
partial match, and we don't need to search for a matching row.
*/
if (has_covering_null_columns)
{
res= TRUE;
goto end;
......@@ -5481,7 +5489,7 @@ bool subselect_rowid_merge_engine::partial_match()
Do not add the non_null_key, since it was already processed above.
*/
bitmap_clear_all(&matching_outer_cols);
for (uint i= test(non_null_key); i < keys_count; i++)
for (uint i= test(non_null_key); i < merge_keys_count; i++)
{
DBUG_ASSERT(merge_keys[i]->get_column_count() == 1);
if (merge_keys[i]->get_search_key(0)->null_value)
......@@ -5519,7 +5527,6 @@ bool subselect_rowid_merge_engine::partial_match()
min_key= (Ordered_key*) queue_remove_top(&pq);
min_row_num= min_key->current();
bitmap_copy(&matching_keys, &null_only_columns);
bitmap_set_bit(&matching_keys, min_key->get_keyid());
bitmap_union(&matching_keys, &matching_outer_cols);
if (min_key->next_same())
......@@ -5555,7 +5562,6 @@ bool subselect_rowid_merge_engine::partial_match()
{
min_key= cur_key;
min_row_num= cur_row_num;
bitmap_copy(&matching_keys, &null_only_columns);
bitmap_set_bit(&matching_keys, min_key->get_keyid());
bitmap_union(&matching_keys, &matching_outer_cols);
}
......@@ -5588,10 +5594,12 @@ subselect_table_scan_engine::subselect_table_scan_engine(
Item_subselect *item_arg,
select_result_interceptor *result_arg,
List<Item> *equi_join_conds_arg,
uint covering_null_row_width_arg)
bool has_covering_null_row_arg,
bool has_covering_null_columns_arg)
:subselect_partial_match_engine(thd_arg, engine_arg, tmp_table_arg, item_arg,
result_arg, equi_join_conds_arg,
covering_null_row_width_arg)
has_covering_null_row_arg,
has_covering_null_columns_arg)
{}
......@@ -5630,10 +5638,6 @@ bool subselect_table_scan_engine::partial_match()
tmp_table->file->extra_opt(HA_EXTRA_CACHE,
current_thd->variables.read_buff_size);
/*
TIMOUR:
scan_table() also calls "table->null_row= 0;", why, do we need it?
*/
for (;;)
{
error= tmp_table->file->ha_rnd_next(tmp_table->record[0]);
......
......@@ -1131,11 +1131,18 @@ protected:
/* A list of equalities between each pair of IN operands. */
List<Item> *equi_join_conds;
/*
If there is a row, such that all its NULL-able components are NULL, this
member is set to the number of covered columns. If there is no covering
row, then this is 0.
True if there is an all NULL row in tmp_table. If so, then if there is
no complete match, there is a guaranteed partial match.
*/
uint covering_null_row_width;
bool has_covering_null_row;
/*
True if all nullable columns of tmp_table consist of only NULL values.
If so, then if there is a match in the non-null columns, there is a
guaranteed partial match.
*/
bool has_covering_null_columns;
protected:
virtual bool partial_match()= 0;
public:
......@@ -1144,7 +1151,8 @@ public:
TABLE *tmp_table_arg, Item_subselect *item_arg,
select_result_interceptor *result_arg,
List<Item> *equi_join_conds_arg,
uint covering_null_row_width_arg);
bool has_covering_null_row_arg,
bool has_covering_null_columns_arg);
int prepare() { return 0; }
int exec();
void fix_length_and_dec(Item_cache**) {}
......@@ -1191,11 +1199,6 @@ protected:
outer reference.
*/
MY_BITMAP matching_outer_cols;
/*
Columns that consist of only NULLs. Such columns match any value.
Computed once per query execution.
*/
MY_BITMAP null_only_columns;
/*
Indexes of row numbers, sorted by <column_value, row_number>. If an
index may contain NULLs, the NULLs are stored efficiently in a bitmap.
......@@ -1205,13 +1208,13 @@ protected:
non-NULL columns, it is contained in keys[0].
*/
Ordered_key **merge_keys;
/* The number of elements in keys. */
uint keys_count;
/* The number of elements in merge_keys. */
uint merge_keys_count;
/*
An index on all non-NULL columns of 'tmp_table'. The index has the
logical form: <[v_i1 | ... | v_ik], rownum>. It allows to find the row
number where the columns c_i1,...,c1_k contain the values v_i1,...,v_ik.
If such an index exists, it is always the first element of 'keys'.
If such an index exists, it is always the first element of 'merge_keys'.
*/
Ordered_key *non_null_key;
/*
......@@ -1236,15 +1239,17 @@ protected:
public:
subselect_rowid_merge_engine(THD *thd_arg,
subselect_uniquesubquery_engine *engine_arg,
TABLE *tmp_table_arg, uint keys_count_arg,
uint covering_null_row_width_arg,
TABLE *tmp_table_arg, uint merge_keys_count_arg,
bool has_covering_null_row_arg,
bool has_covering_null_columns_arg,
Item_subselect *item_arg,
select_result_interceptor *result_arg,
List<Item> *equi_join_conds_arg)
:subselect_partial_match_engine(thd_arg, engine_arg, tmp_table_arg,
item_arg, result_arg, equi_join_conds_arg,
covering_null_row_width_arg),
keys_count(keys_count_arg), non_null_key(NULL)
has_covering_null_row_arg,
has_covering_null_columns_arg),
merge_keys_count(merge_keys_count_arg), non_null_key(NULL)
{}
~subselect_rowid_merge_engine();
bool init(MY_BITMAP *non_null_key_parts, MY_BITMAP *partial_match_key_parts);
......@@ -1263,7 +1268,8 @@ public:
TABLE *tmp_table_arg, Item_subselect *item_arg,
select_result_interceptor *result_arg,
List<Item> *equi_join_conds_arg,
uint covering_null_row_width_arg);
bool has_covering_null_row_arg,
bool has_covering_null_columns_arg);
void cleanup();
virtual enum_engine_type engine_type() { return TABLE_SCAN_ENGINE; }
};
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment