From a100c0e951cd4e2db8efbc385883e408fa164ee9 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 28 May 2003 16:52:56 +0300 Subject: added mem_root switching for subselect if it is necessary (bug #518 fixed) mysql-test/r/subselect.result: test of bug #518 mysql-test/t/subselect.test: test of bug #518 sql/item_subselect.cc: test and switch mem_root if it is necessary exec() - wrapper around engine->exec() to test and switch mem_root if necessary sql/item_subselect.h: added storing THD for mem_root testinmg & switching exec() - wrapper around engine->exec() to test and switch mem_root if necessary --- mysql-test/r/subselect.result | 14 ++++++++++++++ mysql-test/t/subselect.test | 14 ++++++++++++++ sql/item_subselect.cc | 38 +++++++++++++++++++++++++++----------- sql/item_subselect.h | 3 +++ 4 files changed, 58 insertions(+), 11 deletions(-) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 41620bb6e7f..511517ebdfd 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -1134,3 +1134,17 @@ id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY t1 ref salary salary 5 const 1 Using where 2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL Select tables optimized away drop table t1; +CREATE TABLE t1 ( +ID int(10) unsigned NOT NULL auto_increment, +SUB_ID int(3) unsigned NOT NULL default '0', +REF_ID int(10) unsigned default NULL, +REF_SUB int(3) unsigned default '0', +PRIMARY KEY (ID,SUB_ID), +UNIQUE KEY t1_PK (ID,SUB_ID), +KEY t1_FK (REF_ID,REF_SUB), +KEY t1_REFID (REF_ID) +) TYPE=MyISAM CHARSET=cp1251; +INSERT INTO t1 VALUES (1,0,NULL,NULL),(2,0,NULL,NULL); +SELECT DISTINCT REF_ID FROM t1 WHERE ID= (SELECT DISTINCT REF_ID FROM t1 WHERE ID=2); +REF_ID +DROP TABLE t1; diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 8377a756c5b..e47409046cd 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -716,3 +716,17 @@ create table t1 (id int not null auto_increment primary key, salary int, key(sal insert into t1 (salary) values (100),(1000),(10000),(10),(500),(5000),(50000); explain SELECT id FROM t1 where salary = (SELECT MAX(salary) FROM t1); drop table t1; + +CREATE TABLE t1 ( + ID int(10) unsigned NOT NULL auto_increment, + SUB_ID int(3) unsigned NOT NULL default '0', + REF_ID int(10) unsigned default NULL, + REF_SUB int(3) unsigned default '0', + PRIMARY KEY (ID,SUB_ID), + UNIQUE KEY t1_PK (ID,SUB_ID), + KEY t1_FK (REF_ID,REF_SUB), + KEY t1_REFID (REF_ID) +) TYPE=MyISAM CHARSET=cp1251; +INSERT INTO t1 VALUES (1,0,NULL,NULL),(2,0,NULL,NULL); +SELECT DISTINCT REF_ID FROM t1 WHERE ID= (SELECT DISTINCT REF_ID FROM t1 WHERE ID=2); +DROP TABLE t1; diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index c749fba616f..8c9b3eeebde 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -79,8 +79,10 @@ void Item_subselect::select_transformer(THD *thd, st_select_lex_unit *unit) } -bool Item_subselect::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) +bool Item_subselect::fix_fields(THD *thd_param, TABLE_LIST *tables, Item **ref) { + thd= thd_param; + if (substitution) { (*ref)= substitution; @@ -115,6 +117,20 @@ bool Item_subselect::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) return res; } +bool Item_subselect::exec() +{ + MEM_ROOT *old_root= my_pthread_getspecific_ptr(MEM_ROOT*, THR_MALLOC); + if (&thd->mem_root != old_root) + { + my_pthread_setspecific_ptr(THR_MALLOC, &thd->mem_root); + int res= engine->exec(); + my_pthread_setspecific_ptr(THR_MALLOC, old_root); + return (res); + } + else + return engine->exec(); +} + Item::Type Item_subselect::type() const { return SUBSELECT_ITEM; @@ -253,12 +269,12 @@ bool Item_singlerow_subselect::null_inside() void Item_singlerow_subselect::bring_value() { - engine->exec(); + exec(); } double Item_singlerow_subselect::val () { - if (!engine->exec() && !value->null_value) + if (!exec() && !value->null_value) { null_value= 0; return value->val(); @@ -272,7 +288,7 @@ double Item_singlerow_subselect::val () longlong Item_singlerow_subselect::val_int () { - if (!engine->exec() && !value->null_value) + if (!exec() && !value->null_value) { null_value= 0; return value->val_int(); @@ -286,7 +302,7 @@ longlong Item_singlerow_subselect::val_int () String *Item_singlerow_subselect::val_str (String *str) { - if (!engine->exec() && !value->null_value) + if (!exec() && !value->null_value) { null_value= 0; return value->val_str(str); @@ -354,7 +370,7 @@ void Item_exists_subselect::fix_length_and_dec() double Item_exists_subselect::val () { - if (engine->exec()) + if (exec()) { reset(); return 0; @@ -364,7 +380,7 @@ double Item_exists_subselect::val () longlong Item_exists_subselect::val_int () { - if (engine->exec()) + if (exec()) { reset(); return 0; @@ -374,7 +390,7 @@ longlong Item_exists_subselect::val_int () String *Item_exists_subselect::val_str(String *str) { - if (engine->exec()) + if (exec()) { reset(); return 0; @@ -385,7 +401,7 @@ String *Item_exists_subselect::val_str(String *str) double Item_in_subselect::val () { - if (engine->exec()) + if (exec()) { reset(); null_value= 1; @@ -398,7 +414,7 @@ double Item_in_subselect::val () longlong Item_in_subselect::val_int () { - if (engine->exec()) + if (exec()) { reset(); null_value= 1; @@ -411,7 +427,7 @@ longlong Item_in_subselect::val_int () String *Item_in_subselect::val_str(String *str) { - if (engine->exec()) + if (exec()) { reset(); null_value= 1; diff --git a/sql/item_subselect.h b/sql/item_subselect.h index fc4dad5a6b3..3ed3f2af0e9 100644 --- a/sql/item_subselect.h +++ b/sql/item_subselect.h @@ -36,6 +36,8 @@ class Item_subselect :public Item_result_field my_bool engine_owner; /* Is this item owner of engine */ my_bool value_assigned; /* value already assigned to subselect */ protected: + /* thread handler, will be assigned in fix_fields only */ + THD *thd; /* substitution instead of subselect in case of optimization */ Item *substitution; /* engine that perform execution of subselect (single select or union) */ @@ -81,6 +83,7 @@ public: return null_value; } bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref); + bool exec(); virtual void fix_length_and_dec(); table_map used_tables() const; -- cgit v1.2.1