diff options
author | Sinisa@sinisa.nasamreza.org <> | 2003-04-21 21:03:32 +0300 |
---|---|---|
committer | Sinisa@sinisa.nasamreza.org <> | 2003-04-21 21:03:32 +0300 |
commit | adb52cfc70b8624dfbf4d36fa966fc20b3b0452d (patch) | |
tree | 7a08a3618a847d9c0596c98295a731eff9e349b0 | |
parent | 8902b739e9243cd82a06ed4e0b75c646af002814 (diff) | |
download | mariadb-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.result | 12 | ||||
-rw-r--r-- | mysql-test/t/innodb.test | 8 | ||||
-rw-r--r-- | sql/sql_lex.cc | 11 | ||||
-rw-r--r-- | sql/sql_lex.h | 4 | ||||
-rw-r--r-- | sql/sql_select.cc | 25 | ||||
-rw-r--r-- | sql/sql_union.cc | 20 |
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 ? |