Skip to content

Commit

Permalink
Merge branch '5.5' into 10.0
Browse files Browse the repository at this point in the history
  • Loading branch information
vuvova committed Apr 28, 2018
2 parents d6dbe8e + 5cfe523 commit c4499a0
Show file tree
Hide file tree
Showing 15 changed files with 228 additions and 24 deletions.
34 changes: 34 additions & 0 deletions mysql-test/r/sp-innodb.result
Original file line number Diff line number Diff line change
Expand Up @@ -130,3 +130,37 @@ SET @@innodb_lock_wait_timeout= @innodb_lock_wait_timeout_saved;
#
# BUG 16041903: End of test case
#
#
# MDEV-15035: SP using query with outer join and a parameter
# in ON expression
#
CREATE TABLE t1 (
id int NOT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1), (2);
CREATE TABLE t2 (
id int NOT NULL,
id_foo int NOT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB;
INSERT INTO t2 VALUES (1, 1);
DROP PROCEDURE IF EXISTS test_proc;
CREATE PROCEDURE test_proc(IN param int)
LANGUAGE SQL
READS SQL DATA
BEGIN
SELECT DISTINCT f.id
FROM t1 f
LEFT OUTER JOIN t2 b ON b.id_foo = f.id
WHERE (param <> 0 OR b.id IS NOT NULL);
END|
CALL test_proc(0);
id
1
CALL test_proc(1);
id
1
2
DROP PROCEDURE IF EXISTS test_proc;
DROP TABLE t1, t2;
26 changes: 26 additions & 0 deletions mysql-test/r/subselect_sj.result
Original file line number Diff line number Diff line change
Expand Up @@ -3155,4 +3155,30 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
Warnings:
Note 1003 select `test`.`t1`.`c1` AS `c1`,`test`.`t2`.`c2` AS `c2`,`test`.`t4`.`c4` AS `c4` from `test`.`t1` left join (`test`.`t2` join `test`.`t4`) on(((`test`.`t2`.`c2` = `test`.`t1`.`c1`) and <in_optimizer>(`test`.`t1`.`c1`,<exists>(select `test`.`t3`.`c3` from `test`.`t3` where (<cache>(`test`.`t2`.`c2`) = `test`.`t3`.`c3`))))) where 1
DROP TABLE t1,t2,t3,t4;
#
# MDEV-13699: Assertion `!new_field->field_name.str ||
# strlen(new_field->field_name.str) == new_field->field_name.length'
# failed in create_tmp_table on 2nd execution of PS with semijoin
#
CREATE TABLE t1 (a INT);
INSERT INTO t1 VALUES (1),(2);
CREATE TABLE t2 (b INT);
INSERT INTO t2 VALUES (3),(4);
CREATE TABLE t3 (c INT);
CREATE ALGORITHM=MERGE VIEW v3 AS SELECT * FROM t3;
INSERT INTO t3 VALUES (5),(6);
PREPARE stmt FROM
"SELECT * FROM t1
WHERE EXISTS (
SELECT * FROM t2 WHERE t1.a IN ( SELECT c AS fld FROM v3 )
)";
EXECUTE stmt;
a
EXECUTE stmt;
a
EXECUTE stmt;
a
drop view v3;
drop table t1,t2,t3;
# End of 5.5 test
set optimizer_switch=@subselect_sj_tmp;
26 changes: 26 additions & 0 deletions mysql-test/r/subselect_sj_jcl6.result
Original file line number Diff line number Diff line change
Expand Up @@ -3169,6 +3169,32 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
Warnings:
Note 1003 select `test`.`t1`.`c1` AS `c1`,`test`.`t2`.`c2` AS `c2`,`test`.`t4`.`c4` AS `c4` from `test`.`t1` left join (`test`.`t2` join `test`.`t4`) on(((`test`.`t2`.`c2` = `test`.`t1`.`c1`) and <in_optimizer>(`test`.`t1`.`c1`,<exists>(select `test`.`t3`.`c3` from `test`.`t3` where (<cache>(`test`.`t2`.`c2`) = `test`.`t3`.`c3`))))) where 1
DROP TABLE t1,t2,t3,t4;
#
# MDEV-13699: Assertion `!new_field->field_name.str ||
# strlen(new_field->field_name.str) == new_field->field_name.length'
# failed in create_tmp_table on 2nd execution of PS with semijoin
#
CREATE TABLE t1 (a INT);
INSERT INTO t1 VALUES (1),(2);
CREATE TABLE t2 (b INT);
INSERT INTO t2 VALUES (3),(4);
CREATE TABLE t3 (c INT);
CREATE ALGORITHM=MERGE VIEW v3 AS SELECT * FROM t3;
INSERT INTO t3 VALUES (5),(6);
PREPARE stmt FROM
"SELECT * FROM t1
WHERE EXISTS (
SELECT * FROM t2 WHERE t1.a IN ( SELECT c AS fld FROM v3 )
)";
EXECUTE stmt;
a
EXECUTE stmt;
a
EXECUTE stmt;
a
drop view v3;
drop table t1,t2,t3;
# End of 5.5 test
set optimizer_switch=@subselect_sj_tmp;
#
# BUG#49129: Wrong result with IN-subquery with join_cache_level=6 and firstmatch=off
Expand Down
42 changes: 42 additions & 0 deletions mysql-test/t/sp-innodb.test
Original file line number Diff line number Diff line change
Expand Up @@ -158,5 +158,47 @@ SET @@innodb_lock_wait_timeout= @innodb_lock_wait_timeout_saved;
--echo # BUG 16041903: End of test case
--echo #

--echo #
--echo # MDEV-15035: SP using query with outer join and a parameter
--echo # in ON expression
--echo #

CREATE TABLE t1 (
id int NOT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB;

INSERT INTO t1 VALUES (1), (2);

CREATE TABLE t2 (
id int NOT NULL,
id_foo int NOT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB;

INSERT INTO t2 VALUES (1, 1);

--disable_warnings
DROP PROCEDURE IF EXISTS test_proc;
--enable_warnings

DELIMITER |;
CREATE PROCEDURE test_proc(IN param int)
LANGUAGE SQL
READS SQL DATA
BEGIN
SELECT DISTINCT f.id
FROM t1 f
LEFT OUTER JOIN t2 b ON b.id_foo = f.id
WHERE (param <> 0 OR b.id IS NOT NULL);
END|
DELIMITER ;|

CALL test_proc(0);
CALL test_proc(1);

DROP PROCEDURE IF EXISTS test_proc;
DROP TABLE t1, t2;

# Wait till we reached the initial number of concurrent sessions
--source include/wait_until_count_sessions.inc
30 changes: 30 additions & 0 deletions mysql-test/t/subselect_sj.test
Original file line number Diff line number Diff line change
Expand Up @@ -2845,5 +2845,35 @@ eval EXPLAIN EXTENDED $q2;

DROP TABLE t1,t2,t3,t4;

--echo #
--echo # MDEV-13699: Assertion `!new_field->field_name.str ||
--echo # strlen(new_field->field_name.str) == new_field->field_name.length'
--echo # failed in create_tmp_table on 2nd execution of PS with semijoin
--echo #

CREATE TABLE t1 (a INT);
INSERT INTO t1 VALUES (1),(2);

CREATE TABLE t2 (b INT);
INSERT INTO t2 VALUES (3),(4);

CREATE TABLE t3 (c INT);
CREATE ALGORITHM=MERGE VIEW v3 AS SELECT * FROM t3;
INSERT INTO t3 VALUES (5),(6);

PREPARE stmt FROM
"SELECT * FROM t1
WHERE EXISTS (
SELECT * FROM t2 WHERE t1.a IN ( SELECT c AS fld FROM v3 )
)";
EXECUTE stmt;
EXECUTE stmt;
EXECUTE stmt;

drop view v3;
drop table t1,t2,t3;

--echo # End of 5.5 test

# The following command must be the last one the file
set optimizer_switch=@subselect_sj_tmp;
2 changes: 1 addition & 1 deletion sql-common/client.c
Original file line number Diff line number Diff line change
Expand Up @@ -1503,7 +1503,7 @@ MYSQL_DATA *cli_read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields,
else
{
cur->data[field] = to;
if (len > (ulong) (end_to - to))
if (to + len > end_to)
{
free_rows(result);
set_mysql_error(mysql, CR_MALFORMED_PACKET, unknown_sqlstate);
Expand Down
7 changes: 7 additions & 0 deletions sql/item.cc
Original file line number Diff line number Diff line change
Expand Up @@ -548,6 +548,7 @@ Item::Item():
in_rollup= 0;
decimals= 0; max_length= 0;
with_subselect= 0;
with_param= 0;
cmp_context= IMPOSSIBLE_RESULT;
/* Initially this item is not attached to any JOIN_TAB. */
join_tab_idx= MAX_TABLES;
Expand Down Expand Up @@ -594,6 +595,7 @@ Item::Item(THD *thd, Item *item):
null_value(item->null_value),
unsigned_flag(item->unsigned_flag),
with_sum_func(item->with_sum_func),
with_param(item->with_param),
with_field(item->with_field),
fixed(item->fixed),
is_autogenerated_name(item->is_autogenerated_name),
Expand Down Expand Up @@ -1475,6 +1477,9 @@ bool Item_sp_variable::fix_fields(THD *thd, Item **)
max_length= it->max_length;
decimals= it->decimals;
unsigned_flag= it->unsigned_flag;
with_param= 1;
if (thd->lex->current_select->master_unit()->item)
thd->lex->current_select->master_unit()->item->with_param= 1;
fixed= 1;
collation.set(it->collation.collation, it->collation.derivation);

Expand Down Expand Up @@ -7220,6 +7225,7 @@ void Item_ref::set_properties()
split_sum_func() doesn't try to change the reference.
*/
with_sum_func= (*ref)->with_sum_func;
with_param= (*ref)->with_param;
with_field= (*ref)->with_field;
unsigned_flag= (*ref)->unsigned_flag;
fixed= 1;
Expand Down Expand Up @@ -7667,6 +7673,7 @@ Item_cache_wrapper::Item_cache_wrapper(Item *item_arg)
decimals= orig_item->decimals;
collation.set(orig_item->collation);
with_sum_func= orig_item->with_sum_func;
with_param= orig_item->with_param;
with_field= orig_item->with_field;
unsigned_flag= orig_item->unsigned_flag;
name= item_arg->name;
Expand Down
1 change: 1 addition & 0 deletions sql/item.h
Original file line number Diff line number Diff line change
Expand Up @@ -669,6 +669,7 @@ class Item {
bool null_value; /* if item is null */
bool unsigned_flag;
bool with_sum_func; /* True if item contains a sum func */
bool with_param; /* True if contains an SP parameter */
/**
True if any item except Item_sum_func contains a field. Set during parsing.
*/
Expand Down
42 changes: 30 additions & 12 deletions sql/item_cmpfunc.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1571,6 +1571,7 @@ bool Item_in_optimizer::fix_left(THD *thd)
}
eval_not_null_tables(NULL);
with_sum_func= args[0]->with_sum_func;
with_param= args[0]->with_param || args[1]->with_param;
with_field= args[0]->with_field;
if ((const_item_cache= args[0]->const_item()))
{
Expand Down Expand Up @@ -1620,6 +1621,7 @@ bool Item_in_optimizer::fix_fields(THD *thd, Item **ref)
with_subselect= 1;
with_sum_func= with_sum_func || args[1]->with_sum_func;
with_field= with_field || args[1]->with_field;
with_param= args[0]->with_param || args[1]->with_param;
used_tables_cache|= args[1]->used_tables();
const_item_cache&= args[1]->const_item();
fixed= 1;
Expand Down Expand Up @@ -2171,6 +2173,7 @@ void Item_func_interval::fix_length_and_dec()
used_tables_cache|= row->used_tables();
not_null_tables_cache= row->not_null_tables();
with_sum_func= with_sum_func || row->with_sum_func;
with_param= with_param || row->with_param;
with_field= with_field || row->with_field;
const_item_cache&= row->const_item();
}
Expand Down Expand Up @@ -4401,6 +4404,7 @@ Item_cond::fix_fields(THD *thd, Item **ref)
List_iterator<Item> li(list);
Item *item;
uchar buff[sizeof(char*)]; // Max local vars in function
bool is_and_cond= functype() == Item_func::COND_AND_FUNC;
not_null_tables_cache= used_tables_cache= 0;
const_item_cache= 1;

Expand Down Expand Up @@ -4462,26 +4466,33 @@ Item_cond::fix_fields(THD *thd, Item **ref)
(item= *li.ref())->check_cols(1))
return TRUE; /* purecov: inspected */
used_tables_cache|= item->used_tables();
if (item->const_item())
if (item->const_item() && !item->with_param &&
!item->is_expensive() && !cond_has_datetime_is_null(item))
{
if (!item->is_expensive() && !cond_has_datetime_is_null(item) &&
item->val_int() == 0)
if (item->val_int() == is_and_cond && top_level())
{
/*
This is "... OR false_cond OR ..."
a. This is "... AND true_cond AND ..."
In this case, true_cond has no effect on cond_and->not_null_tables()
b. This is "... OR false_cond/null cond OR ..."
In this case, false_cond has no effect on cond_or->not_null_tables()
*/
}
else
{
/*
This is "... OR const_cond OR ..."
a. This is "... AND false_cond/null_cond AND ..."
The whole condition is FALSE/UNKNOWN.
b. This is "... OR const_cond OR ..."
In this case, cond_or->not_null_tables()=0, because the condition
const_cond might evaluate to true (regardless of whether some tables
were NULL-complemented).
*/
not_null_tables_cache= (table_map) 0;
and_tables_cache= (table_map) 0;
}
if (thd->is_error())
return TRUE;
}
else
{
Expand All @@ -4493,6 +4504,7 @@ Item_cond::fix_fields(THD *thd, Item **ref)
}

with_sum_func= with_sum_func || item->with_sum_func;
with_param= with_param || item->with_param;
with_field= with_field || item->with_field;
with_subselect|= item->has_subquery();
if (item->maybe_null)
Expand All @@ -4509,30 +4521,36 @@ bool
Item_cond::eval_not_null_tables(uchar *opt_arg)
{
Item *item;
bool is_and_cond= functype() == Item_func::COND_AND_FUNC;
List_iterator<Item> li(list);
not_null_tables_cache= (table_map) 0;
and_tables_cache= ~(table_map) 0;
while ((item=li++))
{
table_map tmp_table_map;
if (item->const_item())
if (item->const_item() && !item->with_param &&
!item->is_expensive() && !cond_has_datetime_is_null(item))
{
if (!item->is_expensive() && !cond_has_datetime_is_null(item) &&
item->val_int() == 0)
if (item->val_int() == is_and_cond && top_level())
{
/*
This is "... OR false_cond OR ..."
a. This is "... AND true_cond AND ..."
In this case, true_cond has no effect on cond_and->not_null_tables()
b. This is "... OR false_cond/null cond OR ..."
In this case, false_cond has no effect on cond_or->not_null_tables()
*/
}
else
{
/*
This is "... OR const_cond OR ..."
a. This is "... AND false_cond/null_cond AND ..."
The whole condition is FALSE/UNKNOWN.
b. This is "... OR const_cond OR ..."
In this case, cond_or->not_null_tables()=0, because the condition
some_cond_or might be true regardless of what tables are
NULL-complemented.
const_cond might evaluate to true (regardless of whether some tables
were NULL-complemented).
*/
not_null_tables_cache= (table_map) 0;
and_tables_cache= (table_map) 0;
}
}
Expand Down
1 change: 1 addition & 0 deletions sql/item_func.cc
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,7 @@ Item_func::fix_fields(THD *thd, Item **ref)
maybe_null=1;

with_sum_func= with_sum_func || item->with_sum_func;
with_param= with_param || item->with_param;
with_field= with_field || item->with_field;
used_tables_cache|= item->used_tables();
const_item_cache&= item->const_item();
Expand Down
Loading

0 comments on commit c4499a0

Please sign in to comment.