Commit acda3d79 authored by unknown's avatar unknown

fixed memory overrun (bug 380)


mysql-test/r/func_group.result:
  new tests
mysql-test/t/func_group.test:
  new tests
sql/item.cc:
  count items in select list
sql/item_subselect.cc:
  use number of item in select list for array creation
sql/item_sum.cc:
  with_sum_func now is boolean
sql/sql_derived.cc:
  use number of item in select list for array creation
sql/sql_lex.cc:
  create_refs changed with parsing_place enum variable
sql/sql_lex.h:
  added items in select list counter
  create_refs changed with parsing_place enum variable
  with_sum_func now is boolean
sql/sql_select.cc:
  use number of item in select list for array creation
sql/sql_union.cc:
  use number of item in select list for array creation
sql/sql_yacc.yy:
  create_refs changed with parsing_place enum variable
parent ddabd51c
...@@ -561,4 +561,13 @@ select concat(min(t1.a1),min(t2.a4)) from t1, t2 where t2.a4 <> 'AME'; ...@@ -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 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 t1 index NULL PRIMARY 3 NULL 14 Using index
1 SIMPLE t2 index NULL k2 4 NULL 6 Using where; 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;
...@@ -326,6 +326,11 @@ explain ...@@ -326,6 +326,11 @@ explain
select min(a4) from t1 where (a4 + 0.01) between 0.07 and 0.08; select min(a4) from t1 where (a4 + 0.01) between 0.07 and 0.08;
explain explain
select concat(min(t1.a1),min(t2.a4)) from t1, t2 where t2.a4 <> 'AME'; 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
...@@ -46,6 +46,8 @@ Item::Item(): ...@@ -46,6 +46,8 @@ Item::Item():
next= thd->free_list; // Put in free list next= thd->free_list; // Put in free list
thd->free_list= this; thd->free_list= this;
loop_id= 0; loop_id= 0;
if (thd->lex.current_select->parsing_place == SELECT_LEX_NODE::SELECT_LIST)
thd->lex.current_select->select_items++;
} }
/* /*
......
...@@ -492,7 +492,7 @@ void Item_in_subselect::single_value_transformer(THD *thd, ...@@ -492,7 +492,7 @@ void Item_in_subselect::single_value_transformer(THD *thd,
{ {
sl->item_list.push_back(item); sl->item_list.push_back(item);
setup_ref_array(thd, &sl->ref_pointer_array, 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); sl->order_list.elements + sl->group_list.elements);
// To prevent crash on Item_ref_null_helper destruction in case of error // To prevent crash on Item_ref_null_helper destruction in case of error
sl->ref_pointer_array[0]= 0; sl->ref_pointer_array[0]= 0;
......
...@@ -57,8 +57,7 @@ Item_sum::Item_sum(THD *thd, Item_sum &item): ...@@ -57,8 +57,7 @@ Item_sum::Item_sum(THD *thd, Item_sum &item):
void Item_sum::mark_as_sum_func() void Item_sum::mark_as_sum_func()
{ {
current_thd->lex.current_select->with_sum_func++; current_thd->lex.current_select->with_sum_func= with_sum_func= 1;
with_sum_func= 1;
} }
......
...@@ -125,7 +125,7 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, ...@@ -125,7 +125,7 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit,
item_list= select_cursor->item_list; item_list= select_cursor->item_list;
select_cursor->with_wild= 0; select_cursor->with_wild= 0;
if (setup_ref_array(thd, &select_cursor->ref_pointer_array, 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->order_list.elements +
select_cursor->group_list.elements)) || select_cursor->group_list.elements)) ||
setup_fields(thd, select_cursor->ref_pointer_array, first_table, item_list, setup_fields(thd, select_cursor->ref_pointer_array, first_table, item_list,
......
...@@ -111,7 +111,8 @@ LEX *lex_start(THD *thd, uchar *buf,uint length) ...@@ -111,7 +111,8 @@ LEX *lex_start(THD *thd, uchar *buf,uint length)
lex->next_state=MY_LEX_START; lex->next_state=MY_LEX_START;
lex->end_of_query=(lex->ptr=buf)+length; lex->end_of_query=(lex->ptr=buf)+length;
lex->yylineno = 1; 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->length=0;
lex->select_lex.in_sum_expr=0; lex->select_lex.in_sum_expr=0;
lex->select_lex.expr_list.empty(); lex->select_lex.expr_list.empty();
...@@ -973,8 +974,9 @@ void st_select_lex_node::init_select() ...@@ -973,8 +974,9 @@ void st_select_lex_node::init_select()
order_list.next= (byte**) &order_list.first; order_list.next= (byte**) &order_list.first;
select_limit= HA_POS_ERROR; select_limit= HA_POS_ERROR;
offset_limit= 0; offset_limit= 0;
select_items= 0;
with_sum_func= 0; with_sum_func= 0;
create_refs= 0; parsing_place= SELECT_LEX_NODE::NO_MATTER;
} }
void st_select_lex_unit::init_query() void st_select_lex_unit::init_query()
......
...@@ -77,7 +77,6 @@ enum enum_sql_command { ...@@ -77,7 +77,6 @@ enum enum_sql_command {
SQLCOM_END SQLCOM_END
}; };
typedef List<Item> List_item; typedef List<Item> List_item;
typedef struct st_lex_master_info typedef struct st_lex_master_info
...@@ -191,6 +190,13 @@ protected: ...@@ -191,6 +190,13 @@ protected:
*master, *slave, /* vertical links */ *master, *slave, /* vertical links */
*link_next, **link_prev; /* list of whole SELECT_LEX */ *link_next, **link_prev; /* list of whole SELECT_LEX */
public: public:
enum enum_parsing_place
{
NO_MATTER,
IN_HAVING,
SELECT_LIST
};
ulong options; ulong options;
enum sub_select_type linkage; enum sub_select_type linkage;
SQL_LIST order_list; /* ORDER clause */ SQL_LIST order_list; /* ORDER clause */
...@@ -200,8 +206,9 @@ public: ...@@ -200,8 +206,9 @@ public:
// Arrays of pointers to top elements of all_fields list // Arrays of pointers to top elements of all_fields list
Item **ref_pointer_array; Item **ref_pointer_array;
uint with_sum_func; /* sum function indicator and number of it */ uint select_items; /* number of items in select_list */
bool create_refs; 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 dependent; /* dependent from outer select subselect */
bool uncacheable; /* result of this query can't be cached */ bool uncacheable; /* result of this query can't be cached */
bool no_table_names_allowed; /* used for global order by */ bool no_table_names_allowed; /* used for global order by */
......
...@@ -289,7 +289,7 @@ JOIN::prepare(Item ***rref_pointer_array, ...@@ -289,7 +289,7 @@ JOIN::prepare(Item ***rref_pointer_array,
fields_list, fields_list,
&all_fields, wild_num))) || &all_fields, wild_num))) ||
setup_ref_array(thd, rref_pointer_array, (fields_list.elements + setup_ref_array(thd, rref_pointer_array, (fields_list.elements +
select_lex->with_sum_func + select_lex->select_items +
og_num)) || og_num)) ||
setup_fields(thd, (*rref_pointer_array), tables_list, fields_list, 1, setup_fields(thd, (*rref_pointer_array), tables_list, fields_list, 1,
&all_fields, 1) || &all_fields, 1) ||
......
...@@ -159,7 +159,7 @@ int st_select_lex_unit::prepare(THD *thd, select_result *sel_result, ...@@ -159,7 +159,7 @@ int st_select_lex_unit::prepare(THD *thd, select_result *sel_result,
item_list= select_cursor->item_list; item_list= select_cursor->item_list;
select_cursor->with_wild= 0; select_cursor->with_wild= 0;
if (setup_ref_array(thd, &select_cursor->ref_pointer_array, 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->order_list.elements +
select_cursor->group_list.elements)) || select_cursor->group_list.elements)) ||
setup_fields(thd, select_cursor->ref_pointer_array, first_table, setup_fields(thd, select_cursor->ref_pointer_array, first_table,
......
...@@ -925,8 +925,13 @@ create3: ...@@ -925,8 +925,13 @@ create3:
LEX *lex=Lex; LEX *lex=Lex;
lex->lock_option= (using_update_log) ? TL_READ_NO_INSERT : TL_READ; lex->lock_option= (using_update_log) ? TL_READ_NO_INSERT : TL_READ;
mysql_init_select(lex); 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: opt_as:
...@@ -1883,8 +1888,13 @@ select_part2: ...@@ -1883,8 +1888,13 @@ select_part2:
lex->lock_option= TL_READ; /* Only for global SELECT */ lex->lock_option= TL_READ; /* Only for global SELECT */
if (sel->linkage != UNION_TYPE) if (sel->linkage != UNION_TYPE)
mysql_init_select(lex); 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: select_into:
opt_limit_clause {} opt_limit_clause {}
...@@ -2917,10 +2927,15 @@ where_clause: ...@@ -2917,10 +2927,15 @@ where_clause:
having_clause: having_clause:
/* empty */ /* 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(); 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) if ($3)
$3->top_level_item(); $3->top_level_item();
} }
...@@ -3348,8 +3363,13 @@ insert_values: ...@@ -3348,8 +3363,13 @@ insert_values:
SQLCOM_INSERT_SELECT : SQLCOM_REPLACE_SELECT); SQLCOM_INSERT_SELECT : SQLCOM_REPLACE_SELECT);
lex->lock_option= (using_update_log) ? TL_READ_NO_INSERT : TL_READ; lex->lock_option= (using_update_log) ? TL_READ_NO_INSERT : TL_READ;
mysql_init_select(lex); 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 {} union_clause {}
; ;
...@@ -4030,7 +4050,10 @@ simple_ident: ...@@ -4030,7 +4050,10 @@ simple_ident:
ident ident
{ {
SELECT_LEX_NODE *sel=Select; 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 | ident '.' ident
{ {
...@@ -4043,7 +4066,10 @@ simple_ident: ...@@ -4043,7 +4066,10 @@ simple_ident:
ER(ER_TABLENAME_NOT_ALLOWED_HERE), ER(ER_TABLENAME_NOT_ALLOWED_HERE),
MYF(0), $1.str, thd->where); 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 | '.' ident '.' ident
{ {
...@@ -4056,7 +4082,10 @@ simple_ident: ...@@ -4056,7 +4082,10 @@ simple_ident:
ER(ER_TABLENAME_NOT_ALLOWED_HERE), ER(ER_TABLENAME_NOT_ALLOWED_HERE),
MYF(0), $2.str, thd->where); 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 | ident '.' ident '.' ident
{ {
...@@ -4069,7 +4098,14 @@ simple_ident: ...@@ -4069,7 +4098,14 @@ simple_ident:
ER(ER_TABLENAME_NOT_ALLOWED_HERE), ER(ER_TABLENAME_NOT_ALLOWED_HERE),
MYF(0), $3.str, thd->where); 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);
}; };
......
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