Skip to content

Commit 294fb44

Browse files
author
Tor Didriksen
committed
merge 5.1 => 5.5 : Bug#12329653
2 parents e889b48 + 9baf84e commit 294fb44

12 files changed

+124
-50
lines changed

mysql-test/r/explain.result

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -176,10 +176,12 @@ SELECT @@session.sql_mode INTO @old_sql_mode;
176176
SET SESSION sql_mode='ONLY_FULL_GROUP_BY';
177177
EXPLAIN EXTENDED SELECT 1 FROM t1
178178
WHERE f1 > ALL( SELECT t.f1 FROM t1,t1 AS t );
179-
ERROR 42000: Mixing of GROUP columns (MIN(),MAX(),COUNT(),...) with no GROUP columns is illegal if there is no GROUP BY clause
180-
SHOW WARNINGS;
181-
Level Code Message
182-
Error 1140 Mixing of GROUP columns (MIN(),MAX(),COUNT(),...) with no GROUP columns is illegal if there is no GROUP BY clause
179+
id select_type table type possible_keys key key_len ref rows filtered Extra
180+
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
181+
2 SUBQUERY t1 system NULL NULL NULL NULL 0 0.00 const row not found
182+
2 SUBQUERY t system NULL NULL NULL NULL 0 0.00 const row not found
183+
Warnings:
184+
Note 1003 select 1 AS `1` from `test`.`t1` where 0
183185
SET SESSION sql_mode=@old_sql_mode;
184186
DROP TABLE t1;
185187
End of 5.0 tests.

mysql-test/r/subselect.result

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4442,6 +4442,32 @@ pk int_key
44424442
3 3
44434443
7 3
44444444
DROP TABLE t1,t2;
4445+
#
4446+
# Bug#12329653
4447+
# EXPLAIN, UNION, PREPARED STATEMENT, CRASH, SQL_FULL_GROUP_BY
4448+
#
4449+
CREATE TABLE t1(a1 int);
4450+
INSERT INTO t1 VALUES (1),(2);
4451+
SELECT @@session.sql_mode INTO @old_sql_mode;
4452+
SET SESSION sql_mode='ONLY_FULL_GROUP_BY';
4453+
SELECT 1 FROM t1 WHERE 1 < SOME (SELECT a1 FROM t1);
4454+
1
4455+
1
4456+
1
4457+
PREPARE stmt FROM
4458+
'SELECT 1 UNION ALL
4459+
SELECT 1 FROM t1
4460+
ORDER BY
4461+
(SELECT 1 FROM t1 AS t1_0
4462+
WHERE 1 < SOME (SELECT a1 FROM t1)
4463+
)' ;
4464+
EXECUTE stmt ;
4465+
ERROR 21000: Subquery returns more than 1 row
4466+
EXECUTE stmt ;
4467+
ERROR 21000: Subquery returns more than 1 row
4468+
SET SESSION sql_mode=@old_sql_mode;
4469+
DEALLOCATE PREPARE stmt;
4470+
DROP TABLE t1;
44454471
End of 5.0 tests.
44464472
CREATE TABLE t1 (a INT, b INT);
44474473
INSERT INTO t1 VALUES (2,22),(1,11),(2,22);

mysql-test/t/explain.test

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -157,11 +157,12 @@ CREATE TABLE t1 (f1 INT);
157157
SELECT @@session.sql_mode INTO @old_sql_mode;
158158
SET SESSION sql_mode='ONLY_FULL_GROUP_BY';
159159

160-
# EXPLAIN EXTENDED (with subselect). used to crash. should give NOTICE.
161-
--error ER_MIX_OF_GROUP_FUNC_AND_FIELDS
160+
# EXPLAIN EXTENDED (with subselect). used to crash.
161+
# This is actually a valid query for this sql_mode,
162+
# but it was transformed in such a way that it failed, see
163+
# Bug#12329653 - EXPLAIN, UNION, PREPARED STATEMENT, CRASH, SQL_FULL_GROUP_BY
162164
EXPLAIN EXTENDED SELECT 1 FROM t1
163165
WHERE f1 > ALL( SELECT t.f1 FROM t1,t1 AS t );
164-
SHOW WARNINGS;
165166

166167
SET SESSION sql_mode=@old_sql_mode;
167168

mysql-test/t/subselect.test

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3387,6 +3387,39 @@ ORDER BY outr.pk;
33873387

33883388
DROP TABLE t1,t2;
33893389

3390+
--echo #
3391+
--echo # Bug#12329653
3392+
--echo # EXPLAIN, UNION, PREPARED STATEMENT, CRASH, SQL_FULL_GROUP_BY
3393+
--echo #
3394+
3395+
CREATE TABLE t1(a1 int);
3396+
INSERT INTO t1 VALUES (1),(2);
3397+
3398+
SELECT @@session.sql_mode INTO @old_sql_mode;
3399+
SET SESSION sql_mode='ONLY_FULL_GROUP_BY';
3400+
3401+
## First a simpler query, illustrating the transformation
3402+
## '1 < some (...)' => '1 < max(...)'
3403+
SELECT 1 FROM t1 WHERE 1 < SOME (SELECT a1 FROM t1);
3404+
3405+
## The query which made the server crash.
3406+
PREPARE stmt FROM
3407+
'SELECT 1 UNION ALL
3408+
SELECT 1 FROM t1
3409+
ORDER BY
3410+
(SELECT 1 FROM t1 AS t1_0
3411+
WHERE 1 < SOME (SELECT a1 FROM t1)
3412+
)' ;
3413+
3414+
--error ER_SUBQUERY_NO_1_ROW
3415+
EXECUTE stmt ;
3416+
--error ER_SUBQUERY_NO_1_ROW
3417+
EXECUTE stmt ;
3418+
3419+
SET SESSION sql_mode=@old_sql_mode;
3420+
3421+
DEALLOCATE PREPARE stmt;
3422+
DROP TABLE t1;
33903423

33913424
--echo End of 5.0 tests.
33923425

sql/item.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4759,14 +4759,14 @@ bool Item_field::fix_fields(THD *thd, Item **reference)
47594759
SELECT_LEX *select_lex= cached_table ?
47604760
cached_table->select_lex : context->select_lex;
47614761
if (!thd->lex->in_sum_func)
4762-
select_lex->full_group_by_flag|= NON_AGG_FIELD_USED;
4762+
select_lex->set_non_agg_field_used(true);
47634763
else
47644764
{
47654765
if (outer_fixed)
47664766
thd->lex->in_sum_func->outer_fields.push_back(this);
47674767
else if (thd->lex->in_sum_func->nest_level !=
47684768
thd->lex->current_select->nest_level)
4769-
select_lex->full_group_by_flag|= NON_AGG_FIELD_USED;
4769+
select_lex->set_non_agg_field_used(true);
47704770
}
47714771
}
47724772
return FALSE;

sql/item_subselect.cc

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include "set_var.h"
3939
#include "sql_select.h"
4040
#include "sql_parse.h" // check_stack_overrun
41+
#include "sql_test.h"
4142

4243
inline Item * and_items(Item* cond, Item *item)
4344
{
@@ -1025,6 +1026,14 @@ Item_in_subselect::single_value_transformer(JOIN *join,
10251026
it.replace(item);
10261027
}
10271028

1029+
DBUG_EXECUTE("where",
1030+
print_where(item, "rewrite with MIN/MAX", QT_ORDINARY););
1031+
if (thd->variables.sql_mode & MODE_ONLY_FULL_GROUP_BY)
1032+
{
1033+
DBUG_ASSERT(select_lex->non_agg_field_used());
1034+
select_lex->set_non_agg_field_used(false);
1035+
}
1036+
10281037
save_allow_sum_func= thd->lex->allow_sum_func;
10291038
thd->lex->allow_sum_func|= 1 << thd->lex->current_select->nest_level;
10301039
/*

sql/item_sum.cc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -259,10 +259,10 @@ bool Item_sum::check_sum_func(THD *thd, Item **ref)
259259
in_sum_func->outer_fields.push_back(field);
260260
}
261261
else
262-
sel->full_group_by_flag|= NON_AGG_FIELD_USED;
262+
sel->set_non_agg_field_used(true);
263263
}
264264
if (sel->nest_level > aggr_level &&
265-
(sel->full_group_by_flag & SUM_FUNC_USED) &&
265+
(sel->agg_func_used()) &&
266266
!sel->group_list.elements)
267267
{
268268
my_message(ER_MIX_OF_GROUP_FUNC_AND_FIELDS,
@@ -271,7 +271,7 @@ bool Item_sum::check_sum_func(THD *thd, Item **ref)
271271
}
272272
}
273273
}
274-
aggr_sel->full_group_by_flag|= SUM_FUNC_USED;
274+
aggr_sel->set_agg_func_used(true);
275275
update_used_tables();
276276
thd->lex->in_sum_func= in_sum_func;
277277
return FALSE;

sql/sql_lex.cc

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1755,6 +1755,8 @@ void st_select_lex::init_query()
17551755
exclude_from_table_unique_test= no_wrap_view_item= FALSE;
17561756
nest_level= 0;
17571757
link_next= 0;
1758+
m_non_agg_field_used= false;
1759+
m_agg_func_used= false;
17581760
}
17591761

17601762
void st_select_lex::init_select()
@@ -1785,7 +1787,8 @@ void st_select_lex::init_select()
17851787
non_agg_fields.empty();
17861788
cond_value= having_value= Item::COND_UNDEF;
17871789
inner_refs_list.empty();
1788-
full_group_by_flag= 0;
1790+
m_non_agg_field_used= false;
1791+
m_agg_func_used= false;
17891792
}
17901793

17911794
/*

sql/sql_lex.h

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -800,16 +800,7 @@ class st_select_lex: public st_select_lex_node
800800
joins on the right.
801801
*/
802802
List<String> *prev_join_using;
803-
/*
804-
Bitmap used in the ONLY_FULL_GROUP_BY_MODE to prevent mixture of aggregate
805-
functions and non aggregated fields when GROUP BY list is absent.
806-
Bits:
807-
0 - non aggregated fields are used in this select,
808-
defined as NON_AGG_FIELD_USED.
809-
1 - aggregate functions are used in this select,
810-
defined as SUM_FUNC_USED.
811-
*/
812-
uint8 full_group_by_flag;
803+
813804
void init_query();
814805
void init_select();
815806
st_select_lex_unit* master_unit();
@@ -918,7 +909,22 @@ class st_select_lex: public st_select_lex_node
918909

919910
void clear_index_hints(void) { index_hints= NULL; }
920911

921-
private:
912+
/*
913+
For MODE_ONLY_FULL_GROUP_BY we need to maintain two flags:
914+
- Non-aggregated fields are used in this select.
915+
- Aggregate functions are used in this select.
916+
In MODE_ONLY_FULL_GROUP_BY only one of these may be true.
917+
*/
918+
bool non_agg_field_used() const { return m_non_agg_field_used; }
919+
bool agg_func_used() const { return m_agg_func_used; }
920+
921+
void set_non_agg_field_used(bool val) { m_non_agg_field_used= val; }
922+
void set_agg_func_used(bool val) { m_agg_func_used= val; }
923+
924+
private:
925+
bool m_non_agg_field_used;
926+
bool m_agg_func_used;
927+
922928
/* current index hint kind. used in filling up index_hints */
923929
enum index_hint_type current_index_hint_type;
924930
index_clause_map current_index_hint_clause;

sql/sql_partition.cc

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1077,8 +1077,6 @@ static bool fix_fields_part_func(THD *thd, Item* func_expr, TABLE *table,
10771077
int error;
10781078
LEX *old_lex= thd->lex;
10791079
LEX lex;
1080-
uint8 saved_full_group_by_flag;
1081-
nesting_map saved_allow_sum_func;
10821080
DBUG_ENTER("fix_fields_part_func");
10831081

10841082
if (init_lex_with_single_table(thd, table, &lex))
@@ -1103,19 +1101,22 @@ static bool fix_fields_part_func(THD *thd, Item* func_expr, TABLE *table,
11031101
This is a tricky call to prepare for since it can have a large number
11041102
of interesting side effects, both desirable and undesirable.
11051103
*/
1106-
saved_full_group_by_flag= thd->lex->current_select->full_group_by_flag;
1107-
saved_allow_sum_func= thd->lex->allow_sum_func;
1108-
thd->lex->allow_sum_func= 0;
1109-
1110-
error= func_expr->fix_fields(thd, (Item**)&func_expr);
1104+
{
1105+
const bool save_agg_field= thd->lex->current_select->non_agg_field_used();
1106+
const bool save_agg_func= thd->lex->current_select->agg_func_used();
1107+
const nesting_map saved_allow_sum_func= thd->lex->allow_sum_func;
1108+
thd->lex->allow_sum_func= 0;
11111109

1112-
/*
1113-
Restore full_group_by_flag and allow_sum_func,
1114-
fix_fields should not affect mysql_select later, see Bug#46923.
1115-
*/
1116-
thd->lex->current_select->full_group_by_flag= saved_full_group_by_flag;
1117-
thd->lex->allow_sum_func= saved_allow_sum_func;
1110+
error= func_expr->fix_fields(thd, (Item**)&func_expr);
11181111

1112+
/*
1113+
Restore agg_field/agg_func and allow_sum_func,
1114+
fix_fields should not affect mysql_select later, see Bug#46923.
1115+
*/
1116+
thd->lex->current_select->set_non_agg_field_used(save_agg_field);
1117+
thd->lex->current_select->set_agg_func_used(save_agg_func);
1118+
thd->lex->allow_sum_func= saved_allow_sum_func;
1119+
}
11191120
if (unlikely(error))
11201121
{
11211122
DBUG_PRINT("info", ("Field in partition function not part of table"));

sql/sql_priv.h

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -260,13 +260,6 @@ enum enum_yes_no_unknown
260260
#endif /* MYSQL_SERVER */
261261

262262
#ifdef MYSQL_SERVER
263-
/*
264-
A set of constants used for checking non aggregated fields and sum
265-
functions mixture in the ONLY_FULL_GROUP_BY_MODE.
266-
*/
267-
#define NON_AGG_FIELD_USED 1
268-
#define SUM_FUNC_USED 2
269-
270263
/*
271264
External variables
272265
*/

sql/sql_select.cc

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -455,19 +455,18 @@ inline int setup_without_group(THD *thd, Item **ref_pointer_array,
455455
int res;
456456
nesting_map save_allow_sum_func=thd->lex->allow_sum_func ;
457457
/*
458-
Need to save the value, so we can turn off only the new NON_AGG_FIELD
458+
Need to save the value, so we can turn off only any new non_agg_field_used
459459
additions coming from the WHERE
460460
*/
461-
uint8 saved_flag= thd->lex->current_select->full_group_by_flag;
461+
const bool saved_non_agg_field_used=
462+
thd->lex->current_select->non_agg_field_used();
462463
DBUG_ENTER("setup_without_group");
463464

464465
thd->lex->allow_sum_func&= ~(1 << thd->lex->current_select->nest_level);
465466
res= setup_conds(thd, tables, leaves, conds);
466467

467468
/* it's not wrong to have non-aggregated columns in a WHERE */
468-
if (thd->variables.sql_mode & MODE_ONLY_FULL_GROUP_BY)
469-
thd->lex->current_select->full_group_by_flag= saved_flag |
470-
(thd->lex->current_select->full_group_by_flag & ~NON_AGG_FIELD_USED);
469+
thd->lex->current_select->set_non_agg_field_used(saved_non_agg_field_used);
471470

472471
thd->lex->allow_sum_func|= 1 << thd->lex->current_select->nest_level;
473472
res= res || setup_order(thd, ref_pointer_array, tables, fields, all_fields,
@@ -673,7 +672,8 @@ JOIN::prepare(Item ***rref_pointer_array,
673672
aggregate functions with implicit grouping (there is no GROUP BY).
674673
*/
675674
if (thd->variables.sql_mode & MODE_ONLY_FULL_GROUP_BY && !group_list &&
676-
select_lex->full_group_by_flag == (NON_AGG_FIELD_USED | SUM_FUNC_USED))
675+
select_lex->non_agg_field_used() &&
676+
select_lex->agg_func_used())
677677
{
678678
my_message(ER_MIX_OF_GROUP_FUNC_AND_FIELDS,
679679
ER(ER_MIX_OF_GROUP_FUNC_AND_FIELDS), MYF(0));

0 commit comments

Comments
 (0)