Commit d790ec42 authored by igor@olga.mysql.com's avatar igor@olga.mysql.com
Browse files

Fixed bug #30396.

The bug caused memory corruption for some queries with top OR level
in the WHERE condition if they contained equality predicates and 
other sargable predicates in disjunctive parts of the condition.

The corruption happened because the upper bound of the memory
allocated for KEY_FIELD and SARGABLE_PARAM internal structures
containing info about potential lookup keys was calculated incorrectly
in some cases. In particular it was calculated incorrectly when the
WHERE condition was an OR formula with disjuncts being AND formulas
including equalities and other sargable predicates.
parent 1cc8f0e3
Loading
Loading
Loading
Loading
+57 −0
Original line number Diff line number Diff line
@@ -4005,4 +4005,61 @@ id select_type table type possible_keys key key_len ref rows Extra
EXPLAIN SELECT c1 FROM t1 WHERE (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT (SELECT COUNT(c2))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))) > 0;
ERROR HY000: Too high level of nesting for select
DROP TABLE t1;
CREATE TABLE t1 (
c1 int(11) NOT NULL AUTO_INCREMENT,
c2 varchar(1000) DEFAULT NULL,
c3 bigint(20) DEFAULT NULL,
c4 bigint(20) DEFAULT NULL,
PRIMARY KEY (c1)
);
EXPLAIN EXTENDED 
SELECT  join_2.c1  
FROM 
t1 AS join_0, 
t1 AS join_1, 
t1 AS join_2, 
t1 AS join_3, 
t1 AS join_4, 
t1 AS join_5, 
t1 AS join_6, 
t1 AS join_7
WHERE 
join_0.c1=join_1.c1  AND 
join_1.c1=join_2.c1  AND 
join_2.c1=join_3.c1  AND 
join_3.c1=join_4.c1  AND 
join_4.c1=join_5.c1  AND 
join_5.c1=join_6.c1  AND 
join_6.c1=join_7.c1 
OR 
join_0.c2 < '?'  AND 
join_1.c2 < '?'  AND
join_2.c2 > '?'  AND
join_2.c2 < '!'  AND
join_3.c2 > '?'  AND 
join_4.c2 = '?'  AND 
join_5.c2 <> '?' AND
join_6.c2 <> '?' AND 
join_7.c2 >= '?' AND
join_0.c1=join_1.c1  AND 
join_1.c1=join_2.c1  AND 
join_2.c1=join_3.c1  AND
join_3.c1=join_4.c1  AND 
join_4.c1=join_5.c1  AND 
join_5.c1=join_6.c1  AND 
join_6.c1=join_7.c1
GROUP BY 
join_3.c1,
join_2.c1,
join_7.c1,
join_1.c1,
join_0.c1;
id	select_type	table	type	possible_keys	key	key_len	ref	rows	Extra
1	SIMPLE	NULL	NULL	NULL	NULL	NULL	NULL	NULL	Impossible WHERE noticed after reading const tables
Warnings:
Note	1003	select '0' AS `c1` from `test`.`t1` `join_0` join `test`.`t1` `join_1` join `test`.`t1` `join_2` join `test`.`t1` `join_3` join `test`.`t1` `join_4` join `test`.`t1` `join_5` join `test`.`t1` `join_6` join `test`.`t1` `join_7` where 0 group by '0','0','0','0','0'
SHOW WARNINGS;
Level	Code	Message
Note	1003	select '0' AS `c1` from `test`.`t1` `join_0` join `test`.`t1` `join_1` join `test`.`t1` `join_2` join `test`.`t1` `join_3` join `test`.`t1` `join_4` join `test`.`t1` `join_5` join `test`.`t1` `join_6` join `test`.`t1` `join_7` where 0 group by '0','0','0','0','0'
DROP TABLE t1;
End of 5.0 tests
+60 −0
Original line number Diff line number Diff line
@@ -3400,4 +3400,64 @@ eval EXPLAIN SELECT c1 FROM t1 WHERE $q > 0;

DROP TABLE t1;

#
# Bug #30396: crash for a join with equalities and sargable predicates
#             in disjunctive parts of the WHERE condition 
#

CREATE TABLE t1 (
  c1 int(11) NOT NULL AUTO_INCREMENT,
  c2 varchar(1000) DEFAULT NULL,
  c3 bigint(20) DEFAULT NULL,
  c4 bigint(20) DEFAULT NULL,
  PRIMARY KEY (c1)
);

EXPLAIN EXTENDED 
SELECT  join_2.c1  
FROM 
	t1 AS join_0, 
	t1 AS join_1, 
	t1 AS join_2, 
	t1 AS join_3, 
	t1 AS join_4, 
	t1 AS join_5, 
	t1 AS join_6, 
	t1 AS join_7
WHERE 
	join_0.c1=join_1.c1  AND 
	join_1.c1=join_2.c1  AND 
	join_2.c1=join_3.c1  AND 
	join_3.c1=join_4.c1  AND 
	join_4.c1=join_5.c1  AND 
	join_5.c1=join_6.c1  AND 
	join_6.c1=join_7.c1 
         OR 
	join_0.c2 < '?'  AND 
	join_1.c2 < '?'  AND
	join_2.c2 > '?'  AND
	join_2.c2 < '!'  AND
	join_3.c2 > '?'  AND 
	join_4.c2 = '?'  AND 
	join_5.c2 <> '?' AND
	join_6.c2 <> '?' AND 
	join_7.c2 >= '?' AND
        join_0.c1=join_1.c1  AND 
	join_1.c1=join_2.c1  AND 
        join_2.c1=join_3.c1  AND
	join_3.c1=join_4.c1  AND 
	join_4.c1=join_5.c1  AND 
	join_5.c1=join_6.c1  AND 
	join_6.c1=join_7.c1
GROUP BY 
	join_3.c1,
	join_2.c1,
	join_7.c1,
	join_1.c1,
	join_0.c1;
	
SHOW WARNINGS;

DROP TABLE t1;

--echo End of 5.0 tests
+0 −1
Original line number Diff line number Diff line
@@ -1506,7 +1506,6 @@ class COND_EQUAL: public Sql_alloc
                                     the current and level           */
  COND_EQUAL()
  { 
    max_members= 0;
    upper_levels= 0;
  }
};
+1 −0
Original line number Diff line number Diff line
@@ -5611,6 +5611,7 @@ int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves,
  thd->set_query_id=1;
  select_lex->cond_count= 0;
  select_lex->between_count= 0;
  select_lex->max_equal_elems= 0;

  for (table= tables; table; table= table->next_local)
  {
+1 −0
Original line number Diff line number Diff line
@@ -1183,6 +1183,7 @@ void st_select_lex::init_query()
  */
  parent_lex->push_context(&context);
  cond_count= between_count= with_wild= 0;
  max_equal_elems= 0;
  conds_processed_with_permanent_arena= 0;
  ref_pointer_array= 0;
  select_n_where_fields= 0;
Loading