summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSinisa@sinisa.nasamreza.org <>2003-04-21 21:03:32 +0300
committerSinisa@sinisa.nasamreza.org <>2003-04-21 21:03:32 +0300
commitadb52cfc70b8624dfbf4d36fa966fc20b3b0452d (patch)
tree7a08a3618a847d9c0596c98295a731eff9e349b0
parent8902b739e9243cd82a06ed4e0b75c646af002814 (diff)
downloadmariadb-git-adb52cfc70b8624dfbf4d36fa966fc20b3b0452d.tar.gz
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.
-rw-r--r--mysql-test/r/innodb.result12
-rw-r--r--mysql-test/t/innodb.test8
-rw-r--r--sql/sql_lex.cc11
-rw-r--r--sql/sql_lex.h4
-rw-r--r--sql/sql_select.cc25
-rw-r--r--sql/sql_union.cc20
6 files changed, 64 insertions, 16 deletions
diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result
index 52b6fc307ae..765f6050466 100644
--- a/mysql-test/r/innodb.result
+++ b/mysql-test/r/innodb.result
@@ -1203,3 +1203,15 @@ a b
8 5
9 5
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;
diff --git a/mysql-test/t/innodb.test b/mysql-test/t/innodb.test
index 4d1a620d67f..9773d1ec17c 100644
--- a/mysql-test/t/innodb.test
+++ b/mysql-test/t/innodb.test
@@ -805,3 +805,11 @@ select * from t1;
select * from 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;
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index d5d438fc3a1..ec77668c968 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -1365,6 +1365,17 @@ ulong st_select_lex::get_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 &
st_select_lex::set_lock_for_tables in sql_parse.cc
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 9fb0f8cfdf5..97cf19454ae 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -396,6 +396,8 @@ public:
}
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)
{
select_number=INT_MAX;
@@ -478,7 +480,7 @@ typedef struct st_lex
CHARSET_INFO *charset;
char *help_arg;
SQL_LIST *gorder_list;
-
+ st_lex() {;}
inline void uncacheable()
{
safe_to_cache_query= 0;
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 3fdff4e96a4..bf17497fa19 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -1281,9 +1281,18 @@ JOIN::cleanup(THD *thd)
JOIN_TAB *tab, *end;
for (tab= join_tab, end= tab+tables ; tab != end ; tab++)
{
- delete tab->select;
- delete tab->quick;
+ if (tab->select)
+ {
+ delete tab->select;
+ tab->select=0;
+ }
+ if (tab->quick)
+ {
+ delete tab->quick;
+ tab->quick=0;
+ }
x_free(tab->cache.buff);
+ tab->cache.buff= 0;
}
}
tmp_join->tmp_join= 0;
@@ -3283,8 +3292,16 @@ join_free(JOIN *join, bool full)
{
for (tab=join->join_tab,end=tab+join->tables ; tab != end ; tab++)
{
- delete tab->select;
- delete tab->quick;
+ if (tab->select)
+ {
+ delete tab->select;
+ tab->select=0;
+ }
+ if (tab->quick)
+ {
+ delete tab->quick;
+ tab->quick=0;
+ }
x_free(tab->cache.buff);
tab->cache.buff= 0;
if (tab->table)
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index 594eac2c942..48f536c68cf 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -124,10 +124,11 @@ int st_select_lex_unit::prepare(THD *thd, select_result *sel_result,
prepared= 1;
res= 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;
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();
/* Global option */
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;
}
- tmp_table_param->field_count=item_list.elements;
- if (!(table= create_tmp_table(thd, tmp_table_param, item_list,
+ tmp_table_param.field_count=item_list.elements;
+ if (!(table= create_tmp_table(thd, &tmp_table_param, item_list,
(ORDER*) 0, !union_option,
1, (select_cursor->options | thd->options |
TMP_TABLE_ALL_COLUMNS),
@@ -185,7 +186,8 @@ int st_select_lex_unit::prepare(THD *thd, select_result *sel_result,
goto err;
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
@@ -250,11 +252,9 @@ int st_select_lex_unit::exec()
{
int do_print_slow= 0;
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");
- LINT_INIT(last_select);
-
if (executed && !(dependent || uncacheable))
DBUG_RETURN(0);
executed= 1;
@@ -269,7 +269,6 @@ int st_select_lex_unit::exec()
}
for (SELECT_LEX *sl= select_cursor; sl; sl= sl->next_select())
{
- last_select=sl;
if (optimized)
res= sl->join->reinit();
else
@@ -335,8 +334,7 @@ int st_select_lex_unit::exec()
if (!thd->is_fatal_error) // Check if EOM
{
- SELECT_LEX *fake_select = new SELECT_LEX();
- fake_select->make_empty_select(last_select);
+ SELECT_LEX *fake_select = new SELECT_LEX(&thd->lex);
offset_limit_cnt= (select_cursor->braces ?
global_parameters->offset_limit : 0);
select_limit_cnt= (select_cursor->braces ?