mirror of
https://github.com/MariaDB/server.git
synced 2025-12-24 11:21:21 +03:00
Merge
This commit is contained in:
@@ -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;
|
||||
|
||||
151
sql/item.cc
151
sql/item.cc
@@ -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 &&
|
||||
|
||||
26
sql/item.h
26
sql/item.h
@@ -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 @@ public:
|
||||
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 @@ public:
|
||||
};
|
||||
|
||||
|
||||
class Item_equal;
|
||||
class COND_EQUAL;
|
||||
|
||||
class Item_field :public Item_ident
|
||||
{
|
||||
protected:
|
||||
@@ -1723,6 +1727,8 @@ public:
|
||||
{
|
||||
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 @@ public:
|
||||
*/
|
||||
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 @@ public:
|
||||
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);
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -5525,43 +5525,92 @@ Item *Item_bool_rowready_func2::negated_item()
|
||||
return 0;
|
||||
}
|
||||
|
||||
Item_equal::Item_equal(Item_field *f1, Item_field *f2)
|
||||
: Item_bool_func(), const_item(0), eval_item(0), cond_false(0),
|
||||
compare_as_dates(FALSE)
|
||||
{
|
||||
const_item_cache= 0;
|
||||
fields.push_back(f1);
|
||||
fields.push_back(f2);
|
||||
}
|
||||
|
||||
Item_equal::Item_equal(Item *c, Item_field *f)
|
||||
/**
|
||||
Construct a minimal multiple equality item
|
||||
|
||||
@param f1 the first equal item
|
||||
@param f2 the second equal item
|
||||
@param with_const_item TRUE if the first item is constant
|
||||
|
||||
@details
|
||||
The constructor builds a new item equal object for the equality f1=f2.
|
||||
One of the equal items can be constant. If this is the case it is passed
|
||||
always as the first parameter and the parameter with_const_item serves
|
||||
as an indicator of this case.
|
||||
Currently any non-constant parameter items must point to an item of the
|
||||
of the type Item_field or Item_direct_view_ref(Item_field).
|
||||
*/
|
||||
|
||||
Item_equal::Item_equal(Item *f1, Item *f2, bool with_const_item)
|
||||
: Item_bool_func(), eval_item(0), cond_false(0)
|
||||
{
|
||||
const_item_cache= 0;
|
||||
fields.push_back(f);
|
||||
const_item= c;
|
||||
compare_as_dates= f->is_datetime();
|
||||
with_const= with_const_item;
|
||||
compare_as_dates= with_const_item && f2->is_datetime();
|
||||
equal_items.push_back(f1);
|
||||
equal_items.push_back(f2);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Copy constructor for a multiple equality
|
||||
|
||||
@param item_equal source item for the constructor
|
||||
|
||||
@details
|
||||
The function creates a copy of an Item_equal object.
|
||||
This constructor is used when an item belongs to a multiple equality
|
||||
of an upper level (an upper AND/OR level or an upper level of a nested
|
||||
outer join).
|
||||
*/
|
||||
|
||||
Item_equal::Item_equal(Item_equal *item_equal)
|
||||
: Item_bool_func(), eval_item(0), cond_false(0)
|
||||
{
|
||||
const_item_cache= 0;
|
||||
List_iterator_fast<Item_field> li(item_equal->fields);
|
||||
Item_field *item;
|
||||
List_iterator_fast<Item> li(item_equal->equal_items);
|
||||
Item *item;
|
||||
while ((item= li++))
|
||||
{
|
||||
fields.push_back(item);
|
||||
equal_items.push_back(item);
|
||||
}
|
||||
const_item= item_equal->const_item;
|
||||
with_const= item_equal->with_const;
|
||||
compare_as_dates= item_equal->compare_as_dates;
|
||||
cond_false= item_equal->cond_false;
|
||||
}
|
||||
|
||||
|
||||
void Item_equal::compare_const(Item *c)
|
||||
/*
|
||||
@brief
|
||||
Add a constant item to the Item_equal object
|
||||
|
||||
@param[in] c the constant to add
|
||||
@param[in] f item from the list equal_items the item c is equal to
|
||||
(this parameter is optional)
|
||||
|
||||
@details
|
||||
The method adds the constant item c to the equal_items list. If the list
|
||||
doesn't have any constant item yet the item c is just put in the front
|
||||
the list. Otherwise the value of c is compared with the value of the
|
||||
constant item from equal_items. If they are not equal cond_false is set
|
||||
to TRUE. This serves as an indicator that this Item_equal is always FALSE.
|
||||
The optional parameter f is used to adjust the flag compare_as_dates.
|
||||
*/
|
||||
|
||||
void Item_equal::add_const(Item *c, Item *f)
|
||||
{
|
||||
if (cond_false)
|
||||
return;
|
||||
if (!with_const)
|
||||
{
|
||||
with_const= TRUE;
|
||||
if (f)
|
||||
compare_as_dates= f->is_datetime();
|
||||
equal_items.push_front(c);
|
||||
return;
|
||||
}
|
||||
Item *const_item= get_const();
|
||||
if (compare_as_dates)
|
||||
{
|
||||
cmp.set_datetime_cmp_func(this, &c, &const_item);
|
||||
@@ -5579,64 +5628,28 @@ void Item_equal::compare_const(Item *c)
|
||||
}
|
||||
|
||||
|
||||
void Item_equal::add(Item *c, Item_field *f)
|
||||
{
|
||||
if (cond_false)
|
||||
return;
|
||||
if (!const_item)
|
||||
{
|
||||
DBUG_ASSERT(f);
|
||||
const_item= c;
|
||||
compare_as_dates= f->is_datetime();
|
||||
return;
|
||||
}
|
||||
compare_const(c);
|
||||
}
|
||||
|
||||
|
||||
void Item_equal::add(Item *c)
|
||||
{
|
||||
if (cond_false)
|
||||
return;
|
||||
if (!const_item)
|
||||
{
|
||||
const_item= c;
|
||||
return;
|
||||
}
|
||||
compare_const(c);
|
||||
}
|
||||
|
||||
void Item_equal::add(Item_field *f)
|
||||
{
|
||||
fields.push_back(f);
|
||||
}
|
||||
|
||||
uint Item_equal::members()
|
||||
{
|
||||
return fields.elements;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Check whether a field is referred in the multiple equality.
|
||||
|
||||
The function checks whether field is occurred in the Item_equal object .
|
||||
@brief
|
||||
Check whether a field is referred to in the multiple equality
|
||||
|
||||
@param field field whose occurrence is to be checked
|
||||
|
||||
@details
|
||||
The function checks whether field is referred to by one of the
|
||||
items from the equal_items list.
|
||||
|
||||
@retval
|
||||
1 if nultiple equality contains a reference to field
|
||||
1 if multiple equality contains a reference to field
|
||||
@retval
|
||||
0 otherwise
|
||||
*/
|
||||
|
||||
bool Item_equal::contains(Field *field)
|
||||
{
|
||||
List_iterator_fast<Item_field> it(fields);
|
||||
Item_field *item;
|
||||
while ((item= it++))
|
||||
Item_equal_fields_iterator it(*this);
|
||||
while (it++)
|
||||
{
|
||||
if (field->eq(item->field))
|
||||
if (field->eq(it.get_curr_field()))
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
@@ -5644,111 +5657,168 @@ bool Item_equal::contains(Field *field)
|
||||
|
||||
|
||||
/**
|
||||
Join members of another Item_equal object.
|
||||
@brief
|
||||
Join members of another Item_equal object
|
||||
|
||||
The function actually merges two multiple equalities.
|
||||
After this operation the Item_equal object additionally contains
|
||||
the field items of another item of the type Item_equal.
|
||||
If the optional constant items are not equal the cond_false flag is
|
||||
set to 1.
|
||||
@param item multiple equality whose members are to be joined
|
||||
|
||||
@details
|
||||
The function actually merges two multiple equalities. After this operation
|
||||
the Item_equal object additionally contains the field items of another item of
|
||||
the type Item_equal.
|
||||
If the optional constant items are not equal the cond_false flag is set to TRUE.
|
||||
|
||||
@notes
|
||||
The function is called for any equality f1=f2 such that f1 and f2 are items
|
||||
of the type Item_field or Item_direct_view_ref(Item_field), and, f1->field is
|
||||
referred to in the list this->equal_items, while the list item->equal_items
|
||||
contains a reference to f2->field.
|
||||
*/
|
||||
|
||||
void Item_equal::merge(Item_equal *item)
|
||||
{
|
||||
fields.concat(&item->fields);
|
||||
Item *c= item->const_item;
|
||||
Item *c= item->get_const();
|
||||
if (c)
|
||||
item->equal_items.pop();
|
||||
equal_items.concat(&item->equal_items);
|
||||
if (c)
|
||||
{
|
||||
/*
|
||||
The flag cond_false will be set to 1 after this, if
|
||||
The flag cond_false will be set to TRUE after this if
|
||||
the multiple equality already contains a constant and its
|
||||
value is not equal to the value of c.
|
||||
value is not equal to the value of c.
|
||||
*/
|
||||
add(c);
|
||||
add_const(c);
|
||||
}
|
||||
cond_false|= item->cond_false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Order field items in multiple equality according to a sorting criteria.
|
||||
@brief
|
||||
Order equal items of the multiple equality according to a sorting criteria
|
||||
|
||||
The function perform ordering of the field items in the Item_equal
|
||||
object according to the criteria determined by the cmp callback parameter.
|
||||
If cmp(item_field1,item_field2,arg)<0 than item_field1 must be
|
||||
placed after item_fiel2.
|
||||
@param compare function to compare items from the equal_items list
|
||||
@param arg context extra parameter for the cmp function
|
||||
|
||||
The function sorts field items by the bubble sort algorithm.
|
||||
@details
|
||||
The function performs ordering of the items from the equal_items list
|
||||
according to the criteria determined by the cmp callback parameter.
|
||||
If cmp(item1,item2,arg)<0 than item1 must be placed after item2.
|
||||
|
||||
@notes
|
||||
The function sorts equal items by the bubble sort algorithm.
|
||||
The list of field items is looked through and whenever two neighboring
|
||||
members follow in a wrong order they are swapped. This is performed
|
||||
again and again until we get all members in a right order.
|
||||
|
||||
@param compare function to compare field item
|
||||
@param arg context extra parameter for the cmp function
|
||||
*/
|
||||
|
||||
void Item_equal::sort(Item_field_cmpfunc compare, void *arg)
|
||||
{
|
||||
bubble_sort<Item_field>(&fields, compare, arg);
|
||||
bubble_sort<Item>(&equal_items, compare, arg);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Check appearance of new constant items in the multiple equality object.
|
||||
@brief
|
||||
Check appearance of new constant items in the multiple equality object
|
||||
|
||||
The function checks appearance of new constant items among
|
||||
the members of multiple equalities. Each new constant item is
|
||||
compared with the designated constant item if there is any in the
|
||||
multiple equality. If there is none the first new constant item
|
||||
becomes designated.
|
||||
@details
|
||||
The function checks appearance of new constant items among the members
|
||||
of the equal_items list. Each new constant item is compared with
|
||||
the constant item from the list if there is any. If there is none the first
|
||||
new constant item is placed at the very beginning of the list and
|
||||
with_const is set to TRUE. If it happens that the compared constant items
|
||||
are unequal then the flag cond_false is set to TRUE.
|
||||
|
||||
@notes
|
||||
Currently this function is called only after substitution of constant tables.
|
||||
*/
|
||||
|
||||
void Item_equal::update_const()
|
||||
{
|
||||
List_iterator<Item_field> it(fields);
|
||||
Item *item;
|
||||
while ((item= it++))
|
||||
List_iterator<Item> it(equal_items);
|
||||
if (with_const)
|
||||
it++;
|
||||
Item *item= it++;
|
||||
while (item)
|
||||
{
|
||||
if (item->const_item())
|
||||
{
|
||||
it.remove();
|
||||
add(item);
|
||||
Item *next_item= it++;
|
||||
add_const(item);
|
||||
item= next_item;
|
||||
}
|
||||
else
|
||||
item= it++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@brief
|
||||
Fix fields in a completely built multiple equality
|
||||
|
||||
@param thd currently not used thread handle
|
||||
@param ref not used
|
||||
|
||||
@details
|
||||
This function is called once the multiple equality has been built out of
|
||||
the WHERE/ON condition and no new members are expected to be added to the
|
||||
equal_items list anymore.
|
||||
As any implementation of the virtual fix_fields method the function
|
||||
calculates the cached values of not_null_tables_cache, used_tables_cache,
|
||||
const_item_cache and calls fix_length_and_dec().
|
||||
Additionally the function sets a reference to the Item_equal object in
|
||||
the non-constant items of the equal_items list unless such a reference has
|
||||
been already set.
|
||||
|
||||
@notes
|
||||
Currently this function is called only in the function
|
||||
build_equal_items_for_cond.
|
||||
|
||||
@retval
|
||||
FALSE always
|
||||
*/
|
||||
|
||||
bool Item_equal::fix_fields(THD *thd, Item **ref)
|
||||
{
|
||||
List_iterator_fast<Item_field> li(fields);
|
||||
Item_field *item;
|
||||
{
|
||||
DBUG_ASSERT(fixed == 0);
|
||||
Item_equal_fields_iterator it(*this);
|
||||
Item *item;
|
||||
not_null_tables_cache= used_tables_cache= 0;
|
||||
const_item_cache= 0;
|
||||
while ((item= li++))
|
||||
while ((item= it++))
|
||||
{
|
||||
table_map tmp_table_map;
|
||||
used_tables_cache|= item->used_tables();
|
||||
tmp_table_map= item->not_null_tables();
|
||||
not_null_tables_cache|= tmp_table_map;
|
||||
if (item->maybe_null)
|
||||
maybe_null=1;
|
||||
if (!item->item_equal)
|
||||
item->item_equal= this;
|
||||
maybe_null= 1;
|
||||
if (!item->get_item_equal())
|
||||
item->set_item_equal(this);
|
||||
}
|
||||
fix_length_and_dec();
|
||||
fixed= 1;
|
||||
return 0;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Update the value of the used table attribute and other attributes
|
||||
*/
|
||||
|
||||
void Item_equal::update_used_tables()
|
||||
{
|
||||
List_iterator_fast<Item_field> li(fields);
|
||||
Item *item;
|
||||
not_null_tables_cache= used_tables_cache= 0;
|
||||
if ((const_item_cache= cond_false))
|
||||
return;
|
||||
Item_equal_fields_iterator it(*this);
|
||||
Item *item;
|
||||
const_item_cache= 1;
|
||||
while ((item=li++))
|
||||
while ((item= it++))
|
||||
{
|
||||
item->update_used_tables();
|
||||
used_tables_cache|= item->used_tables();
|
||||
@@ -5756,28 +5826,54 @@ void Item_equal::update_used_tables()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@brief
|
||||
Evaluate multiple equality
|
||||
|
||||
@details
|
||||
The function evaluate multiple equality to a boolean value.
|
||||
The function ignores non-constant items from the equal_items list.
|
||||
The function returns 1 if all constant items from the list are equal.
|
||||
It returns 0 if there are unequal constant items in the list or
|
||||
one of the constant items is evaluated to NULL.
|
||||
|
||||
@notes
|
||||
Currently this function can be called only at the optimization
|
||||
stage after the constant table substitution, since all Item_equals
|
||||
are eliminated before the execution stage.
|
||||
|
||||
@retval
|
||||
0 multiple equality is always FALSE or NULL
|
||||
1 otherwise
|
||||
*/
|
||||
|
||||
longlong Item_equal::val_int()
|
||||
{
|
||||
Item_field *item_field;
|
||||
if (cond_false)
|
||||
return 0;
|
||||
List_iterator_fast<Item_field> it(fields);
|
||||
Item *item= const_item ? const_item : it++;
|
||||
if ((null_value= item->is_null()))
|
||||
return 0;
|
||||
Item *item= get_const();
|
||||
Item_equal_fields_iterator it(*this);
|
||||
if (!item)
|
||||
item= it++;
|
||||
eval_item->store_value(item);
|
||||
while ((item_field= it++))
|
||||
if ((null_value= item->null_value))
|
||||
return 0;
|
||||
while ((item= it++))
|
||||
{
|
||||
Field *field= it.get_curr_field();
|
||||
/* Skip fields of non-const tables. They haven't been read yet */
|
||||
if (item_field->field->table->const_table)
|
||||
if (field->table->const_table)
|
||||
{
|
||||
if ((null_value= item_field->is_null()) || eval_item->cmp(item_field))
|
||||
if (eval_item->cmp(item) || (null_value= item->null_value))
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void Item_equal::fix_length_and_dec()
|
||||
{
|
||||
Item *item= get_first(NULL);
|
||||
@@ -5785,10 +5881,11 @@ void Item_equal::fix_length_and_dec()
|
||||
item->collation.collation);
|
||||
}
|
||||
|
||||
|
||||
bool Item_equal::walk(Item_processor processor, bool walk_subquery, uchar *arg)
|
||||
{
|
||||
List_iterator_fast<Item_field> it(fields);
|
||||
Item *item;
|
||||
Item_equal_fields_iterator it(*this);
|
||||
while ((item= it++))
|
||||
{
|
||||
if (item->walk(processor, walk_subquery, arg))
|
||||
@@ -5797,12 +5894,13 @@ bool Item_equal::walk(Item_processor processor, bool walk_subquery, uchar *arg)
|
||||
return Item_func::walk(processor, walk_subquery, arg);
|
||||
}
|
||||
|
||||
|
||||
Item *Item_equal::transform(Item_transformer transformer, uchar *arg)
|
||||
{
|
||||
DBUG_ASSERT(!current_thd->is_stmt_prepare());
|
||||
|
||||
List_iterator<Item_field> it(fields);
|
||||
Item *item;
|
||||
Item_equal_fields_iterator it(*this);
|
||||
while ((item= it++))
|
||||
{
|
||||
Item *new_item= item->transform(transformer, arg);
|
||||
@@ -5821,19 +5919,15 @@ Item *Item_equal::transform(Item_transformer transformer, uchar *arg)
|
||||
return Item_func::transform(transformer, arg);
|
||||
}
|
||||
|
||||
|
||||
void Item_equal::print(String *str, enum_query_type query_type)
|
||||
{
|
||||
str->append(func_name());
|
||||
str->append('(');
|
||||
List_iterator_fast<Item_field> it(fields);
|
||||
List_iterator_fast<Item> it(equal_items);
|
||||
Item *item;
|
||||
if (const_item)
|
||||
const_item->print(str, query_type);
|
||||
else
|
||||
{
|
||||
item= it++;
|
||||
item->print(str, query_type);
|
||||
}
|
||||
item= it++;
|
||||
item->print(str, query_type);
|
||||
while ((item= it++))
|
||||
{
|
||||
str->append(',');
|
||||
@@ -5844,6 +5938,14 @@ void Item_equal::print(String *str, enum_query_type query_type)
|
||||
}
|
||||
|
||||
|
||||
CHARSET_INFO *Item_equal::compare_collation()
|
||||
{
|
||||
Item_equal_fields_iterator it(*this);
|
||||
Item *item= it++;
|
||||
return item->collation.collation;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
@brief Get the first equal field of multiple equality.
|
||||
@param[in] field the field to get equal field to
|
||||
@@ -5869,13 +5971,14 @@ void Item_equal::print(String *str, enum_query_type query_type)
|
||||
@retval 0 if no field found.
|
||||
*/
|
||||
|
||||
Item_field* Item_equal::get_first(Item_field *field)
|
||||
Item* Item_equal::get_first(Item *field_item)
|
||||
{
|
||||
List_iterator<Item_field> it(fields);
|
||||
Item_field *item;
|
||||
Item_equal_fields_iterator it(*this);
|
||||
Item *item;
|
||||
JOIN_TAB *field_tab;
|
||||
if (!field)
|
||||
return fields.head();
|
||||
if (!field_item)
|
||||
return (it++);
|
||||
Field *field= ((Item_field *) (field_item->real_item()))->field;
|
||||
|
||||
/*
|
||||
Of all equal fields, return the first one we can use. Normally, this is the
|
||||
@@ -5897,9 +6000,9 @@ Item_field* Item_equal::get_first(Item_field *field)
|
||||
in presense of SJM nests.
|
||||
*/
|
||||
|
||||
field_tab= field->field->table->reginfo.join_tab;
|
||||
field_tab= field->table->reginfo.join_tab;
|
||||
|
||||
TABLE_LIST *emb_nest= field->field->table->pos_in_table_list->embedding;
|
||||
TABLE_LIST *emb_nest= field->table->pos_in_table_list->embedding;
|
||||
|
||||
if (emb_nest && emb_nest->sj_mat_info && emb_nest->sj_mat_info->is_used)
|
||||
{
|
||||
@@ -5926,13 +6029,13 @@ Item_field* Item_equal::get_first(Item_field *field)
|
||||
/* Find an item to substitute for. */
|
||||
while ((item= it++))
|
||||
{
|
||||
if (item->field->table->reginfo.join_tab >= first)
|
||||
if (it.get_curr_field()->table->reginfo.join_tab >= first)
|
||||
{
|
||||
/*
|
||||
If we found given field then return NULL to avoid unnecessary
|
||||
substitution.
|
||||
*/
|
||||
return (item != field) ? item : NULL;
|
||||
return (item != field_item) ? item : NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5956,7 +6059,8 @@ Item_field* Item_equal::get_first(Item_field *field)
|
||||
*/
|
||||
while ((item= it++))
|
||||
{
|
||||
TABLE_LIST *emb_nest= item->field->table->pos_in_table_list->embedding;
|
||||
Item_field *fld_item= (Item_field *) (item->real_item());
|
||||
TABLE_LIST *emb_nest= fld_item->field->table->pos_in_table_list->embedding;
|
||||
if (!emb_nest || !emb_nest->sj_mat_info ||
|
||||
!emb_nest->sj_mat_info->is_used)
|
||||
{
|
||||
@@ -5964,7 +6068,7 @@ Item_field* Item_equal::get_first(Item_field *field)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return fields.head();
|
||||
return equal_items.head();
|
||||
}
|
||||
// Shouldn't get here.
|
||||
DBUG_ASSERT(0);
|
||||
|
||||
@@ -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 @@ public:
|
||||
|
||||
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 @@ public:
|
||||
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 @@ public:
|
||||
};
|
||||
|
||||
|
||||
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
|
||||
|
||||
@@ -3764,28 +3764,28 @@ add_key_field(JOIN *join,
|
||||
|
||||
static void
|
||||
add_key_equal_fields(JOIN *join, KEY_FIELD **key_fields, uint and_level,
|
||||
Item_func *cond, Item_field *field_item,
|
||||
Item_func *cond, Item *field_item,
|
||||
bool eq_func, Item **val,
|
||||
uint num_values, table_map usable_tables,
|
||||
SARGABLE_PARAM **sargables)
|
||||
{
|
||||
Field *field= field_item->field;
|
||||
Field *field= ((Item_field *) (field_item->real_item()))->field;
|
||||
add_key_field(join, key_fields, and_level, cond, field,
|
||||
eq_func, val, num_values, usable_tables, sargables);
|
||||
Item_equal *item_equal= field_item->item_equal;
|
||||
Item_equal *item_equal= field_item->get_item_equal();
|
||||
if (item_equal)
|
||||
{
|
||||
/*
|
||||
Add to the set of possible key values every substitution of
|
||||
the field for an equal field included into item_equal
|
||||
*/
|
||||
Item_equal_iterator it(*item_equal);
|
||||
Item_field *item;
|
||||
while ((item= it++))
|
||||
Item_equal_fields_iterator it(*item_equal);
|
||||
while (it++)
|
||||
{
|
||||
if (!field->eq(item->field))
|
||||
Field *equal_field= it.get_curr_field();
|
||||
if (!field->eq(equal_field))
|
||||
{
|
||||
add_key_field(join, key_fields, and_level, cond, item->field,
|
||||
add_key_field(join, key_fields, and_level, cond, equal_field,
|
||||
eq_func, val, num_values, usable_tables,
|
||||
sargables);
|
||||
}
|
||||
@@ -3982,8 +3982,7 @@ add_key_fields(JOIN *join, KEY_FIELD **key_fields, uint *and_level,
|
||||
case Item_func::OPTIMIZE_EQUAL:
|
||||
Item_equal *item_equal= (Item_equal *) cond;
|
||||
Item *const_item= item_equal->get_const();
|
||||
Item_equal_iterator it(*item_equal);
|
||||
Item_field *item;
|
||||
Item_equal_fields_iterator it(*item_equal);
|
||||
if (const_item)
|
||||
{
|
||||
/*
|
||||
@@ -3991,9 +3990,10 @@ add_key_fields(JOIN *join, KEY_FIELD **key_fields, uint *and_level,
|
||||
field1=const_item as a condition allowing an index access of the table
|
||||
with field1 by the keys value of field1.
|
||||
*/
|
||||
while ((item= it++))
|
||||
while (it++)
|
||||
{
|
||||
add_key_field(join, key_fields, *and_level, cond_func, item->field,
|
||||
Field *equal_field= it.get_curr_field();
|
||||
add_key_field(join, key_fields, *and_level, cond_func, equal_field,
|
||||
TRUE, &const_item, 1, usable_tables, sargables);
|
||||
}
|
||||
}
|
||||
@@ -4005,17 +4005,18 @@ add_key_fields(JOIN *join, KEY_FIELD **key_fields, uint *and_level,
|
||||
field1=field2 as a condition allowing an index access of the table
|
||||
with field1 by the keys value of field2.
|
||||
*/
|
||||
Item_equal_iterator fi(*item_equal);
|
||||
while ((item= fi++))
|
||||
Item_equal_fields_iterator fi(*item_equal);
|
||||
while (fi++)
|
||||
{
|
||||
Field *field= item->field;
|
||||
Field *field= fi.get_curr_field();
|
||||
Item *item;
|
||||
while ((item= it++))
|
||||
{
|
||||
if (!field->eq(item->field))
|
||||
Field *equal_field= it.get_curr_field();
|
||||
if (!field->eq(equal_field))
|
||||
{
|
||||
Item *tmp_item= item;
|
||||
add_key_field(join, key_fields, *and_level, cond_func, field,
|
||||
TRUE, &tmp_item, 1, usable_tables,
|
||||
TRUE, &item, 1, usable_tables,
|
||||
sargables);
|
||||
}
|
||||
}
|
||||
@@ -9291,6 +9292,8 @@ finish:
|
||||
static bool check_simple_equality(Item *left_item, Item *right_item,
|
||||
Item *item, COND_EQUAL *cond_equal)
|
||||
{
|
||||
Item *orig_left_item= left_item;
|
||||
Item *orig_right_item= right_item;
|
||||
if (left_item->type() == Item::REF_ITEM &&
|
||||
((Item_ref*)left_item)->ref_type() == Item_ref::VIEW_REF)
|
||||
{
|
||||
@@ -9357,7 +9360,7 @@ static bool check_simple_equality(Item *left_item, Item *right_item,
|
||||
{
|
||||
/* left item was found in the current or one of the upper levels */
|
||||
if (! right_item_equal)
|
||||
left_item_equal->add((Item_field *) right_item);
|
||||
left_item_equal->add(orig_right_item);
|
||||
else
|
||||
{
|
||||
/* Merge two multiple equalities forming a new one */
|
||||
@@ -9372,12 +9375,13 @@ static bool check_simple_equality(Item *left_item, Item *right_item,
|
||||
{
|
||||
/* left item was not found neither the current nor in upper levels */
|
||||
if (right_item_equal)
|
||||
right_item_equal->add((Item_field *) left_item);
|
||||
right_item_equal->add(orig_left_item);
|
||||
else
|
||||
{
|
||||
/* None of the fields was found in multiple equalities */
|
||||
Item_equal *item_equal= new Item_equal((Item_field *) left_item,
|
||||
(Item_field *) right_item);
|
||||
Item_equal *item_equal= new Item_equal(orig_left_item,
|
||||
orig_right_item,
|
||||
FALSE);
|
||||
cond_equal->current_level.push_back(item_equal);
|
||||
}
|
||||
}
|
||||
@@ -9388,18 +9392,21 @@ static bool check_simple_equality(Item *left_item, Item *right_item,
|
||||
/* The predicate of the form field=const/const=field is processed */
|
||||
Item *const_item= 0;
|
||||
Item_field *field_item= 0;
|
||||
Item *orig_field_item= 0;
|
||||
if (left_item->type() == Item::FIELD_ITEM &&
|
||||
!((Item_field*)left_item)->depended_from &&
|
||||
right_item->const_item())
|
||||
{
|
||||
field_item= (Item_field*) left_item;
|
||||
orig_field_item= left_item;
|
||||
field_item= (Item_field *) left_item;
|
||||
const_item= right_item;
|
||||
}
|
||||
else if (right_item->type() == Item::FIELD_ITEM &&
|
||||
!((Item_field*)right_item)->depended_from &&
|
||||
left_item->const_item())
|
||||
{
|
||||
field_item= (Item_field*) right_item;
|
||||
orig_field_item= right_item;
|
||||
field_item= (Item_field *) right_item;
|
||||
const_item= left_item;
|
||||
}
|
||||
|
||||
@@ -9414,7 +9421,7 @@ static bool check_simple_equality(Item *left_item, Item *right_item,
|
||||
if (!item)
|
||||
{
|
||||
Item_func_eq *eq_item;
|
||||
if ((eq_item= new Item_func_eq(left_item, right_item)))
|
||||
if ((eq_item= new Item_func_eq(orig_left_item, orig_right_item)))
|
||||
return FALSE;
|
||||
eq_item->set_cmp_func();
|
||||
eq_item->quick_fix_field();
|
||||
@@ -9439,11 +9446,11 @@ static bool check_simple_equality(Item *left_item, Item *right_item,
|
||||
already contains a constant and its value is not equal to
|
||||
the value of const_item.
|
||||
*/
|
||||
item_equal->add(const_item, field_item);
|
||||
item_equal->add_const(const_item, orig_field_item);
|
||||
}
|
||||
else
|
||||
{
|
||||
item_equal= new Item_equal(const_item, field_item);
|
||||
item_equal= new Item_equal(const_item, orig_field_item, TRUE);
|
||||
cond_equal->current_level.push_back(item_equal);
|
||||
}
|
||||
return TRUE;
|
||||
@@ -9688,7 +9695,7 @@ static COND *build_equal_items_for_cond(THD *thd, COND *cond,
|
||||
item_equal->fix_fields(thd, NULL);
|
||||
item_equal->update_used_tables();
|
||||
set_if_bigger(thd->lex->current_select->max_equal_elems,
|
||||
item_equal->members());
|
||||
item_equal->n_field_items());
|
||||
}
|
||||
|
||||
((Item_cond_and*)cond)->cond_equal= cond_equal;
|
||||
@@ -9719,7 +9726,8 @@ static COND *build_equal_items_for_cond(THD *thd, COND *cond,
|
||||
args->concat((List<Item> *)&cond_equal.current_level);
|
||||
}
|
||||
}
|
||||
else if (cond->type() == Item::FUNC_ITEM)
|
||||
else if (cond->type() == Item::FUNC_ITEM ||
|
||||
cond->real_item()->type() == Item::FIELD_ITEM)
|
||||
{
|
||||
List<Item> eq_list;
|
||||
/*
|
||||
@@ -9741,10 +9749,10 @@ static COND *build_equal_items_for_cond(THD *thd, COND *cond,
|
||||
{
|
||||
if ((item_equal= cond_equal.current_level.pop()))
|
||||
{
|
||||
item_equal->fix_length_and_dec();
|
||||
item_equal->fix_fields(thd, NULL);
|
||||
item_equal->update_used_tables();
|
||||
set_if_bigger(thd->lex->current_select->max_equal_elems,
|
||||
item_equal->members());
|
||||
item_equal->n_field_items());
|
||||
return item_equal;
|
||||
}
|
||||
|
||||
@@ -9765,7 +9773,7 @@ static COND *build_equal_items_for_cond(THD *thd, COND *cond,
|
||||
item_equal->fix_length_and_dec();
|
||||
item_equal->update_used_tables();
|
||||
set_if_bigger(thd->lex->current_select->max_equal_elems,
|
||||
item_equal->members());
|
||||
item_equal->n_field_items());
|
||||
}
|
||||
and_cond->cond_equal= cond_equal;
|
||||
args->concat((List<Item> *)&cond_equal.current_level);
|
||||
@@ -9779,9 +9787,10 @@ static COND *build_equal_items_for_cond(THD *thd, COND *cond,
|
||||
as soon the field is not of a string type or the field reference is
|
||||
an argument of a comparison predicate.
|
||||
*/
|
||||
uchar *is_subst_valid= (uchar *) 1;
|
||||
uchar is_subst_valid= (uchar) 1;
|
||||
uchar *is_subst_valid_ptr= &is_subst_valid;
|
||||
cond= cond->compile(&Item::subst_argument_checker,
|
||||
&is_subst_valid,
|
||||
&is_subst_valid_ptr,
|
||||
&Item::equal_fields_propagator,
|
||||
(uchar *) inherited);
|
||||
cond->update_used_tables();
|
||||
@@ -9935,18 +9944,24 @@ static COND *build_equal_items(THD *thd, COND *cond,
|
||||
0 otherwise
|
||||
*/
|
||||
|
||||
static int compare_fields_by_table_order(Item_field *field1,
|
||||
Item_field *field2,
|
||||
static int compare_fields_by_table_order(Item *field1,
|
||||
Item *field2,
|
||||
void *table_join_idx)
|
||||
{
|
||||
int cmp= 0;
|
||||
bool outer_ref= 0;
|
||||
if (field2->used_tables() & OUTER_REF_TABLE_BIT)
|
||||
Item_field *f1= (Item_field *) (field1->real_item());
|
||||
Item_field *f2= (Item_field *) (field2->real_item());
|
||||
if (f1->const_item())
|
||||
return 1;
|
||||
if (f2->const_item())
|
||||
return -1;
|
||||
if (f2->used_tables() & OUTER_REF_TABLE_BIT)
|
||||
{
|
||||
outer_ref= 1;
|
||||
cmp= -1;
|
||||
}
|
||||
if (field1->used_tables() & OUTER_REF_TABLE_BIT)
|
||||
if (f1->used_tables() & OUTER_REF_TABLE_BIT)
|
||||
{
|
||||
outer_ref= 1;
|
||||
cmp++;
|
||||
@@ -9954,10 +9969,10 @@ static int compare_fields_by_table_order(Item_field *field1,
|
||||
if (outer_ref)
|
||||
return cmp;
|
||||
JOIN_TAB **idx= (JOIN_TAB **) table_join_idx;
|
||||
cmp= idx[field2->field->table->tablenr]-idx[field1->field->table->tablenr];
|
||||
cmp= idx[f2->field->table->tablenr]-idx[f1->field->table->tablenr];
|
||||
if (!cmp)
|
||||
{
|
||||
JOIN_TAB *tab= idx[field1->field->table->tablenr];
|
||||
JOIN_TAB *tab= idx[f1->field->table->tablenr];
|
||||
uint keyno= MAX_KEY;
|
||||
if (tab->ref.key_parts)
|
||||
keyno= tab->ref.key;
|
||||
@@ -9965,9 +9980,9 @@ static int compare_fields_by_table_order(Item_field *field1,
|
||||
keyno = tab->select->quick->index;
|
||||
if (keyno != MAX_KEY)
|
||||
{
|
||||
if (field2->field->part_of_key.is_set(keyno))
|
||||
if (f2->field->part_of_key.is_set(keyno))
|
||||
cmp= -1;
|
||||
if (field1->field->part_of_key.is_set(keyno))
|
||||
if (f1->field->part_of_key.is_set(keyno))
|
||||
cmp++;
|
||||
if (!cmp)
|
||||
{
|
||||
@@ -9975,12 +9990,12 @@ static int compare_fields_by_table_order(Item_field *field1,
|
||||
for (uint i= 0; i < key_info->key_parts; i++)
|
||||
{
|
||||
Field *fld= key_info->key_part[i].field;
|
||||
if (fld->eq(field2->field))
|
||||
if (fld->eq(f2->field))
|
||||
{
|
||||
cmp= -1;
|
||||
break;
|
||||
}
|
||||
if (fld->eq(field1->field))
|
||||
if (fld->eq(f1->field))
|
||||
{
|
||||
cmp= 1;
|
||||
break;
|
||||
@@ -9989,14 +10004,15 @@ static int compare_fields_by_table_order(Item_field *field1,
|
||||
}
|
||||
}
|
||||
else
|
||||
cmp= field2->field->field_index-field1->field->field_index;
|
||||
cmp= f2->field->field_index-f1->field->field_index;
|
||||
}
|
||||
return cmp < 0 ? -1 : (cmp ? 1 : 0);
|
||||
}
|
||||
|
||||
|
||||
static TABLE_LIST* embedding_sjm(Item_field *item_field)
|
||||
static TABLE_LIST* embedding_sjm(Item *item)
|
||||
{
|
||||
Item_field *item_field= (Item_field *) (item->real_item());
|
||||
TABLE_LIST *nest= item_field->field->table->pos_in_table_list->embedding;
|
||||
if (nest && nest->sj_mat_info && nest->sj_mat_info->is_used)
|
||||
return nest;
|
||||
@@ -10069,7 +10085,7 @@ Item *eliminate_item_equal(COND *cond, COND_EQUAL *upper_levels,
|
||||
if (((Item *) item_equal)->const_item() && !item_equal->val_int())
|
||||
return new Item_int((longlong) 0,1);
|
||||
Item *item_const= item_equal->get_const();
|
||||
Item_equal_iterator it(*item_equal);
|
||||
Item_equal_fields_iterator it(*item_equal);
|
||||
Item *head;
|
||||
DBUG_ASSERT(!cond || cond->type() == Item::COND_ITEM);
|
||||
|
||||
@@ -10085,27 +10101,26 @@ Item *eliminate_item_equal(COND *cond, COND_EQUAL *upper_levels,
|
||||
else
|
||||
{
|
||||
TABLE_LIST *emb_nest;
|
||||
Item_field *item_field;
|
||||
head= item_field= item_equal->get_first(NULL);
|
||||
head= item_equal->get_first(NULL);
|
||||
it++;
|
||||
if ((emb_nest= embedding_sjm(item_field)))
|
||||
if ((emb_nest= embedding_sjm(head)))
|
||||
{
|
||||
current_sjm= emb_nest;
|
||||
current_sjm_head= head;
|
||||
}
|
||||
}
|
||||
|
||||
Item_field *item_field;
|
||||
Item *field_item;
|
||||
/*
|
||||
For each other item, generate "item=head" equality (except the tables that
|
||||
are within SJ-Materialization nests, for those "head" is defined
|
||||
differently)
|
||||
*/
|
||||
while ((item_field= it++))
|
||||
while ((field_item= it++))
|
||||
{
|
||||
Item_equal *upper= item_field->find_item_equal(upper_levels);
|
||||
Item_field *item= item_field;
|
||||
TABLE_LIST *field_sjm= embedding_sjm(item_field);
|
||||
Item_equal *upper= field_item->find_item_equal(upper_levels);
|
||||
Item *item= field_item;
|
||||
TABLE_LIST *field_sjm= embedding_sjm(field_item);
|
||||
if (!field_sjm)
|
||||
{
|
||||
current_sjm= NULL;
|
||||
@@ -10122,8 +10137,8 @@ Item *eliminate_item_equal(COND *cond, COND_EQUAL *upper_levels,
|
||||
item= 0;
|
||||
else
|
||||
{
|
||||
Item_equal_iterator li(*item_equal);
|
||||
while ((item= li++) != item_field)
|
||||
Item_equal_fields_iterator li(*item_equal);
|
||||
while ((item= li++) != field_item)
|
||||
{
|
||||
if (item->find_item_equal(upper_levels) == upper)
|
||||
break;
|
||||
@@ -10131,11 +10146,11 @@ Item *eliminate_item_equal(COND *cond, COND_EQUAL *upper_levels,
|
||||
}
|
||||
}
|
||||
|
||||
bool produce_equality= test(item == item_field);
|
||||
bool produce_equality= test(item == field_item);
|
||||
if (!item_const && field_sjm && field_sjm != current_sjm)
|
||||
{
|
||||
/* Entering an SJM nest */
|
||||
current_sjm_head= item_field;
|
||||
current_sjm_head= field_item;
|
||||
if (!field_sjm->sj_mat_info->is_sj_scan)
|
||||
produce_equality= FALSE;
|
||||
}
|
||||
@@ -10144,8 +10159,13 @@ Item *eliminate_item_equal(COND *cond, COND_EQUAL *upper_levels,
|
||||
{
|
||||
if (eq_item)
|
||||
eq_list.push_back(eq_item);
|
||||
|
||||
Item *head_item= current_sjm? current_sjm_head: head;
|
||||
Item *head_real_item= head_item->real_item();
|
||||
if (head_real_item->type() == Item::FIELD_ITEM)
|
||||
head_item= head_real_item;
|
||||
|
||||
eq_item= new Item_func_eq(item_field, current_sjm? current_sjm_head: head);
|
||||
eq_item= new Item_func_eq(field_item->real_item(), head_item);
|
||||
|
||||
if (!eq_item)
|
||||
return 0;
|
||||
@@ -10330,11 +10350,10 @@ static void update_const_equal_items(COND *cond, JOIN_TAB *tab)
|
||||
if (!contained_const && item_equal->get_const())
|
||||
{
|
||||
/* Update keys for range analysis */
|
||||
Item_equal_iterator it(*item_equal);
|
||||
Item_field *item_field;
|
||||
while ((item_field= it++))
|
||||
Item_equal_fields_iterator it(*item_equal);
|
||||
while (it++)
|
||||
{
|
||||
Field *field= item_field->field;
|
||||
Field *field= it.get_curr_field();
|
||||
JOIN_TAB *stat= field->table->reginfo.join_tab;
|
||||
key_map possible_keys= field->key_start;
|
||||
possible_keys.intersect(field->table->keys_in_use_for_query);
|
||||
|
||||
Reference in New Issue
Block a user