summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorunknown <igor@olga.mysql.com>2007-08-15 10:24:18 -0700
committerunknown <igor@olga.mysql.com>2007-08-15 10:24:18 -0700
commita8f8e5483e7925ce804c3900752f88fdf43cb3ee (patch)
treea8cef5ced9d5c39ccf4804a0b7d3b1f661bd187b /sql
parent83fdcb2b7bddfffcf5a750ac9830f7ea38d2b8fc (diff)
downloadmariadb-git-a8f8e5483e7925ce804c3900752f88fdf43cb3ee.tar.gz
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. mysql-test/r/select.result: Added a test case for bug #30396. mysql-test/t/select.test: Added a test case for bug #30396. sql/item_cmpfunc.h: Removed max_members from the COND_EQUAL class as not useful anymore. sql/sql_base.cc: Added the max_equal_elems field to the st_select_lex structure. sql/sql_lex.cc: Added the max_equal_elems field to the st_select_lex structure. sql/sql_lex.h: Added the max_equal_elems field to the st_select_lex structure. The field contains the maximal number of elements in multiple equalities built for the query conditions. sql/sql_select.cc: 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. The max_equal_elems field to the st_select_lex structure is used now to calculate the above mentioned upper bound. The field contains the maximal number of elements in multiple equalities built for the query conditions.
Diffstat (limited to 'sql')
-rw-r--r--sql/item_cmpfunc.h1
-rw-r--r--sql/sql_base.cc1
-rw-r--r--sql/sql_lex.cc1
-rw-r--r--sql/sql_lex.h3
-rw-r--r--sql/sql_select.cc38
5 files changed, 16 insertions, 28 deletions
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index 9afc0507817..7b6eaef08ec 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -1506,7 +1506,6 @@ public:
the current and level */
COND_EQUAL()
{
- max_members= 0;
upper_levels= 0;
}
};
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 1c01248c283..e8562cdffbd 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -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)
{
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 7911da69862..d11c2b21635 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -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;
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index b9c6abd2b06..94015a9fe07 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -533,7 +533,8 @@ public:
*/
uint select_n_having_items;
uint cond_count; /* number of arguments of and/or/xor in where/having/on */
- uint between_count; /* number of between predicates in where/having/on */
+ uint between_count; /* number of between predicates in where/having/on */
+ uint max_equal_elems; /* maximal number of elements in multiple equalities */
/*
Number of fields used in select list or where clause of current select
and all inner subselects.
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index ac8dc84f118..b7846a7433d 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -3524,10 +3524,7 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab,
uint and_level,i,found_eq_constant;
KEY_FIELD *key_fields, *end, *field;
uint sz;
- uint m= 1;
-
- if (cond_equal && cond_equal->max_members)
- m= cond_equal->max_members;
+ uint m= max(select_lex->max_equal_elems,1);
/*
We use the same piece of memory to store both KEY_FIELD
@@ -3547,7 +3544,8 @@ update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,JOIN_TAB *join_tab,
it is considered as sargable only for its first argument.
Multiple equality can add elements that are filled after
substitution of field arguments by equal fields. There
- can be not more than cond_equal->max_members such substitutions.
+ can be not more than select_lex->max_equal_elems such
+ substitutions.
*/
sz= max(sizeof(KEY_FIELD),sizeof(SARGABLE_PARAM))*
(((thd->lex->current_select->cond_count+1)*2 +
@@ -7189,8 +7187,7 @@ static bool check_equality(THD *thd, Item *item, COND_EQUAL *cond_equal,
just an argument of a comparison predicate.
The function also determines the maximum number of members in
equality lists of each Item_cond_and object assigning it to
- cond_equal->max_members of this object and updating accordingly
- the upper levels COND_EQUAL structures.
+ thd->lex->current_select->max_equal_elems.
NOTES
Multiple equality predicate =(f1,..fn) is equivalent to the conjuction of
@@ -7235,7 +7232,6 @@ static COND *build_equal_items_for_cond(THD *thd, COND *cond,
COND_EQUAL *inherited)
{
Item_equal *item_equal;
- uint members;
COND_EQUAL cond_equal;
cond_equal.upper_levels= inherited;
@@ -7273,19 +7269,8 @@ static COND *build_equal_items_for_cond(THD *thd, COND *cond,
{
item_equal->fix_length_and_dec();
item_equal->update_used_tables();
- members= item_equal->members();
- if (cond_equal.max_members < members)
- cond_equal.max_members= members;
- }
- members= cond_equal.max_members;
- if (inherited && inherited->max_members < members)
- {
- do
- {
- inherited->max_members= members;
- inherited= inherited->upper_levels;
- }
- while (inherited);
+ set_if_bigger(thd->lex->current_select->max_equal_elems,
+ item_equal->members());
}
((Item_cond_and*)cond)->cond_equal= cond_equal;
@@ -7340,10 +7325,12 @@ static COND *build_equal_items_for_cond(THD *thd, COND *cond,
{
item_equal->fix_length_and_dec();
item_equal->update_used_tables();
- return item_equal;
}
else
- return eq_list.pop();
+ item_equal= (Item_equal *) eq_list.pop();
+ set_if_bigger(thd->lex->current_select->max_equal_elems,
+ item_equal->members());
+ return item_equal;
}
else
{
@@ -7359,9 +7346,8 @@ static COND *build_equal_items_for_cond(THD *thd, COND *cond,
{
item_equal->fix_length_and_dec();
item_equal->update_used_tables();
- members= item_equal->members();
- if (cond_equal.max_members < members)
- cond_equal.max_members= members;
+ set_if_bigger(thd->lex->current_select->max_equal_elems,
+ item_equal->members());
}
and_cond->cond_equal= cond_equal;
args->concat((List<Item> *)&cond_equal.current_level);