From 3e8a5e1d34cf9e83a2ed9bdfc9c6fc74c76a5ec4 Mon Sep 17 00:00:00 2001 From: "bell@sanja.is.com.ua" <> Date: Thu, 31 Oct 2002 02:11:59 +0200 Subject: [PATCH] IN subselect with ORDER BY, HAVING & sum functions --- mysql-test/r/subselect.result | 11 +++++++++++ mysql-test/t/subselect.test | 5 +++++ sql/item.h | 10 ++++------ sql/item_subselect.cc | 29 ++++++++++++++++++++++------- sql/item_sum.cc | 7 +++++-- sql/item_sum.h | 11 ++++++++--- sql/sql_lex.cc | 3 ++- sql/sql_lex.h | 1 + 8 files changed, 58 insertions(+), 19 deletions(-) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index cccdd05f9b..1bbc652426 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -230,4 +230,15 @@ id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY searchconthardwarefr3 index NULL topic 3 NULL 2 Using index 2 SUBSELECT No tables used 3 UNION No tables used +SELECT 1 IN (SELECT 1 FROM searchconthardwarefr3 HAVING a); +Unknown column 'a' in 'having clause' +SELECT * from searchconthardwarefr3 where topic IN (SELECT topic FROM searchconthardwarefr3 GROUP BY date); +topic date pseudo +40143 2002-08-03 joce +43506 2002-10-02 joce +SELECT * from searchconthardwarefr3 where topic IN (SELECT topic FROM searchconthardwarefr3 GROUP BY date HAVING topic < 4100); +topic date pseudo +43506 2002-10-02 joce +SELECT * from searchconthardwarefr3 where topic IN (SELECT SUM(topic) FROM searchconthardwarefr3); +topic date pseudo drop table searchconthardwarefr3; diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 0cf976b4be..5e868aaa67 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -120,4 +120,9 @@ SELECT 1 FROM searchconthardwarefr3 WHERE 1=(SELECT 1 UNION SELECT 1) UNION ALL -- error 1240 SELECT 1 FROM searchconthardwarefr3 WHERE 1=(SELECT 1 UNION ALL SELECT 1) UNION SELECT 1; EXPLAIN SELECT 1 FROM searchconthardwarefr3 WHERE 1=(SELECT 1 UNION SELECT 1); +-- error 1054 +SELECT 1 IN (SELECT 1 FROM searchconthardwarefr3 HAVING a); +SELECT * from searchconthardwarefr3 where topic IN (SELECT topic FROM searchconthardwarefr3 GROUP BY date); +SELECT * from searchconthardwarefr3 where topic IN (SELECT topic FROM searchconthardwarefr3 GROUP BY date HAVING topic < 4100); +SELECT * from searchconthardwarefr3 where topic IN (SELECT SUM(topic) FROM searchconthardwarefr3); drop table searchconthardwarefr3; \ No newline at end of file diff --git a/sql/item.h b/sql/item.h index 2b92d7c9ed..391ec347b7 100644 --- a/sql/item.h +++ b/sql/item.h @@ -116,11 +116,10 @@ public: */ class Item_outer_select_context_saver :public Item_wrapper { - Item *item; public: - Item_outer_select_context_saver(Item *i): - item(i) + Item_outer_select_context_saver(Item *i) { + item= i; } bool fix_fields(THD *, struct st_table_list *, Item ** ref); }; @@ -130,11 +129,10 @@ public: */ class Item_asterisk_remover :public Item_wrapper { - Item *item; public: - Item_asterisk_remover(Item *i): - item(i) + Item_asterisk_remover(Item *i) { + item= i; } bool fix_fields(THD *, struct st_table_list *, Item ** ref); }; diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index f68af3079d..2f7c7aad9a 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -254,15 +254,30 @@ void Item_in_subselect::select_transformer(st_select_lex *select_lex, } else item= (Item*) sl->item_list.pop(); - sl->item_list.empty(); - sl->item_list.push_back(new Item_int(1)); + left_expr= new Item_outer_select_context_saver(left_expr); - item= new Item_asterisk_remover(item); - if (sl->where) - sl->where= new Item_cond_and(sl->where, - new Item_func_eq(item, left_expr)); + + if (sl->having || sl->with_sum_func || sl->group_list.first) + { + sl->item_list.push_back(item); + item= new Item_ref(sl->item_list.head_ref(), 0, "<result>"); + if (sl->having) + sl->having= new Item_cond_and(sl->having, + new Item_func_eq(item, left_expr)); + else + sl->having= new Item_func_eq(item, left_expr); + } else - sl->where= new Item_func_eq(item, left_expr); + { + sl->item_list.empty(); + sl->item_list.push_back(new Item_int(1)); + item= new Item_asterisk_remover(item); + if (sl->where) + sl->where= new Item_cond_and(sl->where, + new Item_func_eq(item, left_expr)); + else + sl->where= new Item_func_eq(item, left_expr); + } } DBUG_VOID_RETURN; } diff --git a/sql/item_sum.cc b/sql/item_sum.cc index ae1a86845b..0b1150cb69 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -23,7 +23,6 @@ #include "mysql_priv.h" - Item_sum::Item_sum(List<Item> &list) { arg_count=list.elements; @@ -38,10 +37,14 @@ Item_sum::Item_sum(List<Item> &list) args[i++]= item; } } - with_sum_func=1; + mark_as_sum_func(); list.empty(); // Fields are used } +void Item_sum::mark_as_sum_func() +{ + current_thd->lex.select->with_sum_func= with_sum_func= 1; +} void Item_sum::make_field(Send_field *tmp_field) { diff --git a/sql/item_sum.h b/sql/item_sum.h index 3e67f1e362..a169a0ee56 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -34,23 +34,28 @@ public: uint arg_count; bool quick_group; /* If incremental update of fields */ - Item_sum() : arg_count(0),quick_group(1) { with_sum_func=1; } + Item_sum() : arg_count(0),quick_group(1) + { + mark_as_sum_func(); + } Item_sum(Item *a) :quick_group(1) { arg_count=1; args=tmp_args; args[0]=a; - with_sum_func = 1; + mark_as_sum_func(); } Item_sum( Item *a, Item *b ) :quick_group(1) { arg_count=2; args=tmp_args; args[0]=a; args[1]=b; - with_sum_func=1; + mark_as_sum_func(); } Item_sum(List<Item> &list); ~Item_sum() { result_field=0; } + inline void mark_as_sum_func(); + enum Type type() const { return SUM_FUNC_ITEM; } virtual enum Sumfunctype sum_func () const=0; virtual void reset()=0; diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 52f1be6bdd..31f7e99a2b 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -934,7 +934,8 @@ void st_select_lex_node::init_select() order_list.first= 0; order_list.next= (byte**) &order_list.first; select_limit= HA_POS_ERROR; - offset_limit= 0; + offset_limit= 0; + with_sum_func= 0; } void st_select_lex_unit::init_query() diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 50bff7c7f6..64186fb49e 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -196,6 +196,7 @@ public: enum sub_select_type linkage; SQL_LIST order_list; /* ORDER clause */ ha_rows select_limit, offset_limit; /* LIMIT clause parameters */ + bool with_sum_func; void init_query(); void init_select(); void include_down(st_select_lex_node *upper); -- 2.30.9