diff options
-rw-r--r-- | mysql-test/r/func_group.result | 11 | ||||
-rw-r--r-- | mysql-test/t/func_group.test | 9 | ||||
-rw-r--r-- | sql/item.cc | 2 | ||||
-rw-r--r-- | sql/item_subselect.cc | 2 | ||||
-rw-r--r-- | sql/item_sum.cc | 3 | ||||
-rw-r--r-- | sql/sql_derived.cc | 2 | ||||
-rw-r--r-- | sql/sql_lex.cc | 6 | ||||
-rw-r--r-- | sql/sql_lex.h | 13 | ||||
-rw-r--r-- | sql/sql_select.cc | 2 | ||||
-rw-r--r-- | sql/sql_union.cc | 2 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 54 |
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); }; |