Commit 13c736f5 authored by Igor Babaev's avatar Igor Babaev

Changed the fixes for the following bugs:

Bug #39022: completed
Bug #39653: reverted as invalid
Bug #45640: ameliorated, simplified, optimized
Bug #48483: completed
Bug #49324: improved
Bug #51242/52336: reverted, applied a real fix.
parent 7add1877
......@@ -470,9 +470,10 @@ WHERE table2.f1 = 2
GROUP BY table1.f1, table2.f2
HAVING (table2.f2 = 8 AND table1.f1 >= 6);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible HAVING noticed after reading const tables
1 SIMPLE table2 const PRIMARY PRIMARY 4 const 1 100.00 Using filesort
1 SIMPLE table1 ALL NULL NULL NULL NULL 4 100.00 Using where
Warnings:
Note 1003 select `test`.`table1`.`f1` AS `f1`,'7' AS `f2` from `test`.`t1` `table1` join `test`.`t1` `table2` where ((`test`.`table1`.`f3` = '9')) group by `test`.`table1`.`f1`,'7' having 0
Note 1003 select `test`.`table1`.`f1` AS `f1`,'7' AS `f2` from `test`.`t1` `table1` join `test`.`t1` `table2` where ((`test`.`table1`.`f3` = '9')) group by `test`.`table1`.`f1`,'7' having (('7' = 8) and (`test`.`table1`.`f1` >= 6))
EXPLAIN EXTENDED
SELECT table1.f1, table2.f2
FROM t1 AS table1
......@@ -481,9 +482,10 @@ WHERE table2.f1 = 2
GROUP BY table1.f1, table2.f2
HAVING (table2.f2 = 8);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible HAVING noticed after reading const tables
1 SIMPLE table2 const PRIMARY PRIMARY 4 const 1 100.00 Using filesort
1 SIMPLE table1 ALL NULL NULL NULL NULL 4 100.00 Using where
Warnings:
Note 1003 select `test`.`table1`.`f1` AS `f1`,'7' AS `f2` from `test`.`t1` `table1` join `test`.`t1` `table2` where ((`test`.`table1`.`f3` = '9')) group by `test`.`table1`.`f1`,'7' having 0
Note 1003 select `test`.`table1`.`f1` AS `f1`,'7' AS `f2` from `test`.`t1` `table1` join `test`.`t1` `table2` where ((`test`.`table1`.`f3` = '9')) group by `test`.`table1`.`f1`,'7' having ('7' = 8)
DROP TABLE t1;
#
# Bug#52336 Segfault / crash in 5.1 copy_fields (param=0x9872980) at sql_select.cc:15355
......
......@@ -2296,28 +2296,6 @@ id select_type table type possible_keys key key_len ref rows Extra
drop table t1,t2;
#
#
# Bug #39653: find_shortest_key in sql_select.cc does not consider
# clustered primary keys
#
CREATE TABLE t1 (a INT PRIMARY KEY, b INT, c INT, d INT, e INT, f INT,
KEY (b,c)) ENGINE=INNODB;
INSERT INTO t1 VALUES (1,1,1,1,1,1), (2,2,2,2,2,2), (3,3,3,3,3,3),
(4,4,4,4,4,4), (5,5,5,5,5,5), (6,6,6,6,6,6),
(7,7,7,7,7,7), (8,8,8,8,8,8), (9,9,9,9,9,9),
(11,11,11,11,11,11);
EXPLAIN SELECT COUNT(*) FROM t1;
id 1
select_type SIMPLE
table t1
type index
possible_keys NULL
key b
key_len 10
ref NULL
rows 10
Extra Using index
DROP TABLE t1;
#
# Bug #49838: DROP INDEX and ADD UNIQUE INDEX for same index may
# corrupt definition at engine
#
......
......@@ -560,23 +560,6 @@ drop table t1,t2;
--echo #
--echo #
--echo # Bug #39653: find_shortest_key in sql_select.cc does not consider
--echo # clustered primary keys
--echo #
CREATE TABLE t1 (a INT PRIMARY KEY, b INT, c INT, d INT, e INT, f INT,
KEY (b,c)) ENGINE=INNODB;
INSERT INTO t1 VALUES (1,1,1,1,1,1), (2,2,2,2,2,2), (3,3,3,3,3,3),
(4,4,4,4,4,4), (5,5,5,5,5,5), (6,6,6,6,6,6),
(7,7,7,7,7,7), (8,8,8,8,8,8), (9,9,9,9,9,9),
(11,11,11,11,11,11);
--query_vertical EXPLAIN SELECT COUNT(*) FROM t1
DROP TABLE t1;
--echo #
--echo # Bug #49838: DROP INDEX and ADD UNIQUE INDEX for same index may
--echo # corrupt definition at engine
......
......@@ -608,7 +608,9 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select,
}
if (error == 0)
param->examined_rows++;
if (error == 0 && (!select || select->skip_record() == 0))
int rc= 0;
if (error == 0 && (!select || select->skip_record(thd) > 0))
{
if (idx == param->keys)
{
......@@ -621,6 +623,7 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select,
}
else
file->unlock_row();
/* It does not make sense to read more keys in case of a fatal error */
if (thd->is_error())
break;
......
......@@ -4321,31 +4321,18 @@ bool Item_field::fix_fields(THD *thd, Item **reference)
It's not an Item_field in the select list so we must make a new
Item_ref to point to the Item in the select list and replace the
Item_field created by the parser with the new Item_ref.
NOTE: If we are fixing an alias reference inside ORDER/GROUP BY
item tree, then we use new Item_ref as an intermediate value
to resolve referenced item only.
In this case the new Item_ref item is unused.
*/
Item_ref *rf= new Item_ref(context, db_name,table_name,field_name);
if (!rf)
return 1;
bool save_group_fix_field= thd->lex->current_select->group_fix_field;
/*
No need for recursive resolving of aliases.
*/
thd->lex->current_select->group_fix_field= 0;
bool ret= rf->fix_fields(thd, (Item **) &rf) || rf->check_cols(1);
thd->lex->current_select->group_fix_field= save_group_fix_field;
if (ret)
return TRUE;
if (save_group_fix_field && alias_name_used)
thd->change_item_tree(reference, *rf->ref);
else
thd->change_item_tree(reference, rf);
SELECT_LEX *select= thd->lex->current_select;
thd->change_item_tree(reference,
select->parsing_place == IN_GROUP_BY &&
alias_name_used ? *rf->ref : rf);
return FALSE;
}
......@@ -6438,6 +6425,42 @@ bool Item_outer_ref::fix_fields(THD *thd, Item **reference)
}
/**
Mark references from inner selects used in group by clause
The method is used by the walk method when called for the expressions
from the group by clause. The callsare occurred in the function
fix_inner_refs invoked by JOIN::prepare.
The parameter passed to Item_outer_ref::check_inner_refs_processor
is the iterator over the list of inner references from the subselects
of the select to be prepared. The function marks those references
from this list whose occurrences are encountered in the group by
expressions passed to the walk method.
@param arg pointer to the iterator over a list of inner references
@return
FALSE always
*/
bool Item_outer_ref::check_inner_refs_processor(uchar *arg)
{
List_iterator_fast<Item_outer_ref> *it=
((List_iterator_fast<Item_outer_ref> *) arg);
Item_outer_ref *ref;
while ((ref= (*it)++))
{
if (ref == this)
{
ref->found_in_group_by= 1;
break;
}
}
(*it).rewind();
return FALSE;
}
/**
Compare two view column references for equality.
......
......@@ -905,7 +905,6 @@ class Item {
virtual bool change_context_processor(uchar *context) { return 0; }
virtual bool reset_query_id_processor(uchar *query_id_arg) { return 0; }
virtual bool is_expensive_processor(uchar *arg) { return 0; }
virtual bool find_item_processor(uchar *arg) { return this == (void *) arg; }
virtual bool register_field_in_read_map(uchar *arg) { return 0; }
virtual bool enumerate_field_refs_processor(uchar *arg) { return 0; }
virtual bool mark_as_eliminated_processor(uchar *arg) { return 0; }
......@@ -998,6 +997,8 @@ class Item {
return FALSE;
}
virtual bool check_inner_refs_processor(uchar *arg) { return FALSE; }
/*
For SP local variable returns pointer to Item representing its
current value and pointer to current Item otherwise.
......@@ -2450,12 +2451,13 @@ class Item_outer_ref :public Item_direct_ref
of the outer select.
*/
bool found_in_select_list;
bool found_in_group_by;
Item_outer_ref(Name_resolution_context *context_arg,
Item_field *outer_field_arg)
:Item_direct_ref(context_arg, 0, outer_field_arg->table_name,
outer_field_arg->field_name),
outer_ref(outer_field_arg), in_sum_func(0),
found_in_select_list(0)
found_in_select_list(0), found_in_group_by(0)
{
ref= &outer_ref;
set_properties();
......@@ -2466,7 +2468,7 @@ class Item_outer_ref :public Item_direct_ref
bool alias_name_used_arg)
:Item_direct_ref(context_arg, item, table_name_arg, field_name_arg,
alias_name_used_arg),
outer_ref(0), in_sum_func(0), found_in_select_list(1)
outer_ref(0), in_sum_func(0), found_in_select_list(1), found_in_group_by(0)
{}
void save_in_result_field(bool no_conversions)
{
......@@ -2478,6 +2480,7 @@ class Item_outer_ref :public Item_direct_ref
return (*ref)->const_item() ? 0 : OUTER_REF_TABLE_BIT;
}
virtual Ref_Type ref_type() { return OUTER_REF; }
bool check_inner_refs_processor(uchar * arg);
};
......
......@@ -640,7 +640,8 @@ enum enum_parsing_place
IN_HAVING,
SELECT_LIST,
IN_WHERE,
IN_ON
IN_ON,
IN_GROUP_BY
};
struct st_table;
......@@ -1196,7 +1197,7 @@ int setup_group(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
List<Item> &fields, List<Item> &all_fields, ORDER *order,
bool *hidden_group_fields);
bool fix_inner_refs(THD *thd, List<Item> &all_fields, SELECT_LEX *select,
Item **ref_pointer_array, ORDER *group_list= NULL);
Item **ref_pointer_array);
bool handle_select(THD *thd, LEX *lex, select_result *result,
ulong setup_tables_done_option);
......
......@@ -718,7 +718,19 @@ class SQL_SELECT :public Sql_alloc {
tmp.set_all();
return test_quick_select(thd, tmp, 0, limit, force_quick_range) < 0;
}
inline bool skip_record() { return cond ? cond->val_int() == 0 : 0; }
/*
RETURN
0 if record must be skipped <-> (cond && cond->val_int() == 0)
-1 if error
1 otherwise
*/
inline int skip_record(THD *thd)
{
int rc= test(!cond || cond->val_int());
if (thd->is_error())
rc= -1;
return rc;
}
int test_quick_select(THD *thd, key_map keys, table_map prev_tables,
ha_rows limit, bool force_quick_range);
};
......
......@@ -305,9 +305,8 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
! thd->is_error())
{
// thd->is_error() is tested to disallow delete row on error
if (!(select && select->skip_record())&& ! thd->is_error() )
if (!select || select->skip_record(thd) > 0)
{
if (triggers_applicable &&
table->triggers->process_triggers(thd, TRG_EVENT_DELETE,
TRG_ACTION_BEFORE, FALSE))
......
......@@ -1603,7 +1603,6 @@ void st_select_lex::init_query()
having= prep_having= where= prep_where= 0;
olap= UNSPECIFIED_OLAP_TYPE;
having_fix_field= 0;
group_fix_field= 0;
context.select_lex= this;
context.init();
/*
......
......@@ -647,8 +647,6 @@ class st_select_lex: public st_select_lex_node
bool braces; /* SELECT ... UNION (SELECT ... ) <- this braces */
/* TRUE when having fix field called in processing of this SELECT */
bool having_fix_field;
/* TRUE when GROUP BY fix field called in processing of this SELECT */
bool group_fix_field;
/* List of references to fields referenced from inner selects */
List<Item_outer_ref> inner_refs_list;
/* Number of Item_sum-derived objects in this SELECT */
......
This diff is collapsed.
......@@ -469,9 +469,10 @@ int mysql_update(THD *thd,
thd_proc_info(thd, "Searching rows for update");
ha_rows tmp_limit= limit;
while (!(error=info.read_record(&info)) && !thd->killed)
while (!(error=info.read_record(&info)) &&
!thd->killed && !thd->is_error())
{
if (!(select && select->skip_record()))
if (!select || select->skip_record(thd) > 0)
{
if (table->file->was_semi_consistent_read())
continue; /* repeat the read of the same row if it still exists */
......@@ -577,7 +578,7 @@ int mysql_update(THD *thd,
while (!(error=info.read_record(&info)) && !thd->killed)
{
if (!(select && select->skip_record()))
if (!select || select->skip_record(thd) > 0)
{
if (table->file->was_semi_consistent_read())
continue; /* repeat the read of the same row if it still exists */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment