Commit 3e8a5e1d authored by bell@sanja.is.com.ua's avatar bell@sanja.is.com.ua

IN subselect with ORDER BY, HAVING & sum functions

parent 465664a1
...@@ -230,4 +230,15 @@ id select_type table type possible_keys key key_len ref rows Extra ...@@ -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 1 PRIMARY searchconthardwarefr3 index NULL topic 3 NULL 2 Using index
2 SUBSELECT No tables used 2 SUBSELECT No tables used
3 UNION 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; drop table searchconthardwarefr3;
...@@ -120,4 +120,9 @@ SELECT 1 FROM searchconthardwarefr3 WHERE 1=(SELECT 1 UNION SELECT 1) UNION ALL ...@@ -120,4 +120,9 @@ SELECT 1 FROM searchconthardwarefr3 WHERE 1=(SELECT 1 UNION SELECT 1) UNION ALL
-- error 1240 -- error 1240
SELECT 1 FROM searchconthardwarefr3 WHERE 1=(SELECT 1 UNION ALL SELECT 1) UNION SELECT 1; 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); 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; drop table searchconthardwarefr3;
\ No newline at end of file
...@@ -116,11 +116,10 @@ public: ...@@ -116,11 +116,10 @@ public:
*/ */
class Item_outer_select_context_saver :public Item_wrapper class Item_outer_select_context_saver :public Item_wrapper
{ {
Item *item;
public: public:
Item_outer_select_context_saver(Item *i): Item_outer_select_context_saver(Item *i)
item(i)
{ {
item= i;
} }
bool fix_fields(THD *, struct st_table_list *, Item ** ref); bool fix_fields(THD *, struct st_table_list *, Item ** ref);
}; };
...@@ -130,11 +129,10 @@ public: ...@@ -130,11 +129,10 @@ public:
*/ */
class Item_asterisk_remover :public Item_wrapper class Item_asterisk_remover :public Item_wrapper
{ {
Item *item;
public: public:
Item_asterisk_remover(Item *i): Item_asterisk_remover(Item *i)
item(i)
{ {
item= i;
} }
bool fix_fields(THD *, struct st_table_list *, Item ** ref); bool fix_fields(THD *, struct st_table_list *, Item ** ref);
}; };
......
...@@ -254,9 +254,23 @@ void Item_in_subselect::select_transformer(st_select_lex *select_lex, ...@@ -254,9 +254,23 @@ void Item_in_subselect::select_transformer(st_select_lex *select_lex,
} }
else else
item= (Item*) sl->item_list.pop(); item= (Item*) sl->item_list.pop();
left_expr= new Item_outer_select_context_saver(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->item_list.empty(); sl->item_list.empty();
sl->item_list.push_back(new Item_int(1)); 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); item= new Item_asterisk_remover(item);
if (sl->where) if (sl->where)
sl->where= new Item_cond_and(sl->where, sl->where= new Item_cond_and(sl->where,
...@@ -264,6 +278,7 @@ void Item_in_subselect::select_transformer(st_select_lex *select_lex, ...@@ -264,6 +278,7 @@ void Item_in_subselect::select_transformer(st_select_lex *select_lex,
else else
sl->where= new Item_func_eq(item, left_expr); sl->where= new Item_func_eq(item, left_expr);
} }
}
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
......
...@@ -23,7 +23,6 @@ ...@@ -23,7 +23,6 @@
#include "mysql_priv.h" #include "mysql_priv.h"
Item_sum::Item_sum(List<Item> &list) Item_sum::Item_sum(List<Item> &list)
{ {
arg_count=list.elements; arg_count=list.elements;
...@@ -38,10 +37,14 @@ Item_sum::Item_sum(List<Item> &list) ...@@ -38,10 +37,14 @@ Item_sum::Item_sum(List<Item> &list)
args[i++]= item; args[i++]= item;
} }
} }
with_sum_func=1; mark_as_sum_func();
list.empty(); // Fields are used 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) void Item_sum::make_field(Send_field *tmp_field)
{ {
......
...@@ -34,23 +34,28 @@ public: ...@@ -34,23 +34,28 @@ public:
uint arg_count; uint arg_count;
bool quick_group; /* If incremental update of fields */ 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) Item_sum(Item *a) :quick_group(1)
{ {
arg_count=1; arg_count=1;
args=tmp_args; args=tmp_args;
args[0]=a; args[0]=a;
with_sum_func = 1; mark_as_sum_func();
} }
Item_sum( Item *a, Item *b ) :quick_group(1) Item_sum( Item *a, Item *b ) :quick_group(1)
{ {
arg_count=2; arg_count=2;
args=tmp_args; args=tmp_args;
args[0]=a; args[1]=b; args[0]=a; args[1]=b;
with_sum_func=1; mark_as_sum_func();
} }
Item_sum(List<Item> &list); Item_sum(List<Item> &list);
~Item_sum() { result_field=0; } ~Item_sum() { result_field=0; }
inline void mark_as_sum_func();
enum Type type() const { return SUM_FUNC_ITEM; } enum Type type() const { return SUM_FUNC_ITEM; }
virtual enum Sumfunctype sum_func () const=0; virtual enum Sumfunctype sum_func () const=0;
virtual void reset()=0; virtual void reset()=0;
......
...@@ -935,6 +935,7 @@ void st_select_lex_node::init_select() ...@@ -935,6 +935,7 @@ void st_select_lex_node::init_select()
order_list.next= (byte**) &order_list.first; order_list.next= (byte**) &order_list.first;
select_limit= HA_POS_ERROR; select_limit= HA_POS_ERROR;
offset_limit= 0; offset_limit= 0;
with_sum_func= 0;
} }
void st_select_lex_unit::init_query() void st_select_lex_unit::init_query()
......
...@@ -196,6 +196,7 @@ public: ...@@ -196,6 +196,7 @@ public:
enum sub_select_type linkage; enum sub_select_type linkage;
SQL_LIST order_list; /* ORDER clause */ SQL_LIST order_list; /* ORDER clause */
ha_rows select_limit, offset_limit; /* LIMIT clause parameters */ ha_rows select_limit, offset_limit; /* LIMIT clause parameters */
bool with_sum_func;
void init_query(); void init_query();
void init_select(); void init_select();
void include_down(st_select_lex_node *upper); void include_down(st_select_lex_node *upper);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment