mirror of
https://github.com/MariaDB/server.git
synced 2025-08-01 03:47:19 +03:00
Fix for a bug record #307.
Very nasty bug. It was caused by double free()-ing memory of join->select and join->quick. I was able to pinpoint it only after using Valgrind. Plus better fix for bug with TMP_TABLE_PARAM. Plus new constructor for SELECT_LEX.
This commit is contained in:
@ -1203,3 +1203,15 @@ a b
|
|||||||
8 5
|
8 5
|
||||||
9 5
|
9 5
|
||||||
drop table t1,t2;
|
drop table t1,t2;
|
||||||
|
CREATE TABLE t1 (col1 int(1))TYPE=InnoDB;
|
||||||
|
CREATE TABLE t2 (col1 int(1),stamp TIMESTAMP(+0),INDEX stamp_idx
|
||||||
|
(stamp))TYPE=InnoDB;
|
||||||
|
insert into t1 values (1),(2),(3);
|
||||||
|
insert into t2 values (1, 20020204130000),(2, 20020204130000),(4,20020204310000 );
|
||||||
|
SELECT col1 FROM t1 UNION SELECT col1 FROM t2 WHERE stamp <
|
||||||
|
'20020204120000' GROUP BY col1;
|
||||||
|
col1
|
||||||
|
1
|
||||||
|
2
|
||||||
|
3
|
||||||
|
drop table t1,t2;
|
||||||
|
@ -805,3 +805,11 @@ select * from t1;
|
|||||||
select * from t2;
|
select * from t2;
|
||||||
|
|
||||||
drop table t1,t2;
|
drop table t1,t2;
|
||||||
|
CREATE TABLE t1 (col1 int(1))TYPE=InnoDB;
|
||||||
|
CREATE TABLE t2 (col1 int(1),stamp TIMESTAMP(+0),INDEX stamp_idx
|
||||||
|
(stamp))TYPE=InnoDB;
|
||||||
|
insert into t1 values (1),(2),(3);
|
||||||
|
insert into t2 values (1, 20020204130000),(2, 20020204130000),(4,20020204310000 );
|
||||||
|
SELECT col1 FROM t1 UNION SELECT col1 FROM t2 WHERE stamp <
|
||||||
|
'20020204120000' GROUP BY col1;
|
||||||
|
drop table t1,t2;
|
||||||
|
@ -1365,6 +1365,17 @@ ulong st_select_lex::get_table_join_options()
|
|||||||
return table_join_options;
|
return table_join_options;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
st_select_lex::st_select_lex(struct st_lex *lex)
|
||||||
|
{
|
||||||
|
select_number= ++lex->thd->select_number;
|
||||||
|
init_query();
|
||||||
|
init_select();
|
||||||
|
include_neighbour(lex->current_select);
|
||||||
|
include_global((st_select_lex_node**)&lex->all_selects_list);
|
||||||
|
lex->current_select= this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
There are st_select_lex::add_table_to_list &
|
There are st_select_lex::add_table_to_list &
|
||||||
st_select_lex::set_lock_for_tables in sql_parse.cc
|
st_select_lex::set_lock_for_tables in sql_parse.cc
|
||||||
|
@ -396,6 +396,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
friend void mysql_init_query(THD *thd);
|
friend void mysql_init_query(THD *thd);
|
||||||
|
st_select_lex(struct st_lex *lex);
|
||||||
|
st_select_lex() {;}
|
||||||
void make_empty_select(st_select_lex *last_select)
|
void make_empty_select(st_select_lex *last_select)
|
||||||
{
|
{
|
||||||
select_number=INT_MAX;
|
select_number=INT_MAX;
|
||||||
@ -478,7 +480,7 @@ typedef struct st_lex
|
|||||||
CHARSET_INFO *charset;
|
CHARSET_INFO *charset;
|
||||||
char *help_arg;
|
char *help_arg;
|
||||||
SQL_LIST *gorder_list;
|
SQL_LIST *gorder_list;
|
||||||
|
st_lex() {;}
|
||||||
inline void uncacheable()
|
inline void uncacheable()
|
||||||
{
|
{
|
||||||
safe_to_cache_query= 0;
|
safe_to_cache_query= 0;
|
||||||
|
@ -1280,10 +1280,19 @@ JOIN::cleanup(THD *thd)
|
|||||||
{
|
{
|
||||||
JOIN_TAB *tab, *end;
|
JOIN_TAB *tab, *end;
|
||||||
for (tab= join_tab, end= tab+tables ; tab != end ; tab++)
|
for (tab= join_tab, end= tab+tables ; tab != end ; tab++)
|
||||||
|
{
|
||||||
|
if (tab->select)
|
||||||
{
|
{
|
||||||
delete tab->select;
|
delete tab->select;
|
||||||
|
tab->select=0;
|
||||||
|
}
|
||||||
|
if (tab->quick)
|
||||||
|
{
|
||||||
delete tab->quick;
|
delete tab->quick;
|
||||||
|
tab->quick=0;
|
||||||
|
}
|
||||||
x_free(tab->cache.buff);
|
x_free(tab->cache.buff);
|
||||||
|
tab->cache.buff= 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tmp_join->tmp_join= 0;
|
tmp_join->tmp_join= 0;
|
||||||
@ -3282,9 +3291,17 @@ join_free(JOIN *join, bool full)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (tab=join->join_tab,end=tab+join->tables ; tab != end ; tab++)
|
for (tab=join->join_tab,end=tab+join->tables ; tab != end ; tab++)
|
||||||
|
{
|
||||||
|
if (tab->select)
|
||||||
{
|
{
|
||||||
delete tab->select;
|
delete tab->select;
|
||||||
|
tab->select=0;
|
||||||
|
}
|
||||||
|
if (tab->quick)
|
||||||
|
{
|
||||||
delete tab->quick;
|
delete tab->quick;
|
||||||
|
tab->quick=0;
|
||||||
|
}
|
||||||
x_free(tab->cache.buff);
|
x_free(tab->cache.buff);
|
||||||
tab->cache.buff= 0;
|
tab->cache.buff= 0;
|
||||||
if (tab->table)
|
if (tab->table)
|
||||||
|
@ -124,10 +124,11 @@ int st_select_lex_unit::prepare(THD *thd, select_result *sel_result,
|
|||||||
prepared= 1;
|
prepared= 1;
|
||||||
res= 0;
|
res= 0;
|
||||||
found_rows_for_union= 0;
|
found_rows_for_union= 0;
|
||||||
TMP_TABLE_PARAM *tmp_table_param= (TMP_TABLE_PARAM *)sql_calloc(sizeof(TMP_TABLE_PARAM));
|
TMP_TABLE_PARAM tmp_table_param;
|
||||||
result= sel_result;
|
result= sel_result;
|
||||||
t_and_f= tables_and_fields_initied;
|
t_and_f= tables_and_fields_initied;
|
||||||
|
|
||||||
|
bzero((char *)&tmp_table_param,sizeof(TMP_TABLE_PARAM));
|
||||||
thd->lex.current_select= select_cursor= first_select_in_union();
|
thd->lex.current_select= select_cursor= first_select_in_union();
|
||||||
/* Global option */
|
/* Global option */
|
||||||
if (((void*)(global_parameters)) == ((void*)this))
|
if (((void*)(global_parameters)) == ((void*)this))
|
||||||
@ -167,8 +168,8 @@ int st_select_lex_unit::prepare(THD *thd, select_result *sel_result,
|
|||||||
t_and_f= 1;
|
t_and_f= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
tmp_table_param->field_count=item_list.elements;
|
tmp_table_param.field_count=item_list.elements;
|
||||||
if (!(table= create_tmp_table(thd, tmp_table_param, item_list,
|
if (!(table= create_tmp_table(thd, &tmp_table_param, item_list,
|
||||||
(ORDER*) 0, !union_option,
|
(ORDER*) 0, !union_option,
|
||||||
1, (select_cursor->options | thd->options |
|
1, (select_cursor->options | thd->options |
|
||||||
TMP_TABLE_ALL_COLUMNS),
|
TMP_TABLE_ALL_COLUMNS),
|
||||||
@ -185,7 +186,8 @@ int st_select_lex_unit::prepare(THD *thd, select_result *sel_result,
|
|||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
union_result->not_describe=1;
|
union_result->not_describe=1;
|
||||||
union_result->tmp_table_param=tmp_table_param;
|
if (!(union_result->tmp_table_param=(TMP_TABLE_PARAM *)thd->memdup((char *)&tmp_table_param, sizeof(TMP_TABLE_PARAM))))
|
||||||
|
goto err;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The following piece of code is placed here solely for the purpose of
|
The following piece of code is placed here solely for the purpose of
|
||||||
@ -250,11 +252,9 @@ int st_select_lex_unit::exec()
|
|||||||
{
|
{
|
||||||
int do_print_slow= 0;
|
int do_print_slow= 0;
|
||||||
SELECT_LEX_NODE *lex_select_save= thd->lex.current_select;
|
SELECT_LEX_NODE *lex_select_save= thd->lex.current_select;
|
||||||
SELECT_LEX *select_cursor=first_select_in_union(), *last_select;
|
SELECT_LEX *select_cursor=first_select_in_union();
|
||||||
DBUG_ENTER("st_select_lex_unit::exec");
|
DBUG_ENTER("st_select_lex_unit::exec");
|
||||||
|
|
||||||
LINT_INIT(last_select);
|
|
||||||
|
|
||||||
if (executed && !(dependent || uncacheable))
|
if (executed && !(dependent || uncacheable))
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
executed= 1;
|
executed= 1;
|
||||||
@ -269,7 +269,6 @@ int st_select_lex_unit::exec()
|
|||||||
}
|
}
|
||||||
for (SELECT_LEX *sl= select_cursor; sl; sl= sl->next_select())
|
for (SELECT_LEX *sl= select_cursor; sl; sl= sl->next_select())
|
||||||
{
|
{
|
||||||
last_select=sl;
|
|
||||||
if (optimized)
|
if (optimized)
|
||||||
res= sl->join->reinit();
|
res= sl->join->reinit();
|
||||||
else
|
else
|
||||||
@ -335,8 +334,7 @@ int st_select_lex_unit::exec()
|
|||||||
|
|
||||||
if (!thd->is_fatal_error) // Check if EOM
|
if (!thd->is_fatal_error) // Check if EOM
|
||||||
{
|
{
|
||||||
SELECT_LEX *fake_select = new SELECT_LEX();
|
SELECT_LEX *fake_select = new SELECT_LEX(&thd->lex);
|
||||||
fake_select->make_empty_select(last_select);
|
|
||||||
offset_limit_cnt= (select_cursor->braces ?
|
offset_limit_cnt= (select_cursor->braces ?
|
||||||
global_parameters->offset_limit : 0);
|
global_parameters->offset_limit : 0);
|
||||||
select_limit_cnt= (select_cursor->braces ?
|
select_limit_cnt= (select_cursor->braces ?
|
||||||
|
Reference in New Issue
Block a user