Commit 37e9714c authored by Sergey Petrunya's avatar Sergey Petrunya

MDEV-4840: Wrong result (missing rows) on LEFT JOIN with InnoDB tables

Fix two problems in table elimination code:
- Before marking a "value" as bound, check if it is already bound. Marking the 
  same value as bound twice could confuse a module that depends on this value, 
  because Dep_module_XXX use counters to know when they become bound.

- When checking whether field is part of a key, ignore "extended keys" property.
parent c97ae6b5
...@@ -628,4 +628,24 @@ id select_type table type possible_keys key key_len ref rows filtered Extra ...@@ -628,4 +628,24 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
Warnings: Warnings:
Note 1003 select `test`.`t2`.`b` AS `b` from `test`.`t2` where <expr_cache><`test`.`t2`.`b`>(<in_optimizer>(`test`.`t2`.`b`,<exists>(select sum(1) from dual having (<cache>(`test`.`t2`.`b`) = <ref_null_helper>(sum(1)))))) Note 1003 select `test`.`t2`.`b` AS `b` from `test`.`t2` where <expr_cache><`test`.`t2`.`b`>(<in_optimizer>(`test`.`t2`.`b`,<exists>(select sum(1) from dual having (<cache>(`test`.`t2`.`b`) = <ref_null_helper>(sum(1))))))
DROP TABLE t1,t2; DROP TABLE t1,t2;
#
# MDEV-4840: Wrong result (missing rows) on LEFT JOIN with InnoDB tables
#
CREATE TABLE t1 (alpha3 VARCHAR(3));
INSERT INTO t1 VALUES ('USA'),('CAN');
CREATE TABLE t2 ( t3_code VARCHAR(3), name VARCHAR(64));
INSERT INTO t2 VALUES ('USA','Austin'),('USA','Boston');
CREATE TABLE t3 ( code VARCHAR(3), name VARCHAR(64), PRIMARY KEY (code), UNIQUE KEY (name));
INSERT INTO t3 VALUES ('CAN','Canada'),('USA','United States');
SELECT * FROM t1 LEFT JOIN ( t2 LEFT JOIN t3 ON t2.t3_code = t3.code ) ON t1.alpha3 = t3.code;
alpha3 t3_code name code name
USA USA Austin USA United States
USA USA Boston USA United States
CAN NULL NULL NULL NULL
SELECT t1.alpha3 FROM t1 LEFT JOIN ( t2 LEFT JOIN t3 ON t2.t3_code = t3.code ) ON t1.alpha3 = t3.code;
alpha3
USA
USA
CAN
DROP TABLE t1, t2, t3;
SET optimizer_switch=@save_optimizer_switch; SET optimizer_switch=@save_optimizer_switch;
...@@ -561,4 +561,21 @@ EXPLAIN EXTENDED ...@@ -561,4 +561,21 @@ EXPLAIN EXTENDED
DROP TABLE t1,t2; DROP TABLE t1,t2;
--echo #
--echo # MDEV-4840: Wrong result (missing rows) on LEFT JOIN with InnoDB tables
--echo #
CREATE TABLE t1 (alpha3 VARCHAR(3));
INSERT INTO t1 VALUES ('USA'),('CAN');
CREATE TABLE t2 ( t3_code VARCHAR(3), name VARCHAR(64));
INSERT INTO t2 VALUES ('USA','Austin'),('USA','Boston');
CREATE TABLE t3 ( code VARCHAR(3), name VARCHAR(64), PRIMARY KEY (code), UNIQUE KEY (name));
INSERT INTO t3 VALUES ('CAN','Canada'),('USA','United States');
SELECT * FROM t1 LEFT JOIN ( t2 LEFT JOIN t3 ON t2.t3_code = t3.code ) ON t1.alpha3 = t3.code;
SELECT t1.alpha3 FROM t1 LEFT JOIN ( t2 LEFT JOIN t3 ON t2.t3_code = t3.code ) ON t1.alpha3 = t3.code;
DROP TABLE t1, t2, t3;
SET optimizer_switch=@save_optimizer_switch; SET optimizer_switch=@save_optimizer_switch;
...@@ -892,8 +892,11 @@ bool Dep_analysis_context::run_wave(List<Dep_module> *new_bound_modules) ...@@ -892,8 +892,11 @@ bool Dep_analysis_context::run_wave(List<Dep_module> *new_bound_modules)
iter= module->init_unbound_values_iter(iter_buf); iter= module->init_unbound_values_iter(iter_buf);
while ((value= module->get_next_unbound_value(this, iter))) while ((value= module->get_next_unbound_value(this, iter)))
{ {
value->make_bound(); if (!value->is_bound())
new_bound_values.push_back(value); {
value->make_bound();
new_bound_values.push_back(value);
}
} }
} }
new_bound_modules->empty(); new_bound_modules->empty();
...@@ -1740,7 +1743,7 @@ Dep_module* Dep_value_field::get_next_unbound_module(Dep_analysis_context *dac, ...@@ -1740,7 +1743,7 @@ Dep_module* Dep_value_field::get_next_unbound_module(Dep_analysis_context *dac,
- have this field as a part of them - have this field as a part of them
*/ */
while (key_dep && (key_dep->is_applicable() || while (key_dep && (key_dep->is_applicable() ||
!field->part_of_key.is_set(key_dep->keyno))) !field->part_of_key_not_clustered.is_set(key_dep->keyno)))
{ {
key_dep= key_dep->next_table_key; key_dep= key_dep->next_table_key;
} }
......
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