Commit 55af024c authored by Tor Didriksen's avatar Tor Didriksen

merge 5.0 => 5.1 : Bug#12329653

parents b3e92932 ab3c7688
...@@ -176,11 +176,12 @@ SELECT @@session.sql_mode INTO @old_sql_mode; ...@@ -176,11 +176,12 @@ SELECT @@session.sql_mode INTO @old_sql_mode;
SET SESSION sql_mode='ONLY_FULL_GROUP_BY'; SET SESSION sql_mode='ONLY_FULL_GROUP_BY';
EXPLAIN EXTENDED SELECT 1 FROM t1 EXPLAIN EXTENDED SELECT 1 FROM t1
WHERE f1 > ALL( SELECT t.f1 FROM t1,t1 AS t ); WHERE f1 > ALL( SELECT t.f1 FROM t1,t1 AS t );
ERROR 42000: Mixing of GROUP columns (MIN(),MAX(),COUNT(),...) with no GROUP columns is illegal if there is no GROUP BY clause id select_type table type possible_keys key key_len ref rows filtered Extra
SHOW WARNINGS; 1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
Level Code Message 2 SUBQUERY t1 system NULL NULL NULL NULL 0 0.00 const row not found
Error 1140 Mixing of GROUP columns (MIN(),MAX(),COUNT(),...) with no GROUP columns is illegal if there is no GROUP BY clause 2 SUBQUERY t system NULL NULL NULL NULL 0 0.00 const row not found
Note 1003 select 1 AS `1` from `test`.`t1` where <not>(<exists>(...)) Warnings:
Note 1003 select 1 AS `1` from `test`.`t1` where 0
SET SESSION sql_mode=@old_sql_mode; SET SESSION sql_mode=@old_sql_mode;
DROP TABLE t1; DROP TABLE t1;
End of 5.0 tests. End of 5.0 tests.
......
...@@ -4435,6 +4435,32 @@ pk int_key ...@@ -4435,6 +4435,32 @@ pk int_key
3 3 3 3
7 3 7 3
DROP TABLE t1,t2; DROP TABLE t1,t2;
#
# Bug#12329653
# EXPLAIN, UNION, PREPARED STATEMENT, CRASH, SQL_FULL_GROUP_BY
#
CREATE TABLE t1(a1 int);
INSERT INTO t1 VALUES (1),(2);
SELECT @@session.sql_mode INTO @old_sql_mode;
SET SESSION sql_mode='ONLY_FULL_GROUP_BY';
SELECT 1 FROM t1 WHERE 1 < SOME (SELECT a1 FROM t1);
1
1
1
PREPARE stmt FROM
'SELECT 1 UNION ALL
SELECT 1 FROM t1
ORDER BY
(SELECT 1 FROM t1 AS t1_0
WHERE 1 < SOME (SELECT a1 FROM t1)
)' ;
EXECUTE stmt ;
ERROR 21000: Subquery returns more than 1 row
EXECUTE stmt ;
ERROR 21000: Subquery returns more than 1 row
SET SESSION sql_mode=@old_sql_mode;
DEALLOCATE PREPARE stmt;
DROP TABLE t1;
End of 5.0 tests. End of 5.0 tests.
CREATE TABLE t1 (a INT, b INT); CREATE TABLE t1 (a INT, b INT);
INSERT INTO t1 VALUES (2,22),(1,11),(2,22); INSERT INTO t1 VALUES (2,22),(1,11),(2,22);
......
# #
# Test of different EXPLAIN's # Test of different EXPLAINs
--disable_warnings --disable_warnings
drop table if exists t1; drop table if exists t1;
...@@ -157,11 +157,12 @@ CREATE TABLE t1 (f1 INT); ...@@ -157,11 +157,12 @@ CREATE TABLE t1 (f1 INT);
SELECT @@session.sql_mode INTO @old_sql_mode; SELECT @@session.sql_mode INTO @old_sql_mode;
SET SESSION sql_mode='ONLY_FULL_GROUP_BY'; SET SESSION sql_mode='ONLY_FULL_GROUP_BY';
# EXPLAIN EXTENDED (with subselect). used to crash. should give NOTICE. # EXPLAIN EXTENDED (with subselect). used to crash.
--error ER_MIX_OF_GROUP_FUNC_AND_FIELDS # This is actually a valid query for this sql_mode,
# but it was transformed in such a way that it failed, see
# Bug#12329653 - EXPLAIN, UNION, PREPARED STATEMENT, CRASH, SQL_FULL_GROUP_BY
EXPLAIN EXTENDED SELECT 1 FROM t1 EXPLAIN EXTENDED SELECT 1 FROM t1
WHERE f1 > ALL( SELECT t.f1 FROM t1,t1 AS t ); WHERE f1 > ALL( SELECT t.f1 FROM t1,t1 AS t );
SHOW WARNINGS;
SET SESSION sql_mode=@old_sql_mode; SET SESSION sql_mode=@old_sql_mode;
......
...@@ -3393,6 +3393,39 @@ ORDER BY outr.pk; ...@@ -3393,6 +3393,39 @@ ORDER BY outr.pk;
DROP TABLE t1,t2; DROP TABLE t1,t2;
--echo #
--echo # Bug#12329653
--echo # EXPLAIN, UNION, PREPARED STATEMENT, CRASH, SQL_FULL_GROUP_BY
--echo #
CREATE TABLE t1(a1 int);
INSERT INTO t1 VALUES (1),(2);
SELECT @@session.sql_mode INTO @old_sql_mode;
SET SESSION sql_mode='ONLY_FULL_GROUP_BY';
## First a simpler query, illustrating the transformation
## '1 < some (...)' => '1 < max(...)'
SELECT 1 FROM t1 WHERE 1 < SOME (SELECT a1 FROM t1);
## The query which made the server crash.
PREPARE stmt FROM
'SELECT 1 UNION ALL
SELECT 1 FROM t1
ORDER BY
(SELECT 1 FROM t1 AS t1_0
WHERE 1 < SOME (SELECT a1 FROM t1)
)' ;
--error ER_SUBQUERY_NO_1_ROW
EXECUTE stmt ;
--error ER_SUBQUERY_NO_1_ROW
EXECUTE stmt ;
SET SESSION sql_mode=@old_sql_mode;
DEALLOCATE PREPARE stmt;
DROP TABLE t1;
--echo End of 5.0 tests. --echo End of 5.0 tests.
......
...@@ -4464,14 +4464,14 @@ bool Item_field::fix_fields(THD *thd, Item **reference) ...@@ -4464,14 +4464,14 @@ bool Item_field::fix_fields(THD *thd, Item **reference)
SELECT_LEX *select_lex= cached_table ? SELECT_LEX *select_lex= cached_table ?
cached_table->select_lex : context->select_lex; cached_table->select_lex : context->select_lex;
if (!thd->lex->in_sum_func) if (!thd->lex->in_sum_func)
select_lex->full_group_by_flag|= NON_AGG_FIELD_USED; select_lex->set_non_agg_field_used(true);
else else
{ {
if (outer_fixed) if (outer_fixed)
thd->lex->in_sum_func->outer_fields.push_back(this); thd->lex->in_sum_func->outer_fields.push_back(this);
else if (thd->lex->in_sum_func->nest_level != else if (thd->lex->in_sum_func->nest_level !=
thd->lex->current_select->nest_level) thd->lex->current_select->nest_level)
select_lex->full_group_by_flag|= NON_AGG_FIELD_USED; select_lex->set_non_agg_field_used(true);
} }
} }
return FALSE; return FALSE;
......
...@@ -1016,6 +1016,14 @@ Item_in_subselect::single_value_transformer(JOIN *join, ...@@ -1016,6 +1016,14 @@ Item_in_subselect::single_value_transformer(JOIN *join,
it.replace(item); it.replace(item);
} }
DBUG_EXECUTE("where",
print_where(item, "rewrite with MIN/MAX", QT_ORDINARY););
if (thd->variables.sql_mode & MODE_ONLY_FULL_GROUP_BY)
{
DBUG_ASSERT(select_lex->non_agg_field_used());
select_lex->set_non_agg_field_used(false);
}
save_allow_sum_func= thd->lex->allow_sum_func; save_allow_sum_func= thd->lex->allow_sum_func;
thd->lex->allow_sum_func|= 1 << thd->lex->current_select->nest_level; thd->lex->allow_sum_func|= 1 << thd->lex->current_select->nest_level;
/* /*
......
...@@ -247,10 +247,10 @@ bool Item_sum::check_sum_func(THD *thd, Item **ref) ...@@ -247,10 +247,10 @@ bool Item_sum::check_sum_func(THD *thd, Item **ref)
in_sum_func->outer_fields.push_back(field); in_sum_func->outer_fields.push_back(field);
} }
else else
sel->full_group_by_flag|= NON_AGG_FIELD_USED; sel->set_non_agg_field_used(true);
} }
if (sel->nest_level > aggr_level && if (sel->nest_level > aggr_level &&
(sel->full_group_by_flag & SUM_FUNC_USED) && (sel->agg_func_used()) &&
!sel->group_list.elements) !sel->group_list.elements)
{ {
my_message(ER_MIX_OF_GROUP_FUNC_AND_FIELDS, my_message(ER_MIX_OF_GROUP_FUNC_AND_FIELDS,
...@@ -259,7 +259,7 @@ bool Item_sum::check_sum_func(THD *thd, Item **ref) ...@@ -259,7 +259,7 @@ bool Item_sum::check_sum_func(THD *thd, Item **ref)
} }
} }
} }
aggr_sel->full_group_by_flag|= SUM_FUNC_USED; aggr_sel->set_agg_func_used(true);
update_used_tables(); update_used_tables();
thd->lex->in_sum_func= in_sum_func; thd->lex->in_sum_func= in_sum_func;
return FALSE; return FALSE;
......
...@@ -1469,13 +1469,6 @@ SQL_SELECT *make_select(TABLE *head, table_map const_tables, ...@@ -1469,13 +1469,6 @@ SQL_SELECT *make_select(TABLE *head, table_map const_tables,
bool allow_null_cond, int *error); bool allow_null_cond, int *error);
extern Item **not_found_item; extern Item **not_found_item;
/*
A set of constants used for checking non aggregated fields and sum
functions mixture in the ONLY_FULL_GROUP_BY_MODE.
*/
#define NON_AGG_FIELD_USED 1
#define SUM_FUNC_USED 2
/* /*
This enumeration type is used only by the function find_item_in_list This enumeration type is used only by the function find_item_in_list
to return the info on how an item has been resolved against a list to return the info on how an item has been resolved against a list
......
...@@ -1621,6 +1621,8 @@ void st_select_lex::init_query() ...@@ -1621,6 +1621,8 @@ void st_select_lex::init_query()
nest_level= 0; nest_level= 0;
link_next= 0; link_next= 0;
lock_option= TL_READ_DEFAULT; lock_option= TL_READ_DEFAULT;
m_non_agg_field_used= false;
m_agg_func_used= false;
} }
void st_select_lex::init_select() void st_select_lex::init_select()
...@@ -1651,7 +1653,8 @@ void st_select_lex::init_select() ...@@ -1651,7 +1653,8 @@ void st_select_lex::init_select()
non_agg_fields.empty(); non_agg_fields.empty();
cond_value= having_value= Item::COND_UNDEF; cond_value= having_value= Item::COND_UNDEF;
inner_refs_list.empty(); inner_refs_list.empty();
full_group_by_flag= 0; m_non_agg_field_used= false;
m_agg_func_used= false;
} }
/* /*
......
...@@ -713,16 +713,7 @@ class st_select_lex: public st_select_lex_node ...@@ -713,16 +713,7 @@ class st_select_lex: public st_select_lex_node
joins on the right. joins on the right.
*/ */
List<String> *prev_join_using; List<String> *prev_join_using;
/*
Bitmap used in the ONLY_FULL_GROUP_BY_MODE to prevent mixture of aggregate
functions and non aggregated fields when GROUP BY list is absent.
Bits:
0 - non aggregated fields are used in this select,
defined as NON_AGG_FIELD_USED.
1 - aggregate functions are used in this select,
defined as SUM_FUNC_USED.
*/
uint8 full_group_by_flag;
void init_query(); void init_query();
void init_select(); void init_select();
st_select_lex_unit* master_unit(); st_select_lex_unit* master_unit();
...@@ -830,7 +821,22 @@ class st_select_lex: public st_select_lex_node ...@@ -830,7 +821,22 @@ class st_select_lex: public st_select_lex_node
void clear_index_hints(void) { index_hints= NULL; } void clear_index_hints(void) { index_hints= NULL; }
/*
For MODE_ONLY_FULL_GROUP_BY we need to maintain two flags:
- Non-aggregated fields are used in this select.
- Aggregate functions are used in this select.
In MODE_ONLY_FULL_GROUP_BY only one of these may be true.
*/
bool non_agg_field_used() const { return m_non_agg_field_used; }
bool agg_func_used() const { return m_agg_func_used; }
void set_non_agg_field_used(bool val) { m_non_agg_field_used= val; }
void set_agg_func_used(bool val) { m_agg_func_used= val; }
private: private:
bool m_non_agg_field_used;
bool m_agg_func_used;
/* current index hint kind. used in filling up index_hints */ /* current index hint kind. used in filling up index_hints */
enum index_hint_type current_index_hint_type; enum index_hint_type current_index_hint_type;
index_clause_map current_index_hint_clause; index_clause_map current_index_hint_clause;
......
...@@ -930,9 +930,6 @@ static bool fix_fields_part_func(THD *thd, Item* func_expr, TABLE *table, ...@@ -930,9 +930,6 @@ static bool fix_fields_part_func(THD *thd, Item* func_expr, TABLE *table,
const char *save_where; const char *save_where;
char* db_name; char* db_name;
char db_name_string[FN_REFLEN]; char db_name_string[FN_REFLEN];
bool save_use_only_table_context;
uint8 saved_full_group_by_flag;
nesting_map saved_allow_sum_func;
DBUG_ENTER("fix_fields_part_func"); DBUG_ENTER("fix_fields_part_func");
if (part_info->fixed) if (part_info->fixed)
...@@ -999,23 +996,26 @@ static bool fix_fields_part_func(THD *thd, Item* func_expr, TABLE *table, ...@@ -999,23 +996,26 @@ static bool fix_fields_part_func(THD *thd, Item* func_expr, TABLE *table,
of interesting side effects, both desirable and undesirable. of interesting side effects, both desirable and undesirable.
*/ */
save_use_only_table_context= thd->lex->use_only_table_context; {
const bool save_use_only_table_context= thd->lex->use_only_table_context;
thd->lex->use_only_table_context= TRUE; thd->lex->use_only_table_context= TRUE;
thd->lex->current_select->cur_pos_in_select_list= UNDEF_POS; thd->lex->current_select->cur_pos_in_select_list= UNDEF_POS;
saved_full_group_by_flag= thd->lex->current_select->full_group_by_flag; const bool save_agg_field= thd->lex->current_select->non_agg_field_used();
saved_allow_sum_func= thd->lex->allow_sum_func; const bool save_agg_func= thd->lex->current_select->agg_func_used();
const nesting_map saved_allow_sum_func= thd->lex->allow_sum_func;
thd->lex->allow_sum_func= 0; thd->lex->allow_sum_func= 0;
error= func_expr->fix_fields(thd, (Item**)&func_expr); error= func_expr->fix_fields(thd, (Item**)&func_expr);
/* /*
Restore full_group_by_flag and allow_sum_func, Restore agg_field/agg_func and allow_sum_func,
fix_fields should not affect mysql_select later, see Bug#46923. fix_fields should not affect mysql_select later, see Bug#46923.
*/ */
thd->lex->current_select->full_group_by_flag= saved_full_group_by_flag; thd->lex->current_select->set_non_agg_field_used(save_agg_field);
thd->lex->current_select->set_agg_func_used(save_agg_func);
thd->lex->allow_sum_func= saved_allow_sum_func; thd->lex->allow_sum_func= saved_allow_sum_func;
thd->lex->use_only_table_context= save_use_only_table_context; thd->lex->use_only_table_context= save_use_only_table_context;
}
context->table_list= save_table_list; context->table_list= save_table_list;
context->first_name_resolution_table= save_first_table; context->first_name_resolution_table= save_first_table;
......
...@@ -426,19 +426,18 @@ inline int setup_without_group(THD *thd, Item **ref_pointer_array, ...@@ -426,19 +426,18 @@ inline int setup_without_group(THD *thd, Item **ref_pointer_array,
int res; int res;
nesting_map save_allow_sum_func=thd->lex->allow_sum_func ; nesting_map save_allow_sum_func=thd->lex->allow_sum_func ;
/* /*
Need to save the value, so we can turn off only the new NON_AGG_FIELD Need to save the value, so we can turn off only any new non_agg_field_used
additions coming from the WHERE additions coming from the WHERE
*/ */
uint8 saved_flag= thd->lex->current_select->full_group_by_flag; const bool saved_non_agg_field_used=
thd->lex->current_select->non_agg_field_used();
DBUG_ENTER("setup_without_group"); DBUG_ENTER("setup_without_group");
thd->lex->allow_sum_func&= ~(1 << thd->lex->current_select->nest_level); thd->lex->allow_sum_func&= ~(1 << thd->lex->current_select->nest_level);
res= setup_conds(thd, tables, leaves, conds); res= setup_conds(thd, tables, leaves, conds);
/* it's not wrong to have non-aggregated columns in a WHERE */ /* it's not wrong to have non-aggregated columns in a WHERE */
if (thd->variables.sql_mode & MODE_ONLY_FULL_GROUP_BY) thd->lex->current_select->set_non_agg_field_used(saved_non_agg_field_used);
thd->lex->current_select->full_group_by_flag= saved_flag |
(thd->lex->current_select->full_group_by_flag & ~NON_AGG_FIELD_USED);
thd->lex->allow_sum_func|= 1 << thd->lex->current_select->nest_level; thd->lex->allow_sum_func|= 1 << thd->lex->current_select->nest_level;
res= res || setup_order(thd, ref_pointer_array, tables, fields, all_fields, res= res || setup_order(thd, ref_pointer_array, tables, fields, all_fields,
...@@ -644,7 +643,8 @@ JOIN::prepare(Item ***rref_pointer_array, ...@@ -644,7 +643,8 @@ JOIN::prepare(Item ***rref_pointer_array,
aggregate functions with implicit grouping (there is no GROUP BY). aggregate functions with implicit grouping (there is no GROUP BY).
*/ */
if (thd->variables.sql_mode & MODE_ONLY_FULL_GROUP_BY && !group_list && if (thd->variables.sql_mode & MODE_ONLY_FULL_GROUP_BY && !group_list &&
select_lex->full_group_by_flag == (NON_AGG_FIELD_USED | SUM_FUNC_USED)) select_lex->non_agg_field_used() &&
select_lex->agg_func_used())
{ {
my_message(ER_MIX_OF_GROUP_FUNC_AND_FIELDS, my_message(ER_MIX_OF_GROUP_FUNC_AND_FIELDS,
ER(ER_MIX_OF_GROUP_FUNC_AND_FIELDS), MYF(0)); ER(ER_MIX_OF_GROUP_FUNC_AND_FIELDS), MYF(0));
......
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