Commit 5c078ceb authored by Igor Babaev's avatar Igor Babaev

Merge

parents 1474a17f 1a18998c
......@@ -3974,3 +3974,158 @@ WHERE t3.pk = v1.a AND t2.b = 1 AND t2.b = t3.pk AND v1.a BETWEEN 2 AND 5;
a pk b pk b
DROP VIEW v1;
DROP TABLE t1, t2, t3;
#
# Bug#717577: substitution for best field in a query over a view and
# with OR in the WHERE condition
#
create table t1 (a int, b int);
insert into t1 values (2,4), (1,3);
create table t2 (c int);
insert into t2 values (6), (4), (1), (3), (8), (3), (4), (2);
select * from t1,t2 where t2.c=t1.a and t2.c < 3 or t2.c=t1.b and t2.c >=4;
a b c
2 4 4
1 3 1
2 4 4
2 4 2
explain extended
select * from t1,t2 where t2.c=t1.a and t2.c < 3 or t2.c=t1.b and t2.c >=4;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
1 SIMPLE t2 ALL NULL NULL NULL NULL 8 100.00 Using where; Using join buffer (flat, BNL join)
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t1` join `test`.`t2` where (((`test`.`t2`.`c` = `test`.`t1`.`a`) and (`test`.`t1`.`a` < 3)) or ((`test`.`t2`.`c` = `test`.`t1`.`b`) and (`test`.`t1`.`b` >= 4)))
create view v1 as select * from t2;
select * from t1,v1 where v1.c=t1.a and v1.c < 3 or v1.c=t1.b and v1.c >=4;
a b c
2 4 4
1 3 1
2 4 4
2 4 2
explain extended
select * from t1,v1 where v1.c=t1.a and v1.c < 3 or v1.c=t1.b and v1.c >=4;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
1 SIMPLE t2 ALL NULL NULL NULL NULL 8 100.00 Using where; Using join buffer (flat, BNL join)
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t1` join `test`.`t2` where (((`test`.`t2`.`c` = `test`.`t1`.`a`) and (`test`.`t1`.`a` < 3)) or ((`test`.`t2`.`c` = `test`.`t1`.`b`) and (`test`.`t1`.`b` >= 4)))
create view v2 as select * from v1;
select * from t1,v2 where v2.c=t1.a and v2.c < 3 or v2.c=t1.b and v2.c >=4;
a b c
2 4 4
1 3 1
2 4 4
2 4 2
explain extended
select * from t1,v2 where v2.c=t1.a and v2.c < 3 or v2.c=t1.b and v2.c >=4;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
1 SIMPLE t2 ALL NULL NULL NULL NULL 8 100.00 Using where; Using join buffer (flat, BNL join)
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t1` join `test`.`t2` where (((`test`.`t2`.`c` = `test`.`t1`.`a`) and (`test`.`t1`.`a` < 3)) or ((`test`.`t2`.`c` = `test`.`t1`.`b`) and (`test`.`t1`.`b` >= 4)))
create view v3 as select * from t1;
select * from v3,v2 where v2.c=v3.a and v2.c < 3 or v2.c=v3.b and v2.c >=4;
a b c
2 4 4
1 3 1
2 4 4
2 4 2
explain extended
select * from v3,v2 where v2.c=v3.a and v2.c < 3 or v2.c=v3.b and v2.c >=4;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
1 SIMPLE t2 ALL NULL NULL NULL NULL 8 100.00 Using where; Using join buffer (flat, BNL join)
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a`,`test`.`t1`.`b` AS `b`,`test`.`t2`.`c` AS `c` from `test`.`t1` join `test`.`t2` where (((`test`.`t2`.`c` = `test`.`t1`.`a`) and (`test`.`t1`.`a` < 3)) or ((`test`.`t2`.`c` = `test`.`t1`.`b`) and (`test`.`t1`.`b` >= 4)))
drop view v1,v2,v3;
drop table t1,t2;
#
# Bug#724942: substitution of the constant into a view field
#
CREATE TABLE t1 (a int);
INSERT INTO t1 VALUES (2), (9), (9), (6), (5), (4), (7);
CREATE VIEW v1 AS SELECT * FROM t1;
SELECT * FROM v1 WHERE a > -1 OR a > 6 AND a = 3;
a
2
9
9
6
5
4
7
EXPLAIN EXTENDED
SELECT * FROM v1 WHERE a > -1 OR a > 6 AND a = 3;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 7 100.00 Using where
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` > -(1))
SELECT * FROM v1 WHERE a > -1 OR a AND a = 0;
a
2
9
9
6
5
4
7
EXPLAIN EXTENDED
SELECT * FROM v1 WHERE a > -1 OR a AND a = 0;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 7 100.00 Using where
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` > -(1))
CREATE VIEW v2 AS SELECT * FROM v1;
SELECT * FROM v2 WHERE a > -1 OR a AND a = 0;
a
2
9
9
6
5
4
7
EXPLAIN EXTENDED
SELECT * FROM v2 WHERE a > -1 OR a AND a = 0;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 7 100.00 Using where
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` > -(1))
DROP VIEW v1,v2;
DROP TABLE t1;
CREATE TABLE t1 (a varchar(10), KEY (a)) ;
INSERT INTO t1 VALUES
('DD'), ('ZZ'), ('ZZ'), ('KK'), ('FF'), ('HH'),('MM');
CREATE VIEW v1 AS SELECT * FROM t1;
SELECT * FROM v1 WHERE a > 'JJ' OR a <> 0 AND a = 'VV';
a
KK
MM
ZZ
ZZ
Warnings:
Warning 1292 Truncated incorrect DOUBLE value: 'VV'
EXPLAIN EXTENDED
SELECT * FROM v1 WHERE a > 'JJ' OR a <> 0 AND a = 'VV';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 range a a 13 NULL 4 100.00 Using where; Using index
Warnings:
Warning 1292 Truncated incorrect DOUBLE value: 'VV'
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` > 'JJ')
SELECT * FROM v1 WHERE a > 'JJ' OR a AND a = 'VV';
a
KK
MM
ZZ
ZZ
Warnings:
Warning 1292 Truncated incorrect INTEGER value: 'VV'
EXPLAIN EXTENDED
SELECT * FROM v1 WHERE a > 'JJ' OR a AND a = 'VV';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 range a a 13 NULL 4 100.00 Using where; Using index
Warnings:
Warning 1292 Truncated incorrect INTEGER value: 'VV'
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` > 'JJ')
DROP VIEW v1;
DROP TABLE t1;
......@@ -3999,3 +3999,77 @@ SELECT * FROM v1, t2, t3
DROP VIEW v1;
DROP TABLE t1, t2, t3;
--echo #
--echo # Bug#717577: substitution for best field in a query over a view and
--echo # with OR in the WHERE condition
--echo #
create table t1 (a int, b int);
insert into t1 values (2,4), (1,3);
create table t2 (c int);
insert into t2 values (6), (4), (1), (3), (8), (3), (4), (2);
select * from t1,t2 where t2.c=t1.a and t2.c < 3 or t2.c=t1.b and t2.c >=4;
explain extended
select * from t1,t2 where t2.c=t1.a and t2.c < 3 or t2.c=t1.b and t2.c >=4;
create view v1 as select * from t2;
select * from t1,v1 where v1.c=t1.a and v1.c < 3 or v1.c=t1.b and v1.c >=4;
explain extended
select * from t1,v1 where v1.c=t1.a and v1.c < 3 or v1.c=t1.b and v1.c >=4;
create view v2 as select * from v1;
select * from t1,v2 where v2.c=t1.a and v2.c < 3 or v2.c=t1.b and v2.c >=4;
explain extended
select * from t1,v2 where v2.c=t1.a and v2.c < 3 or v2.c=t1.b and v2.c >=4;
create view v3 as select * from t1;
select * from v3,v2 where v2.c=v3.a and v2.c < 3 or v2.c=v3.b and v2.c >=4;
explain extended
select * from v3,v2 where v2.c=v3.a and v2.c < 3 or v2.c=v3.b and v2.c >=4;
drop view v1,v2,v3;
drop table t1,t2;
--echo #
--echo # Bug#724942: substitution of the constant into a view field
--echo #
CREATE TABLE t1 (a int);
INSERT INTO t1 VALUES (2), (9), (9), (6), (5), (4), (7);
CREATE VIEW v1 AS SELECT * FROM t1;
SELECT * FROM v1 WHERE a > -1 OR a > 6 AND a = 3;
EXPLAIN EXTENDED
SELECT * FROM v1 WHERE a > -1 OR a > 6 AND a = 3;
SELECT * FROM v1 WHERE a > -1 OR a AND a = 0;
EXPLAIN EXTENDED
SELECT * FROM v1 WHERE a > -1 OR a AND a = 0;
CREATE VIEW v2 AS SELECT * FROM v1;
SELECT * FROM v2 WHERE a > -1 OR a AND a = 0;
EXPLAIN EXTENDED
SELECT * FROM v2 WHERE a > -1 OR a AND a = 0;
DROP VIEW v1,v2;
DROP TABLE t1;
CREATE TABLE t1 (a varchar(10), KEY (a)) ;
INSERT INTO t1 VALUES
('DD'), ('ZZ'), ('ZZ'), ('KK'), ('FF'), ('HH'),('MM');
CREATE VIEW v1 AS SELECT * FROM t1;
SELECT * FROM v1 WHERE a > 'JJ' OR a <> 0 AND a = 'VV';
EXPLAIN EXTENDED
SELECT * FROM v1 WHERE a > 'JJ' OR a <> 0 AND a = 'VV';
SELECT * FROM v1 WHERE a > 'JJ' OR a AND a = 'VV';
EXPLAIN EXTENDED
SELECT * FROM v1 WHERE a > 'JJ' OR a AND a = 'VV';
DROP VIEW v1;
DROP TABLE t1;
......@@ -4669,13 +4669,14 @@ Item_equal *Item_field::find_item_equal(COND_EQUAL *cond_equal)
/**
Check whether a field can be substituted by an equal item.
Check whether a field item can be substituted for an equal item
The function checks whether a substitution of the field
occurrence for an equal item is valid.
@details
The function checks whether a substitution of a field item for
an equal item is valid.
@param arg *arg != NULL <-> the field is in the context where
substitution for an equal item is valid
@param arg *arg != NULL && **arg <-> the field is in the context
where substitution for an equal item is valid
@note
The following statement is not always true:
......@@ -4700,7 +4701,8 @@ Item_equal *Item_field::find_item_equal(COND_EQUAL *cond_equal)
bool Item_field::subst_argument_checker(uchar **arg)
{
return (result_type() != STRING_RESULT) || (*arg);
return (!(*arg) && (result_type() != STRING_RESULT)) ||
((*arg) && (**arg));
}
......@@ -4737,6 +4739,7 @@ static void convert_zerofill_number_to_string(Item **item, Field_num *field)
Set a pointer to the multiple equality the field reference belongs to
(if any).
@details
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.
......@@ -4813,6 +4816,7 @@ bool Item_field::set_no_const_sub(uchar *arg)
Replace an Item_field for an equal Item_field that evaluated earlier
(if any).
@details
If this->item_equal points to some item and coincides with arg then
the function returns a pointer to an item that is taken from
the very beginning of the item_equal list which the Item_field
......@@ -4827,7 +4831,7 @@ bool Item_field::set_no_const_sub(uchar *arg)
@note
This function is supposed to be called as a callback parameter in calls
of the thransformer method.
of the transformer method.
@return
- pointer to a replacement Item_field if there is a better equal item or
......@@ -4847,7 +4851,9 @@ Item *Item_field::replace_equal_field(uchar *arg)
return this;
return const_item;
}
Item_field *subst= item_equal->get_first(this);
Item_field *subst= (Item_field *)(item_equal->get_first(this));
if (subst)
subst= (Item_field *) (subst->real_item());
if (subst && !field->eq(subst->field))
return subst;
}
......@@ -6393,10 +6399,11 @@ Item* Item_ref::compile(Item_analyzer analyzer, uchar **arg_p,
/* Compile the Item we are referencing. */
DBUG_ASSERT((*ref) != NULL);
Item *new_item= (*ref)->compile(analyzer, arg_p, transformer, arg_t);
uchar *arg_v= *arg_p;
Item *new_item= (*ref)->compile(analyzer, &arg_v, transformer, arg_t);
if (new_item && *ref != new_item)
current_thd->change_item_tree(ref, new_item);
/* Transform this Item object. */
return (this->*transformer)(arg_t);
}
......@@ -7246,6 +7253,130 @@ bool Item_direct_view_ref::eq(const Item *item, bool binary_cmp) const
return FALSE;
}
Item_equal *Item_direct_view_ref::find_item_equal(COND_EQUAL *cond_equal)
{
Item* field_item= real_item();
if (field_item->type() != FIELD_ITEM)
return NULL;
return ((Item_field *) field_item)->find_item_equal(cond_equal);
}
/**
Check whether a reference to field item can be substituted for an equal item
@details
The function checks whether a substitution of a reference to field item for
an equal item is valid.
@param arg *arg != NULL && **arg <-> the reference is in the context
where substitution for an equal item is valid
@note
See also the note for Item_field::subst_argument_checker
@retval
TRUE substitution is valid
@retval
FALSE otherwise
*/
bool Item_direct_view_ref::subst_argument_checker(uchar **arg)
{
bool res= (!(*arg) && (result_type() != STRING_RESULT)) ||
((*arg) && (**arg));
/* Block any substitution into the wrapped object */
if (*arg)
**arg= (uchar) 0;
return res;
}
/**
Set a pointer to the multiple equality the view field reference belongs to
(if any).
@details
The function looks for a multiple equality containing this item of the type
Item_direct_view_ref 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 item
is substituted for this constant, otherwise the function sets a pointer
to the multiple equality in the item.
@param arg reference to list of multiple equalities where
the item (this object) is to be looked for
@note
This function is supposed to be called as a callback parameter in calls
of the compile method.
@note
The function calls Item_field::equal_fields_propagator for the field item
this->real_item() to do the job. Then it takes the pointer to equal_item
from this field item and assigns it to this->item_equal.
@return
- pointer to the replacing constant item, if the field item was substituted
- pointer to the field item, otherwise.
*/
Item *Item_direct_view_ref::equal_fields_propagator(uchar *arg)
{
Item *field_item= real_item();
if (field_item->type() != FIELD_ITEM)
return this;
Item *item= field_item->equal_fields_propagator(arg);
set_item_equal(field_item->get_item_equal());
field_item->set_item_equal(NULL);
if (item != field_item)
return item;
return this;
}
/**
Replace an Item_direct_view_ref for an equal Item_field evaluated earlier
(if any).
@details
If this->item_equal points to some item and coincides with arg then
the function returns a pointer to a field item that is referred to by the
first element of the item_equal list which the Item_direct_view_ref
object belongs to unless item_equal contains a constant item. In this
case the function returns this constant item (if the substitution does
not require conversion).
If the Item_direct_view_item object does not refer any Item_equal object
'this' is returned .
@param arg NULL or points to so some item of the Item_equal type
@note
This function is supposed to be called as a callback parameter in calls
of the transformer method.
@note
The function calls Item_field::replace_equal_field for the field item
this->real_item() to do the job.
@return
- pointer to a replacement Item_field if there is a better equal item or
a pointer to a constant equal item;
- this - otherwise.
*/
Item *Item_direct_view_ref::replace_equal_field(uchar *arg)
{
Item *field_item= real_item();
if (field_item->type() != FIELD_ITEM)
return this;
field_item->set_item_equal(item_equal);
Item *item= field_item->replace_equal_field(arg);
field_item->set_item_equal(0);
return item;
}
bool Item_default_value::eq(const Item *item, bool binary_cmp) const
{
return item->type() == DEFAULT_VALUE_ITEM &&
......
......@@ -487,6 +487,9 @@ typedef bool (Item::*Item_analyzer) (uchar **argp);
typedef Item* (Item::*Item_transformer) (uchar *arg);
typedef void (*Cond_traverser) (const Item *item, void *arg);
class Item_equal;
class COND_EQUAL;
class Item {
Item(const Item &); /* Prevent use of these */
......@@ -1195,6 +1198,10 @@ class Item {
bool eq_by_collation(Item *item, bool binary_cmp, CHARSET_INFO *cs);
Item* set_expr_cache(THD *thd, List<Item*> &depends_on);
virtual Item_equal *get_item_equal() { return NULL; }
virtual void set_item_equal(Item_equal *item_eq) {};
virtual Item_equal *find_item_equal(COND_EQUAL *cond_equal) { return NULL; }
};
......@@ -1626,9 +1633,6 @@ class Item_ident_for_show :public Item
};
class Item_equal;
class COND_EQUAL;
class Item_field :public Item_ident
{
protected:
......@@ -1723,6 +1727,8 @@ class Item_field :public Item_ident
{
return field->can_be_compared_as_longlong();
}
Item_equal *get_item_equal() { return item_equal; }
void set_item_equal(Item_equal *item_eq) { item_equal= item_eq; }
Item_equal *find_item_equal(COND_EQUAL *cond_equal);
bool subst_argument_checker(uchar **arg);
Item *equal_fields_propagator(uchar *arg);
......@@ -2739,17 +2745,19 @@ class Item_cache_wrapper :public Item_result_field
*/
class Item_direct_view_ref :public Item_direct_ref
{
Item_equal *item_equal;
public:
Item_direct_view_ref(Name_resolution_context *context_arg, Item **item,
const char *table_name_arg,
const char *field_name_arg)
:Item_direct_ref(context_arg, item, table_name_arg, field_name_arg) {}
:Item_direct_ref(context_arg, item, table_name_arg, field_name_arg),
item_equal(0) {}
/* Constructor need to process subselect with temporary tables (see Item) */
Item_direct_view_ref(THD *thd, Item_direct_ref *item)
:Item_direct_ref(thd, item) {}
:Item_direct_ref(thd, item), item_equal(0) {}
Item_direct_view_ref(TABLE_LIST *view_arg, Item **item,
const char *field_name_arg)
:Item_direct_ref(view_arg, item, field_name_arg)
:Item_direct_ref(view_arg, item, field_name_arg), item_equal(0)
{}
bool fix_fields(THD *, Item **);
......@@ -2761,6 +2769,12 @@ class Item_direct_view_ref :public Item_direct_ref
return item;
}
virtual Ref_Type ref_type() { return VIEW_REF; }
Item_equal *get_item_equal() { return item_equal; }
void set_item_equal(Item_equal *item_eq) { item_equal= item_eq; }
Item_equal *find_item_equal(COND_EQUAL *cond_equal);
bool subst_argument_checker(uchar **arg);
Item *equal_fields_propagator(uchar *arg);
Item *replace_equal_field(uchar *arg);
};
......
This diff is collapsed.
......@@ -26,7 +26,7 @@ class Arg_comparator;
typedef int (Arg_comparator::*arg_cmp_func)();
typedef int (*Item_field_cmpfunc)(Item_field *f1, Item_field *f2, void *arg);
typedef int (*Item_field_cmpfunc)(Item *f1, Item *f2, void *arg);
class Arg_comparator: public Sql_alloc
{
......@@ -1614,28 +1614,64 @@ class Item_cond :public Item_bool_func
class Item_equal: public Item_bool_func
{
List<Item_field> fields; /* list of equal field items */
Item *const_item; /* optional constant item equal to fields items */
/*
The list of equal items. Currently the list can contain:
- Item_fields items for references to table columns
- Item_direct_view_ref items for references to view columns
- one const item
If the list contains a constant item this item is always first in the list.
The list contains at least two elements.
Currently all Item_fields/Item_direct_view_ref items in the list should
refer to table columns with equavalent type definitions. In particular
if these are string columns they should have the same charset/collation.
Use objects of the companion class Item_equal_fields_iterator to iterate
over all items from the list of the Item_field/Item_direct_view_ref classes.
*/
List<Item> equal_items;
/*
TRUE <-> one of the items is a const item.
Such item is always first in in the equal_items list
*/
bool with_const;
/*
The field eval_item is used when this item is evaluated
with the method val_int()
*/
cmp_item *eval_item;
Arg_comparator cmp;
/*
This initially is set to FALSE. It becomes TRUE when this item is evaluated
as being always false. If the flag is TRUE the contents of the list
the equal_items should be ignored.
*/
bool cond_false;
/*
compare_as_dates=TRUE <-> constants equal to fields from equal_items
must be compared as datetimes and not as strings.
compare_as_dates can be TRUE only if with_const=TRUE
*/
bool compare_as_dates;
/*
The comparator used to compare constants equal to fields from equal_items
as datetimes. The comparator is used only if compare_as_dates=TRUE
*/
Arg_comparator cmp;
public:
inline Item_equal()
: Item_bool_func(), const_item(0), eval_item(0), cond_false(0)
: Item_bool_func(), with_const(FALSE), eval_item(0), cond_false(0)
{ const_item_cache=0 ;}
Item_equal(Item_field *f1, Item_field *f2);
Item_equal(Item *c, Item_field *f);
Item_equal(Item *f1, Item *f2, bool with_const_item);
Item_equal(Item_equal *item_equal);
inline Item* get_const() { return const_item; }
void compare_const(Item *c);
void add(Item *c, Item_field *f);
void add(Item *c);
void add(Item_field *f);
uint members();
/* Currently the const item is always the first in the list of equal items */
inline Item* get_const() { return with_const ? equal_items.head() : NULL; }
void add_const(Item *c, Item *f = NULL);
/** Add a non-constant item to the multiple equality */
void add(Item *f) { equal_items.push_back(f); }
bool contains(Field *field);
Item_field* get_first(Item_field *field);
uint n_fields() { return fields.elements; }
Item* get_first(Item *field);
/** Get number of field items / references to field items in this object */
uint n_field_items() { return equal_items.elements-test(with_const); }
void merge(Item_equal *item);
void update_const();
enum Functype functype() const { return MULT_EQUAL_FUNC; }
......@@ -1643,15 +1679,14 @@ class Item_equal: public Item_bool_func
const char *func_name() const { return "multiple equal"; }
optimize_type select_optimize() const { return OPTIMIZE_EQUAL; }
void sort(Item_field_cmpfunc compare, void *arg);
friend class Item_equal_iterator;
void fix_length_and_dec();
bool fix_fields(THD *thd, Item **ref);
void update_used_tables();
bool walk(Item_processor processor, bool walk_subquery, uchar *arg);
Item *transform(Item_transformer transformer, uchar *arg);
virtual void print(String *str, enum_query_type query_type);
CHARSET_INFO *compare_collation()
{ return fields.head()->collation.collation; }
CHARSET_INFO *compare_collation();
friend class Item_equal_fields_iterator;
friend Item *eliminate_item_equal(COND *cond, COND_EQUAL *upper_levels,
Item_equal *item_equal);
friend bool setup_sj_materialization(struct st_join_table *tab);
......@@ -1672,23 +1707,52 @@ class COND_EQUAL: public Sql_alloc
};
class Item_equal_iterator : public List_iterator_fast<Item_field>
/*
The class Item_equal_fields_iterator is used to iterate over references
to table/view columns from a list of equal items.
*/
class Item_equal_fields_iterator : public List_iterator_fast<Item>
{
Item_equal *item_equal;
Item *curr_item;
public:
inline Item_equal_iterator(Item_equal &item_equal)
:List_iterator_fast<Item_field> (item_equal.fields)
{}
inline Item_field* operator++(int)
{
Item_field *item= (*(List_iterator_fast<Item_field> *) this)++;
return item;
Item_equal_fields_iterator(Item_equal &item_eq)
:List_iterator_fast<Item> (item_eq.equal_items)
{
curr_item= NULL;
item_equal= &item_eq;
if (item_eq.with_const)
{
List_iterator_fast<Item> *list_it= this;
curr_item= (*list_it)++;
}
}
inline void rewind(void)
Item* operator++(int)
{
List_iterator_fast<Item_field>::rewind();
List_iterator_fast<Item> *list_it= this;
curr_item= (*list_it)++;
return curr_item;
}
Item ** ref()
{
return List_iterator_fast<Item>::ref();
}
void rewind(void)
{
List_iterator_fast<Item> *list_it= this;
list_it->rewind();
if (item_equal->with_const)
curr_item= (*list_it)++;
}
Field *get_curr_field()
{
Item_field *item= (Item_field *) (curr_item->real_item());
return item->field;
}
};
class Item_cond_and :public Item_cond
{
public:
......
......@@ -7104,11 +7104,10 @@ static SEL_TREE *get_full_func_mm_tree(RANGE_OPT_PARAM *param,
Item_equal *item_equal= field_item->item_equal;
if (item_equal)
{
Item_equal_iterator it(*item_equal);
Item_field *item;
while ((item= it++))
Item_equal_fields_iterator it(*item_equal);
while (it++)
{
Field *f= item->field;
Field *f= it.get_curr_field();
if (field->eq(f))
continue;
if (!((ref_tables | f->table->map) & param_comp))
......@@ -7259,11 +7258,11 @@ static SEL_TREE *get_mm_tree(RANGE_OPT_PARAM *param,COND *cond)
Item_equal *item_equal= (Item_equal *) cond;
if (!(value= item_equal->get_const()))
DBUG_RETURN(0);
Item_equal_iterator it(*item_equal);
Item_equal_fields_iterator it(*item_equal);
ref_tables= value->used_tables();
while ((field_item= it++))
while (it++)
{
Field *field= field_item->field;
Field *field= it.get_curr_field();
Item_result cmp_type= field->cmp_type();
if (!((ref_tables | field->table->map) & param_comp))
{
......
......@@ -2386,13 +2386,13 @@ bool setup_sj_materialization(JOIN_TAB *tab)
if (item_eq)
{
List_iterator<Item_field> it(item_eq->fields);
Item_field *item;
List_iterator<Item> it(item_eq->equal_items);
Item *item;
while ((item= it++))
{
if (!(item->used_tables() & ~emb_sj_nest->sj_inner_tables))
{
copy_to= item->field;
copy_to= ((Item_field *) (item->real_item()))->field;
break;
}
}
......
......@@ -473,7 +473,7 @@ bool simple_pred(Item_func *func_item, Item **args, bool *inv_order)
/* MULT_EQUAL_FUNC */
{
Item_equal *item_equal= (Item_equal *) func_item;
Item_equal_iterator it(*item_equal);
Item_equal_fields_iterator it(*item_equal);
args[0]= it++;
if (it++)
return 0;
......
......@@ -1208,15 +1208,16 @@ void build_eq_mods_for_cond(Dep_analysis_context *ctx,
if (!(fvl= new List<Dep_value_field>))
break; /* purecov: inspected */
Item_equal_iterator it(*item_equal);
Item_field *item;
Item_equal_fields_iterator it(*item_equal);
Item *item;
Item *bound_item= item_equal->get_const();
while ((item= it++))
{
Field *equal_field= it.get_curr_field();
if ((item->used_tables() & ctx->usable_tables))
{
Dep_value_field *field_val;
if ((field_val= ctx->get_field_value(item->field)))
if ((field_val= ctx->get_field_value(equal_field)))
fvl->push_back(field_val);
}
else
......
This diff is collapsed.
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