summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/func_group.result11
-rw-r--r--mysql-test/t/func_group.test9
-rw-r--r--sql/item.cc2
-rw-r--r--sql/item_subselect.cc2
-rw-r--r--sql/item_sum.cc3
-rw-r--r--sql/sql_derived.cc2
-rw-r--r--sql/sql_lex.cc6
-rw-r--r--sql/sql_lex.h13
-rw-r--r--sql/sql_select.cc2
-rw-r--r--sql/sql_union.cc2
-rw-r--r--sql/sql_yacc.yy54
11 files changed, 83 insertions, 23 deletions
diff --git a/mysql-test/r/func_group.result b/mysql-test/r/func_group.result
index b7bf3a5cd80..9e1fa4ff67c 100644
--- a/mysql-test/r/func_group.result
+++ b/mysql-test/r/func_group.result
@@ -561,4 +561,13 @@ select concat(min(t1.a1),min(t2.a4)) from t1, t2 where t2.a4 <> 'AME';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index NULL PRIMARY 3 NULL 14 Using index
1 SIMPLE t2 index NULL k2 4 NULL 6 Using where; Using index
-drop table if exists t1, t2;
+drop table t1, t2;
+create table t1 (USR_ID integer not null, MAX_REQ integer not null, constraint PK_SEA_USER primary key (USR_ID)) type=InnoDB;
+insert into t1 values (1, 3);
+select count(*) + MAX_REQ - MAX_REQ + MAX_REQ - MAX_REQ + MAX_REQ - MAX_REQ + MAX_REQ - MAX_REQ + MAX_REQ - MAX_REQ from t1 group by MAX_REQ;
+count(*) + MAX_REQ - MAX_REQ + MAX_REQ - MAX_REQ + MAX_REQ - MAX_REQ + MAX_REQ - MAX_REQ + MAX_REQ - MAX_REQ
+1
+select Case When Count(*) < MAX_REQ Then 1 Else 0 End from t1 where t1.USR_ID = 1 group by MAX_REQ;
+Case When Count(*) < MAX_REQ Then 1 Else 0 End
+1
+drop table t1;
diff --git a/mysql-test/t/func_group.test b/mysql-test/t/func_group.test
index c78509d3869..659032c431b 100644
--- a/mysql-test/t/func_group.test
+++ b/mysql-test/t/func_group.test
@@ -326,6 +326,11 @@ explain
select min(a4) from t1 where (a4 + 0.01) between 0.07 and 0.08;
explain
select concat(min(t1.a1),min(t2.a4)) from t1, t2 where t2.a4 <> 'AME';
+drop table t1, t2;
+
+create table t1 (USR_ID integer not null, MAX_REQ integer not null, constraint PK_SEA_USER primary key (USR_ID)) type=InnoDB;
+insert into t1 values (1, 3);
+select count(*) + MAX_REQ - MAX_REQ + MAX_REQ - MAX_REQ + MAX_REQ - MAX_REQ + MAX_REQ - MAX_REQ + MAX_REQ - MAX_REQ from t1 group by MAX_REQ;
+select Case When Count(*) < MAX_REQ Then 1 Else 0 End from t1 where t1.USR_ID = 1 group by MAX_REQ;
+drop table t1;
-# Clean up
-drop table if exists t1, t2; \ No newline at end of file
diff --git a/sql/item.cc b/sql/item.cc
index 053a94cb695..0a885edec2a 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -46,6 +46,8 @@ Item::Item():
next= thd->free_list; // Put in free list
thd->free_list= this;
loop_id= 0;
+ if (thd->lex.current_select->parsing_place == SELECT_LEX_NODE::SELECT_LIST)
+ thd->lex.current_select->select_items++;
}
/*
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index c749fba616f..e7a2c6e7f24 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -492,7 +492,7 @@ void Item_in_subselect::single_value_transformer(THD *thd,
{
sl->item_list.push_back(item);
setup_ref_array(thd, &sl->ref_pointer_array,
- 1 + sl->with_sum_func +
+ 1 + sl->select_items +
sl->order_list.elements + sl->group_list.elements);
// To prevent crash on Item_ref_null_helper destruction in case of error
sl->ref_pointer_array[0]= 0;
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index 11c850f9d5f..631c5cf9a0e 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -57,8 +57,7 @@ Item_sum::Item_sum(THD *thd, Item_sum &item):
void Item_sum::mark_as_sum_func()
{
- current_thd->lex.current_select->with_sum_func++;
- with_sum_func= 1;
+ current_thd->lex.current_select->with_sum_func= with_sum_func= 1;
}
diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc
index 7f555f37d40..4ede6462058 100644
--- a/sql/sql_derived.cc
+++ b/sql/sql_derived.cc
@@ -125,7 +125,7 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit,
item_list= select_cursor->item_list;
select_cursor->with_wild= 0;
if (setup_ref_array(thd, &select_cursor->ref_pointer_array,
- (item_list.elements + select_cursor->with_sum_func +
+ (item_list.elements + select_cursor->select_items +
select_cursor->order_list.elements +
select_cursor->group_list.elements)) ||
setup_fields(thd, select_cursor->ref_pointer_array, first_table, item_list,
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 9bc4dfc74e7..c61149b8313 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -111,7 +111,8 @@ LEX *lex_start(THD *thd, uchar *buf,uint length)
lex->next_state=MY_LEX_START;
lex->end_of_query=(lex->ptr=buf)+length;
lex->yylineno = 1;
- lex->select_lex.create_refs=lex->in_comment=0;
+ lex->select_lex.parsing_place= SELECT_LEX_NODE::NO_MATTER;
+ lex->in_comment=0;
lex->length=0;
lex->select_lex.in_sum_expr=0;
lex->select_lex.expr_list.empty();
@@ -973,8 +974,9 @@ void st_select_lex_node::init_select()
order_list.next= (byte**) &order_list.first;
select_limit= HA_POS_ERROR;
offset_limit= 0;
+ select_items= 0;
with_sum_func= 0;
- create_refs= 0;
+ parsing_place= SELECT_LEX_NODE::NO_MATTER;
}
void st_select_lex_unit::init_query()
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index f31b3305e07..b4444c03280 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -77,7 +77,6 @@ enum enum_sql_command {
SQLCOM_END
};
-
typedef List<Item> List_item;
typedef struct st_lex_master_info
@@ -191,6 +190,13 @@ protected:
*master, *slave, /* vertical links */
*link_next, **link_prev; /* list of whole SELECT_LEX */
public:
+ enum enum_parsing_place
+ {
+ NO_MATTER,
+ IN_HAVING,
+ SELECT_LIST
+ };
+
ulong options;
enum sub_select_type linkage;
SQL_LIST order_list; /* ORDER clause */
@@ -200,8 +206,9 @@ public:
// Arrays of pointers to top elements of all_fields list
Item **ref_pointer_array;
- uint with_sum_func; /* sum function indicator and number of it */
- bool create_refs;
+ uint select_items; /* number of items in select_list */
+ enum_parsing_place parsing_place; /* where we are parsing expression */
+ bool with_sum_func; /* sum function indicator */
bool dependent; /* dependent from outer select subselect */
bool uncacheable; /* result of this query can't be cached */
bool no_table_names_allowed; /* used for global order by */
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 85ebb9f207f..bee41cee346 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -289,7 +289,7 @@ JOIN::prepare(Item ***rref_pointer_array,
fields_list,
&all_fields, wild_num))) ||
setup_ref_array(thd, rref_pointer_array, (fields_list.elements +
- select_lex->with_sum_func +
+ select_lex->select_items +
og_num)) ||
setup_fields(thd, (*rref_pointer_array), tables_list, fields_list, 1,
&all_fields, 1) ||
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index fe4ca49da14..df50e98c2c4 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -159,7 +159,7 @@ int st_select_lex_unit::prepare(THD *thd, select_result *sel_result,
item_list= select_cursor->item_list;
select_cursor->with_wild= 0;
if (setup_ref_array(thd, &select_cursor->ref_pointer_array,
- (item_list.elements + select_cursor->with_sum_func +
+ (item_list.elements + select_cursor->select_items +
select_cursor->order_list.elements +
select_cursor->group_list.elements)) ||
setup_fields(thd, select_cursor->ref_pointer_array, first_table,
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index ad60270ccb3..12482d98220 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -925,8 +925,13 @@ create3:
LEX *lex=Lex;
lex->lock_option= (using_update_log) ? TL_READ_NO_INSERT : TL_READ;
mysql_init_select(lex);
+ lex->current_select->parsing_place= SELECT_LEX_NODE::SELECT_LIST;
}
- select_options select_item_list opt_select_from union_clause {}
+ select_options select_item_list
+ {
+ Select->parsing_place= SELECT_LEX_NODE::NO_MATTER;
+ }
+ opt_select_from union_clause {}
;
opt_as:
@@ -1883,8 +1888,13 @@ select_part2:
lex->lock_option= TL_READ; /* Only for global SELECT */
if (sel->linkage != UNION_TYPE)
mysql_init_select(lex);
+ lex->current_select->parsing_place= SELECT_LEX_NODE::SELECT_LIST;
+ }
+ select_options select_item_list
+ {
+ Select->parsing_place= SELECT_LEX_NODE::NO_MATTER;
}
- select_options select_item_list select_into select_lock_type;
+ select_into select_lock_type;
select_into:
opt_limit_clause {}
@@ -2917,10 +2927,15 @@ where_clause:
having_clause:
/* empty */
- | HAVING { Select->select_lex()->create_refs= 1; } expr
+ | HAVING
+ {
+ Select->select_lex()->parsing_place= SELECT_LEX_NODE::IN_HAVING;
+ }
+ expr
{
SELECT_LEX *sel= Select->select_lex();
- sel->having= $3; sel->create_refs=0;
+ sel->having= $3;
+ sel->parsing_place= SELECT_LEX_NODE::NO_MATTER;
if ($3)
$3->top_level_item();
}
@@ -3348,8 +3363,13 @@ insert_values:
SQLCOM_INSERT_SELECT : SQLCOM_REPLACE_SELECT);
lex->lock_option= (using_update_log) ? TL_READ_NO_INSERT : TL_READ;
mysql_init_select(lex);
+ lex->current_select->parsing_place= SELECT_LEX_NODE::SELECT_LIST;
+ }
+ select_options select_item_list
+ {
+ Select->parsing_place= SELECT_LEX_NODE::NO_MATTER;
}
- select_options select_item_list opt_select_from select_lock_type
+ opt_select_from select_lock_type
union_clause {}
;
@@ -4030,7 +4050,10 @@ simple_ident:
ident
{
SELECT_LEX_NODE *sel=Select;
- $$ = !sel->create_refs || sel->get_in_sum_expr() > 0 ? (Item*) new Item_field(NullS,NullS,$1.str) : (Item*) new Item_ref(NullS,NullS,$1.str);
+ $$= (sel->parsing_place != SELECT_LEX_NODE::IN_HAVING ||
+ sel->get_in_sum_expr() > 0) ?
+ (Item*) new Item_field(NullS,NullS,$1.str) :
+ (Item*) new Item_ref(NullS,NullS,$1.str);
}
| ident '.' ident
{
@@ -4043,7 +4066,10 @@ simple_ident:
ER(ER_TABLENAME_NOT_ALLOWED_HERE),
MYF(0), $1.str, thd->where);
}
- $$ = !sel->create_refs || sel->get_in_sum_expr() > 0 ? (Item*) new Item_field(NullS,$1.str,$3.str) : (Item*) new Item_ref(NullS,$1.str,$3.str);
+ $$= (sel->parsing_place != SELECT_LEX_NODE::IN_HAVING ||
+ sel->get_in_sum_expr() > 0) ?
+ (Item*) new Item_field(NullS,$1.str,$3.str) :
+ (Item*) new Item_ref(NullS,$1.str,$3.str);
}
| '.' ident '.' ident
{
@@ -4056,7 +4082,10 @@ simple_ident:
ER(ER_TABLENAME_NOT_ALLOWED_HERE),
MYF(0), $2.str, thd->where);
}
- $$ = !sel->create_refs || sel->get_in_sum_expr() > 0 ? (Item*) new Item_field(NullS,$2.str,$4.str) : (Item*) new Item_ref(NullS,$2.str,$4.str);
+ $$= (sel->parsing_place != SELECT_LEX_NODE::IN_HAVING ||
+ sel->get_in_sum_expr() > 0) ?
+ (Item*) new Item_field(NullS,$2.str,$4.str) :
+ (Item*) new Item_ref(NullS,$2.str,$4.str);
}
| ident '.' ident '.' ident
{
@@ -4069,7 +4098,14 @@ simple_ident:
ER(ER_TABLENAME_NOT_ALLOWED_HERE),
MYF(0), $3.str, thd->where);
}
- $$ = !sel->create_refs || sel->get_in_sum_expr() > 0 ? (Item*) new Item_field((YYTHD->client_capabilities & CLIENT_NO_SCHEMA ? NullS :$1.str),$3.str,$5.str) : (Item*) new Item_ref((YYTHD->client_capabilities & CLIENT_NO_SCHEMA ? NullS :$1.str),$3.str,$5.str);
+ $$= (sel->parsing_place != SELECT_LEX_NODE::IN_HAVING ||
+ sel->get_in_sum_expr() > 0) ?
+ (Item*) new Item_field((YYTHD->client_capabilities &
+ CLIENT_NO_SCHEMA ? NullS : $1.str),
+ $3.str, $5.str) :
+ (Item*) new Item_ref((YYTHD->client_capabilities &
+ CLIENT_NO_SCHEMA ? NullS : $1.str),
+ $3.str, $5.str);
};