Commit d70f886f authored by igor@rurik.mysql.com's avatar igor@rurik.mysql.com

subselect2.result, select.result:

  Post-merge fixes for nested joins.
  The join_tab_cmp function in sql_select has been changed.
join_nested.result:
  Post-merge fixes for nested joins. 
  The join_tab_cmp function in sql_select has been changed
sql_select.cc:
  Post-merge fixes for nested joins.
  Avoided re-execution of eliminate_not_funcs and simplify_joins
  in optimize_cond.
  Changed the join_tab_cmp function to take into account
  the dependent relation.
sql_lex.cc, sql_lex.h:
  Added the first_cond_optimization flag to st_select_lex to avoid
  re-execution of some optimizations in optimize_cond.
sql_base.cc:
  Post-merge fixes for nested joins. 
  Fixed problems with a proper column list substituted for '*' in
  queries with natural joins.
parent 29f61620
...@@ -216,10 +216,10 @@ SELECT t6.a,t6.b,t7.a,t7.b ...@@ -216,10 +216,10 @@ SELECT t6.a,t6.b,t7.a,t7.b
FROM t6,t7; FROM t6,t7;
a b a b a b a b
3 2 1 1 3 2 1 1
6 2 1 1
6 1 1 1
3 2 2 2 3 2 2 2
6 2 1 1
6 2 2 2 6 2 2 2
6 1 1 1
6 1 2 2 6 1 2 2
SELECT t8.a,t8.b SELECT t8.a,t8.b
FROM t8; FROM t8;
...@@ -234,8 +234,8 @@ LEFT JOIN ...@@ -234,8 +234,8 @@ LEFT JOIN
t8 t8
ON t7.b=t8.b AND t6.b < 10; ON t7.b=t8.b AND t6.b < 10;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t6 ALL NULL NULL NULL NULL 3
1 SIMPLE t7 ALL NULL NULL NULL NULL 2 1 SIMPLE t7 ALL NULL NULL NULL NULL 2
1 SIMPLE t6 ALL NULL NULL NULL NULL 3
1 SIMPLE t8 ALL NULL NULL NULL NULL 2 1 SIMPLE t8 ALL NULL NULL NULL NULL 2
SELECT t6.a,t6.b,t7.a,t7.b,t8.a,t8.b SELECT t6.a,t6.b,t7.a,t7.b,t8.a,t8.b
FROM t6, FROM t6,
...@@ -245,12 +245,12 @@ t8 ...@@ -245,12 +245,12 @@ t8
ON t7.b=t8.b AND t6.b < 10; ON t7.b=t8.b AND t6.b < 10;
a b a b a b a b a b a b
3 2 1 1 NULL NULL 3 2 1 1 NULL NULL
6 2 1 1 NULL NULL
6 1 1 1 NULL NULL
3 2 2 2 0 2 3 2 2 2 0 2
3 2 2 2 1 2 3 2 2 2 1 2
6 2 1 1 NULL NULL
6 2 2 2 0 2 6 2 2 2 0 2
6 2 2 2 1 2 6 2 2 2 1 2
6 1 1 1 NULL NULL
6 1 2 2 0 2 6 1 2 2 0 2
6 1 2 2 1 2 6 1 2 2 1 2
SELECT t5.a,t5.b SELECT t5.a,t5.b
...@@ -831,18 +831,18 @@ ON t3.a=1 AND t2.b=t4.b ...@@ -831,18 +831,18 @@ ON t3.a=1 AND t2.b=t4.b
WHERE t1.a <= 2; WHERE t1.a <= 2;
a b a b a b a b a b a b a b a b
1 3 3 3 1 2 NULL NULL 1 3 3 3 1 2 NULL NULL
2 2 3 3 1 2 NULL NULL
1 3 3 3 2 2 NULL NULL 1 3 3 3 2 2 NULL NULL
2 2 3 3 1 2 NULL NULL
2 2 3 3 2 2 NULL NULL 2 2 3 3 2 2 NULL NULL
1 3 4 2 1 2 3 2 1 3 4 2 1 2 3 2
1 3 4 2 1 2 4 2 1 3 4 2 1 2 4 2
1 3 4 2 2 2 NULL NULL
2 2 4 2 1 2 3 2 2 2 4 2 1 2 3 2
2 2 4 2 1 2 4 2 2 2 4 2 1 2 4 2
1 3 4 2 2 2 NULL NULL
2 2 4 2 2 2 NULL NULL 2 2 4 2 2 2 NULL NULL
1 3 5 3 1 2 NULL NULL 1 3 5 3 1 2 NULL NULL
2 2 5 3 1 2 NULL NULL
1 3 5 3 2 2 NULL NULL 1 3 5 3 2 2 NULL NULL
2 2 5 3 1 2 NULL NULL
2 2 5 3 2 2 NULL NULL 2 2 5 3 2 2 NULL NULL
CREATE INDEX idx_b ON t2(b); CREATE INDEX idx_b ON t2(b);
EXPLAIN EXPLAIN
......
...@@ -2253,10 +2253,10 @@ a a ...@@ -2253,10 +2253,10 @@ a a
2 2 2 2
3 3 3 3
select * from (t1 as t2 left join t1 as t3 using (a)) natural join t1; select * from (t1 as t2 left join t1 as t3 using (a)) natural join t1;
a a a a a
1 1 1 1 1
2 2 2 2 2
3 3 3 3 3
drop table t1; drop table t1;
CREATE TABLE t1 ( aa char(2), id int(11) NOT NULL auto_increment, t2_id int(11) NOT NULL default '0', PRIMARY KEY (id), KEY replace_id (t2_id)) ENGINE=MyISAM; CREATE TABLE t1 ( aa char(2), id int(11) NOT NULL auto_increment, t2_id int(11) NOT NULL default '0', PRIMARY KEY (id), KEY replace_id (t2_id)) ENGINE=MyISAM;
INSERT INTO t1 VALUES ("1",8264,2506),("2",8299,2517),("3",8301,2518),("4",8302,2519),("5",8303,2520),("6",8304,2521),("7",8305,2522); INSERT INTO t1 VALUES ("1",8264,2506),("2",8299,2517),("3",8301,2518),("4",8302,2519),("5",8303,2520),("6",8304,2521),("7",8305,2522);
...@@ -2283,8 +2283,8 @@ left join t4 on id3 = id4 where id2 = 1 or id4 = 1; ...@@ -2283,8 +2283,8 @@ left join t4 on id3 = id4 where id2 = 1 or id4 = 1;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t3 system NULL NULL NULL NULL 0 const row not found 1 SIMPLE t3 system NULL NULL NULL NULL 0 const row not found
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 1 SIMPLE t1 ALL NULL NULL NULL NULL 2
1 SIMPLE t4 ALL id4 NULL NULL NULL 1 1 SIMPLE t2 ALL NULL NULL NULL NULL 1
1 SIMPLE t2 ALL NULL NULL NULL NULL 1 Using where 1 SIMPLE t4 ALL id4 NULL NULL NULL 1 Using where
select * from t1 left join t2 on id1 = id2 left join t3 on id1 = id3 select * from t1 left join t2 on id1 = id2 left join t3 on id1 = id3
left join t4 on id3 = id4 where id2 = 1 or id4 = 1; left join t4 on id3 = id4 where id2 = 1 or id4 = 1;
id1 id2 id3 id4 id44 id1 id2 id3 id4 id44
......
...@@ -121,8 +121,8 @@ c373e9f5ad07993f3859444553544200 Last Discussion c373e9f5ad079174ff1744455354420 ...@@ -121,8 +121,8 @@ c373e9f5ad07993f3859444553544200 Last Discussion c373e9f5ad079174ff1744455354420
EXPLAIN SELECT t2.*, t4.DOCTYPENAME, t1.CONTENTSIZE,t1.MIMETYPE FROM t2 INNER JOIN t4 ON t2.DOCTYPEID = t4.DOCTYPEID LEFT OUTER JOIN t1 ON t2.DOCID = t1.DOCID WHERE t2.FOLDERID IN(SELECT t3.FOLDERID FROM t3 WHERE t3.PARENTID IN(SELECT t3.FOLDERID FROM t3 WHERE t3.PARENTID IN(SELECT t3.FOLDERID FROM t3 WHERE t3.PARENTID IN(SELECT t3.FOLDERID FROM t3 WHERE t3.PARENTID IN(SELECT t3.FOLDERID FROM t3 WHERE t3.PARENTID='2f6161e879db43c1a5b82c21ddc49089' AND t3.FOLDERNAME = 'Level1') AND t3.FOLDERNAME = 'Level2') AND t3.FOLDERNAME = 'Level3') AND t3.FOLDERNAME = 'CopiedFolder') AND t3.FOLDERNAME = 'Movie Reviews') AND t2.DOCNAME = 'Last Discussion'; EXPLAIN SELECT t2.*, t4.DOCTYPENAME, t1.CONTENTSIZE,t1.MIMETYPE FROM t2 INNER JOIN t4 ON t2.DOCTYPEID = t4.DOCTYPEID LEFT OUTER JOIN t1 ON t2.DOCID = t1.DOCID WHERE t2.FOLDERID IN(SELECT t3.FOLDERID FROM t3 WHERE t3.PARENTID IN(SELECT t3.FOLDERID FROM t3 WHERE t3.PARENTID IN(SELECT t3.FOLDERID FROM t3 WHERE t3.PARENTID IN(SELECT t3.FOLDERID FROM t3 WHERE t3.PARENTID IN(SELECT t3.FOLDERID FROM t3 WHERE t3.PARENTID='2f6161e879db43c1a5b82c21ddc49089' AND t3.FOLDERNAME = 'Level1') AND t3.FOLDERNAME = 'Level2') AND t3.FOLDERNAME = 'Level3') AND t3.FOLDERNAME = 'CopiedFolder') AND t3.FOLDERNAME = 'Movie Reviews') AND t2.DOCNAME = 'Last Discussion';
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL DDOCTYPEID_IDX NULL NULL NULL 10 Using where 1 PRIMARY t2 ALL DDOCTYPEID_IDX NULL NULL NULL 10 Using where
1 PRIMARY t4 eq_ref PRIMARY PRIMARY 32 test.t2.DOCTYPEID 1
1 PRIMARY t1 eq_ref PRIMARY PRIMARY 32 test.t2.DOCID 1 1 PRIMARY t1 eq_ref PRIMARY PRIMARY 32 test.t2.DOCID 1
1 PRIMARY t4 eq_ref PRIMARY PRIMARY 32 test.t2.DOCTYPEID 1
2 DEPENDENT SUBQUERY t3 unique_subquery PRIMARY,FFOLDERID_IDX PRIMARY 32 func 1 Using index; Using where 2 DEPENDENT SUBQUERY t3 unique_subquery PRIMARY,FFOLDERID_IDX PRIMARY 32 func 1 Using index; Using where
3 DEPENDENT SUBQUERY t3 unique_subquery PRIMARY,FFOLDERID_IDX PRIMARY 32 func 1 Using index; Using where 3 DEPENDENT SUBQUERY t3 unique_subquery PRIMARY,FFOLDERID_IDX PRIMARY 32 func 1 Using index; Using where
4 DEPENDENT SUBQUERY t3 unique_subquery PRIMARY,FFOLDERID_IDX PRIMARY 32 func 1 Using index; Using where 4 DEPENDENT SUBQUERY t3 unique_subquery PRIMARY,FFOLDERID_IDX PRIMARY 32 func 1 Using index; Using where
......
...@@ -2373,10 +2373,33 @@ insert_fields(THD *thd,TABLE_LIST *tables, const char *db_name, ...@@ -2373,10 +2373,33 @@ insert_fields(THD *thd,TABLE_LIST *tables, const char *db_name,
TABLE *natural_join_table= 0; TABLE *natural_join_table= 0;
thd->used_tables|=table->map; thd->used_tables|=table->map;
if (!table->outer_join && TABLE_LIST *embedded= tables;
tables->natural_join && TABLE_LIST *last= embedded;
!tables->natural_join->table->outer_join) TABLE_LIST *embedding;
natural_join_table= tables->natural_join->table;
while ((embedding= embedded->embedding) &&
embedding->join_list->elements != 1)
{
TABLE_LIST *next;
List_iterator_fast<TABLE_LIST> it(embedding->nested_join->join_list);
last= it++;
while ((next= it++))
last= next;
if (last != tables)
break;
embedded= embedding;
}
if (tables == last &&
!embedded->outer_join &&
embedded->natural_join &&
!embedded->natural_join->outer_join)
{
embedding= embedded->natural_join;
while (embedding->nested_join)
embedding= embedding->nested_join->join_list.head();
natural_join_table= embedding->table;
}
while ((field = *ptr++)) while ((field = *ptr++))
{ {
...@@ -2533,7 +2556,7 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds) ...@@ -2533,7 +2556,7 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
select_lex->cond_count+= cond_and->list.elements; select_lex->cond_count+= cond_and->list.elements;
// to prevent natural join processing during PS re-execution // to prevent natural join processing during PS re-execution
table->natural_join= 0; embedding->natural_join= 0;
COND *on_expr= cond_and; COND *on_expr= cond_and;
on_expr->fix_fields(thd, 0, &on_expr); on_expr->fix_fields(thd, 0, &on_expr);
......
...@@ -1019,6 +1019,7 @@ void st_select_lex::init_query() ...@@ -1019,6 +1019,7 @@ void st_select_lex::init_query()
prep_where= 0; prep_where= 0;
explicit_limit= 0; explicit_limit= 0;
first_execution= 1; first_execution= 1;
first_cond_optimization= 1;
} }
void st_select_lex::init_select() void st_select_lex::init_select()
......
...@@ -454,6 +454,7 @@ public: ...@@ -454,6 +454,7 @@ public:
/* explicit LIMIT clause was used */ /* explicit LIMIT clause was used */
bool explicit_limit; bool explicit_limit;
bool first_execution; /* first execution in SP or PS */ bool first_execution; /* first execution in SP or PS */
bool first_cond_optimization;
/* /*
SELECT for SELECT command st_select_lex. Used to privent scaning SELECT for SELECT command st_select_lex. Used to privent scaning
......
...@@ -92,7 +92,7 @@ static int return_zero_rows(JOIN *join, select_result *res,TABLE_LIST *tables, ...@@ -92,7 +92,7 @@ static int return_zero_rows(JOIN *join, select_result *res,TABLE_LIST *tables,
SELECT_LEX_UNIT *unit); SELECT_LEX_UNIT *unit);
static COND *simplify_joins(JOIN *join, List<TABLE_LIST> *join_list, static COND *simplify_joins(JOIN *join, List<TABLE_LIST> *join_list,
COND *conds, bool top); COND *conds, bool top);
static COND *optimize_cond(THD *thd, COND *conds, static COND *optimize_cond(JOIN *join, COND *conds,
Item::cond_result *cond_value); Item::cond_result *cond_value);
static bool resolve_nested_join (TABLE_LIST *table); static bool resolve_nested_join (TABLE_LIST *table);
static COND *remove_eq_conds(THD *thd, COND *cond, static COND *remove_eq_conds(THD *thd, COND *cond,
...@@ -570,10 +570,7 @@ JOIN::optimize() ...@@ -570,10 +570,7 @@ JOIN::optimize()
} }
#endif #endif
/* Convert all outer joins to inner joins if possible */ conds= optimize_cond(this, conds,&cond_value);
conds= simplify_joins(this, join_list, conds, TRUE);
conds= optimize_cond(thd, conds,&cond_value);
if (thd->net.report_error) if (thd->net.report_error)
{ {
error= 1; error= 1;
...@@ -3025,7 +3022,7 @@ best_access_path(JOIN *join, ...@@ -3025,7 +3022,7 @@ best_access_path(JOIN *join,
{ {
/* Estimate cost of reading table. */ /* Estimate cost of reading table. */
tmp= s->table->file->scan_time(); tmp= s->table->file->scan_time();
if (s->on_expr) // Can't use join cache if (s->table->map & join->outer_join) // Can't use join cache
{ {
/* /*
For each record we have to: For each record we have to:
...@@ -3172,12 +3169,16 @@ join_tab_cmp(const void* ptr1, const void* ptr2) ...@@ -3172,12 +3169,16 @@ join_tab_cmp(const void* ptr1, const void* ptr2)
{ {
JOIN_TAB *jt1= *(JOIN_TAB**) ptr1; JOIN_TAB *jt1= *(JOIN_TAB**) ptr1;
JOIN_TAB *jt2= *(JOIN_TAB**) ptr2; JOIN_TAB *jt2= *(JOIN_TAB**) ptr2;
if (jt1->dependent & jt2->table->map)
return 1;
if (jt2->dependent & jt1->table->map)
return -1;
if (jt1->found_records > jt2->found_records) if (jt1->found_records > jt2->found_records)
return 1; return 1;
else if (jt1->found_records < jt2->found_records) if (jt1->found_records < jt2->found_records)
return -1; return -1;
else return jt1 > jt2 ? 1 : (jt1 < jt2 ? -1 : 0);
return 0;
} }
...@@ -4465,6 +4466,8 @@ add_found_match_trig_cond(JOIN_TAB *tab, COND *cond, JOIN_TAB *root_tab) ...@@ -4465,6 +4466,8 @@ add_found_match_trig_cond(JOIN_TAB *tab, COND *cond, JOIN_TAB *root_tab)
{ {
tmp= new Item_func_trig_cond(tmp, &tab->found); tmp= new Item_func_trig_cond(tmp, &tab->found);
} }
if (!tmp)
tmp->quick_fix_field();
return tmp; return tmp;
} }
...@@ -4788,11 +4791,14 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) ...@@ -4788,11 +4791,14 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
*/ */
tmp= new Item_func_trig_cond(tmp, tmp= new Item_func_trig_cond(tmp,
&first_inner_tab->not_null_compl); &first_inner_tab->not_null_compl);
if (tmp)
tmp->quick_fix_field();
/* Add the predicate to other pushed down predicates */ /* Add the predicate to other pushed down predicates */
cond_tab->select_cond= !cond_tab->select_cond ? tmp : cond_tab->select_cond= !cond_tab->select_cond ? tmp :
new Item_cond_and(cond_tab->select_cond,tmp); new Item_cond_and(cond_tab->select_cond,tmp);
if (!cond_tab->select_cond) if (!cond_tab->select_cond)
DBUG_RETURN(1); DBUG_RETURN(1);
cond_tab->select_cond->quick_fix_field();
} }
} }
first_inner_tab= first_inner_tab->first_upper; first_inner_tab= first_inner_tab->first_upper;
...@@ -5827,17 +5833,42 @@ simplify_joins(JOIN *join, List<TABLE_LIST> *join_list, COND *conds, bool top) ...@@ -5827,17 +5833,42 @@ simplify_joins(JOIN *join, List<TABLE_LIST> *join_list, COND *conds, bool top)
} }
static COND * static COND *
optimize_cond(THD *thd, COND *conds, Item::cond_result *cond_value) optimize_cond(JOIN *join, COND *conds, Item::cond_result *cond_value)
{ {
DBUG_ENTER("optimize_cond"); DBUG_ENTER("optimize_cond");
THD *thd= join->thd;
SELECT_LEX *select= thd->lex->current_select;
if (select->first_cond_optimization)
{
Item_arena *arena= select->first_cond_optimization ?
thd->current_arena : 0;
Item_arena backup;
if (arena)
thd->set_n_backup_item_arena(arena, &backup);
if (conds)
{
DBUG_EXECUTE("where",print_where(conds,"original"););
/* eliminate NOT operators */
conds= eliminate_not_funcs(thd, conds);
}
/* Convert all outer joins to inner joins if possible */
conds= simplify_joins(join, join->join_list, conds, TRUE);
select->prep_where= conds ? conds->copy_andor_structure(thd) : 0;
select->first_cond_optimization= 0;
if (arena)
thd->restore_backup_item_arena(arena, &backup);
}
if (!conds) if (!conds)
{ {
*cond_value= Item::COND_TRUE; *cond_value= Item::COND_TRUE;
DBUG_RETURN(conds); DBUG_RETURN(conds);
} }
DBUG_EXECUTE("where",print_where(conds,"original"););
/* eliminate NOT operators */
conds= eliminate_not_funcs(thd, conds);
DBUG_EXECUTE("where", print_where(conds, "after negation elimination");); DBUG_EXECUTE("where", print_where(conds, "after negation elimination"););
/* change field = field to field = const for each found field = const */ /* change field = field to field = const for each found field = const */
propagate_cond_constants((I_List<COND_CMP> *) 0,conds,conds); propagate_cond_constants((I_List<COND_CMP> *) 0,conds,conds);
......
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