Commit b2354133 authored by unknown's avatar unknown

fixed subselects with temporary tables (SCRUM)

fixed memory leacks


mysql-test/r/subselect.result:
  some changes in subselect tests
mysql-test/t/subselect.test:
  some changes in subselect tests
sql/item.cc:
  some item made copyable
  methods for creating copy of item list
  tmp_table_field() splited
sql/item.h:
  some item made copyable
  methods for creating copy of item list
  tmp_table_field() splited
sql/item_cmpfunc.cc:
  changed references creation
sql/item_cmpfunc.h:
  changed references creation
sql/item_func.cc:
  some item made copyable
  methods for creating copy of item list
  changed references creation
sql/item_func.h:
  some item made copyable
  methods for creating copy of item list
  changed references creation
  tmp_table_field() splited
sql/item_subselect.cc:
  changed references creation
sql/item_sum.cc:
  some item made copyable
  methods for creating copy of item list
sql/item_sum.h:
  some item made copyable
  methods for creating copy of item list
sql/item_timefunc.h:
  tmp_table_field() splited
sql/item_uniq.h:
  some item made copyable
  methods for creating copy of item list
sql/mysql_priv.h:
  fixed subselects with temporary tables
sql/sql_base.cc:
  fixed subselects with temporary tables
sql/sql_class.h:
  fixed subselects with temporary tables
sql/sql_delete.cc:
  fixed subselects with temporary tables
sql/sql_derived.cc:
  fixed subselects with temporary tables
sql/sql_do.cc:
  fixed subselects with temporary tables
sql/sql_insert.cc:
  fixed subselects with temporary tables
sql/sql_lex.cc:
  fixed subselects with temporary tables
sql/sql_lex.h:
  fixed subselects with temporary tables
sql/sql_list.h:
  fixed subselects with temporary tables
sql/sql_load.cc:
  fixed subselects with temporary tables
sql/sql_olap.cc:
  fixed subselects with temporary tables
sql/sql_parse.cc:
  fixed subselects with temporary tables
sql/sql_prepare.cc:
  fixed subselects with temporary tables
sql/sql_select.cc:
  fixed subselects with temporary tables
sql/sql_select.h:
  fixed subselects with temporary tables
sql/sql_table.cc:
  fixed subselects with temporary tables
sql/sql_union.cc:
  fixed subselects with temporary tables
sql/sql_update.cc:
  fixed subselects with temporary tables
sql/sql_yacc.yy:
  fixed subselects with temporary tables
parent 3b33f0c2
...@@ -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,6 +1009,7 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) ...@@ -961,6 +1009,7 @@ 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,
&counter,
REPORT_EXCEPT_NOT_FOUND)) != REPORT_EXCEPT_NOT_FOUND)) !=
(Item **)not_found_item) (Item **)not_found_item)
break; break;
...@@ -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,11 +303,15 @@ void Item_in_subselect::single_value_transformer(st_select_lex *select_lex, ...@@ -301,11 +303,15 @@ 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,
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>")); 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)
...@@ -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 (!original)
{
if (table) if (table)
free_tmp_table(current_thd, table); free_tmp_table(current_thd, table);
delete tmp_table_param; delete tmp_table_param;
if (use_tree) if (use_tree)
delete_tree(&tree); delete_tree(tree);
}
} }
...@@ -1072,7 +1108,7 @@ bool Item_sum_count_distinct::setup(THD *thd) ...@@ -1072,7 +1108,7 @@ 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);
......
...@@ -2013,10 +2013,14 @@ const Item **not_found_item= (const Item**) 0x1; ...@@ -2013,10 +2013,14 @@ 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,22 +2105,18 @@ find_item_in_list(Item *find, List<Item> &items, ...@@ -2096,22 +2105,18 @@ 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] == '*')
...@@ -2119,7 +2124,7 @@ int setup_fields(THD *thd, TABLE_LIST *tables, List<Item> &fields, ...@@ -2119,7 +2124,7 @@ int setup_fields(THD *thd, TABLE_LIST *tables, List<Item> &fields,
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,23 +2134,44 @@ int setup_fields(THD *thd, TABLE_LIST *tables, List<Item> &fields, ...@@ -2129,23 +2134,44 @@ 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 }
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) || if (item->check_cols(1) ||
item->fix_fields(thd, tables, it.ref())) item->fix_fields(thd, tables, it.ref()))
DBUG_RETURN(-1); /* purecov: inspected */ DBUG_RETURN(-1); /* purecov: inspected */
item= *(it.ref()); //Item can be chenged in fix fields 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 && if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM &&
sum_func_list) sum_func_list)
item->split_sum_func(*sum_func_list); item->split_sum_func(ref_pointer_array, *sum_func_list);
thd->used_tables|=item->used_tables(); thd->used_tables|=item->used_tables();
} }
}
DBUG_RETURN(test(thd->fatal_error || thd->net.report_error)); DBUG_RETURN(test(thd->fatal_error || thd->net.report_error));
} }
/* /*
Remap table numbers if INSERT ... SELECT Remap table numbers if INSERT ... SELECT
Check also that the 'used keys' and 'ignored keys' exists and set up the Check also that the 'used keys' and 'ignored keys' exists and set up the
...@@ -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()
...@@ -1110,7 +1114,7 @@ bool st_select_lex_node::add_group_to_list(THD *thd, Item *item, bool asc) ...@@ -1110,7 +1114,7 @@ bool st_select_lex_node::add_group_to_list(THD *thd, Item *item, bool asc)
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,7 +208,10 @@ class st_select_lex_node { ...@@ -208,7 +208,10 @@ 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
Item **ref_pointer_array;
uint with_sum_func; /* sum function indicator and number of it */
bool create_refs; bool create_refs;
bool dependent; /* dependent from outer select subselect */ bool dependent; /* dependent from outer select subselect */
...@@ -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;
...@@ -179,6 +184,8 @@ class JOIN :public Sql_alloc ...@@ -179,6 +184,8 @@ class JOIN :public Sql_alloc
// 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,
skip_sort_order, need_tmp, skip_sort_order, need_tmp,
...@@ -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))
{
error|= sl->join->cleanup(thd);
delete join; delete join;
} }
joins.empty(); }
DBUG_RETURN(0); DBUG_RETURN(error);
} }
...@@ -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