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

fixed subselects with temporary tables (SCRUM)

fixed memory leacks
parent 710881e4
...@@ -81,21 +81,18 @@ select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1); ...@@ -81,21 +81,18 @@ select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1);
a b a b
1 7 1 7
2 7 2 7
select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1) select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1) union (select * from t4 order by a limit 2) limit 3;
union (select * from t4 order by a limit 2) limit 3;
a b a b
1 7 1 7
2 7 2 7
3 8 3 8
select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1) select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1) union (select * from t4 where t4.b=(select max(t2.a)*4 from t2) order by a);
union (select * from t4 where t4.b=(select max(t2.a)*4 from t2) order by a);
a b a b
1 7 1 7
2 7 2 7
3 8 3 8
4 8 4 8
explain select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1) explain select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1) union (select * from t4 where t4.b=(select max(t2.a)*4 from t2) order by a);
union (select * from t4 where t4.b=(select max(t2.a)*4 from t2) order by a);
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Using where 1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Using where
2 SUBSELECT t3 ALL NULL NULL NULL NULL 3 Using filesort 2 SUBSELECT t3 ALL NULL NULL NULL NULL 3 Using filesort
...@@ -330,19 +327,15 @@ Unknown column 'a' in 'having clause' ...@@ -330,19 +327,15 @@ Unknown column 'a' in 'having clause'
SELECT * from t2 where topic IN (SELECT topic FROM t2 GROUP BY date); SELECT * from t2 where topic IN (SELECT topic FROM t2 GROUP BY date);
mot topic date pseudo mot topic date pseudo
joce 40143 2002-10-22 joce joce 40143 2002-10-22 joce
joce 43506 2002-10-22 joce
SELECT * from t2 where topic IN (SELECT topic FROM t2 GROUP BY date HAVING topic < 4100); SELECT * from t2 where topic IN (SELECT topic FROM t2 GROUP BY date HAVING topic < 4100);
mot topic date pseudo mot topic date pseudo
joce 43506 2002-10-22 joce
SELECT * from t2 where topic IN (SELECT SUM(topic) FROM t1); SELECT * from t2 where topic IN (SELECT SUM(topic) FROM t1);
mot topic date pseudo mot topic date pseudo
SELECT * from t2 where topic = any (SELECT topic FROM t2 GROUP BY date); SELECT * from t2 where topic = any (SELECT topic FROM t2 GROUP BY date);
mot topic date pseudo mot topic date pseudo
joce 40143 2002-10-22 joce joce 40143 2002-10-22 joce
joce 43506 2002-10-22 joce
SELECT * from t2 where topic = any (SELECT topic FROM t2 GROUP BY date HAVING topic < 4100); SELECT * from t2 where topic = any (SELECT topic FROM t2 GROUP BY date HAVING topic < 4100);
mot topic date pseudo mot topic date pseudo
joce 43506 2002-10-22 joce
SELECT * from t2 where topic = any (SELECT SUM(topic) FROM t1); SELECT * from t2 where topic = any (SELECT SUM(topic) FROM t1);
mot topic date pseudo mot topic date pseudo
SELECT * from t2 where topic = all (SELECT topic FROM t2 GROUP BY date); SELECT * from t2 where topic = all (SELECT topic FROM t2 GROUP BY date);
...@@ -351,6 +344,7 @@ joce 40143 2002-10-22 joce ...@@ -351,6 +344,7 @@ joce 40143 2002-10-22 joce
SELECT * from t2 where topic = all (SELECT topic FROM t2 GROUP BY date HAVING topic < 4100); SELECT * from t2 where topic = all (SELECT topic FROM t2 GROUP BY date HAVING topic < 4100);
mot topic date pseudo mot topic date pseudo
joce 40143 2002-10-22 joce joce 40143 2002-10-22 joce
joce 43506 2002-10-22 joce
SELECT * from t2 where topic = all (SELECT SUM(topic) FROM t2); SELECT * from t2 where topic = all (SELECT SUM(topic) FROM t2);
mot topic date pseudo mot topic date pseudo
SELECT * from t2 where topic <> any (SELECT SUM(topic) FROM t2); SELECT * from t2 where topic <> any (SELECT SUM(topic) FROM t2);
......
...@@ -42,12 +42,9 @@ select (select a from t3), a from t2; ...@@ -42,12 +42,9 @@ select (select a from t3), a from t2;
select * from t2 where t2.a=(select a from t1); select * from t2 where t2.a=(select a from t1);
insert into t3 values (6),(7),(3); insert into t3 values (6),(7),(3);
select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1); select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1);
select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1) select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1) union (select * from t4 order by a limit 2) limit 3;
union (select * from t4 order by a limit 2) limit 3; select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1) union (select * from t4 where t4.b=(select max(t2.a)*4 from t2) order by a);
select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1) explain select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1) union (select * from t4 where t4.b=(select max(t2.a)*4 from t2) order by a);
union (select * from t4 where t4.b=(select max(t2.a)*4 from t2) order by a);
explain select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)
union (select * from t4 where t4.b=(select max(t2.a)*4 from t2) order by a);
select (select a from t3 where a<t2.a*4 order by 1 desc limit 1), a from t2; select (select a from t3 where a<t2.a*4 order by 1 desc limit 1), a from t2;
select (select t3.a from t3 where a<8 order by 1 desc limit 1), a from select (select t3.a from t3 where a<8 order by 1 desc limit 1), a from
(select * from t2 where a>1) as tt; (select * from t2 where a>1) as tt;
...@@ -190,7 +187,10 @@ SELECT * from t2 where topic = any (SELECT topic FROM t2 GROUP BY date); ...@@ -190,7 +187,10 @@ SELECT * from t2 where topic = any (SELECT topic FROM t2 GROUP BY date);
SELECT * from t2 where topic = any (SELECT topic FROM t2 GROUP BY date HAVING topic < 4100); SELECT * from t2 where topic = any (SELECT topic FROM t2 GROUP BY date HAVING topic < 4100);
SELECT * from t2 where topic = any (SELECT SUM(topic) FROM t1); SELECT * from t2 where topic = any (SELECT SUM(topic) FROM t1);
SELECT * from t2 where topic = all (SELECT topic FROM t2 GROUP BY date); SELECT * from t2 where topic = all (SELECT topic FROM t2 GROUP BY date);
SELECT topic FROM t2 GROUP BY date;
SELECT topic FROM t2 GROUP BY date HAVING topic < 4100;
SELECT * from t2 where topic = all (SELECT topic FROM t2 GROUP BY date HAVING topic < 4100); SELECT * from t2 where topic = all (SELECT topic FROM t2 GROUP BY date HAVING topic < 4100);
SELECT *, date as fff from t2 where not (SELECT date FROM t2 GROUP BY date HAVING topic < 4100 and fff!=date);
SELECT * from t2 where topic = all (SELECT SUM(topic) FROM t2); SELECT * from t2 where topic = all (SELECT SUM(topic) FROM t2);
SELECT * from t2 where topic <> any (SELECT SUM(topic) FROM t2); SELECT * from t2 where topic <> any (SELECT SUM(topic) FROM t2);
drop table t1,t2; drop table t1,t2;
......
...@@ -46,6 +46,31 @@ Item::Item(): ...@@ -46,6 +46,31 @@ Item::Item():
loop_id= 0; loop_id= 0;
} }
Item::Item(Item &item):
loop_id(0),
str_value(item.str_value),
name(item.name),
max_length(item.max_length),
marker(item.marker),
decimals(item.decimals),
maybe_null(item.maybe_null),
null_value(item.null_value),
unsigned_flag(item.unsigned_flag),
with_sum_func(item.with_sum_func),
fixed(item.fixed)
{
next=current_thd->free_list; // Put in free list
current_thd->free_list= this;
}
Item_ident::Item_ident(Item_ident &item):
Item(item),
db_name(item.db_name),
table_name(item.table_name),
field_name(item.field_name),
depended_from(item.depended_from)
{}
bool Item::check_loop(uint id) bool Item::check_loop(uint id)
{ {
DBUG_ENTER("Item::check_loop"); DBUG_ENTER("Item::check_loop");
...@@ -153,6 +178,11 @@ Item_field::Item_field(Field *f) :Item_ident(NullS,f->table_name,f->field_name) ...@@ -153,6 +178,11 @@ Item_field::Item_field(Field *f) :Item_ident(NullS,f->table_name,f->field_name)
fixed= 1; // This item is not needed in fix_fields fixed= 1; // This item is not needed in fix_fields
} }
Item_field::Item_field(Item_field &item):
Item_ident(item),
field(item.field),
result_field(item.result_field)
{}
void Item_field::set_field(Field *field_par) void Item_field::set_field(Field *field_par)
{ {
...@@ -262,6 +292,13 @@ table_map Item_field::used_tables() const ...@@ -262,6 +292,13 @@ table_map Item_field::used_tables() const
return field->table->map; return field->table->map;
} }
Item * Item_field::get_tmp_table_item()
{
Item_field *new_item= new Item_field(*this);
if (new_item)
new_item->field= new_item->result_field;
return new_item;
}
String *Item_int::val_str(String *str) String *Item_int::val_str(String *str)
{ {
...@@ -535,6 +572,7 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) ...@@ -535,6 +572,7 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
SELECT_LEX *last= 0; SELECT_LEX *last= 0;
Item **refer= (Item **)not_found_item; Item **refer= (Item **)not_found_item;
uint counter= 0;
// Prevent using outer fields in subselects, that is not supported now // Prevent using outer fields in subselects, that is not supported now
SELECT_LEX *cursel=(SELECT_LEX *) thd->lex.current_select; SELECT_LEX *cursel=(SELECT_LEX *) thd->lex.current_select;
if (cursel->linkage != DERIVED_TABLE_TYPE) if (cursel->linkage != DERIVED_TABLE_TYPE)
...@@ -546,7 +584,7 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) ...@@ -546,7 +584,7 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
(last= sl)->get_table_list(), (last= sl)->get_table_list(),
0)) != not_found_field) 0)) != not_found_field)
break; break;
if ((refer= find_item_in_list(this, sl->item_list, if ((refer= find_item_in_list(this, sl->item_list, &counter,
REPORT_EXCEPT_NOT_FOUND)) != REPORT_EXCEPT_NOT_FOUND)) !=
(Item **)not_found_item) (Item **)not_found_item)
break; break;
...@@ -565,8 +603,16 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) ...@@ -565,8 +603,16 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
} }
else if (refer != (Item **)not_found_item) else if (refer != (Item **)not_found_item)
{ {
if (!(*refer)->fixed)
{
my_error(ER_ILLEGAL_REFERENCE, MYF(0), name,
"forward reference in item list");
return -1;
}
Item_ref *r; Item_ref *r;
*ref= r= new Item_ref(refer, (char *)table_name, *ref= r= new Item_ref(last->ref_pointer_array + counter-1
, (char *)table_name,
(char *)field_name); (char *)field_name);
if (!r) if (!r)
return 1; return 1;
...@@ -930,6 +976,7 @@ bool Item_null::send(THD *thd, String *packet) ...@@ -930,6 +976,7 @@ bool Item_null::send(THD *thd, String *packet)
bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
{ {
uint counter= 0;
if (!ref) if (!ref)
{ {
SELECT_LEX *sl= thd->lex.current_select->outer_select(); SELECT_LEX *sl= thd->lex.current_select->outer_select();
...@@ -940,6 +987,7 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) ...@@ -940,6 +987,7 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
*/ */
if ((ref= find_item_in_list(this, if ((ref= find_item_in_list(this,
*(thd->lex.current_select->get_item_list()), *(thd->lex.current_select->get_item_list()),
&counter,
((sl && ((sl &&
thd->lex.current_select->linkage != thd->lex.current_select->linkage !=
DERIVED_TABLE_TYPE) ? DERIVED_TABLE_TYPE) ?
...@@ -961,7 +1009,8 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) ...@@ -961,7 +1009,8 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
for ( ; sl ; sl= sl->outer_select()) for ( ; sl ; sl= sl->outer_select())
{ {
if ((ref= find_item_in_list(this, (last= sl)->item_list, if ((ref= find_item_in_list(this, (last= sl)->item_list,
REPORT_EXCEPT_NOT_FOUND)) != &counter,
REPORT_EXCEPT_NOT_FOUND)) !=
(Item **)not_found_item) (Item **)not_found_item)
break; break;
if ((tmp= find_field_in_tables(thd, this, if ((tmp= find_field_in_tables(thd, this,
...@@ -980,6 +1029,7 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) ...@@ -980,6 +1029,7 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
// Call to report error // Call to report error
find_item_in_list(this, find_item_in_list(this,
*(thd->lex.current_select->get_item_list()), *(thd->lex.current_select->get_item_list()),
&counter,
REPORT_ALL_ERRORS); REPORT_ALL_ERRORS);
ref= 0; ref= 0;
return 1; return 1;
...@@ -996,17 +1046,35 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) ...@@ -996,17 +1046,35 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
} }
else else
{ {
depended_from= last; if (!(*ref)->fixed)
{
my_error(ER_ILLEGAL_REFERENCE, MYF(0), name,
"forward reference in item list");
return -1;
}
ref= (depended_from= last)->ref_pointer_array + counter-1;
thd->lex.current_select->mark_as_dependent(last); thd->lex.current_select->mark_as_dependent(last);
thd->add_possible_loop(this); thd->add_possible_loop(this);
} }
} }
else if (!ref) else if (!ref)
return 1; return 1;
else
{
if (!(*ref)->fixed)
{
my_error(ER_ILLEGAL_REFERENCE, MYF(0), name,
"forward reference in item list");
return -1;
}
ref= thd->lex.current_select->ref_pointer_array + counter-1;
}
max_length= (*ref)->max_length; max_length= (*ref)->max_length;
maybe_null= (*ref)->maybe_null; maybe_null= (*ref)->maybe_null;
decimals= (*ref)->decimals; decimals= (*ref)->decimals;
} }
if (((*ref)->with_sum_func && if (((*ref)->with_sum_func &&
(depended_from || (depended_from ||
!(thd->lex.current_select->linkage != GLOBAL_OPTIONS_TYPE && !(thd->lex.current_select->linkage != GLOBAL_OPTIONS_TYPE &&
......
...@@ -50,6 +50,8 @@ class Item { ...@@ -50,6 +50,8 @@ class Item {
// alloc & destruct is done as start of select using sql_alloc // alloc & destruct is done as start of select using sql_alloc
Item(); Item();
// copy constructor used by Item_field, Item_ref & agregate (sum) functions
Item(Item &item);
virtual ~Item() { name=0; } /*lint -e1509 */ virtual ~Item() { name=0; } /*lint -e1509 */
void set_name(const char *str,uint length=0); void set_name(const char *str,uint length=0);
void init_make_field(Send_field *tmp_field,enum enum_field_types type); void init_make_field(Send_field *tmp_field,enum enum_field_types type);
...@@ -67,7 +69,8 @@ class Item { ...@@ -67,7 +69,8 @@ class Item {
virtual longlong val_int()=0; virtual longlong val_int()=0;
virtual String *val_str(String*)=0; virtual String *val_str(String*)=0;
virtual void make_field(Send_field *field)=0; virtual void make_field(Send_field *field)=0;
virtual Field *tmp_table_field(TABLE *t_arg=(TABLE *)0) { return 0; } virtual Field *tmp_table_field() { return 0; }
virtual Field *tmp_table_field(TABLE *t_arg) { return 0; }
virtual const char *full_name() const { return name ? name : "???"; } virtual const char *full_name() const { return name ? name : "???"; }
virtual double val_result() { return val(); } virtual double val_result() { return val(); }
virtual longlong val_int_result() { return val_int(); } virtual longlong val_int_result() { return val_int(); }
...@@ -82,12 +85,14 @@ class Item { ...@@ -82,12 +85,14 @@ class Item {
virtual bool const_item() const { return used_tables() == 0; } virtual bool const_item() const { return used_tables() == 0; }
virtual void print(String *str_arg) { str_arg->append(full_name()); } virtual void print(String *str_arg) { str_arg->append(full_name()); }
virtual void update_used_tables() {} virtual void update_used_tables() {}
virtual void split_sum_func(List<Item> &fields) {} virtual void split_sum_func(Item **ref_pointer_array, List<Item> &fields) {}
virtual bool get_date(TIME *ltime,bool fuzzydate); virtual bool get_date(TIME *ltime,bool fuzzydate);
virtual bool get_time(TIME *ltime); virtual bool get_time(TIME *ltime);
virtual bool is_null() { return 0; }; virtual bool is_null() { return 0; };
virtual bool check_loop(uint id); virtual bool check_loop(uint id);
virtual void top_level_item() {} virtual void top_level_item() {}
virtual Item * get_same() { return this; }
virtual Item * get_tmp_table_item() { return get_same(); }
virtual bool binary() const virtual bool binary() const
{ return str_value.charset()->state & MY_CS_BINSORT ? 1 : 0 ; } { return str_value.charset()->state & MY_CS_BINSORT ? 1 : 0 ; }
...@@ -159,11 +164,14 @@ class Item_ident :public Item ...@@ -159,11 +164,14 @@ class Item_ident :public Item
const char *table_name; const char *table_name;
const char *field_name; const char *field_name;
st_select_lex *depended_from; st_select_lex *depended_from;
Item_ident(const char *db_name_par,const char *table_name_par, Item_ident(const char *db_name_par,const char *table_name_par,
const char *field_name_par) const char *field_name_par)
:db_name(db_name_par),table_name(table_name_par), :db_name(db_name_par),table_name(table_name_par),
field_name(field_name_par), depended_from(0) field_name(field_name_par), depended_from(0)
{ name = (char*) field_name_par; } { name = (char*) field_name_par; }
// copy constructor used by Item_field & Item_ref
Item_ident(Item_ident &item);
const char *full_name() const; const char *full_name() const;
}; };
...@@ -179,6 +187,8 @@ class Item_field :public Item_ident ...@@ -179,6 +187,8 @@ class Item_field :public Item_ident
const char *field_name_par) const char *field_name_par)
:Item_ident(db_par,table_name_par,field_name_par),field(0),result_field(0) :Item_ident(db_par,table_name_par,field_name_par),field(0),result_field(0)
{} {}
// copy constructor need to process subselect with temporary tables
Item_field(Item_field &item);
Item_field(Field *field); Item_field(Field *field);
enum Type type() const { return FIELD_ITEM; } enum Type type() const { return FIELD_ITEM; }
bool eq(const Item *item, bool binary_cmp) const; bool eq(const Item *item, bool binary_cmp) const;
...@@ -202,10 +212,12 @@ class Item_field :public Item_ident ...@@ -202,10 +212,12 @@ class Item_field :public Item_ident
{ {
return field->result_type(); return field->result_type();
} }
Field *tmp_table_field(TABLE *t_arg=(TABLE *)0) { return result_field; } Field *tmp_table_field() { return result_field; }
Field *tmp_table_field(TABLE *t_arg) { return result_field; }
bool get_date(TIME *ltime,bool fuzzydate); bool get_date(TIME *ltime,bool fuzzydate);
bool get_time(TIME *ltime); bool get_time(TIME *ltime);
bool is_null() { return field->is_null(); } bool is_null() { return field->is_null(); }
Item * get_tmp_table_item();
}; };
...@@ -448,8 +460,13 @@ class Item_result_field :public Item /* Item with result field */ ...@@ -448,8 +460,13 @@ class Item_result_field :public Item /* Item with result field */
public: public:
Field *result_field; /* Save result here */ Field *result_field; /* Save result here */
Item_result_field() :result_field(0) {} Item_result_field() :result_field(0) {}
Item_result_field(Item_result_field &item): Item(item)
{
result_field= item.result_field;
}
~Item_result_field() {} /* Required with gcc 2.95 */ ~Item_result_field() {} /* Required with gcc 2.95 */
Field *tmp_table_field(TABLE *t_arg=(TABLE *)0) { return result_field; } Field *tmp_table_field() { return result_field; }
Field *tmp_table_field(TABLE *t_arg) { return result_field; }
table_map used_tables() const { return 1; } table_map used_tables() const { return 1; }
virtual void fix_length_and_dec()=0; virtual void fix_length_and_dec()=0;
}; };
...@@ -463,6 +480,8 @@ class Item_ref :public Item_ident ...@@ -463,6 +480,8 @@ class Item_ref :public Item_ident
:Item_ident(db_par,table_name_par,field_name_par),ref(0) {} :Item_ident(db_par,table_name_par,field_name_par),ref(0) {}
Item_ref(Item **item, char *table_name_par,char *field_name_par) Item_ref(Item **item, char *table_name_par,char *field_name_par)
:Item_ident(NullS,table_name_par,field_name_par),ref(item) {} :Item_ident(NullS,table_name_par,field_name_par),ref(item) {}
// copy constructor need to process subselect with temporary tables
Item_ref(Item_ref &item): Item_ident(item), ref(item.ref) {}
enum Type type() const { return REF_ITEM; } enum Type type() const { return REF_ITEM; }
bool eq(const Item *item, bool binary_cmp) const bool eq(const Item *item, bool binary_cmp) const
{ return ref && (*ref)->eq(item, binary_cmp); } { return ref && (*ref)->eq(item, binary_cmp); }
......
...@@ -1175,16 +1175,20 @@ void Item_func_in::update_used_tables() ...@@ -1175,16 +1175,20 @@ void Item_func_in::update_used_tables()
const_item_cache&=item->const_item(); const_item_cache&=item->const_item();
} }
void Item_func_in::split_sum_func(List<Item> &fields) void Item_func_in::split_sum_func(Item **ref_pointer_array, List<Item> &fields)
{ {
if (item->with_sum_func && item->type() != SUM_FUNC_ITEM) if (item->with_sum_func && item->type() != SUM_FUNC_ITEM)
item->split_sum_func(fields); item->split_sum_func(ref_pointer_array, fields);
else if (item->used_tables() || item->type() == SUM_FUNC_ITEM) else if (item->used_tables() || item->type() == SUM_FUNC_ITEM)
{ {
uint el= fields.elements;
fields.push_front(item); fields.push_front(item);
item=new Item_ref((Item**) fields.head_ref(),0,item->name); ref_pointer_array[el]= item;
item=new Item_ref(ref_pointer_array + el,
0, item->name);
} }
Item_func::split_sum_func(fields); Item_func::split_sum_func(ref_pointer_array, fields);
} }
...@@ -1281,7 +1285,7 @@ bool Item_cond::check_loop(uint id) ...@@ -1281,7 +1285,7 @@ bool Item_cond::check_loop(uint id)
DBUG_RETURN(0); DBUG_RETURN(0);
} }
void Item_cond::split_sum_func(List<Item> &fields) void Item_cond::split_sum_func(Item **ref_pointer_array, List<Item> &fields)
{ {
List_iterator<Item> li(list); List_iterator<Item> li(list);
Item *item; Item *item;
...@@ -1290,11 +1294,13 @@ void Item_cond::split_sum_func(List<Item> &fields) ...@@ -1290,11 +1294,13 @@ void Item_cond::split_sum_func(List<Item> &fields)
while ((item=li++)) while ((item=li++))
{ {
if (item->with_sum_func && item->type() != SUM_FUNC_ITEM) if (item->with_sum_func && item->type() != SUM_FUNC_ITEM)
item->split_sum_func(fields); item->split_sum_func(ref_pointer_array, fields);
else if (item->used_tables() || item->type() == SUM_FUNC_ITEM) else if (item->used_tables() || item->type() == SUM_FUNC_ITEM)
{ {
uint el= fields.elements;
fields.push_front(item); fields.push_front(item);
li.replace(new Item_ref((Item**) fields.head_ref(),0,item->name)); ref_pointer_array[el]= item;
li.replace(new Item_ref(ref_pointer_array + el, 0, item->name));
} }
item->update_used_tables(); item->update_used_tables();
used_tables_cache|=item->used_tables(); used_tables_cache|=item->used_tables();
......
...@@ -509,7 +509,7 @@ class Item_func_in :public Item_int_func ...@@ -509,7 +509,7 @@ class Item_func_in :public Item_int_func
enum Functype functype() const { return IN_FUNC; } enum Functype functype() const { return IN_FUNC; }
const char *func_name() const { return " IN "; } const char *func_name() const { return " IN "; }
void update_used_tables(); void update_used_tables();
void split_sum_func(List<Item> &fields); void split_sum_func(Item **ref_pointer_array, List<Item> &fields);
bool check_loop(uint id) bool check_loop(uint id)
{ {
DBUG_ENTER("Item_func_in::check_loop"); DBUG_ENTER("Item_func_in::check_loop");
...@@ -656,7 +656,7 @@ class Item_cond :public Item_bool_func ...@@ -656,7 +656,7 @@ class Item_cond :public Item_bool_func
table_map used_tables() const; table_map used_tables() const;
void update_used_tables(); void update_used_tables();
void print(String *str); void print(String *str);
void split_sum_func(List<Item> &fields); void split_sum_func(Item **ref_pointer_array, List<Item> &fields);
friend int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds); friend int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds);
bool check_loop(uint id); bool check_loop(uint id);
void top_level_item() { abort_on_null=1; } void top_level_item() { abort_on_null=1; }
......
...@@ -146,17 +146,19 @@ bool Item_func::check_loop(uint id) ...@@ -146,17 +146,19 @@ bool Item_func::check_loop(uint id)
DBUG_RETURN(0); DBUG_RETURN(0);
} }
void Item_func::split_sum_func(List<Item> &fields) void Item_func::split_sum_func(Item **ref_pointer_array, List<Item> &fields)
{ {
Item **arg,**arg_end; Item **arg,**arg_end;
for (arg=args, arg_end=args+arg_count; arg != arg_end ; arg++) for (arg=args, arg_end=args+arg_count; arg != arg_end ; arg++)
{ {
if ((*arg)->with_sum_func && (*arg)->type() != SUM_FUNC_ITEM) if ((*arg)->with_sum_func && (*arg)->type() != SUM_FUNC_ITEM)
(*arg)->split_sum_func(fields); (*arg)->split_sum_func(ref_pointer_array, fields);
else if ((*arg)->used_tables() || (*arg)->type() == SUM_FUNC_ITEM) else if ((*arg)->used_tables() || (*arg)->type() == SUM_FUNC_ITEM)
{ {
uint el= fields.elements;
fields.push_front(*arg); fields.push_front(*arg);
*arg=new Item_ref((Item**) fields.head_ref(),0,(*arg)->name); ref_pointer_array[el]= *arg;
*arg=new Item_ref(ref_pointer_array + el, 0, (*arg)->name);
} }
} }
} }
...@@ -225,14 +227,11 @@ bool Item_func::eq(const Item *item, bool binary_cmp) const ...@@ -225,14 +227,11 @@ bool Item_func::eq(const Item *item, bool binary_cmp) const
return 1; return 1;
} }
Field *Item_func::tmp_table_field(TABLE *t_arg) Field *Item_func::tmp_table_field(TABLE *t_arg)
{ {
Field *res; Field *res;
LINT_INIT(res); LINT_INIT(res);
if (!t_arg)
return result_field;
switch (result_type()) { switch (result_type()) {
case INT_RESULT: case INT_RESULT:
if (max_length > 11) if (max_length > 11)
...@@ -303,6 +302,16 @@ void Item_func::fix_num_length_and_dec() ...@@ -303,6 +302,16 @@ void Item_func::fix_num_length_and_dec()
max_length=float_length(decimals); max_length=float_length(decimals);
} }
Item * Item_func::get_tmp_table_item()
{
if (!with_sum_func && !const_item())
{
return new Item_field(result_field);
}
else
return get_same();
}
String *Item_int_func::val_str(String *str) String *Item_int_func::val_str(String *str)
{ {
longlong nr=val_int(); longlong nr=val_int();
......
...@@ -118,7 +118,7 @@ class Item_func :public Item_result_field ...@@ -118,7 +118,7 @@ class Item_func :public Item_result_field
inline Item **arguments() const { return args; } inline Item **arguments() const { return args; }
inline uint argument_count() const { return arg_count; } inline uint argument_count() const { return arg_count; }
inline void remove_arguments() { arg_count=0; } inline void remove_arguments() { arg_count=0; }
virtual void split_sum_func(List<Item> &fields); virtual void split_sum_func(Item **ref_pointer_array, List<Item> &fields);
void print(String *str); void print(String *str);
void print_op(String *str); void print_op(String *str);
void fix_num_length_and_dec(); void fix_num_length_and_dec();
...@@ -132,8 +132,10 @@ class Item_func :public Item_result_field ...@@ -132,8 +132,10 @@ class Item_func :public Item_result_field
} }
bool is_null() { (void) val_int(); return null_value; } bool is_null() { (void) val_int(); return null_value; }
friend class udf_handler; friend class udf_handler;
Field *tmp_table_field() { return result_field; }
Field *tmp_table_field(TABLE *t_arg); Field *tmp_table_field(TABLE *t_arg);
bool check_loop(uint id); bool check_loop(uint id);
Item * get_tmp_table_item();
}; };
......
...@@ -288,6 +288,8 @@ void Item_in_subselect::single_value_transformer(st_select_lex *select_lex, ...@@ -288,6 +288,8 @@ void Item_in_subselect::single_value_transformer(st_select_lex *select_lex,
compare_func_creator func) compare_func_creator func)
{ {
DBUG_ENTER("Item_in_subselect::single_value_transformer"); DBUG_ENTER("Item_in_subselect::single_value_transformer");
THD *thd= current_thd;
for (SELECT_LEX * sl= select_lex; sl; sl= sl->next_select()) for (SELECT_LEX * sl= select_lex; sl; sl= sl->next_select())
{ {
Item *item; Item *item;
...@@ -301,12 +303,16 @@ void Item_in_subselect::single_value_transformer(st_select_lex *select_lex, ...@@ -301,12 +303,16 @@ void Item_in_subselect::single_value_transformer(st_select_lex *select_lex,
Item *expr= new Item_outer_select_context_saver(left_expr); Item *expr= new Item_outer_select_context_saver(left_expr);
if (sl->having || sl->with_sum_func || sl->group_list.first || if (sl->having || sl->with_sum_func || sl->group_list.elements ||
sl->order_list.first) sl->order_list.elements)
{ {
sl->item_list.push_back(item); sl->item_list.push_back(item);
item= (*func)(expr, new Item_ref(sl->item_list.head_ref(), setup_ref_array(thd, &sl->ref_pointer_array,
0, (char*)"<result>")); 1+ select_lex->with_sum_func +
select_lex->order_list.elements +
select_lex->group_list.elements);
item= (*func)(expr, new Item_ref(sl->ref_pointer_array,
0, (char*)"<result>"));
if (sl->having || sl->with_sum_func || sl->group_list.first) if (sl->having || sl->with_sum_func || sl->group_list.first)
if (sl->having) if (sl->having)
sl->having= new Item_cond_and(sl->having, item); sl->having= new Item_cond_and(sl->having, item);
...@@ -348,7 +354,6 @@ void Item_in_subselect::single_value_transformer(st_select_lex *select_lex, ...@@ -348,7 +354,6 @@ void Item_in_subselect::single_value_transformer(st_select_lex *select_lex,
// it is single select without tables => possible optimization // it is single select without tables => possible optimization
item= (*func)(left_expr, item); item= (*func)(left_expr, item);
substitution= item; substitution= item;
THD *thd= current_thd;
if (thd->lex.describe) if (thd->lex.describe)
{ {
char warn_buff[MYSQL_ERRMSG_SIZE]; char warn_buff[MYSQL_ERRMSG_SIZE];
...@@ -424,8 +429,12 @@ int subselect_single_select_engine::prepare() ...@@ -424,8 +429,12 @@ int subselect_single_select_engine::prepare()
prepared= 1; prepared= 1;
SELECT_LEX_NODE *save_select= thd->lex.current_select; SELECT_LEX_NODE *save_select= thd->lex.current_select;
thd->lex.current_select= select_lex; thd->lex.current_select= select_lex;
if(join->prepare((TABLE_LIST*) select_lex->table_list.first, if(join->prepare(&select_lex->ref_pointer_array,
(TABLE_LIST*) select_lex->table_list.first,
select_lex->with_wild,
select_lex->where, select_lex->where,
select_lex->order_list.elements +
select_lex->group_list.elements,
(ORDER*) select_lex->order_list.first, (ORDER*) select_lex->order_list.first,
(ORDER*) select_lex->group_list.first, (ORDER*) select_lex->group_list.first,
select_lex->having, select_lex->having,
......
...@@ -41,9 +41,22 @@ Item_sum::Item_sum(List<Item> &list) ...@@ -41,9 +41,22 @@ Item_sum::Item_sum(List<Item> &list)
list.empty(); // Fields are used list.empty(); // Fields are used
} }
Item_sum::Item_sum(Item_sum &item):
Item_result_field(item), quick_group(item.quick_group)
{
arg_count= item.arg_count;
if (arg_count <= 2)
args=tmp_args;
else
if (!(args=(Item**) sql_alloc(sizeof(Item*)*arg_count)))
return;
for(uint i= 0; i < arg_count; i++)
args[i]= item.args[i];
}
void Item_sum::mark_as_sum_func() void Item_sum::mark_as_sum_func()
{ {
current_thd->lex.current_select->with_sum_func=1; current_thd->lex.current_select->with_sum_func++;
with_sum_func= 1; with_sum_func= 1;
} }
...@@ -90,6 +103,26 @@ void Item_sum::fix_num_length_and_dec() ...@@ -90,6 +103,26 @@ void Item_sum::fix_num_length_and_dec()
max_length=float_length(decimals); max_length=float_length(decimals);
} }
Item * Item_sum::get_tmp_table_item()
{
Item_sum* sum_item= (Item_sum *) get_same();
if (sum_item && sum_item->result_field) // If not a const sum func
{
Field *result_field= sum_item->result_field;
for (uint i=0 ; i < sum_item->arg_count ; i++)
{
Item *arg= sum_item->args[i];
if (!arg->const_item())
{
if (arg->type() == Item::FIELD_ITEM)
((Item_field*) arg)->field= result_field++;
else
sum_item->args[i]= new Item_field(result_field++);
}
}
}
return sum_item;
}
String * String *
Item_sum_num::val_str(String *str) Item_sum_num::val_str(String *str)
...@@ -933,7 +966,7 @@ int dump_leaf(byte* key, uint32 count __attribute__((unused)), ...@@ -933,7 +966,7 @@ int dump_leaf(byte* key, uint32 count __attribute__((unused)),
The first item->rec_offset bytes are taken care of with The first item->rec_offset bytes are taken care of with
restore_record(table,2) in setup() restore_record(table,2) in setup()
*/ */
memcpy(buf + item->rec_offset, key, item->tree.size_of_element); memcpy(buf + item->rec_offset, key, item->tree->size_of_element);
if ((error = item->table->file->write_row(buf))) if ((error = item->table->file->write_row(buf)))
{ {
if (error != HA_ERR_FOUND_DUPP_KEY && if (error != HA_ERR_FOUND_DUPP_KEY &&
...@@ -946,11 +979,14 @@ int dump_leaf(byte* key, uint32 count __attribute__((unused)), ...@@ -946,11 +979,14 @@ int dump_leaf(byte* key, uint32 count __attribute__((unused)),
Item_sum_count_distinct::~Item_sum_count_distinct() Item_sum_count_distinct::~Item_sum_count_distinct()
{ {
if (table) if (!original)
free_tmp_table(current_thd, table); {
delete tmp_table_param; if (table)
if (use_tree) free_tmp_table(current_thd, table);
delete_tree(&tree); delete tmp_table_param;
if (use_tree)
delete_tree(tree);
}
} }
...@@ -1072,8 +1108,8 @@ bool Item_sum_count_distinct::setup(THD *thd) ...@@ -1072,8 +1108,8 @@ bool Item_sum_count_distinct::setup(THD *thd)
} }
} }
init_tree(&tree, min(thd->variables.max_heap_table_size, init_tree(tree, min(thd->variables.max_heap_table_size,
thd->variables.sortbuff_size/16), 0, thd->variables.sortbuff_size/16), 0,
key_length, compare_key, 0, NULL, cmp_arg); key_length, compare_key, 0, NULL, cmp_arg);
use_tree = 1; use_tree = 1;
...@@ -1085,6 +1121,12 @@ bool Item_sum_count_distinct::setup(THD *thd) ...@@ -1085,6 +1121,12 @@ bool Item_sum_count_distinct::setup(THD *thd)
*/ */
max_elements_in_tree = ((key_length) ? max_elements_in_tree = ((key_length) ?
thd->variables.max_heap_table_size/key_length : 1); thd->variables.max_heap_table_size/key_length : 1);
}
if (original)
{
original->table= table;
original->use_tree= use_tree;
} }
return 0; return 0;
} }
...@@ -1094,10 +1136,10 @@ int Item_sum_count_distinct::tree_to_myisam() ...@@ -1094,10 +1136,10 @@ int Item_sum_count_distinct::tree_to_myisam()
{ {
if (create_myisam_from_heap(current_thd, table, tmp_table_param, if (create_myisam_from_heap(current_thd, table, tmp_table_param,
HA_ERR_RECORD_FILE_FULL, 1) || HA_ERR_RECORD_FILE_FULL, 1) ||
tree_walk(&tree, (tree_walk_action)&dump_leaf, (void*)this, tree_walk(tree, (tree_walk_action)&dump_leaf, (void*)this,
left_root_right)) left_root_right))
return 1; return 1;
delete_tree(&tree); delete_tree(tree);
use_tree = 0; use_tree = 0;
return 0; return 0;
} }
...@@ -1105,7 +1147,7 @@ int Item_sum_count_distinct::tree_to_myisam() ...@@ -1105,7 +1147,7 @@ int Item_sum_count_distinct::tree_to_myisam()
void Item_sum_count_distinct::reset() void Item_sum_count_distinct::reset()
{ {
if (use_tree) if (use_tree)
reset_tree(&tree); reset_tree(tree);
else if (table) else if (table)
{ {
table->file->extra(HA_EXTRA_NO_CACHE); table->file->extra(HA_EXTRA_NO_CACHE);
...@@ -1133,13 +1175,13 @@ bool Item_sum_count_distinct::add() ...@@ -1133,13 +1175,13 @@ bool Item_sum_count_distinct::add()
If the tree got too big, convert to MyISAM, otherwise insert into the If the tree got too big, convert to MyISAM, otherwise insert into the
tree. tree.
*/ */
if (tree.elements_in_tree > max_elements_in_tree) if (tree->elements_in_tree > max_elements_in_tree)
{ {
if (tree_to_myisam()) if (tree_to_myisam())
return 1; return 1;
} }
else if (!tree_insert(&tree, table->record[0] + rec_offset, 0, else if (!tree_insert(tree, table->record[0] + rec_offset, 0,
tree.custom_arg)) tree->custom_arg))
return 1; return 1;
} }
else if ((error=table->file->write_row(table->record[0]))) else if ((error=table->file->write_row(table->record[0])))
...@@ -1161,7 +1203,7 @@ longlong Item_sum_count_distinct::val_int() ...@@ -1161,7 +1203,7 @@ longlong Item_sum_count_distinct::val_int()
if (!table) // Empty query if (!table) // Empty query
return LL(0); return LL(0);
if (use_tree) if (use_tree)
return tree.elements_in_tree; return tree->elements_in_tree;
table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK); table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
return table->file->records; return table->file->records;
} }
......
This diff is collapsed.
...@@ -330,9 +330,10 @@ class Item_date :public Item_func ...@@ -330,9 +330,10 @@ class Item_date :public Item_func
{ {
init_make_field(tmp_field,FIELD_TYPE_DATE); init_make_field(tmp_field,FIELD_TYPE_DATE);
} }
Field *tmp_table_field() { return result_field; }
Field *tmp_table_field(TABLE *t_arg) Field *tmp_table_field(TABLE *t_arg)
{ {
return (!t_arg) ? result_field : new Field_date(maybe_null, name, t_arg, thd_charset()); return (new Field_date(maybe_null, name, t_arg, thd_charset()));
} }
}; };
...@@ -347,10 +348,10 @@ class Item_date_func :public Item_str_func ...@@ -347,10 +348,10 @@ class Item_date_func :public Item_str_func
{ {
init_make_field(tmp_field,FIELD_TYPE_DATETIME); init_make_field(tmp_field,FIELD_TYPE_DATETIME);
} }
Field *tmp_table_field() { return result_field; }
Field *tmp_table_field(TABLE *t_arg) Field *tmp_table_field(TABLE *t_arg)
{ {
return (!t_arg) ? result_field : new Field_datetime(maybe_null, name, return (new Field_datetime(maybe_null, name, t_arg, thd_charset()));
t_arg, thd_charset());
} }
}; };
...@@ -373,10 +374,10 @@ class Item_func_curtime :public Item_func ...@@ -373,10 +374,10 @@ class Item_func_curtime :public Item_func
{ {
init_make_field(tmp_field,FIELD_TYPE_TIME); init_make_field(tmp_field,FIELD_TYPE_TIME);
} }
Field *tmp_table_field() { return result_field; }
Field *tmp_table_field(TABLE *t_arg) Field *tmp_table_field(TABLE *t_arg)
{ {
return (!t_arg) ? result_field : return (new Field_time(maybe_null, name, t_arg, thd_charset()));
new Field_time(maybe_null, name, t_arg, thd_charset());
} }
}; };
...@@ -475,10 +476,10 @@ class Item_func_sec_to_time :public Item_str_func ...@@ -475,10 +476,10 @@ class Item_func_sec_to_time :public Item_str_func
{ {
init_make_field(tmp_field,FIELD_TYPE_TIME); init_make_field(tmp_field,FIELD_TYPE_TIME);
} }
Field *tmp_table_field() { return result_field; }
Field *tmp_table_field(TABLE *t_arg) Field *tmp_table_field(TABLE *t_arg)
{ {
return (!t_arg) ? result_field : return (new Field_time(maybe_null, name, t_arg, thd_charset()));
new Field_time(maybe_null, name, t_arg, thd_charset());
} }
}; };
...@@ -570,10 +571,10 @@ class Item_date_typecast :public Item_typecast ...@@ -570,10 +571,10 @@ class Item_date_typecast :public Item_typecast
{ {
init_make_field(tmp_field,FIELD_TYPE_DATE); init_make_field(tmp_field,FIELD_TYPE_DATE);
} }
Field *tmp_table_field() { return result_field; }
Field *tmp_table_field(TABLE *t_arg) Field *tmp_table_field(TABLE *t_arg)
{ {
return (!t_arg) ? result_field : return (new Field_date(maybe_null, name, t_arg, thd_charset()));
new Field_date(maybe_null, name, t_arg, thd_charset());
} }
}; };
...@@ -587,10 +588,10 @@ class Item_time_typecast :public Item_typecast ...@@ -587,10 +588,10 @@ class Item_time_typecast :public Item_typecast
{ {
init_make_field(tmp_field,FIELD_TYPE_TIME); init_make_field(tmp_field,FIELD_TYPE_TIME);
} }
Field *tmp_table_field() { return result_field; }
Field *tmp_table_field(TABLE *t_arg) Field *tmp_table_field(TABLE *t_arg)
{ {
return (!t_arg) ? result_field : return (new Field_time(maybe_null, name, t_arg, thd_charset()));
new Field_time(maybe_null, name, t_arg, thd_charset());
} }
}; };
...@@ -604,9 +605,9 @@ class Item_datetime_typecast :public Item_typecast ...@@ -604,9 +605,9 @@ class Item_datetime_typecast :public Item_typecast
{ {
init_make_field(tmp_field,FIELD_TYPE_DATETIME); init_make_field(tmp_field,FIELD_TYPE_DATETIME);
} }
Field *tmp_table_field() { return result_field; }
Field *tmp_table_field(TABLE *t_arg) Field *tmp_table_field(TABLE *t_arg)
{ {
return (!t_arg) ? result_field : new Field_datetime(maybe_null, name, return (new Field_datetime(maybe_null, name, t_arg, thd_charset()));
t_arg, thd_charset());
} }
}; };
...@@ -37,6 +37,7 @@ class Item_sum_unique_users :public Item_sum_num ...@@ -37,6 +37,7 @@ class Item_sum_unique_users :public Item_sum_num
public: public:
Item_sum_unique_users(Item *name_arg,int start,int end,Item *item_arg) Item_sum_unique_users(Item *name_arg,int start,int end,Item *item_arg)
:Item_sum_num(item_arg) {} :Item_sum_num(item_arg) {}
Item_sum_unique_users(Item_sum_unique_users &item): Item_sum_num(item) {}
double val() { return 0.0; } double val() { return 0.0; }
enum Sumfunctype sum_func () const {return UNIQUE_USERS_FUNC;} enum Sumfunctype sum_func () const {return UNIQUE_USERS_FUNC;}
void reset() {} void reset() {}
...@@ -48,4 +49,5 @@ class Item_sum_unique_users :public Item_sum_num ...@@ -48,4 +49,5 @@ class Item_sum_unique_users :public Item_sum_num
fixed= 1; fixed= 1;
return 0; return 0;
} }
Item_sum * get_same() { return new Item_sum_unique_users(*this); }
}; };
...@@ -402,18 +402,21 @@ bool net_store_data(String *packet,CONVERT *convert, const char *from, ...@@ -402,18 +402,21 @@ bool net_store_data(String *packet,CONVERT *convert, const char *from,
bool net_store_data(String *packet, CONVERT *convert, const char *from); bool net_store_data(String *packet, CONVERT *convert, const char *from);
SORT_FIELD * make_unireg_sortorder(ORDER *order, uint *length); SORT_FIELD * make_unireg_sortorder(ORDER *order, uint *length);
int setup_order(THD *thd,TABLE_LIST *tables, List<Item> &fields, int setup_ref_array(THD *thd, Item ***rref_pointer_array, uint elements);
List <Item> &all_fields, ORDER *order); int setup_order(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
int setup_group(THD *thd,TABLE_LIST *tables,List<Item> &fields, List<Item> &fields, List <Item> &all_fields, ORDER *order);
List<Item> &all_fields, ORDER *order, int setup_group(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
List<Item> &fields, List<Item> &all_fields, ORDER *order,
bool *hidden_group_fields); bool *hidden_group_fields);
int handle_select(THD *thd, LEX *lex, select_result *result); int handle_select(THD *thd, LEX *lex, select_result *result);
int mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &list,COND *conds, int mysql_select(THD *thd, Item ***rref_pointer_array,
ORDER *order, ORDER *group,Item *having,ORDER *proc_param, TABLE_LIST *tables, uint wild_num, List<Item> &list,
ulong select_type,select_result *result, COND *conds, uint og_num, ORDER *order, ORDER *group,
SELECT_LEX_UNIT *unit, SELECT_LEX *select_lex, Item *having, ORDER *proc_param, ulong select_type,
bool fake_select_lex); select_result *result, SELECT_LEX_UNIT *unit,
SELECT_LEX *select_lex, bool fake_select_lex);
void free_ulderlayed_joins(THD *thd, SELECT_LEX *select);
void fix_tables_pointers(SELECT_LEX *select_lex); void fix_tables_pointers(SELECT_LEX *select_lex);
int mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, int mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit,
select_result *result); select_result *result);
...@@ -440,7 +443,7 @@ int mysql_alter_table(THD *thd, char *new_db, char *new_name, ...@@ -440,7 +443,7 @@ int mysql_alter_table(THD *thd, char *new_db, char *new_name,
List<create_field> &fields, List<create_field> &fields,
List<Key> &keys,List<Alter_drop> &drop_list, List<Key> &keys,List<Alter_drop> &drop_list,
List<Alter_column> &alter_list, List<Alter_column> &alter_list,
ORDER *order, uint order_num, ORDER *order,
bool drop_primary, bool drop_primary,
enum enum_duplicates handle_duplicates, enum enum_duplicates handle_duplicates,
enum enum_enable_or_disable keys_onoff=LEAVE_AS_IS, enum enum_enable_or_disable keys_onoff=LEAVE_AS_IS,
...@@ -456,7 +459,7 @@ int mysql_drop_index(THD *thd, TABLE_LIST *table_list, ...@@ -456,7 +459,7 @@ int mysql_drop_index(THD *thd, TABLE_LIST *table_list,
List<Alter_drop> &drop_list); List<Alter_drop> &drop_list);
int mysql_update(THD *thd,TABLE_LIST *tables,List<Item> &fields, int mysql_update(THD *thd,TABLE_LIST *tables,List<Item> &fields,
List<Item> &values,COND *conds, List<Item> &values,COND *conds,
ORDER *order, ha_rows limit, uint order_num, ORDER *order, ha_rows limit,
enum enum_duplicates handle_duplicates); enum enum_duplicates handle_duplicates);
int mysql_multi_update(THD *thd, TABLE_LIST *table_list, int mysql_multi_update(THD *thd, TABLE_LIST *table_list,
List<Item> *fields, List<Item> *values, List<Item> *fields, List<Item> *values,
...@@ -575,15 +578,17 @@ SQL_SELECT *make_select(TABLE *head, table_map const_tables, ...@@ -575,15 +578,17 @@ SQL_SELECT *make_select(TABLE *head, table_map const_tables,
enum find_item_error_report_type {REPORT_ALL_ERRORS, REPORT_EXCEPT_NOT_FOUND, enum find_item_error_report_type {REPORT_ALL_ERRORS, REPORT_EXCEPT_NOT_FOUND,
IGNORE_ERRORS}; IGNORE_ERRORS};
extern const Item **not_found_item; extern const Item **not_found_item;
Item ** find_item_in_list(Item *item, List<Item> &items, Item ** find_item_in_list(Item *item, List<Item> &items, uint *counter,
find_item_error_report_type report_error); find_item_error_report_type report_error);
bool insert_fields(THD *thd,TABLE_LIST *tables, bool insert_fields(THD *thd,TABLE_LIST *tables,
const char *db_name, const char *table_name, const char *db_name, const char *table_name,
List_iterator<Item> *it); List_iterator<Item> *it);
bool setup_tables(TABLE_LIST *tables); bool setup_tables(TABLE_LIST *tables);
int setup_fields(THD *thd,TABLE_LIST *tables,List<Item> &item, int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
bool set_query_id,List<Item> *sum_func_list, List<Item> *sum_func_list, uint wild_num);
bool allow_sum_func); int setup_fields(THD *thd, Item** ref_pointer_array, TABLE_LIST *tables,
List<Item> &item, bool set_query_id,
List<Item> *sum_func_list, bool allow_sum_func);
int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds); int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds);
int setup_ftfuncs(SELECT_LEX* select); int setup_ftfuncs(SELECT_LEX* select);
int init_ftfuncs(THD *thd, SELECT_LEX* select, bool no_order); int init_ftfuncs(THD *thd, SELECT_LEX* select, bool no_order);
......
...@@ -2012,11 +2012,15 @@ const Item **not_found_item= (const Item**) 0x1; ...@@ -2012,11 +2012,15 @@ const Item **not_found_item= (const Item**) 0x1;
/* /*
Find Item in list of items (find_field_in_tables analog) Find Item in list of items (find_field_in_tables analog)
TODO
is it better return only counter?
SYNOPSIS SYNOPSIS
find_item_in_list() find_item_in_list()
find - item to find find - item to find
items - list of items items - list of items
counter - to return number of found item
report_error report_error
REPORT_ALL_ERRORS - report errors, return 0 if error REPORT_ALL_ERRORS - report errors, return 0 if error
REPORT_EXCEPT_NOT_FOUND - do not report 'not found' error and return not_ found_item, report other errors, return 0 REPORT_EXCEPT_NOT_FOUND - do not report 'not found' error and return not_ found_item, report other errors, return 0
...@@ -2033,7 +2037,7 @@ const Item **not_found_item= (const Item**) 0x1; ...@@ -2033,7 +2037,7 @@ const Item **not_found_item= (const Item**) 0x1;
*/ */
Item ** Item **
find_item_in_list(Item *find, List<Item> &items, find_item_in_list(Item *find, List<Item> &items, uint *counter,
find_item_error_report_type report_error) find_item_error_report_type report_error)
{ {
List_iterator<Item> li(items); List_iterator<Item> li(items);
...@@ -2046,8 +2050,10 @@ find_item_in_list(Item *find, List<Item> &items, ...@@ -2046,8 +2050,10 @@ find_item_in_list(Item *find, List<Item> &items,
table_name= ((Item_ident*) find)->table_name; table_name= ((Item_ident*) find)->table_name;
} }
uint i= 0;
while ((item=li++)) while ((item=li++))
{ {
i++;
if (field_name && item->type() == Item::FIELD_ITEM) if (field_name && item->type() == Item::FIELD_ITEM)
{ {
if (!my_strcasecmp(system_charset_info, if (!my_strcasecmp(system_charset_info,
...@@ -2064,11 +2070,13 @@ find_item_in_list(Item *find, List<Item> &items, ...@@ -2064,11 +2070,13 @@ find_item_in_list(Item *find, List<Item> &items,
find->full_name(), current_thd->where); find->full_name(), current_thd->where);
return (Item**) 0; return (Item**) 0;
} }
found=li.ref(); found= li.ref();
*counter= i;
} }
else if (!strcmp(((Item_field*) item)->table_name,table_name)) else if (!strcmp(((Item_field*) item)->table_name,table_name))
{ {
found=li.ref(); found= li.ref();
*counter= i;
break; break;
} }
} }
...@@ -2078,7 +2086,8 @@ find_item_in_list(Item *find, List<Item> &items, ...@@ -2078,7 +2086,8 @@ find_item_in_list(Item *find, List<Item> &items,
!my_strcasecmp(system_charset_info, !my_strcasecmp(system_charset_info,
item->name,find->name))) item->name,find->name)))
{ {
found=li.ref(); found= li.ref();
*counter= i;
break; break;
} }
} }
...@@ -2096,30 +2105,26 @@ find_item_in_list(Item *find, List<Item> &items, ...@@ -2096,30 +2105,26 @@ find_item_in_list(Item *find, List<Item> &items,
} }
/**************************************************************************** /****************************************************************************
** Check that all given fields exists and fill struct with current data ** Expand all '*' in given fields
****************************************************************************/ ****************************************************************************/
int setup_fields(THD *thd, TABLE_LIST *tables, List<Item> &fields, int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
bool set_query_id, List<Item> *sum_func_list, List<Item> *sum_func_list,
bool allow_sum_func) uint wild_num)
{ {
if (!wild_num)
return 0;
reg2 Item *item; reg2 Item *item;
List_iterator<Item> it(fields); List_iterator<Item> it(fields);
DBUG_ENTER("setup_fields"); while ( wild_num && (item= it++))
{
thd->set_query_id=set_query_id;
thd->allow_sum_func= allow_sum_func;
thd->where="field list";
while ((item=it++))
{
if (item->type() == Item::FIELD_ITEM && ((Item_field*) item)->field_name && if (item->type() == Item::FIELD_ITEM && ((Item_field*) item)->field_name &&
((Item_field*) item)->field_name[0] == '*') ((Item_field*) item)->field_name[0] == '*')
{ {
uint elem= fields.elements; uint elem= fields.elements;
if (insert_fields(thd,tables,((Item_field*) item)->db_name, if (insert_fields(thd,tables,((Item_field*) item)->db_name,
((Item_field*) item)->table_name, &it)) ((Item_field*) item)->table_name, &it))
DBUG_RETURN(-1); /* purecov: inspected */ return (-1);
if (sum_func_list) if (sum_func_list)
{ {
/* /*
...@@ -2129,22 +2134,43 @@ int setup_fields(THD *thd, TABLE_LIST *tables, List<Item> &fields, ...@@ -2129,22 +2134,43 @@ int setup_fields(THD *thd, TABLE_LIST *tables, List<Item> &fields,
*/ */
sum_func_list->elements+= fields.elements - elem; sum_func_list->elements+= fields.elements - elem;
} }
} wild_num--;
else
{
if (item->check_cols(1) ||
item->fix_fields(thd, tables, it.ref()))
DBUG_RETURN(-1); /* purecov: inspected */
item= *(it.ref()); //Item can be chenged in fix fields
if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM &&
sum_func_list)
item->split_sum_func(*sum_func_list);
thd->used_tables|=item->used_tables();
} }
} }
DBUG_RETURN(test(thd->fatal_error || thd->net.report_error)); return 0;
} }
/****************************************************************************
** Check that all given fields exists and fill struct with current data
****************************************************************************/
int setup_fields(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
List<Item> &fields, bool set_query_id,
List<Item> *sum_func_list, bool allow_sum_func)
{
reg2 Item *item;
List_iterator<Item> it(fields);
DBUG_ENTER("setup_fields");
thd->set_query_id=set_query_id;
thd->allow_sum_func= allow_sum_func;
thd->where="field list";
for (uint i= 0; (item= it++); i++)
{
if (item->check_cols(1) ||
item->fix_fields(thd, tables, it.ref()))
DBUG_RETURN(-1); /* purecov: inspected */
item= *(it.ref()); //Item can be chenged in fix fields
if (ref_pointer_array)
ref_pointer_array[i]= item;
if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM &&
sum_func_list)
item->split_sum_func(ref_pointer_array, *sum_func_list);
thd->used_tables|=item->used_tables();
}
DBUG_RETURN(test(thd->fatal_error || thd->net.report_error));
}
/* /*
Remap table numbers if INSERT ... SELECT Remap table numbers if INSERT ... SELECT
...@@ -2459,7 +2485,7 @@ int mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys) ...@@ -2459,7 +2485,7 @@ int mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys)
create_info.table_charset=default_charset_info; create_info.table_charset=default_charset_info;
DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->real_name, DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->real_name,
&create_info, table_list, &create_info, table_list,
fields, keys, drop, alter, (ORDER*)0, FALSE, fields, keys, drop, alter, 0, (ORDER*)0, FALSE,
DUP_ERROR)); DUP_ERROR));
} }
...@@ -2476,7 +2502,7 @@ int mysql_drop_index(THD *thd, TABLE_LIST *table_list, List<Alter_drop> &drop) ...@@ -2476,7 +2502,7 @@ int mysql_drop_index(THD *thd, TABLE_LIST *table_list, List<Alter_drop> &drop)
create_info.table_charset=default_charset_info; create_info.table_charset=default_charset_info;
DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->real_name, DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->real_name,
&create_info, table_list, &create_info, table_list,
fields, keys, drop, alter, (ORDER*)0, FALSE, fields, keys, drop, alter, 0, (ORDER*)0, FALSE,
DUP_ERROR)); DUP_ERROR));
} }
......
...@@ -376,7 +376,7 @@ struct system_variables ...@@ -376,7 +376,7 @@ struct system_variables
CONVERT *convert_set; CONVERT *convert_set;
}; };
void free_tmp_table(THD *thd, TABLE *entry);
/* /*
For each client connection we create a separate thread with THD serving as For each client connection we create a separate thread with THD serving as
a thread/connection descriptor a thread/connection descriptor
...@@ -486,6 +486,7 @@ class THD :public ilink { ...@@ -486,6 +486,7 @@ class THD :public ilink {
CHARSET_INFO *db_charset; CHARSET_INFO *db_charset;
CHARSET_INFO *thd_charset; CHARSET_INFO *thd_charset;
List<Item> *possible_loops; // Items that may cause loops in subselects List<Item> *possible_loops; // Items that may cause loops in subselects
List<TABLE> temporary_tables_should_be_free; // list of temporary tables
List <MYSQL_ERROR> warn_list; List <MYSQL_ERROR> warn_list;
uint warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_END]; uint warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_END];
uint total_warn_count, old_total_warn_count; uint total_warn_count, old_total_warn_count;
...@@ -640,6 +641,17 @@ class THD :public ilink { ...@@ -640,6 +641,17 @@ class THD :public ilink {
net.report_error= 0; net.report_error= 0;
} }
void add_possible_loop(Item *); void add_possible_loop(Item *);
void free_tmp_tables()
{
if (temporary_tables_should_be_free.elements)
{
List_iterator_fast<TABLE> lt(temporary_tables_should_be_free);
TABLE *table;
while ((table= lt++))
free_tmp_table(this,table);
temporary_tables_should_be_free.empty();
}
}
}; };
/* /*
......
...@@ -92,6 +92,7 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order, ...@@ -92,6 +92,7 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order,
if ((select && select->check_quick(safe_update, limit)) || !limit) if ((select && select->check_quick(safe_update, limit)) || !limit)
{ {
delete select; delete select;
free_ulderlayed_joins(thd, &thd->lex.select_lex);
send_ok(thd,0L); send_ok(thd,0L);
DBUG_RETURN(0); // Nothing to delete DBUG_RETURN(0); // Nothing to delete
} }
...@@ -103,6 +104,7 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order, ...@@ -103,6 +104,7 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order,
if (safe_update && !using_limit) if (safe_update && !using_limit)
{ {
delete select; delete select;
free_ulderlayed_joins(thd, &thd->lex.select_lex);
send_error(thd,ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE); send_error(thd,ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE);
DBUG_RETURN(1); DBUG_RETURN(1);
} }
...@@ -124,7 +126,7 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order, ...@@ -124,7 +126,7 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order,
table->io_cache = (IO_CACHE *) my_malloc(sizeof(IO_CACHE), table->io_cache = (IO_CACHE *) my_malloc(sizeof(IO_CACHE),
MYF(MY_FAE | MY_ZEROFILL)); MYF(MY_FAE | MY_ZEROFILL));
if (setup_order(thd, &tables, fields, all_fields, order) || if (setup_order(thd, 0, &tables, fields, all_fields, order) ||
!(sortorder=make_unireg_sortorder(order, &length)) || !(sortorder=make_unireg_sortorder(order, &length)) ||
(table->found_records = filesort(thd, table, sortorder, length, (table->found_records = filesort(thd, table, sortorder, length,
(SQL_SELECT *) 0, HA_POS_ERROR, (SQL_SELECT *) 0, HA_POS_ERROR,
...@@ -132,6 +134,7 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order, ...@@ -132,6 +134,7 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order,
== HA_POS_ERROR) == HA_POS_ERROR)
{ {
delete select; delete select;
free_ulderlayed_joins(thd, &thd->lex.select_lex);
DBUG_RETURN(-1); // This will force out message DBUG_RETURN(-1); // This will force out message
} }
} }
...@@ -207,6 +210,7 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order, ...@@ -207,6 +210,7 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order,
thd->lock=0; thd->lock=0;
} }
delete select; delete select;
free_ulderlayed_joins(thd, &thd->lex.select_lex);
if (error >= 0 || thd->net.report_error) if (error >= 0 || thd->net.report_error)
send_error(thd,thd->killed ? ER_SERVER_SHUTDOWN: 0); send_error(thd,thd->killed ? ER_SERVER_SHUTDOWN: 0);
else else
......
...@@ -58,7 +58,8 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t) ...@@ -58,7 +58,8 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
if (!(res=open_and_lock_tables(thd,tables))) if (!(res=open_and_lock_tables(thd,tables)))
{ {
if (setup_fields(thd,tables,item_list,0,0,1)) if (setup_wild(thd, tables, item_list, 0, sl->with_wild) ||
setup_fields(thd, 0, tables, item_list, 0, 0, 1))
{ {
res=-1; res=-1;
goto exit; goto exit;
...@@ -87,9 +88,11 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t) ...@@ -87,9 +88,11 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
SELECT_LEX_NODE *save_current_select= lex->current_select; SELECT_LEX_NODE *save_current_select= lex->current_select;
lex->current_select= sl; lex->current_select= sl;
res= mysql_select(thd, tables, sl->item_list, res= mysql_select(thd, &sl->ref_pointer_array, tables, sl->with_wild,
sl->where, (ORDER *) sl->order_list.first, sl->item_list, sl->where,
(ORDER*) sl->group_list.first, sl->order_list.elements+sl->group_list.elements,
(ORDER *) sl->order_list.first,
(ORDER *) sl->group_list.first,
sl->having, (ORDER*) NULL, sl->having, (ORDER*) NULL,
sl->options | thd->options | SELECT_NO_UNLOCK, sl->options | thd->options | SELECT_NO_UNLOCK,
derived_result, unit, sl, 0); derived_result, unit, sl, 0);
...@@ -122,6 +125,8 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t) ...@@ -122,6 +125,8 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
} }
if (res) if (res)
free_tmp_table(thd,table); free_tmp_table(thd,table);
else
thd->temporary_tables_should_be_free.push_front(table);
exit: exit:
close_thread_tables(thd); close_thread_tables(thd);
} }
......
...@@ -25,7 +25,7 @@ int mysql_do(THD *thd, List<Item> &values) ...@@ -25,7 +25,7 @@ int mysql_do(THD *thd, List<Item> &values)
List_iterator<Item> li(values); List_iterator<Item> li(values);
Item *value; Item *value;
DBUG_ENTER("mysql_do"); DBUG_ENTER("mysql_do");
if (setup_fields(thd,0, values, 0, 0, 0)) if (setup_fields(thd, 0, 0, values, 0, 0, 0))
DBUG_RETURN(-1); DBUG_RETURN(-1);
while ((value = li++)) while ((value = li++))
value->val_int(); value->val_int();
......
...@@ -81,7 +81,7 @@ check_insert_fields(THD *thd,TABLE *table,List<Item> &fields, ...@@ -81,7 +81,7 @@ check_insert_fields(THD *thd,TABLE *table,List<Item> &fields,
thd->dupp_field=0; thd->dupp_field=0;
if (setup_tables(&table_list) || if (setup_tables(&table_list) ||
setup_fields(thd,&table_list,fields,1,0,0)) setup_fields(thd, 0, &table_list,fields,1,0,0))
return -1; return -1;
if (thd->dupp_field) if (thd->dupp_field)
{ {
...@@ -171,10 +171,10 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, ...@@ -171,10 +171,10 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
values= its++; values= its++;
if (check_insert_fields(thd,table,fields,*values,1) || if (check_insert_fields(thd,table,fields,*values,1) ||
setup_tables(insert_table_list) || setup_tables(insert_table_list) ||
setup_fields(thd, insert_table_list, *values, 0, 0, 0) || setup_fields(thd, 0, insert_table_list, *values, 0, 0, 0) ||
(duplic == DUP_UPDATE && (duplic == DUP_UPDATE &&
(setup_fields(thd, insert_table_list, update_fields, 0, 0, 0) || (setup_fields(thd, 0, insert_table_list, update_fields, 0, 0, 0) ||
setup_fields(thd, insert_table_list, update_values, 0, 0, 0)))) setup_fields(thd, 0, insert_table_list, update_values, 0, 0, 0))))
goto abort; goto abort;
if (find_real_table_in_list(table_list->next, if (find_real_table_in_list(table_list->next,
table_list->db, table_list->real_name)) table_list->db, table_list->real_name))
...@@ -194,7 +194,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, ...@@ -194,7 +194,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
MYF(0),counter); MYF(0),counter);
goto abort; goto abort;
} }
if (setup_fields(thd,insert_table_list,*values,0,0,0)) if (setup_fields(thd, 0, insert_table_list, *values, 0, 0, 0))
goto abort; goto abort;
} }
its.rewind (); its.rewind ();
...@@ -381,11 +381,13 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, ...@@ -381,11 +381,13 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
thd->cuted_fields); thd->cuted_fields);
::send_ok(thd,info.copied+info.deleted,(ulonglong)id,buff); ::send_ok(thd,info.copied+info.deleted,(ulonglong)id,buff);
} }
free_ulderlayed_joins(thd, &thd->lex.select_lex);
DBUG_RETURN(0); DBUG_RETURN(0);
abort: abort:
if (lock_type == TL_WRITE_DELAYED) if (lock_type == TL_WRITE_DELAYED)
end_delayed_insert(thd); end_delayed_insert(thd);
free_ulderlayed_joins(thd, &thd->lex.select_lex);
DBUG_RETURN(-1); DBUG_RETURN(-1);
} }
......
...@@ -944,6 +944,7 @@ void st_select_lex_node::init_query() ...@@ -944,6 +944,7 @@ void st_select_lex_node::init_query()
next= master= slave= link_next= 0; next= master= slave= link_next= 0;
prev= link_prev= 0; prev= link_prev= 0;
dependent= 0; dependent= 0;
ref_pointer_array= 0;
} }
void st_select_lex_node::init_select() void st_select_lex_node::init_select()
...@@ -967,6 +968,8 @@ void st_select_lex_unit::init_query() ...@@ -967,6 +968,8 @@ void st_select_lex_unit::init_query()
union_option= 0; union_option= 0;
prepared= optimized= executed= 0; prepared= optimized= executed= 0;
item= 0; item= 0;
union_result= 0;
table= 0;
} }
void st_select_lex::init_query() void st_select_lex::init_query()
...@@ -979,6 +982,7 @@ void st_select_lex::init_query() ...@@ -979,6 +982,7 @@ void st_select_lex::init_query()
join= 0; join= 0;
olap= UNSPECIFIED_OLAP_TYPE; olap= UNSPECIFIED_OLAP_TYPE;
having_fix_field= 0; having_fix_field= 0;
with_wild= 0;
} }
void st_select_lex::init_select() void st_select_lex::init_select()
...@@ -1105,12 +1109,12 @@ bool st_select_lex_node::add_item_to_list(THD *thd, Item *item) ...@@ -1105,12 +1109,12 @@ bool st_select_lex_node::add_item_to_list(THD *thd, Item *item)
bool st_select_lex_node::add_group_to_list(THD *thd, Item *item, bool asc) bool st_select_lex_node::add_group_to_list(THD *thd, Item *item, bool asc)
{ {
return 1; return 1;
} }
bool st_select_lex_node::add_order_to_list(THD *thd, Item *item, bool asc) bool st_select_lex_node::add_order_to_list(THD *thd, Item *item, bool asc)
{ {
return add_to_list(thd, order_list,item,asc); return add_to_list(thd, order_list, item, asc);
} }
bool st_select_lex_node::add_ftfunc_to_list(Item_func_match *func) bool st_select_lex_node::add_ftfunc_to_list(Item_func_match *func)
......
...@@ -208,8 +208,11 @@ class st_select_lex_node { ...@@ -208,8 +208,11 @@ class st_select_lex_node {
List<List_item> expr_list; List<List_item> expr_list;
List<List_item> when_list; /* WHEN clause (expression) */ List<List_item> when_list; /* WHEN clause (expression) */
ha_rows select_limit, offset_limit; /* LIMIT clause parameters */ ha_rows select_limit, offset_limit; /* LIMIT clause parameters */
bool with_sum_func; // Arrays of pointers to top elements of all_fields list
bool create_refs; Item **ref_pointer_array;
uint with_sum_func; /* sum function indicator and number of it */
bool create_refs;
bool dependent; /* dependent from outer select subselect */ bool dependent; /* dependent from outer select subselect */
static void *operator new(size_t size) static void *operator new(size_t size)
...@@ -269,11 +272,10 @@ class select_union; ...@@ -269,11 +272,10 @@ class select_union;
class st_select_lex_unit: public st_select_lex_node { class st_select_lex_unit: public st_select_lex_node {
protected: protected:
List<Item> item_list; List<Item> item_list;
List<JOIN*> joins; /* list of *JOINs, to delete it in cleanup() */
TABLE_LIST result_table_list; TABLE_LIST result_table_list;
select_union *union_result; select_union *union_result;
TABLE *table; /* temporary table using for appending UNION results */ TABLE *table; /* temporary table using for appending UNION results */
THD *thd;
select_result *result; select_result *result;
int res; int res;
bool describe, found_rows_for_union, bool describe, found_rows_for_union,
...@@ -290,6 +292,8 @@ class st_select_lex_unit: public st_select_lex_node { ...@@ -290,6 +292,8 @@ class st_select_lex_unit: public st_select_lex_node {
ha_rows select_limit_cnt, offset_limit_cnt; ha_rows select_limit_cnt, offset_limit_cnt;
/* not NULL if union used in subselect, point to subselect item */ /* not NULL if union used in subselect, point to subselect item */
Item_subselect *item; Item_subselect *item;
THD *thd;
uint union_option; uint union_option;
void init_query(); void init_query();
...@@ -336,6 +340,7 @@ class st_select_lex: public st_select_lex_node ...@@ -336,6 +340,7 @@ class st_select_lex: public st_select_lex_node
const char *type; /* type of select for EXPLAIN */ const char *type; /* type of select for EXPLAIN */
uint in_sum_expr; uint in_sum_expr;
uint select_number; /* number of select (used for EXPLAIN) */ uint select_number; /* number of select (used for EXPLAIN) */
uint with_wild; /* item list contain '*' */
bool braces; /* SELECT ... UNION (SELECT ... ) <- this braces */ bool braces; /* SELECT ... UNION (SELECT ... ) <- this braces */
/* TRUE when having fix field called in processing of this SELECT */ /* TRUE when having fix field called in processing of this SELECT */
bool having_fix_field; bool having_fix_field;
......
...@@ -147,12 +147,20 @@ class base_list :public Sql_alloc { ...@@ -147,12 +147,20 @@ class base_list :public Sql_alloc {
class base_list_iterator class base_list_iterator
{ {
protected:
base_list *list; base_list *list;
list_node **el,**prev,*current; list_node **el,**prev,*current;
void sublist(base_list &ls, uint elm)
{
ls.first= *el;
ls.last= list->last;
ls.elements= elm;
}
public: public:
base_list_iterator(base_list &list_par) :list(&list_par),el(&list_par.first), base_list_iterator(base_list &list_par)
prev(0),current(0) :list(&list_par), el(&list_par.first), prev(0), current(0)
{} {}
inline void *next(void) inline void *next(void)
{ {
prev=el; prev=el;
...@@ -212,7 +220,6 @@ class base_list_iterator ...@@ -212,7 +220,6 @@ class base_list_iterator
friend class error_list_iterator; friend class error_list_iterator;
}; };
template <class T> class List :public base_list template <class T> class List :public base_list
{ {
public: public:
...@@ -260,6 +267,10 @@ template <class T> class List_iterator_fast :public base_list_iterator ...@@ -260,6 +267,10 @@ template <class T> class List_iterator_fast :public base_list_iterator
List_iterator_fast(List<T> &a) : base_list_iterator(a) {} List_iterator_fast(List<T> &a) : base_list_iterator(a) {}
inline T* operator++(int) { return (T*) base_list_iterator::next_fast(); } inline T* operator++(int) { return (T*) base_list_iterator::next_fast(); }
inline void rewind(void) { base_list_iterator::rewind(); } inline void rewind(void) { base_list_iterator::rewind(); }
void sublist(List<T> &list, uint el)
{
base_list_iterator::sublist(list, el);
}
}; };
......
...@@ -117,7 +117,8 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, ...@@ -117,7 +117,8 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
else else
{ // Part field list { // Part field list
thd->dupp_field=0; thd->dupp_field=0;
if (setup_tables(table_list) || setup_fields(thd,table_list,fields,1,0,0)) if (setup_tables(table_list) ||
setup_fields(thd, 0, table_list, fields, 1, 0, 0))
DBUG_RETURN(-1); DBUG_RETURN(-1);
if (thd->dupp_field) if (thd->dupp_field)
{ {
......
...@@ -164,8 +164,10 @@ int handle_olaps(LEX *lex, SELECT_LEX *select_lex) ...@@ -164,8 +164,10 @@ int handle_olaps(LEX *lex, SELECT_LEX *select_lex)
if (setup_tables((TABLE_LIST *)select_lex->table_list.first) || if (setup_tables((TABLE_LIST *)select_lex->table_list.first) ||
setup_fields(lex->thd,(TABLE_LIST *)select_lex->table_list.first,select_lex->item_list,1,&all_fields,1) || setup_fields(lex->thd, 0, (TABLE_LIST *)select_lex->table_list.first,
setup_fields(lex->thd,(TABLE_LIST *)select_lex->table_list.first,item_list_copy,1,&all_fields,1)) select_lex->item_list, 1, &all_fields,1) ||
setup_fields(lex->thd, 0, (TABLE_LIST *)select_lex->table_list.first,
item_list_copy, 1, &all_fields, 1))
return -1; return -1;
if (select_lex->olap == CUBE_TYPE) if (select_lex->olap == CUBE_TYPE)
......
...@@ -1915,6 +1915,7 @@ mysql_execute_command(THD *thd) ...@@ -1915,6 +1915,7 @@ mysql_execute_command(THD *thd)
&lex->create_info, &lex->create_info,
tables, lex->create_list, tables, lex->create_list,
lex->key_list, lex->drop_list, lex->alter_list, lex->key_list, lex->drop_list, lex->alter_list,
select_lex->order_list.elements,
(ORDER *) select_lex->order_list.first, (ORDER *) select_lex->order_list.first,
lex->drop_primary, lex->duplicates, lex->drop_primary, lex->duplicates,
lex->alter_keys_onoff, lex->simple_alter); lex->alter_keys_onoff, lex->simple_alter);
...@@ -2026,8 +2027,8 @@ mysql_execute_command(THD *thd) ...@@ -2026,8 +2027,8 @@ mysql_execute_command(THD *thd)
res= mysql_alter_table(thd, NullS, NullS, &create_info, res= mysql_alter_table(thd, NullS, NullS, &create_info,
tables, lex->create_list, tables, lex->create_list,
lex->key_list, lex->drop_list, lex->alter_list, lex->key_list, lex->drop_list, lex->alter_list,
(ORDER *) 0, 0, (ORDER *) 0,
0,DUP_ERROR); 0, DUP_ERROR);
} }
else else
res = mysql_optimize_table(thd, tables, &lex->check_opt); res = mysql_optimize_table(thd, tables, &lex->check_opt);
...@@ -2047,6 +2048,7 @@ mysql_execute_command(THD *thd) ...@@ -2047,6 +2048,7 @@ mysql_execute_command(THD *thd)
select_lex->item_list, select_lex->item_list,
lex->value_list, lex->value_list,
select_lex->where, select_lex->where,
select_lex->order_list.elements,
(ORDER *) select_lex->order_list.first, (ORDER *) select_lex->order_list.first,
select_lex->select_limit, select_lex->select_limit,
lex->duplicates); lex->duplicates);
...@@ -2246,10 +2248,12 @@ mysql_execute_command(THD *thd) ...@@ -2246,10 +2248,12 @@ mysql_execute_command(THD *thd)
if (!thd->fatal_error && (result= new multi_delete(thd,aux_tables, if (!thd->fatal_error && (result= new multi_delete(thd,aux_tables,
table_count))) table_count)))
{ {
res= mysql_select(thd,select_lex->get_table_list(), res= mysql_select(thd, &select_lex->ref_pointer_array,
select_lex->get_table_list(),
select_lex->with_wild,
select_lex->item_list, select_lex->item_list,
select_lex->where, select_lex->where,
(ORDER *)NULL,(ORDER *)NULL,(Item *)NULL, 0, (ORDER *)NULL, (ORDER *)NULL, (Item *)NULL,
(ORDER *)NULL, (ORDER *)NULL,
select_lex->options | thd->options | select_lex->options | thd->options |
SELECT_NO_JOIN_CACHE, SELECT_NO_JOIN_CACHE,
...@@ -2741,6 +2745,7 @@ mysql_execute_command(THD *thd) ...@@ -2741,6 +2745,7 @@ mysql_execute_command(THD *thd)
send_ok(thd); send_ok(thd);
break; break;
} }
thd->free_tmp_tables();
thd->proc_info="query end"; // QQ thd->proc_info="query end"; // QQ
if (res < 0) if (res < 0)
send_error(thd,thd->killed ? ER_SERVER_SHUTDOWN : 0); send_error(thd,thd->killed ? ER_SERVER_SHUTDOWN : 0);
...@@ -2988,6 +2993,7 @@ mysql_init_query(THD *thd) ...@@ -2988,6 +2993,7 @@ mysql_init_query(THD *thd)
LEX *lex=&thd->lex; LEX *lex=&thd->lex;
lex->unit.init_query(); lex->unit.init_query();
lex->unit.init_select(); lex->unit.init_select();
lex->unit.thd= thd;
lex->select_lex.init_query(); lex->select_lex.init_query();
lex->value_list.empty(); lex->value_list.empty();
lex->param_list.empty(); lex->param_list.empty();
...@@ -3044,6 +3050,7 @@ mysql_new_select(LEX *lex, bool move_down) ...@@ -3044,6 +3050,7 @@ mysql_new_select(LEX *lex, bool move_down)
return 1; return 1;
unit->init_query(); unit->init_query();
unit->init_select(); unit->init_select();
unit->thd= lex->thd;
unit->include_down(lex->current_select); unit->include_down(lex->current_select);
select_lex->include_down(unit); select_lex->include_down(unit);
} }
......
...@@ -365,7 +365,7 @@ static int check_prepare_fields(THD *thd,TABLE *table, List<Item> &fields, ...@@ -365,7 +365,7 @@ static int check_prepare_fields(THD *thd,TABLE *table, List<Item> &fields,
thd->dupp_field=0; thd->dupp_field=0;
if (setup_tables(&table_list) || if (setup_tables(&table_list) ||
setup_fields(thd,&table_list,fields,1,0,0)) setup_fields(thd, 0, &table_list, fields, 1, 0, 0))
return -1; return -1;
if (thd->dupp_field) if (thd->dupp_field)
{ {
...@@ -446,8 +446,9 @@ static bool mysql_test_upd_fields(PREP_STMT *stmt, TABLE_LIST *table_list, ...@@ -446,8 +446,9 @@ static bool mysql_test_upd_fields(PREP_STMT *stmt, TABLE_LIST *table_list,
if (!(table = open_ltable(thd,table_list,table_list->lock_type))) if (!(table = open_ltable(thd,table_list,table_list->lock_type)))
DBUG_RETURN(1); DBUG_RETURN(1);
if (setup_tables(table_list) || setup_fields(thd,table_list,fields,1,0,0) || if (setup_tables(table_list) ||
setup_conds(thd,table_list,&conds)) setup_fields(thd, 0, table_list, fields, 1, 0, 0) ||
setup_conds(thd, table_list, &conds))
DBUG_RETURN(1); DBUG_RETURN(1);
/* /*
...@@ -488,10 +489,11 @@ static bool mysql_test_select_fields(PREP_STMT *stmt, TABLE_LIST *tables, ...@@ -488,10 +489,11 @@ static bool mysql_test_select_fields(PREP_STMT *stmt, TABLE_LIST *tables,
thd->used_tables=0; // Updated by setup_fields thd->used_tables=0; // Updated by setup_fields
if (setup_tables(tables) || if (setup_tables(tables) ||
setup_fields(thd,tables,fields,1,&all_fields,1) || setup_fields(thd, 0, tables,fields,1,&all_fields,1) ||
setup_conds(thd,tables,&conds) || setup_conds(thd,tables,&conds) ||
setup_order(thd,tables,fields,all_fields,order) || setup_order(thd, 0, tables, fields, all_fields, order) ||
setup_group(thd,tables,fields,all_fields,group,&hidden_group_fields)) setup_group(thd, 0, tables, fields, all_fields, group,
&hidden_group_fields))
DBUG_RETURN(1); DBUG_RETURN(1);
if (having) if (having)
...@@ -502,7 +504,7 @@ static bool mysql_test_select_fields(PREP_STMT *stmt, TABLE_LIST *tables, ...@@ -502,7 +504,7 @@ static bool mysql_test_select_fields(PREP_STMT *stmt, TABLE_LIST *tables,
|| thd->fatal_error) || thd->fatal_error)
DBUG_RETURN(1); DBUG_RETURN(1);
if (having->with_sum_func) if (having->with_sum_func)
having->split_sum_func(all_fields); having->split_sum_func(0, all_fields);
} }
if (setup_ftfuncs(&thd->lex.select_lex)) if (setup_ftfuncs(&thd->lex.select_lex))
DBUG_RETURN(1); DBUG_RETURN(1);
......
This diff is collapsed.
...@@ -119,8 +119,10 @@ class TMP_TABLE_PARAM :public Sql_alloc ...@@ -119,8 +119,10 @@ class TMP_TABLE_PARAM :public Sql_alloc
{ {
public: public:
List<Item> copy_funcs; List<Item> copy_funcs;
List<Item> save_copy_funcs;
List_iterator_fast<Item> copy_funcs_it; List_iterator_fast<Item> copy_funcs_it;
Copy_field *copy_field, *copy_field_end; Copy_field *copy_field, *copy_field_end;
Copy_field *save_copy_field, *save_copy_field_end;
byte *group_buff; byte *group_buff;
Item_result_field **funcs; Item_result_field **funcs;
MI_COLUMNDEF *recinfo,*start_recinfo; MI_COLUMNDEF *recinfo,*start_recinfo;
...@@ -166,10 +168,13 @@ class JOIN :public Sql_alloc ...@@ -166,10 +168,13 @@ class JOIN :public Sql_alloc
List<Item> *fields; List<Item> *fields;
List<Item_buff> group_fields; List<Item_buff> group_fields;
TABLE *tmp_table; TABLE *tmp_table;
// used to store 2 possible tmp table of SELECT
TABLE *exec_tmp_table1, *exec_tmp_table2;
THD *thd; THD *thd;
Item_sum **sum_funcs; Item_sum **sum_funcs;
Procedure *procedure; Procedure *procedure;
Item *having; Item *having;
Item *tmp_having; // To store Having when processed tenporary table
uint select_options; uint select_options;
select_result *result; select_result *result;
TMP_TABLE_PARAM tmp_table_param; TMP_TABLE_PARAM tmp_table_param;
...@@ -178,6 +183,8 @@ class JOIN :public Sql_alloc ...@@ -178,6 +183,8 @@ class JOIN :public Sql_alloc
SELECT_LEX_UNIT *unit; SELECT_LEX_UNIT *unit;
// select that processed // select that processed
SELECT_LEX *select_lex; SELECT_LEX *select_lex;
JOIN *tmp_join; // copy of this JOIN to be used with temporary tables
bool select_distinct, //Is select distinct? bool select_distinct, //Is select distinct?
no_order, simple_order, simple_group, no_order, simple_order, simple_group,
...@@ -186,7 +193,11 @@ class JOIN :public Sql_alloc ...@@ -186,7 +193,11 @@ class JOIN :public Sql_alloc
buffer_result; buffer_result;
DYNAMIC_ARRAY keyuse; DYNAMIC_ARRAY keyuse;
Item::cond_result cond_value; Item::cond_result cond_value;
List<Item> all_fields; List<Item> all_fields; // to store all fields that used in query
//Above list changed to use temporary table
List<Item> tmp_all_fields1, tmp_all_fields2, tmp_all_fields3;
//Part, shared with list above, emulate following list
List<Item> tmp_fields_list1, tmp_fields_list2, tmp_fields_list3;
List<Item> & fields_list; // hold field list passed to mysql_select List<Item> & fields_list; // hold field list passed to mysql_select
int error; int error;
...@@ -194,11 +205,14 @@ class JOIN :public Sql_alloc ...@@ -194,11 +205,14 @@ class JOIN :public Sql_alloc
COND *conds; // ---"--- COND *conds; // ---"---
TABLE_LIST *tables_list; //hold 'tables' parameter of mysql_selec TABLE_LIST *tables_list; //hold 'tables' parameter of mysql_selec
SQL_SELECT *select; //created in optimisation phase SQL_SELECT *select; //created in optimisation phase
TABLE *exec_tmp_table; //used in 'exec' to hold temporary Item **ref_pointer_array; //used pointer reference for this select
// Copy of above to be used with different lists
Item **items0, **items1, **items2, **items3;
uint ref_pointer_array_size; // size of above in bytes
const char *zero_result_cause; // not 0 if exec must return zero result const char *zero_result_cause; // not 0 if exec must return zero result
my_bool union_part; // this subselect is part of union bool union_part; // this subselect is part of union
bool optimized; // flag to avoid double optimization in EXPLAIN
JOIN(THD *thd, List<Item> &fields, JOIN(THD *thd, List<Item> &fields,
ulong select_options, select_result *result): ulong select_options, select_result *result):
...@@ -208,14 +222,16 @@ class JOIN :public Sql_alloc ...@@ -208,14 +222,16 @@ class JOIN :public Sql_alloc
sort_and_group(0), first_record(0), sort_and_group(0), first_record(0),
do_send_rows(1), do_send_rows(1),
send_records(0), found_records(0), examined_rows(0), send_records(0), found_records(0), examined_rows(0),
exec_tmp_table1(0), exec_tmp_table2(0),
thd(thd), thd(thd),
sum_funcs(0), sum_funcs(0),
procedure(0), procedure(0),
having(0), having(0), tmp_having(0),
select_options(select_options), select_options(select_options),
result(result), result(result),
lock(thd->lock), lock(thd->lock),
select_lex(0), //for safety select_lex(0), //for safety
tmp_join(0),
select_distinct(test(select_options & SELECT_DISTINCT)), select_distinct(test(select_options & SELECT_DISTINCT)),
no_order(0), simple_order(0), simple_group(0), skip_sort_order(0), no_order(0), simple_order(0), simple_group(0), skip_sort_order(0),
need_tmp(0), need_tmp(0),
...@@ -226,8 +242,10 @@ class JOIN :public Sql_alloc ...@@ -226,8 +242,10 @@ class JOIN :public Sql_alloc
fields_list(fields), fields_list(fields),
error(0), error(0),
select(0), select(0),
exec_tmp_table(0), ref_pointer_array(0), items0(0), items1(0), items2(0), items3(0),
zero_result_cause(0) ref_pointer_array_size(0),
zero_result_cause(0),
optimized(0)
{ {
fields_list = fields; fields_list = fields;
bzero((char*) &keyuse,sizeof(keyuse)); bzero((char*) &keyuse,sizeof(keyuse));
...@@ -235,16 +253,23 @@ class JOIN :public Sql_alloc ...@@ -235,16 +253,23 @@ class JOIN :public Sql_alloc
tmp_table_param.end_write_records= HA_POS_ERROR; tmp_table_param.end_write_records= HA_POS_ERROR;
} }
int prepare(TABLE_LIST *tables, int prepare(Item ***rref_pointer_array, TABLE_LIST *tables, uint wind_num,
COND *conds, ORDER *order, ORDER *group, Item *having, COND *conds, uint og_num, ORDER *order, ORDER *group,
ORDER *proc_param, SELECT_LEX *select, SELECT_LEX_UNIT *unit, Item *having, ORDER *proc_param, SELECT_LEX *select,
bool fake_select_lex); SELECT_LEX_UNIT *unit, bool fake_select_lex);
int optimize(); int optimize();
int global_optimize();
int reinit(); int reinit();
void exec(); void exec();
int cleanup(THD *thd); int cleanup(THD *thd);
bool check_loop(uint id); bool check_loop(uint id);
void restore_tmp();
inline void init_items_ref_array()
{
items0= ref_pointer_array + all_fields.elements;
ref_pointer_array_size= all_fields.elements*sizeof(Item*);
memcpy(items0, ref_pointer_array, ref_pointer_array_size);
}
}; };
...@@ -263,7 +288,10 @@ TABLE *create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, ...@@ -263,7 +288,10 @@ TABLE *create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
void free_tmp_table(THD *thd, TABLE *entry); void free_tmp_table(THD *thd, TABLE *entry);
void count_field_types(TMP_TABLE_PARAM *param, List<Item> &fields, void count_field_types(TMP_TABLE_PARAM *param, List<Item> &fields,
bool reset_with_sum_func); bool reset_with_sum_func);
bool setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param,List<Item> &fields); bool setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param,
Item **ref_pointer_array,
List<Item> &new_list1, List<Item> &new_list2,
uint elements, List<Item> &fields);
void copy_fields(TMP_TABLE_PARAM *param); void copy_fields(TMP_TABLE_PARAM *param);
void copy_funcs(Item_result_field **func_ptr); void copy_funcs(Item_result_field **func_ptr);
bool create_myisam_from_heap(THD *thd, TABLE *table, TMP_TABLE_PARAM *param, bool create_myisam_from_heap(THD *thd, TABLE *table, TMP_TABLE_PARAM *param,
......
...@@ -37,7 +37,7 @@ static char *make_unique_key_name(const char *field_name,KEY *start,KEY *end); ...@@ -37,7 +37,7 @@ static char *make_unique_key_name(const char *field_name,KEY *start,KEY *end);
static int copy_data_between_tables(TABLE *from,TABLE *to, static int copy_data_between_tables(TABLE *from,TABLE *to,
List<create_field> &create, List<create_field> &create,
enum enum_duplicates handle_duplicates, enum enum_duplicates handle_duplicates,
ORDER *order, uint order_num, ORDER *order,
ha_rows *copied,ha_rows *deleted); ha_rows *copied,ha_rows *deleted);
/***************************************************************************** /*****************************************************************************
...@@ -1415,7 +1415,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -1415,7 +1415,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
List<create_field> &fields, List<create_field> &fields,
List<Key> &keys,List<Alter_drop> &drop_list, List<Key> &keys,List<Alter_drop> &drop_list,
List<Alter_column> &alter_list, List<Alter_column> &alter_list,
ORDER *order, uint order_num, ORDER *order,
bool drop_primary, bool drop_primary,
enum enum_duplicates handle_duplicates, enum enum_duplicates handle_duplicates,
enum enum_enable_or_disable keys_onoff, enum enum_enable_or_disable keys_onoff,
...@@ -1877,7 +1877,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -1877,7 +1877,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
if (!new_table->is_view) if (!new_table->is_view)
error=copy_data_between_tables(table,new_table,create_list, error=copy_data_between_tables(table,new_table,create_list,
handle_duplicates, handle_duplicates,
order, &copied, &deleted); order_num, order, &copied, &deleted);
thd->last_insert_id=next_insert_id; // Needed for correct log thd->last_insert_id=next_insert_id; // Needed for correct log
thd->count_cuted_fields=0; // Don`t calc cuted fields thd->count_cuted_fields=0; // Don`t calc cuted fields
new_table->time_stamp=save_time_stamp; new_table->time_stamp=save_time_stamp;
...@@ -2090,7 +2090,7 @@ static int ...@@ -2090,7 +2090,7 @@ static int
copy_data_between_tables(TABLE *from,TABLE *to, copy_data_between_tables(TABLE *from,TABLE *to,
List<create_field> &create, List<create_field> &create,
enum enum_duplicates handle_duplicates, enum enum_duplicates handle_duplicates,
ORDER *order, uint order_num, ORDER *order,
ha_rows *copied, ha_rows *copied,
ha_rows *deleted) ha_rows *deleted)
{ {
...@@ -2138,7 +2138,10 @@ copy_data_between_tables(TABLE *from,TABLE *to, ...@@ -2138,7 +2138,10 @@ copy_data_between_tables(TABLE *from,TABLE *to,
tables.db = from->table_cache_key; tables.db = from->table_cache_key;
error=1; error=1;
if (setup_order(thd, &tables, fields, all_fields, order) || if (setup_ref_array(thd, &thd->lex.select_lex.ref_pointer_array,
order_num)||
setup_order(thd, thd->lex.select_lex.ref_pointer_array,
&tables, fields, all_fields, order) ||
!(sortorder=make_unireg_sortorder(order, &length)) || !(sortorder=make_unireg_sortorder(order, &length)) ||
(from->found_records = filesort(thd, from, sortorder, length, (from->found_records = filesort(thd, from, sortorder, length,
(SQL_SELECT *) 0, HA_POS_ERROR, (SQL_SELECT *) 0, HA_POS_ERROR,
......
...@@ -108,7 +108,6 @@ bool select_union::flush() ...@@ -108,7 +108,6 @@ bool select_union::flush()
return 0; return 0;
} }
typedef JOIN * JOIN_P;
int st_select_lex_unit::prepare(THD *thd, select_result *result) int st_select_lex_unit::prepare(THD *thd, select_result *result)
{ {
DBUG_ENTER("st_select_lex_unit::prepare"); DBUG_ENTER("st_select_lex_unit::prepare");
...@@ -116,11 +115,9 @@ int st_select_lex_unit::prepare(THD *thd, select_result *result) ...@@ -116,11 +115,9 @@ int st_select_lex_unit::prepare(THD *thd, select_result *result)
if (prepared) if (prepared)
DBUG_RETURN(0); DBUG_RETURN(0);
prepared= 1; prepared= 1;
union_result=0;
res= 0; res= 0;
found_rows_for_union= 0; found_rows_for_union= 0;
TMP_TABLE_PARAM tmp_table_param; TMP_TABLE_PARAM tmp_table_param;
this->thd= thd;
this->result= result; this->result= result;
SELECT_LEX_NODE *lex_select_save= thd->lex.current_select; SELECT_LEX_NODE *lex_select_save= thd->lex.current_select;
SELECT_LEX *sl; SELECT_LEX *sl;
...@@ -143,7 +140,9 @@ int st_select_lex_unit::prepare(THD *thd, select_result *result) ...@@ -143,7 +140,9 @@ int st_select_lex_unit::prepare(THD *thd, select_result *result)
while ((item= it++)) while ((item= it++))
if (item_list.push_back(item)) if (item_list.push_back(item))
goto err; goto err;
if (setup_fields(thd,first_table,item_list,0,0,1)) if (setup_wild(thd, first_table, item_list, 0,
first_select()->with_wild) ||
setup_fields(thd, 0, first_table, item_list, 0, 0, 1))
goto err; goto err;
} }
...@@ -169,13 +168,11 @@ int st_select_lex_unit::prepare(THD *thd, select_result *result) ...@@ -169,13 +168,11 @@ int st_select_lex_unit::prepare(THD *thd, select_result *result)
union_result->tmp_table_param=&tmp_table_param; union_result->tmp_table_param=&tmp_table_param;
// prepare selects // prepare selects
joins.empty();
for (sl= first_select(); sl; sl= sl->next_select()) for (sl= first_select(); sl; sl= sl->next_select())
{ {
JOIN *join= new JOIN(thd, sl->item_list, JOIN *join= new JOIN(thd, sl->item_list,
sl->options | thd->options | SELECT_NO_UNLOCK, sl->options | thd->options | SELECT_NO_UNLOCK,
union_result); union_result);
joins.push_back(new JOIN_P(join));
thd->lex.current_select= sl; thd->lex.current_select= sl;
offset_limit_cnt= sl->offset_limit; offset_limit_cnt= sl->offset_limit;
select_limit_cnt= sl->select_limit+sl->offset_limit; select_limit_cnt= sl->select_limit+sl->offset_limit;
...@@ -184,8 +181,11 @@ int st_select_lex_unit::prepare(THD *thd, select_result *result) ...@@ -184,8 +181,11 @@ int st_select_lex_unit::prepare(THD *thd, select_result *result)
if (select_limit_cnt == HA_POS_ERROR) if (select_limit_cnt == HA_POS_ERROR)
sl->options&= ~OPTION_FOUND_ROWS; sl->options&= ~OPTION_FOUND_ROWS;
res= join->prepare((TABLE_LIST*) sl->table_list.first, res= join->prepare(&sl->ref_pointer_array,
(TABLE_LIST*) sl->table_list.first, sl->with_wild,
sl->where, sl->where,
((sl->braces) ? sl->order_list.elements : 0) +
sl->group_list.elements,
(sl->braces) ? (sl->braces) ?
(ORDER *)sl->order_list.first : (ORDER *) 0, (ORDER *)sl->order_list.first : (ORDER *) 0,
(ORDER*) sl->group_list.first, (ORDER*) sl->group_list.first,
...@@ -286,8 +286,9 @@ int st_select_lex_unit::exec() ...@@ -286,8 +286,9 @@ int st_select_lex_unit::exec()
select_limit_cnt= HA_POS_ERROR; // no limit select_limit_cnt= HA_POS_ERROR; // no limit
if (select_limit_cnt == HA_POS_ERROR) if (select_limit_cnt == HA_POS_ERROR)
thd->options&= ~OPTION_FOUND_ROWS; thd->options&= ~OPTION_FOUND_ROWS;
res= mysql_select(thd,&result_table_list, res= mysql_select(thd, &ref_pointer_array, &result_table_list,
item_list, NULL, 0, item_list, NULL,
global_parameters->order_list.elements,
(ORDER*)global_parameters->order_list.first, (ORDER*)global_parameters->order_list.first,
(ORDER*) NULL, NULL, (ORDER*) NULL, (ORDER*) NULL, NULL, (ORDER*) NULL,
thd->options, result, this, first_select(), 1); thd->options, result, this, first_select(), 1);
...@@ -303,20 +304,24 @@ int st_select_lex_unit::exec() ...@@ -303,20 +304,24 @@ int st_select_lex_unit::exec()
int st_select_lex_unit::cleanup() int st_select_lex_unit::cleanup()
{ {
DBUG_ENTER("st_select_lex_unit::cleanup"); DBUG_ENTER("st_select_lex_unit::cleanup");
int error= 0;
if (union_result) if (union_result)
{ {
delete union_result; delete union_result;
free_tmp_table(thd,table); if (table)
free_tmp_table(thd, table);
table= 0; // Safety table= 0; // Safety
} }
List_iterator<JOIN*> j(joins); for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select())
JOIN** join;
while ((join= j++))
{ {
(*join)->cleanup(thd); JOIN *join;
delete *join; if ((join= sl->join))
delete join; {
error|= sl->join->cleanup(thd);
delete join;
}
} }
joins.empty(); DBUG_RETURN(error);
DBUG_RETURN(0);
} }
...@@ -50,7 +50,7 @@ int mysql_update(THD *thd, ...@@ -50,7 +50,7 @@ int mysql_update(THD *thd,
List<Item> &fields, List<Item> &fields,
List<Item> &values, List<Item> &values,
COND *conds, COND *conds,
ORDER *order, uint order_num, ORDER *order,
ha_rows limit, ha_rows limit,
enum enum_duplicates handle_duplicates) enum enum_duplicates handle_duplicates)
{ {
...@@ -109,7 +109,7 @@ int mysql_update(THD *thd, ...@@ -109,7 +109,7 @@ int mysql_update(THD *thd,
/* Check the fields we are going to modify */ /* Check the fields we are going to modify */
table->grant.want_privilege=want_privilege; table->grant.want_privilege=want_privilege;
if (setup_fields(thd,update_table_list,fields,1,0,0)) if (setup_fields(thd, 0, update_table_list, fields, 1, 0, 0))
DBUG_RETURN(-1); /* purecov: inspected */ DBUG_RETURN(-1); /* purecov: inspected */
if (table->timestamp_field) if (table->timestamp_field)
{ {
...@@ -122,8 +122,9 @@ int mysql_update(THD *thd, ...@@ -122,8 +122,9 @@ int mysql_update(THD *thd,
/* Check values */ /* Check values */
table->grant.want_privilege=(SELECT_ACL & ~table->grant.privilege); table->grant.want_privilege=(SELECT_ACL & ~table->grant.privilege);
if (setup_fields(thd,update_table_list,values,0,0,0)) if (setup_fields(thd, 0, update_table_list, values, 0, 0, 0))
{ {
free_ulderlayed_joins(thd, &thd->lex.select_lex);
DBUG_RETURN(-1); /* purecov: inspected */ DBUG_RETURN(-1); /* purecov: inspected */
} }
...@@ -134,6 +135,7 @@ int mysql_update(THD *thd, ...@@ -134,6 +135,7 @@ int mysql_update(THD *thd,
(select && select->check_quick(safe_update, limit)) || !limit) (select && select->check_quick(safe_update, limit)) || !limit)
{ {
delete select; delete select;
free_ulderlayed_joins(thd, &thd->lex.select_lex);
if (error) if (error)
{ {
DBUG_RETURN(-1); // Error in where DBUG_RETURN(-1); // Error in where
...@@ -148,6 +150,7 @@ int mysql_update(THD *thd, ...@@ -148,6 +150,7 @@ int mysql_update(THD *thd,
if (safe_update && !using_limit) if (safe_update && !using_limit)
{ {
delete select; delete select;
free_ulderlayed_joins(thd, &thd->lex.select_lex);
send_error(thd,ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE); send_error(thd,ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE);
DBUG_RETURN(1); DBUG_RETURN(1);
} }
...@@ -175,6 +178,7 @@ int mysql_update(THD *thd, ...@@ -175,6 +178,7 @@ int mysql_update(THD *thd,
DISK_BUFFER_SIZE, MYF(MY_WME))) DISK_BUFFER_SIZE, MYF(MY_WME)))
{ {
delete select; /* purecov: inspected */ delete select; /* purecov: inspected */
free_ulderlayed_joins(thd, &thd->lex.select_lex);
DBUG_RETURN(-1); DBUG_RETURN(-1);
} }
if (old_used_keys & ((key_map) 1 << used_index)) if (old_used_keys & ((key_map) 1 << used_index))
...@@ -197,7 +201,10 @@ int mysql_update(THD *thd, ...@@ -197,7 +201,10 @@ int mysql_update(THD *thd,
table->io_cache = (IO_CACHE *) my_malloc(sizeof(IO_CACHE), table->io_cache = (IO_CACHE *) my_malloc(sizeof(IO_CACHE),
MYF(MY_FAE | MY_ZEROFILL)); MYF(MY_FAE | MY_ZEROFILL));
if (setup_order(thd, &tables, fields, all_fields, order) || if (setup_ref_array(thd, &thd->lex.select_lex.ref_pointer_array,
order_num)||
setup_order(thd, thd->lex.select_lex.ref_pointer_array,
&tables, fields, all_fields, order) ||
!(sortorder=make_unireg_sortorder(order, &length)) || !(sortorder=make_unireg_sortorder(order, &length)) ||
(table->found_records = filesort(thd, table, sortorder, length, (table->found_records = filesort(thd, table, sortorder, length,
(SQL_SELECT *) 0, (SQL_SELECT *) 0,
...@@ -205,6 +212,7 @@ int mysql_update(THD *thd, ...@@ -205,6 +212,7 @@ int mysql_update(THD *thd,
== HA_POS_ERROR) == HA_POS_ERROR)
{ {
delete select; delete select;
free_ulderlayed_joins(thd, &thd->lex.select_lex);
DBUG_RETURN(-1); DBUG_RETURN(-1);
} }
} }
...@@ -258,6 +266,7 @@ int mysql_update(THD *thd, ...@@ -258,6 +266,7 @@ int mysql_update(THD *thd,
if (error >= 0) if (error >= 0)
{ {
delete select; delete select;
free_ulderlayed_joins(thd, &thd->lex.select_lex);
DBUG_RETURN(-1); DBUG_RETURN(-1);
} }
} }
...@@ -343,6 +352,7 @@ int mysql_update(THD *thd, ...@@ -343,6 +352,7 @@ int mysql_update(THD *thd,
} }
delete select; delete select;
free_ulderlayed_joins(thd, &thd->lex.select_lex);
if (error >= 0) if (error >= 0)
send_error(thd,thd->killed ? ER_SERVER_SHUTDOWN : 0); /* purecov: inspected */ send_error(thd,thd->killed ? ER_SERVER_SHUTDOWN : 0); /* purecov: inspected */
else else
...@@ -357,6 +367,7 @@ int mysql_update(THD *thd, ...@@ -357,6 +367,7 @@ int mysql_update(THD *thd,
} }
thd->count_cuted_fields=0; /* calc cuted fields */ thd->count_cuted_fields=0; /* calc cuted fields */
free_io_cache(table); free_io_cache(table);
DBUG_RETURN(0); DBUG_RETURN(0);
} }
...@@ -388,7 +399,7 @@ int mysql_multi_update(THD *thd, ...@@ -388,7 +399,7 @@ int mysql_multi_update(THD *thd,
DBUG_RETURN(res); DBUG_RETURN(res);
thd->select_limit=HA_POS_ERROR; thd->select_limit=HA_POS_ERROR;
if (setup_fields(thd, table_list, *fields, 1, 0, 0)) if (setup_fields(thd, 0, table_list, *fields, 1, 0, 0))
DBUG_RETURN(-1); DBUG_RETURN(-1);
/* /*
...@@ -411,8 +422,9 @@ int mysql_multi_update(THD *thd, ...@@ -411,8 +422,9 @@ int mysql_multi_update(THD *thd,
DBUG_RETURN(-1); DBUG_RETURN(-1);
List<Item> total_list; List<Item> total_list;
res= mysql_select(thd,table_list,total_list, res= mysql_select(thd, &select_lex->ref_pointer_array,
conds, (ORDER *) NULL, (ORDER *)NULL, (Item *) NULL, table_list, select_lex->with_wild, total_list,
conds, 0, (ORDER *) NULL, (ORDER *)NULL, (Item *) NULL,
(ORDER *)NULL, (ORDER *)NULL,
options | SELECT_NO_JOIN_CACHE, options | SELECT_NO_JOIN_CACHE,
result, unit, select_lex, 0); result, unit, select_lex, 0);
...@@ -467,7 +479,7 @@ int multi_update::prepare(List<Item> &not_used_values, SELECT_LEX_UNIT *unit) ...@@ -467,7 +479,7 @@ int multi_update::prepare(List<Item> &not_used_values, SELECT_LEX_UNIT *unit)
reference tables reference tables
*/ */
if (setup_fields(thd, all_tables, *values, 1,0,0)) if (setup_fields(thd, 0, all_tables, *values, 1, 0, 0))
DBUG_RETURN(1); DBUG_RETURN(1);
/* /*
......
...@@ -1760,8 +1760,10 @@ select_item_list: ...@@ -1760,8 +1760,10 @@ select_item_list:
| select_item | select_item
| '*' | '*'
{ {
if (add_item_to_list(YYTHD, new Item_field(NULL,NULL,"*"))) THD *thd= YYTHD;
if (add_item_to_list(thd, new Item_field(NULL, NULL, "*")))
YYABORT; YYABORT;
(thd->lex.current_select->select_lex()->with_wild)++;
}; };
...@@ -3631,10 +3633,19 @@ insert_ident: ...@@ -3631,10 +3633,19 @@ insert_ident:
| table_wild { $$=$1; }; | table_wild { $$=$1; };
table_wild: table_wild:
ident '.' '*' { $$ = new Item_field(NullS,$1.str,"*"); } ident '.' '*'
{
$$ = new Item_field(NullS,$1.str,"*");
Lex->current_select->select_lex()->with_wild++;
}
| ident '.' ident '.' '*' | ident '.' ident '.' '*'
{ $$ = new Item_field((YYTHD->client_capabilities & {
CLIENT_NO_SCHEMA ? NullS : $1.str),$3.str,"*"); }; $$ = new Item_field((YYTHD->client_capabilities &
CLIENT_NO_SCHEMA ? NullS : $1.str),
$3.str,"*");
Lex->current_select->select_lex()->with_wild++;
}
;
order_ident: order_ident:
expr { $$=$1; }; expr { $$=$1; };
......
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