1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-29 05:21:33 +03:00

Bug#15972635: Incorrect results returned in 32 table join with HAVING

The problem is a shift operation that is not 64-bit safe.
The consequence is that used tables information for a join with 32 tables
or more will be incorrect.

Fixed by adding a type cast in Item_sum::update_used_tables().

Also used the opportunity to fix some other potential bugs by adding an
explicit type-cast to an integer in a left-shift operation.
Some of them were quite harmless, but was fixed in order to get the same
signed-ness as the other operand of the operation it was used in.

sql/item_cmpfunc.cc
  Adjusted signed-ness for some integers in left-shift.

sql/item_subselect.cc
  Added type-cast to nesting_map (which is a 32/64 bit type, so
  potential bug for deeply nested queries).

sql/item_sum.cc
  Added type-cast to nesting_map (32/64-bit type) and table_map
  (64-bit type).

sql/opt_range.cc
  Added type-cast to ulonglong (which is a 64-bit type).

sql/sql_base.cc
  Added type-cast to nesting_map (which is a 32/64-bit type).

sql/sql_select.cc
  Added type-cast to nesting_map (32/64-bit type) and key_part_map
  (64-bit type).

sql/strfunc.cc
  Changed type-cast from longlong to ulonglong, to preserve signed-ness.
This commit is contained in:
Roy Lyseng
2012-12-21 09:53:42 +01:00
parent 7817b81342
commit 8b1d1cf5c0
7 changed files with 45 additions and 37 deletions

View File

@ -453,25 +453,25 @@ inline int setup_without_group(THD *thd, Item **ref_pointer_array,
ORDER *group, bool *hidden_group_fields)
{
int res;
nesting_map save_allow_sum_func=thd->lex->allow_sum_func ;
st_select_lex *const select= thd->lex->current_select;
nesting_map save_allow_sum_func= thd->lex->allow_sum_func;
/*
Need to save the value, so we can turn off only any new non_agg_field_used
additions coming from the WHERE
*/
const bool saved_non_agg_field_used=
thd->lex->current_select->non_agg_field_used();
const bool saved_non_agg_field_used= select->non_agg_field_used();
DBUG_ENTER("setup_without_group");
thd->lex->allow_sum_func&= ~(1 << thd->lex->current_select->nest_level);
thd->lex->allow_sum_func&= ~((nesting_map)1 << select->nest_level);
res= setup_conds(thd, tables, leaves, conds);
/* it's not wrong to have non-aggregated columns in a WHERE */
thd->lex->current_select->set_non_agg_field_used(saved_non_agg_field_used);
select->set_non_agg_field_used(saved_non_agg_field_used);
thd->lex->allow_sum_func|= 1 << thd->lex->current_select->nest_level;
thd->lex->allow_sum_func|= (nesting_map)1 << select->nest_level;
res= res || setup_order(thd, ref_pointer_array, tables, fields, all_fields,
order);
thd->lex->allow_sum_func&= ~(1 << thd->lex->current_select->nest_level);
thd->lex->allow_sum_func&= ~((nesting_map)1 << select->nest_level);
res= res || setup_group(thd, ref_pointer_array, tables, fields, all_fields,
group, hidden_group_fields);
thd->lex->allow_sum_func= save_allow_sum_func;
@ -559,7 +559,7 @@ JOIN::prepare(Item ***rref_pointer_array,
{
nesting_map save_allow_sum_func= thd->lex->allow_sum_func;
thd->where="having clause";
thd->lex->allow_sum_func|= 1 << select_lex_arg->nest_level;
thd->lex->allow_sum_func|= (nesting_map)1 << select_lex_arg->nest_level;
select_lex->having_fix_field= 1;
bool having_fix_rc= (!having->fixed &&
(having->fix_fields(thd, &having) ||
@ -4547,7 +4547,8 @@ best_access_path(JOIN *join,
in ReuseRangeEstimateForRef-3.
*/
if (table->quick_keys.is_set(key) &&
(const_part & ((1 << table->quick_key_parts[key])-1)) ==
(const_part &
(((key_part_map)1 << table->quick_key_parts[key])-1)) ==
(((key_part_map)1 << table->quick_key_parts[key])-1) &&
table->quick_n_ranges[key] == 1 &&
records > (double) table->quick_rows[key])
@ -4714,7 +4715,8 @@ best_access_path(JOIN *join,
*/
if (table->quick_keys.is_set(key) &&
table->quick_key_parts[key] <= max_key_part &&
const_part & (1 << table->quick_key_parts[key]) &&
const_part &
((key_part_map)1 << table->quick_key_parts[key]) &&
table->quick_n_ranges[key] == 1 + test(ref_or_null_part &
const_part) &&
records > (double) table->quick_rows[key])
@ -5950,7 +5952,7 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse,
j->ref.items[i]=keyuse->val; // Save for cond removal
j->ref.cond_guards[i]= keyuse->cond_guard;
if (keyuse->null_rejecting)
j->ref.null_rejecting |= 1 << i;
j->ref.null_rejecting|= (key_part_map)1 << i;
keyuse_uses_no_tables= keyuse_uses_no_tables && !keyuse->used_tables;
if (!keyuse->used_tables &&
!(join->select_options & SELECT_DESCRIBE))
@ -6234,7 +6236,7 @@ static void add_not_null_conds(JOIN *join)
{
for (uint keypart= 0; keypart < tab->ref.key_parts; keypart++)
{
if (tab->ref.null_rejecting & (1 << keypart))
if (tab->ref.null_rejecting & ((key_part_map)1 << keypart))
{
Item *item= tab->ref.items[keypart];
Item *notnull;
@ -10672,11 +10674,11 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
}
else
{
recinfo->null_bit= 1 << (null_count & 7);
recinfo->null_bit= (uint8)1 << (null_count & 7);
recinfo->null_pos= null_count/8;
}
field->move_field(pos,null_flags+null_count/8,
1 << (null_count & 7));
(uint8)1 << (null_count & 7));
null_count++;
}
else
@ -11035,7 +11037,7 @@ TABLE *create_virtual_tmp_table(THD *thd, List<Create_field> &field_list)
{
cur_field->move_field(field_pos, (uchar*) null_pos, null_bit);
null_bit<<= 1;
if (null_bit == (1 << 8))
if (null_bit == (uint)1 << 8)
{
++null_pos;
null_bit= 1;
@ -12386,7 +12388,8 @@ join_read_always_key(JOIN_TAB *tab)
/* Perform "Late NULLs Filtering" (see internals manual for explanations) */
for (uint i= 0 ; i < tab->ref.key_parts ; i++)
{
if ((tab->ref.null_rejecting & 1 << i) && tab->ref.items[i]->is_null())
if ((tab->ref.null_rejecting & ((key_part_map)1 << i)) &&
tab->ref.items[i]->is_null())
return -1;
}