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

table.h, sql_select.h:

  Added the code processing on expressions for applying
  multiple equalities.
sql_select.cc:
  Post-merge fixes for Item_equal patch.
  Added the code processing on expressions for applying
  multiple equalities.
Many files:
  Post-merge fixes for Item_equal patch.
item_cmpfunc.cc:
  Post-merge fixes for Item_equal patch.
  Fixed a problem when an equality field=const cannot be applied to
  the predicate P(field,c) for constant propagation as a conversion
  of field is needed.
item.h, item.cc:
  Fixed a problem when an equality field=const cannot be applied to
  the predicate P(field,c) for constant propagation as a conversion
  of field is needed.
parent 71f6ab7a
...@@ -79,7 +79,7 @@ explain extended select * from t1 where 1 xor 1; ...@@ -79,7 +79,7 @@ explain extended select * from t1 where 1 xor 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 NULL NULL NULL NULL NULL NULL NULL Impossible WHERE 1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
Warnings: Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where (1 xor 1) Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1`
select - a from t1; select - a from t1;
- a - a
-1 -1
......
...@@ -82,7 +82,7 @@ id select_type table type possible_keys key key_len ref rows Extra ...@@ -82,7 +82,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t0 index_merge i2,i3,i4 i2,i3 4,4 NULL 2 Using union(i2,i3); Using where 1 SIMPLE t0 index_merge i2,i3,i4 i2,i3 4,4 NULL 2 Using union(i2,i3); Using where
explain select * from t0 where key2=10 or key3=3 or key4 is null; explain select * from t0 where key2=10 or key3=3 or key4 is null;
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 t0 index_merge i2,i3 i2,i3 4,4 NULL 2 Using where 1 SIMPLE t0 index_merge i2,i3 i2,i3 4,4 NULL 2 Using union(i2,i3); Using where
explain select key1 from t0 where (key1 <=> null) or (key2 < 5) or explain select key1 from t0 where (key1 <=> null) or (key2 < 5) or
(key3=10) or (key4 <=> null); (key3=10) or (key4 <=> null);
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
...@@ -257,8 +257,8 @@ explain ...@@ -257,8 +257,8 @@ explain
select * from t0,t1 where (t0.key1=t1.key1) and select * from t0,t1 where (t0.key1=t1.key1) and
(t0.key1=3 or t0.key2=4) and t1.key1<200; (t0.key1=3 or t0.key2=4) and t1.key1<200;
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 t0 index_merge i1,i2 i1,i2 4,4 NULL 2 Using union(i1,i2); Using where 1 SIMPLE t0 range i1,i2 i1 4 NULL 179 Using where
1 SIMPLE t1 ref i1 i1 4 test.t0.key1 1 Using where 1 SIMPLE t1 ref i1 i1 4 test.t0.key1 1
explain explain
select * from t0,t1 where (t0.key1=t1.key1) and select * from t0,t1 where (t0.key1=t1.key1) and
(t0.key1=3 or t0.key2<4) and t1.key1=2; (t0.key1=3 or t0.key2<4) and t1.key1=2;
......
This diff is collapsed.
...@@ -254,12 +254,12 @@ INSERT INTO t2 VALUES (0),(0),(1),(1),(2),(2); ...@@ -254,12 +254,12 @@ INSERT INTO t2 VALUES (0),(0),(1),(1),(2),(2);
explain select * from t1, t2 where (t1.key1 <t2.keya + 1) and t2.keya=3; explain select * from t1, t2 where (t1.key1 <t2.keya + 1) and t2.keya=3;
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 t2 ref j1 j1 4 const 1 Using index 1 SIMPLE t2 ref j1 j1 4 const 1 Using index
1 SIMPLE t1 ALL i1 NULL NULL NULL 4 Range checked for each record (index map: 0x1) 1 SIMPLE t1 index i1 i1 4 NULL 4 Using where; Using index
explain select * from t1 force index(i1), t2 force index(j1) where explain select * from t1 force index(i1), t2 force index(j1) where
(t1.key1 <t2.keya + 1) and t2.keya=3; (t1.key1 <t2.keya + 1) and t2.keya=3;
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 t2 ref j1 j1 4 const 1 Using index 1 SIMPLE t2 ref j1 j1 4 const 1 Using index
1 SIMPLE t1 ALL i1 NULL NULL NULL 4 Range checked for each record (index map: 0x1) 1 SIMPLE t1 index i1 i1 4 NULL 4 Using where; Using index
DROP TABLE t1,t2; DROP TABLE t1,t2;
CREATE TABLE t1 ( CREATE TABLE t1 (
a int(11) default NULL, a int(11) default NULL,
......
...@@ -331,7 +331,7 @@ id select_type table type possible_keys key key_len ref rows Extra ...@@ -331,7 +331,7 @@ id select_type table type possible_keys key key_len ref rows Extra
2 DEPENDENT SUBQUERY t7 eq_ref PRIMARY PRIMARY 4 test.t6.clinic_uq 1 Using index 2 DEPENDENT SUBQUERY t7 eq_ref PRIMARY PRIMARY 4 test.t6.clinic_uq 1 Using index
Warnings: Warnings:
Note 1276 Field or reference 'clinic_uq' of SELECT #2 was resolved in SELECT #1 Note 1276 Field or reference 'clinic_uq' of SELECT #2 was resolved in SELECT #1
Note 1003 select `test`.`t6`.`patient_uq` AS `patient_uq`,`test`.`t6`.`clinic_uq` AS `clinic_uq` from `test`.`t6` where exists(select 1 AS `Not_used` from `test`.`t7` where (`test`.`t7`.`uq` = `test`.`t6`.`clinic_uq`)) Note 1003 select `test`.`t6`.`patient_uq` AS `patient_uq`,`test`.`t6`.`clinic_uq` AS `clinic_uq` from `test`.`t6` where exists(select 1 AS `Not_used` from `test`.`t7` where (`test`.`t6`.`clinic_uq` = `test`.`t7`.`uq`))
select * from t1 where a= (select a from t2,t4 where t2.b=t4.b); select * from t1 where a= (select a from t2,t4 where t2.b=t4.b);
ERROR 23000: Column 'a' in field list is ambiguous ERROR 23000: Column 'a' in field list is ambiguous
drop table t1,t2,t3; drop table t1,t2,t3;
...@@ -545,7 +545,7 @@ id select_type table type possible_keys key key_len ref rows Extra ...@@ -545,7 +545,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 const PRIMARY,numreponse PRIMARY 7 const,const 1 Using index 1 PRIMARY t1 const PRIMARY,numreponse PRIMARY 7 const,const 1 Using index
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away 2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away
Warnings: Warnings:
Note 1003 select `test`.`t1`.`numreponse` AS `numreponse` from `test`.`t1` where ((`test`.`t1`.`numeropost` = _latin1'1') and (`test`.`t1`.`numreponse` = 3)) Note 1003 select `test`.`t1`.`numreponse` AS `numreponse` from `test`.`t1` where ((`test`.`t1`.`numreponse` = (select max(`test`.`t1`.`numreponse`) AS `MAX(numreponse)` from `test`.`t1` where (`test`.`t1`.`numeropost` = _latin1'1'))) and (`test`.`t1`.`numeropost` = _latin1'1'))
drop table t1; drop table t1;
CREATE TABLE t1 (a int(1)); CREATE TABLE t1 (a int(1));
INSERT INTO t1 VALUES (1); INSERT INTO t1 VALUES (1);
...@@ -1313,7 +1313,7 @@ id select_type table type possible_keys key key_len ref rows Extra ...@@ -1313,7 +1313,7 @@ id select_type table type possible_keys key key_len ref rows Extra
2 DEPENDENT SUBQUERY t1 eq_ref PRIMARY PRIMARY 4 func 1 Using where 2 DEPENDENT SUBQUERY t1 eq_ref PRIMARY PRIMARY 4 func 1 Using where
2 DEPENDENT SUBQUERY t3 eq_ref PRIMARY PRIMARY 4 test.t1.b 1 Using where; Using index 2 DEPENDENT SUBQUERY t3 eq_ref PRIMARY PRIMARY 4 test.t1.b 1 Using where; Using index
Warnings: Warnings:
Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` where <in_optimizer>(`test`.`t2`.`a`,<exists>(select 1 AS `Not_used` from `test`.`t1` join `test`.`t3` where ((`test`.`t1`.`b` = `test`.`t3`.`a`) and (<cache>(`test`.`t2`.`a`) = `test`.`t1`.`a`)))) Note 1003 select `test`.`t2`.`a` AS `a` from `test`.`t2` where <in_optimizer>(`test`.`t2`.`a`,<exists>(select 1 AS `Not_used` from `test`.`t1` join `test`.`t3` where ((`test`.`t3`.`a` = `test`.`t1`.`b`) and (<cache>(`test`.`t2`.`a`) = `test`.`t1`.`a`))))
drop table t1, t2, t3; drop table t1, t2, t3;
create table t1 (a int, b int, index a (a,b)); create table t1 (a int, b int, index a (a,b));
create table t2 (a int, index a (a)); create table t2 (a int, index a (a));
...@@ -1675,10 +1675,10 @@ Note 1003 select `test`.`t1`.`id` AS `id`,`test`.`t1`.`text` AS `text` from `tes ...@@ -1675,10 +1675,10 @@ Note 1003 select `test`.`t1`.`id` AS `id`,`test`.`t1`.`text` AS `text` from `tes
explain extended select * from t1 as tt where not exists (select id from t1 where id < 8 and (id = tt.id or id is null) having id is not null); explain extended select * from t1 as tt where not exists (select id from t1 where id < 8 and (id = tt.id or id is null) having id is not null);
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 tt ALL NULL NULL NULL NULL 12 Using where 1 PRIMARY tt ALL NULL NULL NULL NULL 12 Using where
2 DEPENDENT SUBQUERY t1 eq_ref PRIMARY PRIMARY 4 test.tt.id 7 Using where; Using index 2 DEPENDENT SUBQUERY t1 eq_ref PRIMARY PRIMARY 4 test.tt.id 1 Using where; Using index
Warnings: Warnings:
Note 1276 Field or reference 'tt.id' of SELECT #2 was resolved in SELECT #1 Note 1276 Field or reference 'tt.id' of SELECT #2 was resolved in SELECT #1
Note 1003 select `test`.`tt`.`id` AS `id`,`test`.`tt`.`text` AS `text` from `test`.`t1` `tt` where not(exists(select `test`.`t1`.`id` AS `id` from `test`.`t1` where ((`test`.`t1`.`id` < 8) and ((`test`.`t1`.`id` = `test`.`tt`.`id`) or isnull(`test`.`t1`.`id`))) having (`test`.`t1`.`id` is not null))) Note 1003 select `test`.`tt`.`id` AS `id`,`test`.`tt`.`text` AS `text` from `test`.`t1` `tt` where not(exists(select `test`.`t1`.`id` AS `id` from `test`.`t1` where ((`test`.`t1`.`id` < 8) and (`test`.`tt`.`id` = `test`.`t1`.`id`)) having (`test`.`t1`.`id` is not null)))
insert into t1 (id, text) values (1000, 'text1000'), (1001, 'text1001'); insert into t1 (id, text) values (1000, 'text1000'), (1001, 'text1001');
create table t2 (id int not null, text varchar(20) not null default '', primary key (id)); create table t2 (id int not null, text varchar(20) not null default '', primary key (id));
insert into t2 (id, text) values (1, 'text1'), (2, 'text2'), (3, 'text3'), (4, 'text4'), (5, 'text5'), (6, 'text6'), (7, 'text7'), (8, 'text8'), (9, 'text9'), (10, 'text10'), (11, 'text1'), (12, 'text2'), (13, 'text3'), (14, 'text4'), (15, 'text5'), (16, 'text6'), (17, 'text7'), (18, 'text8'), (19, 'text9'), (20, 'text10'),(21, 'text1'), (22, 'text2'), (23, 'text3'), (24, 'text4'), (25, 'text5'), (26, 'text6'), (27, 'text7'), (28, 'text8'), (29, 'text9'), (30, 'text10'), (31, 'text1'), (32, 'text2'), (33, 'text3'), (34, 'text4'), (35, 'text5'), (36, 'text6'), (37, 'text7'), (38, 'text8'), (39, 'text9'), (40, 'text10'), (41, 'text1'), (42, 'text2'), (43, 'text3'), (44, 'text4'), (45, 'text5'), (46, 'text6'), (47, 'text7'), (48, 'text8'), (49, 'text9'), (50, 'text10'); insert into t2 (id, text) values (1, 'text1'), (2, 'text2'), (3, 'text3'), (4, 'text4'), (5, 'text5'), (6, 'text6'), (7, 'text7'), (8, 'text8'), (9, 'text9'), (10, 'text10'), (11, 'text1'), (12, 'text2'), (13, 'text3'), (14, 'text4'), (15, 'text5'), (16, 'text6'), (17, 'text7'), (18, 'text8'), (19, 'text9'), (20, 'text10'),(21, 'text1'), (22, 'text2'), (23, 'text3'), (24, 'text4'), (25, 'text5'), (26, 'text6'), (27, 'text7'), (28, 'text8'), (29, 'text9'), (30, 'text10'), (31, 'text1'), (32, 'text2'), (33, 'text3'), (34, 'text4'), (35, 'text5'), (36, 'text6'), (37, 'text7'), (38, 'text8'), (39, 'text9'), (40, 'text10'), (41, 'text1'), (42, 'text2'), (43, 'text3'), (44, 'text4'), (45, 'text5'), (46, 'text6'), (47, 'text7'), (48, 'text8'), (49, 'text9'), (50, 'text10');
...@@ -1704,7 +1704,7 @@ id select_type table type possible_keys key key_len ref rows Extra ...@@ -1704,7 +1704,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE b eq_ref PRIMARY PRIMARY 4 test.a.id 2 1 SIMPLE b eq_ref PRIMARY PRIMARY 4 test.a.id 2
1 SIMPLE c eq_ref PRIMARY PRIMARY 4 func 1 Using where 1 SIMPLE c eq_ref PRIMARY PRIMARY 4 func 1 Using where
Warnings: Warnings:
Note 1003 select `test`.`a`.`id` AS `id`,`test`.`a`.`text` AS `text`,`test`.`b`.`id` AS `id`,`test`.`b`.`text` AS `text`,`test`.`c`.`id` AS `id`,`test`.`c`.`text` AS `text` from `test`.`t1` `a` left join `test`.`t2` `b` on(((`test`.`a`.`id` = `test`.`b`.`id`) or isnull(`test`.`b`.`id`))) join `test`.`t1` `c` where (if(isnull(`test`.`b`.`id`),1000,`test`.`b`.`id`) = `test`.`c`.`id`) Note 1003 select `test`.`a`.`id` AS `id`,`test`.`a`.`text` AS `text`,`test`.`b`.`id` AS `id`,`test`.`b`.`text` AS `text`,`test`.`c`.`id` AS `id`,`test`.`c`.`text` AS `text` from `test`.`t1` `a` left join `test`.`t2` `b` on(((`test`.`b`.`id` = `test`.`a`.`id`) or isnull(`test`.`b`.`id`))) join `test`.`t1` `c` where (if(isnull(`test`.`b`.`id`),1000,`test`.`b`.`id`) = `test`.`c`.`id`)
drop table t1,t2; drop table t1,t2;
create table t1 (a int); create table t1 (a int);
insert into t1 values (1); insert into t1 values (1);
...@@ -1832,7 +1832,7 @@ id select_type table type possible_keys key key_len ref rows Extra ...@@ -1832,7 +1832,7 @@ id select_type table type possible_keys key key_len ref rows Extra
2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2 Using where 2 DEPENDENT SUBQUERY t1 ALL NULL NULL NULL NULL 2 Using where
Warnings: Warnings:
Note 1276 Field or reference 'up.a' of SELECT #2 was resolved in SELECT #1 Note 1276 Field or reference 'up.a' of SELECT #2 was resolved in SELECT #1
Note 1003 select `test`.`up`.`a` AS `a`,`test`.`up`.`b` AS `b` from `test`.`t1` `up` where exists(select 1 AS `Not_used` from `test`.`t1` where (`test`.`t1`.`a` = `test`.`up`.`a`)) Note 1003 select `test`.`up`.`a` AS `a`,`test`.`up`.`b` AS `b` from `test`.`t1` `up` where exists(select 1 AS `Not_used` from `test`.`t1` where (`test`.`up`.`a` = `test`.`t1`.`a`))
drop table t1; drop table t1;
CREATE TABLE t1 (t1_a int); CREATE TABLE t1 (t1_a int);
INSERT INTO t1 VALUES (1); INSERT INTO t1 VALUES (1);
......
...@@ -408,7 +408,7 @@ bool DTCollation::aggregate(DTCollation &dt, bool superset_conversion) ...@@ -408,7 +408,7 @@ bool DTCollation::aggregate(DTCollation &dt, bool superset_conversion)
Item_field::Item_field(Field *f) Item_field::Item_field(Field *f)
:Item_ident(NullS, f->table_name, f->field_name), :Item_ident(NullS, f->table_name, f->field_name),
item_equal(0), item_equal(0), no_const_subst(0),
have_privileges(0), any_privileges(0) have_privileges(0), any_privileges(0)
{ {
set_field(f); set_field(f);
...@@ -419,7 +419,7 @@ Item_field::Item_field(Field *f) ...@@ -419,7 +419,7 @@ Item_field::Item_field(Field *f)
Item_field::Item_field(THD *thd, Field *f) Item_field::Item_field(THD *thd, Field *f)
:Item_ident(NullS, thd->strdup(f->table_name), :Item_ident(NullS, thd->strdup(f->table_name),
thd->strdup(f->field_name)), thd->strdup(f->field_name)),
item_equal(0), item_equal(0), no_const_subst(0),
have_privileges(0), any_privileges(0) have_privileges(0), any_privileges(0)
{ {
set_field(f); set_field(f);
...@@ -432,11 +432,12 @@ Item_field::Item_field(THD *thd, Item_field *item) ...@@ -432,11 +432,12 @@ Item_field::Item_field(THD *thd, Item_field *item)
:Item_ident(thd, item), :Item_ident(thd, item),
field(item->field), field(item->field),
result_field(item->result_field), result_field(item->result_field),
item_equal(item->item_equal),
no_const_subst(item->no_const_subst),
have_privileges(item->have_privileges), have_privileges(item->have_privileges),
any_privileges(item->any_privileges) any_privileges(item->any_privileges)
{ {
collation.set(DERIVATION_IMPLICIT); collation.set(DERIVATION_IMPLICIT);
item_equal= item->item_equal;
} }
void Item_field::set_field(Field *field_par) void Item_field::set_field(Field *field_par)
...@@ -1607,7 +1608,101 @@ void Item_field::cleanup() ...@@ -1607,7 +1608,101 @@ void Item_field::cleanup()
First Item_equal containing the field, if success First Item_equal containing the field, if success
0, otherwise 0, otherwise
*/ */
Item_equal *Item_field::find_item_equal(COND_EQUAL *cond_equal)
{
Item_equal *item= 0;
while (cond_equal)
{
List_iterator_fast<Item_equal> li(cond_equal->current_level);
while ((item= li++))
{
if (item->contains(field))
return item;
}
/*
The field is not found in any of the multiple equalities
of the current level. Look for it in upper levels
*/
cond_equal= cond_equal->upper_levels;
}
return 0;
}
/*
Set a pointer to the multiple equality the field reference belongs to (if any)
SYNOPSIS
equal_fields_propagator()
arg - reference to list of multiple equalities where
the field (this object) is to be looked for
DESCRIPTION
The function looks for a multiple equality containing the field item
among those referenced by arg.
In the case such equality exists the function does the following.
If the found multiple equality contains a constant, then the field
reference is substituted for this constant, otherwise it sets a pointer
to the multiple equality in the field item.
NOTES
This function is supposed to be called as a callback parameter in calls
of the transform method.
RETURN VALUES
pointer to the replacing constant item, if the field item was substituted
pointer to the field item, otherwise.
*/
Item *Item_field::equal_fields_propagator(byte *arg)
{
if (no_const_subst)
return this;
item_equal= find_item_equal((COND_EQUAL *) arg);
Item *item= 0;
if (item_equal)
item= item_equal->get_const();
if (!item)
item= this;
return item;
}
/*
Set a pointer to the multiple equality the field reference belongs to (if any)
SYNOPSIS
replace_equal_field_processor()
arg - a dummy parameter, is not used here
DESCRIPTION
The function replaces a pointer to a field in the Item_field object
by a pointer to another field.
The replacement field is taken from the very beginning of
the item_equal list which the Item_field object refers to (belongs to)
If the Item_field object does not refer any Item_equal object,
nothing is done.
NOTES
This function is supposed to be called as a callback parameter in calls
of the walk method.
RETURN VALUES
0
*/
bool Item_field::replace_equal_field_processor(byte *arg)
{
if (item_equal)
{
Item_field *subst= item_equal->get_first();
if (!field->eq(subst->field))
{
field= subst->field;
return 0;
}
}
return 0;
} }
void Item::init_make_field(Send_field *tmp_field, void Item::init_make_field(Send_field *tmp_field,
......
...@@ -457,6 +457,8 @@ protected: ...@@ -457,6 +457,8 @@ protected:
void set_field(Field *field); void set_field(Field *field);
public: public:
Field *field,*result_field; Field *field,*result_field;
Item_equal *item_equal;
bool no_const_subst;
/* /*
if any_privileges set to TRUE then here real effective privileges will if any_privileges set to TRUE then here real effective privileges will
be stored be stored
...@@ -468,7 +470,7 @@ public: ...@@ -468,7 +470,7 @@ public:
Item_field(const char *db_par,const char *table_name_par, Item_field(const char *db_par,const char *table_name_par,
const char *field_name_par) const char *field_name_par)
:Item_ident(db_par,table_name_par,field_name_par), :Item_ident(db_par,table_name_par,field_name_par),
field(0), result_field(0), item_equal(0),} field(0), result_field(0), item_equal(0), no_const_subst(0),
have_privileges(0), any_privileges(0) have_privileges(0), any_privileges(0)
{ collation.set(DERIVATION_IMPLICIT); } { collation.set(DERIVATION_IMPLICIT); }
// Constructor need to process subselect with temporary tables (see Item) // Constructor need to process subselect with temporary tables (see Item)
......
...@@ -231,6 +231,8 @@ void Item_bool_func2::fix_length_and_dec() ...@@ -231,6 +231,8 @@ void Item_bool_func2::fix_length_and_dec()
conv->collation.set(args[weak]->collation.derivation); conv->collation.set(args[weak]->collation.derivation);
conv->fix_fields(thd, 0, &conv); conv->fix_fields(thd, 0, &conv);
} }
if (args[weak]->type() == FIELD_ITEM)
((Item_field *)args[weak])->no_const_subst= 1;
args[weak]= conv ? conv : args[weak]; args[weak]= conv ? conv : args[weak];
} }
} }
...@@ -1956,7 +1958,7 @@ Item_cond::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) ...@@ -1956,7 +1958,7 @@ Item_cond::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
char buff[sizeof(char*)]; // Max local vars in function char buff[sizeof(char*)]; // Max local vars in function
#endif #endif
not_null_tables_cache= used_tables_cache= 0; not_null_tables_cache= used_tables_cache= 0;
const_item_cache= 0; const_item_cache= 1;
/* /*
and_table_cache is the value that Item_cond_or() returns for and_table_cache is the value that Item_cond_or() returns for
not_null_tables() not_null_tables()
...@@ -1987,7 +1989,7 @@ Item_cond::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) ...@@ -1987,7 +1989,7 @@ Item_cond::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
tmp_table_map= item->not_null_tables(); tmp_table_map= item->not_null_tables();
not_null_tables_cache|= tmp_table_map; not_null_tables_cache|= tmp_table_map;
and_tables_cache&= tmp_table_map; and_tables_cache&= tmp_table_map;
const_item_cache&= item->const_item(); const_item_cache&= item->const_item();
with_sum_func= with_sum_func || item->with_sum_func; with_sum_func= with_sum_func || item->with_sum_func;
if (item->maybe_null) if (item->maybe_null)
maybe_null=1; maybe_null=1;
...@@ -2051,7 +2053,7 @@ void Item_cond::split_sum_func(Item **ref_pointer_array, List<Item> &fields) ...@@ -2051,7 +2053,7 @@ void Item_cond::split_sum_func(Item **ref_pointer_array, List<Item> &fields)
List_iterator<Item> li(list); List_iterator<Item> li(list);
Item *item; Item *item;
used_tables_cache=0; used_tables_cache=0;
const_item_cache=0; const_item_cache=1;
while ((item=li++)) while ((item=li++))
{ {
if (item->with_sum_func && item->type() != SUM_FUNC_ITEM) if (item->with_sum_func && item->type() != SUM_FUNC_ITEM)
...@@ -2088,7 +2090,7 @@ void Item_cond::update_used_tables() ...@@ -2088,7 +2090,7 @@ void Item_cond::update_used_tables()
{ {
item->update_used_tables(); item->update_used_tables();
used_tables_cache|= item->used_tables(); used_tables_cache|= item->used_tables();
const_item_cache&= item->const_item(); const_item_cache&= item->const_item();
} }
} }
...@@ -2934,6 +2936,7 @@ void Item_equal::add(Item *c) ...@@ -2934,6 +2936,7 @@ void Item_equal::add(Item *c)
} }
Item_func_eq *func= new Item_func_eq(c, const_item); Item_func_eq *func= new Item_func_eq(c, const_item);
func->set_cmp_func(); func->set_cmp_func();
func->quick_fix_field();
cond_false = !(func->val_int()); cond_false = !(func->val_int());
} }
......
...@@ -3339,6 +3339,63 @@ static SEL_TREE *get_mm_tree(PARAM *param,COND *cond) ...@@ -3339,6 +3339,63 @@ static SEL_TREE *get_mm_tree(PARAM *param,COND *cond)
} }
DBUG_RETURN(ftree); DBUG_RETURN(ftree);
}
default:
if (cond_func->arguments()[0]->type() == Item::FIELD_ITEM)
{
field_item= (Item_field*) (cond_func->arguments()[0]);
value= cond_func->arg_count > 1 ? cond_func->arguments()[1] : 0;
}
else if (cond_func->have_rev_func() &&
cond_func->arguments()[1]->type() == Item::FIELD_ITEM)
{
field_item= (Item_field*) (cond_func->arguments()[1]);
value= cond_func->arguments()[0];
}
else
DBUG_RETURN(0);
}
/*
If the where condition contains a predicate (ti.field op const),
then not only SELL_TREE for this predicate is built, but
the trees for the results of substitution of ti.field for
each tj.field belonging to the same multiple equality as ti.field
are built as well.
E.g. for WHERE t1.a=t2.a AND t2.a > 10
a SEL_TREE for t2.a > 10 will be built for quick select from t2
and
a SEL_TREE for t1.a > 10 will be built for quick select from t1.
*/
for (uint i= 0; i < cond_func->arg_count; i++)
{
Item *arg= cond_func->arguments()[i];
if (arg != field_item)
ref_tables|= arg->used_tables();
}
Field *field= field_item->field;
Item_result cmp_type= field->cmp_type();
if (!((ref_tables | field->table->map) & param_comp))
ftree= get_func_mm_tree(param, cond_func, field, value, cmp_type);
Item_equal *item_equal= field_item->item_equal;
if (item_equal)
{
Item_equal_iterator it(*item_equal);
Item_field *item;
while ((item= it++))
{
Field *f= item->field;
if (field->eq(f))
continue;
if (!((ref_tables | f->table->map) & param_comp))
{
tree= get_func_mm_tree(param, cond_func, f, value, cmp_type);
ftree= !ftree ? tree : tree_and(param, ftree, tree);
}
}
}
DBUG_RETURN(ftree);
} }
......
This diff is collapsed.
...@@ -91,7 +91,8 @@ typedef struct st_join_table { ...@@ -91,7 +91,8 @@ typedef struct st_join_table {
SQL_SELECT *select; SQL_SELECT *select;
COND *select_cond; COND *select_cond;
QUICK_SELECT_I *quick; QUICK_SELECT_I *quick;
Item *on_expr; /* associated on expression */ Item **on_expr_ref; /* pointer to the associated on expression */
COND_EQUAL *cond_equal; /* multiple equalities for the on expression */
st_join_table *first_inner; /* first inner table for including outerjoin */ st_join_table *first_inner; /* first inner table for including outerjoin */
bool found; /* true after all matches or null complement */ bool found; /* true after all matches or null complement */
bool not_null_compl;/* true before null complement is added */ bool not_null_compl;/* true before null complement is added */
......
...@@ -21,6 +21,7 @@ class Item; /* Needed by ORDER */ ...@@ -21,6 +21,7 @@ class Item; /* Needed by ORDER */
class GRANT_TABLE; class GRANT_TABLE;
class st_select_lex_unit; class st_select_lex_unit;
class st_select_lex; class st_select_lex;
class COND_EQUAL;
/* Order clause list element */ /* Order clause list element */
...@@ -209,6 +210,7 @@ typedef struct st_table_list ...@@ -209,6 +210,7 @@ typedef struct st_table_list
char *db, *alias, *real_name; char *db, *alias, *real_name;
char *option; /* Used by cache index */ char *option; /* Used by cache index */
Item *on_expr; /* Used with outer join */ Item *on_expr; /* Used with outer join */
COND_EQUAL *cond_equal; /* Used with outer join */
struct st_table_list *natural_join; /* natural join on this table*/ struct st_table_list *natural_join; /* natural join on this table*/
/* ... join ... USE INDEX ... IGNORE INDEX */ /* ... join ... USE INDEX ... IGNORE INDEX */
List<String> *use_index, *ignore_index; List<String> *use_index, *ignore_index;
......
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