mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
Fix for BUG#4480: In joins with SELECT_STRAIGHT_JOIN re-order tables by outer join dependency,
so we read dependent tables after tables they depend on (this is needed for outer joins)
This commit is contained in:
@ -853,4 +853,19 @@ id select_type table type possible_keys key key_len ref rows Extra
|
|||||||
1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1 Using index
|
1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1 Using index
|
||||||
1 SIMPLE t2 ALL NULL NULL NULL NULL 2
|
1 SIMPLE t2 ALL NULL NULL NULL NULL 2
|
||||||
1 SIMPLE t3 ALL NULL NULL NULL NULL 2
|
1 SIMPLE t3 ALL NULL NULL NULL NULL 2
|
||||||
|
drop table t1,t2;
|
||||||
|
create table t1 (a int, b int);
|
||||||
|
insert into t1 values (1,1),(2,2),(3,3);
|
||||||
|
create table t2 (a int, b int);
|
||||||
|
insert into t2 values (1,1), (2,2);
|
||||||
|
select * from t2 right join t1 on t2.a=t1.a;
|
||||||
|
a b a b
|
||||||
|
1 1 1 1
|
||||||
|
2 2 2 2
|
||||||
|
NULL NULL 3 3
|
||||||
|
select straight_join * from t2 right join t1 on t2.a=t1.a;
|
||||||
|
a b a b
|
||||||
|
1 1 1 1
|
||||||
|
2 2 2 2
|
||||||
|
NULL NULL 3 3
|
||||||
DROP TABLE t0,t1,t2,t3;
|
DROP TABLE t0,t1,t2,t3;
|
||||||
|
@ -606,4 +606,14 @@ INSERT INTO t1 VALUES (0);
|
|||||||
SELECT * FROM t0, t1 LEFT JOIN (t2,t3) ON a1=5 WHERE a0=a1 AND a0=1;
|
SELECT * FROM t0, t1 LEFT JOIN (t2,t3) ON a1=5 WHERE a0=a1 AND a0=1;
|
||||||
EXPLAIN SELECT * FROM t0, t1 LEFT JOIN (t2,t3) ON a1=5 WHERE a0=a1 AND a0=1;
|
EXPLAIN SELECT * FROM t0, t1 LEFT JOIN (t2,t3) ON a1=5 WHERE a0=a1 AND a0=1;
|
||||||
|
|
||||||
|
# Test for BUG#4480
|
||||||
|
drop table t1,t2;
|
||||||
|
create table t1 (a int, b int);
|
||||||
|
insert into t1 values (1,1),(2,2),(3,3);
|
||||||
|
create table t2 (a int, b int);
|
||||||
|
insert into t2 values (1,1), (2,2);
|
||||||
|
|
||||||
|
select * from t2 right join t1 on t2.a=t1.a;
|
||||||
|
select straight_join * from t2 right join t1 on t2.a=t1.a;
|
||||||
|
|
||||||
DROP TABLE t0,t1,t2,t3;
|
DROP TABLE t0,t1,t2,t3;
|
||||||
|
@ -64,6 +64,7 @@ static void best_extension_by_limited_search(JOIN *join,
|
|||||||
uint prune_level);
|
uint prune_level);
|
||||||
static uint determine_search_depth(JOIN* join);
|
static uint determine_search_depth(JOIN* join);
|
||||||
static int join_tab_cmp(const void* ptr1, const void* ptr2);
|
static int join_tab_cmp(const void* ptr1, const void* ptr2);
|
||||||
|
static int join_tab_cmp_straight(const void* ptr1, const void* ptr2);
|
||||||
/*
|
/*
|
||||||
TODO: 'find_best' is here only temporarily until 'greedy_search' is
|
TODO: 'find_best' is here only temporarily until 'greedy_search' is
|
||||||
tested and approved.
|
tested and approved.
|
||||||
@ -3678,22 +3679,26 @@ choose_plan(JOIN *join, table_map join_tables)
|
|||||||
{
|
{
|
||||||
uint search_depth= join->thd->variables.optimizer_search_depth;
|
uint search_depth= join->thd->variables.optimizer_search_depth;
|
||||||
uint prune_level= join->thd->variables.optimizer_prune_level;
|
uint prune_level= join->thd->variables.optimizer_prune_level;
|
||||||
|
bool straight_join= join->select_options & SELECT_STRAIGHT_JOIN;
|
||||||
DBUG_ENTER("choose_plan");
|
DBUG_ENTER("choose_plan");
|
||||||
|
|
||||||
if (join->select_options & SELECT_STRAIGHT_JOIN)
|
/*
|
||||||
|
if (SELECT_STRAIGHT_JOIN option is set)
|
||||||
|
reorder tables so dependent tables come after tables they depend
|
||||||
|
on, otherwise keep tables in the order they were specified in the query
|
||||||
|
else
|
||||||
|
Apply heuristic: pre-sort all access plans with respect to the number of
|
||||||
|
records accessed.
|
||||||
|
*/
|
||||||
|
qsort(join->best_ref + join->const_tables, join->tables - join->const_tables,
|
||||||
|
sizeof(JOIN_TAB*), straight_join?join_tab_cmp_straight:join_tab_cmp);
|
||||||
|
|
||||||
|
if (straight_join)
|
||||||
{
|
{
|
||||||
optimize_straight_join(join, join_tables);
|
optimize_straight_join(join, join_tables);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
Heuristic: pre-sort all access plans with respect to the number of
|
|
||||||
records accessed.
|
|
||||||
*/
|
|
||||||
qsort(join->best_ref + join->const_tables, join->tables - join->const_tables,
|
|
||||||
sizeof(JOIN_TAB*), join_tab_cmp);
|
|
||||||
|
|
||||||
if (search_depth == MAX_TABLES+2)
|
if (search_depth == MAX_TABLES+2)
|
||||||
{ /*
|
{ /*
|
||||||
TODO: 'MAX_TABLES+2' denotes the old implementation of find_best before
|
TODO: 'MAX_TABLES+2' denotes the old implementation of find_best before
|
||||||
@ -3750,6 +3755,23 @@ join_tab_cmp(const void* ptr1, const void* ptr2)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Same as join_tab_cmp, but for use with SELECT_STRAIGHT_JOIN.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int
|
||||||
|
join_tab_cmp_straight(const void* ptr1, const void* ptr2)
|
||||||
|
{
|
||||||
|
JOIN_TAB *jt1= *(JOIN_TAB**) ptr1;
|
||||||
|
JOIN_TAB *jt2= *(JOIN_TAB**) ptr2;
|
||||||
|
|
||||||
|
if (jt1->dependent & jt2->table->map)
|
||||||
|
return 1;
|
||||||
|
if (jt2->dependent & jt1->table->map)
|
||||||
|
return -1;
|
||||||
|
return jt1 > jt2 ? 1 : (jt1 < jt2 ? -1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Heuristic procedure to automatically guess a reasonable degree of
|
Heuristic procedure to automatically guess a reasonable degree of
|
||||||
exhaustiveness for the greedy search procedure.
|
exhaustiveness for the greedy search procedure.
|
||||||
@ -3832,7 +3854,7 @@ optimize_straight_join(JOIN *join, table_map join_tables)
|
|||||||
uint idx= join->const_tables;
|
uint idx= join->const_tables;
|
||||||
double record_count= 1.0;
|
double record_count= 1.0;
|
||||||
double read_time= 0.0;
|
double read_time= 0.0;
|
||||||
|
|
||||||
for (JOIN_TAB **pos= join->best_ref + idx ; (s= *pos) ; pos++)
|
for (JOIN_TAB **pos= join->best_ref + idx ; (s= *pos) ; pos++)
|
||||||
{
|
{
|
||||||
/* Find the best access method from 's' to the current partial plan */
|
/* Find the best access method from 's' to the current partial plan */
|
||||||
|
Reference in New Issue
Block a user