mirror of
https://github.com/MariaDB/server.git
synced 2025-01-17 12:32:27 +01:00
Merge
This commit is contained in:
commit
3d34cadac8
8 changed files with 125 additions and 22 deletions
|
@ -4138,3 +4138,33 @@ 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;
|
||||
#
|
||||
# Bug#777745: crash with equality propagation
|
||||
# over view fields
|
||||
#
|
||||
CREATE TABLE t1 (a int NOT NULL ) ;
|
||||
INSERT INTO t1 VALUES (2), (1);
|
||||
CREATE TABLE t2 (a int NOT NULL , b int NOT NULL) ;
|
||||
INSERT INTO t2 VALUES (2,20),(2,30);
|
||||
CREATE VIEW v2 AS SELECT * FROM t2;
|
||||
EXPLAIN
|
||||
SELECT * FROM t1,v2
|
||||
WHERE v2.a = t1.a AND v2.a = 2 AND v2.a IS NULL AND t1.a != 0;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
|
||||
SELECT * FROM t1,v2
|
||||
WHERE v2.a = t1.a AND v2.a = 2 AND v2.a IS NULL AND t1.a != 0;
|
||||
a a b
|
||||
EXPLAIN
|
||||
SELECT * FROM t1,v2
|
||||
WHERE v2.a = t1.a AND v2.a = 2 AND v2.a+1 > 2 AND t1.a != 0;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 Using where
|
||||
1 SIMPLE t2 ALL NULL NULL NULL NULL 2 Using where; Using join buffer (flat, BNL join)
|
||||
SELECT * FROM t1,v2
|
||||
WHERE v2.a = t1.a AND v2.a = 2 AND v2.a+1 > 2 AND t1.a != 0;
|
||||
a a b
|
||||
2 2 20
|
||||
2 2 30
|
||||
DROP VIEW v2;
|
||||
DROP TABLE t1,t2;
|
||||
|
|
|
@ -4085,3 +4085,31 @@ SELECT * FROM v1 WHERE a > 'JJ' OR a AND a = 'VV';
|
|||
|
||||
DROP VIEW v1;
|
||||
DROP TABLE t1;
|
||||
|
||||
--echo #
|
||||
--echo # Bug#777745: crash with equality propagation
|
||||
--echo # over view fields
|
||||
--echo #
|
||||
|
||||
CREATE TABLE t1 (a int NOT NULL ) ;
|
||||
INSERT INTO t1 VALUES (2), (1);
|
||||
|
||||
CREATE TABLE t2 (a int NOT NULL , b int NOT NULL) ;
|
||||
INSERT INTO t2 VALUES (2,20),(2,30);
|
||||
|
||||
CREATE VIEW v2 AS SELECT * FROM t2;
|
||||
|
||||
EXPLAIN
|
||||
SELECT * FROM t1,v2
|
||||
WHERE v2.a = t1.a AND v2.a = 2 AND v2.a IS NULL AND t1.a != 0;
|
||||
SELECT * FROM t1,v2
|
||||
WHERE v2.a = t1.a AND v2.a = 2 AND v2.a IS NULL AND t1.a != 0;
|
||||
|
||||
EXPLAIN
|
||||
SELECT * FROM t1,v2
|
||||
WHERE v2.a = t1.a AND v2.a = 2 AND v2.a+1 > 2 AND t1.a != 0;
|
||||
SELECT * FROM t1,v2
|
||||
WHERE v2.a = t1.a AND v2.a = 2 AND v2.a+1 > 2 AND t1.a != 0;
|
||||
|
||||
DROP VIEW v2;
|
||||
DROP TABLE t1,t2;
|
||||
|
|
39
sql/item.cc
39
sql/item.cc
|
@ -4733,7 +4733,7 @@ Item_equal *Item_field::find_item_equal(COND_EQUAL *cond_equal)
|
|||
The function checks whether a substitution of a field item for
|
||||
an equal item is valid.
|
||||
|
||||
@param arg *arg != NULL && **arg <-> the field is in the context
|
||||
@param arg *arg != NULL <-> the field is in the context
|
||||
where substitution for an equal item is valid
|
||||
|
||||
@note
|
||||
|
@ -4759,8 +4759,10 @@ Item_equal *Item_field::find_item_equal(COND_EQUAL *cond_equal)
|
|||
|
||||
bool Item_field::subst_argument_checker(uchar **arg)
|
||||
{
|
||||
return (!(*arg) && (result_type() != STRING_RESULT)) ||
|
||||
((*arg) && (**arg));
|
||||
return *arg &&
|
||||
(*arg == (uchar *) Item::ANY_SUBST ||
|
||||
result_type() != STRING_RESULT ||
|
||||
(field->flags & BINARY_FLAG));
|
||||
}
|
||||
|
||||
|
||||
|
@ -6437,9 +6439,11 @@ Item* Item_ref::transform(Item_transformer transformer, uchar *arg)
|
|||
|
||||
First the function applies the analyzer to the Item_ref object. Then
|
||||
if the analizer succeeeds we first applies the compile method to the
|
||||
object the Item_ref object is referencing. If this returns a new
|
||||
object the Item_ref object is referencing. If this returns a new
|
||||
item the old item is substituted for a new one. After this the
|
||||
transformer is applied to the Item_ref object itself.
|
||||
The compile function is not called if the analyzer returns NULL
|
||||
in the parameter arg_p.
|
||||
|
||||
@param analyzer the analyzer callback function to be applied to the
|
||||
nodes of the tree of the object
|
||||
|
@ -6460,10 +6464,13 @@ Item* Item_ref::compile(Item_analyzer analyzer, uchar **arg_p,
|
|||
|
||||
/* Compile the Item we are referencing. */
|
||||
DBUG_ASSERT((*ref) != NULL);
|
||||
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);
|
||||
if (*arg_p)
|
||||
{
|
||||
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);
|
||||
|
@ -7365,7 +7372,7 @@ Item_equal *Item_direct_view_ref::find_item_equal(COND_EQUAL *cond_equal)
|
|||
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
|
||||
@param arg *arg != NULL <-> the reference is in the context
|
||||
where substitution for an equal item is valid
|
||||
|
||||
@note
|
||||
|
@ -7378,11 +7385,19 @@ Item_equal *Item_direct_view_ref::find_item_equal(COND_EQUAL *cond_equal)
|
|||
*/
|
||||
bool Item_direct_view_ref::subst_argument_checker(uchar **arg)
|
||||
{
|
||||
bool res= (!(*arg) && (result_type() != STRING_RESULT)) ||
|
||||
((*arg) && (**arg));
|
||||
bool res= FALSE;
|
||||
if (*arg)
|
||||
{
|
||||
Item *item= real_item();
|
||||
if (item->type() == FIELD_ITEM &&
|
||||
(*arg == (uchar *) Item::ANY_SUBST ||
|
||||
result_type() != STRING_RESULT ||
|
||||
(((Item_field *) item)->field->flags & BINARY_FLAG)))
|
||||
res= TRUE;
|
||||
}
|
||||
/* Block any substitution into the wrapped object */
|
||||
if (*arg)
|
||||
**arg= (uchar) 0;
|
||||
*arg= NULL;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
19
sql/item.h
19
sql/item.h
|
@ -1094,12 +1094,23 @@ public:
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
The enumeration Subst_constraint is currently used only in implementations
|
||||
of the virtual function subst_argument_checker.
|
||||
*/
|
||||
enum Subst_constraint
|
||||
{
|
||||
NO_SUBST= 0, /* No substitution for a field is allowed */
|
||||
ANY_SUBST, /* Any substitution for a field is allowed */
|
||||
IDENTITY_SUBST /* Substitution for a field is allowed if any two
|
||||
different values of the field type are not equal */
|
||||
};
|
||||
|
||||
virtual bool subst_argument_checker(uchar **arg)
|
||||
{
|
||||
if (*arg)
|
||||
*arg= NULL;
|
||||
return TRUE;
|
||||
{
|
||||
return (*arg != NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
@brief
|
||||
Processor used to check acceptability of an item in the defining
|
||||
|
|
|
@ -397,7 +397,10 @@ public:
|
|||
}
|
||||
Item *neg_transformer(THD *thd);
|
||||
virtual Item *negated_item();
|
||||
bool subst_argument_checker(uchar **arg) { return TRUE; }
|
||||
bool subst_argument_checker(uchar **arg)
|
||||
{
|
||||
return (*arg != NULL);
|
||||
}
|
||||
};
|
||||
|
||||
class Item_func_not :public Item_bool_func
|
||||
|
|
|
@ -352,6 +352,8 @@ Item *Item_func::transform(Item_transformer transformer, uchar *argument)
|
|||
the old item is substituted for a new one.
|
||||
After this the transformer is applied to the root node
|
||||
of the Item_func object.
|
||||
The compile function is not called if the analyzer returns NULL
|
||||
in the parameter arg_p.
|
||||
|
||||
@param analyzer the analyzer callback function to be applied to the
|
||||
nodes of the tree of the object
|
||||
|
@ -369,7 +371,7 @@ Item *Item_func::compile(Item_analyzer analyzer, uchar **arg_p,
|
|||
{
|
||||
if (!(this->*analyzer)(arg_p))
|
||||
return 0;
|
||||
if (arg_count)
|
||||
if (*arg_p && arg_count)
|
||||
{
|
||||
Item **arg,**arg_end;
|
||||
for (arg= args, arg_end= args+arg_count; arg != arg_end; arg++)
|
||||
|
@ -377,7 +379,7 @@ Item *Item_func::compile(Item_analyzer analyzer, uchar **arg_p,
|
|||
/*
|
||||
The same parameter value of arg_p must be passed
|
||||
to analyze any argument of the condition formula.
|
||||
*/
|
||||
*/
|
||||
uchar *arg_v= *arg_p;
|
||||
Item *new_item= (*arg)->compile(analyzer, &arg_v, transformer, arg_t);
|
||||
if (new_item && *arg != new_item)
|
||||
|
|
|
@ -251,6 +251,21 @@ public:
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
By default only substitution for a field whose two different values
|
||||
are never equal is allowed in the arguments of a function.
|
||||
This is overruled for the direct arguments of comparison functions.
|
||||
*/
|
||||
bool subst_argument_checker(uchar **arg)
|
||||
{
|
||||
if (*arg)
|
||||
{
|
||||
*arg= (uchar *) Item::IDENTITY_SUBST;
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
We assume the result of any function that has a TIMESTAMP argument to be
|
||||
timezone-dependent, since a TIMESTAMP value in both numeric and string
|
||||
|
|
|
@ -9902,10 +9902,9 @@ 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_ptr= &is_subst_valid;
|
||||
uchar* is_subst_valid= (uchar *) Item::ANY_SUBST;
|
||||
cond= cond->compile(&Item::subst_argument_checker,
|
||||
&is_subst_valid_ptr,
|
||||
&is_subst_valid,
|
||||
&Item::equal_fields_propagator,
|
||||
(uchar *) inherited);
|
||||
cond->update_used_tables();
|
||||
|
|
Loading…
Reference in a new issue