summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <bell@sanja.is.com.ua>2003-01-25 02:25:52 +0200
committerunknown <bell@sanja.is.com.ua>2003-01-25 02:25:52 +0200
commitb23541339c389e452b3d643c249afd4e7fb4899f (patch)
tree043b4b5b889f0d8173b87b17f3de8dc3fbbb1dd2
parent3b33f0c2c14c9e210b81d8ee784c75f83ce99636 (diff)
downloadmariadb-git-b23541339c389e452b3d643c249afd4e7fb4899f.tar.gz
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
-rw-r--r--mysql-test/r/subselect.result14
-rw-r--r--mysql-test/t/subselect.test12
-rw-r--r--sql/item.cc76
-rw-r--r--sql/item.h27
-rw-r--r--sql/item_cmpfunc.cc20
-rw-r--r--sql/item_cmpfunc.h4
-rw-r--r--sql/item_func.cc21
-rw-r--r--sql/item_func.h4
-rw-r--r--sql/item_subselect.cc21
-rw-r--r--sql/item_sum.cc74
-rw-r--r--sql/item_sum.h72
-rw-r--r--sql/item_timefunc.h27
-rw-r--r--sql/item_uniq.h2
-rw-r--r--sql/mysql_priv.h35
-rw-r--r--sql/sql_base.cc90
-rw-r--r--sql/sql_class.h14
-rw-r--r--sql/sql_delete.cc6
-rw-r--r--sql/sql_derived.cc13
-rw-r--r--sql/sql_do.cc2
-rw-r--r--sql/sql_insert.cc12
-rw-r--r--sql/sql_lex.cc10
-rw-r--r--sql/sql_lex.h13
-rw-r--r--sql/sql_list.h17
-rw-r--r--sql/sql_load.cc3
-rw-r--r--sql/sql_olap.cc6
-rw-r--r--sql/sql_parse.cc15
-rw-r--r--sql/sql_prepare.cc16
-rw-r--r--sql/sql_select.cc930
-rw-r--r--sql/sql_select.h54
-rw-r--r--sql/sql_table.cc13
-rw-r--r--sql/sql_union.cc41
-rw-r--r--sql/sql_update.cc28
-rw-r--r--sql/sql_yacc.yy19
33 files changed, 1149 insertions, 562 deletions
diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result
index d442e4d97ce..e2a5494eaf7 100644
--- a/mysql-test/r/subselect.result
+++ b/mysql-test/r/subselect.result
@@ -81,21 +81,18 @@ select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1);
a b
1 7
2 7
-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;
+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;
a b
1 7
2 7
3 8
-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) union (select * from t4 where t4.b=(select max(t2.a)*4 from t2) order by a);
a b
1 7
2 7
3 8
4 8
-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);
+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);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Using where
2 SUBSELECT t3 ALL NULL NULL NULL NULL 3 Using filesort
@@ -330,19 +327,15 @@ Unknown column 'a' in 'having clause'
SELECT * from t2 where topic IN (SELECT topic FROM t2 GROUP BY date);
mot topic date pseudo
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);
mot topic date pseudo
-joce 43506 2002-10-22 joce
SELECT * from t2 where topic IN (SELECT SUM(topic) FROM t1);
mot topic date pseudo
SELECT * from t2 where topic = any (SELECT topic FROM t2 GROUP BY date);
mot topic date pseudo
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);
mot topic date pseudo
-joce 43506 2002-10-22 joce
SELECT * from t2 where topic = any (SELECT SUM(topic) FROM t1);
mot topic date pseudo
SELECT * from t2 where topic = all (SELECT topic FROM t2 GROUP BY date);
@@ -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);
mot topic date pseudo
joce 40143 2002-10-22 joce
+joce 43506 2002-10-22 joce
SELECT * from t2 where topic = all (SELECT SUM(topic) FROM t2);
mot topic date pseudo
SELECT * from t2 where topic <> any (SELECT SUM(topic) FROM t2);
diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test
index 8b174882bc6..c22827dff18 100644
--- a/mysql-test/t/subselect.test
+++ b/mysql-test/t/subselect.test
@@ -42,12 +42,9 @@ select (select a from t3), a from t2;
select * from t2 where t2.a=(select a from t1);
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)
-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);
-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 * 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;
+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);
+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 t3.a from t3 where a<8 order by 1 desc limit 1), a from
(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);
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 = 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 *, 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 <> any (SELECT SUM(topic) FROM t2);
drop table t1,t2;
diff --git a/sql/item.cc b/sql/item.cc
index 5e74820a3f8..81f923faabd 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -46,6 +46,31 @@ Item::Item():
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)
{
DBUG_ENTER("Item::check_loop");
@@ -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
}
+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)
{
@@ -262,6 +292,13 @@ table_map Item_field::used_tables() const
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)
{
@@ -535,6 +572,7 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
SELECT_LEX *last= 0;
Item **refer= (Item **)not_found_item;
+ uint counter= 0;
// Prevent using outer fields in subselects, that is not supported now
SELECT_LEX *cursel=(SELECT_LEX *) thd->lex.current_select;
if (cursel->linkage != DERIVED_TABLE_TYPE)
@@ -546,7 +584,7 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
(last= sl)->get_table_list(),
0)) != not_found_field)
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)) !=
(Item **)not_found_item)
break;
@@ -565,8 +603,16 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
}
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;
- *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);
if (!r)
return 1;
@@ -930,6 +976,7 @@ bool Item_null::send(THD *thd, String *packet)
bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
{
+ uint counter= 0;
if (!ref)
{
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)
*/
if ((ref= find_item_in_list(this,
*(thd->lex.current_select->get_item_list()),
+ &counter,
((sl &&
thd->lex.current_select->linkage !=
DERIVED_TABLE_TYPE) ?
@@ -961,7 +1009,8 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
for ( ; sl ; sl= sl->outer_select())
{
if ((ref= find_item_in_list(this, (last= sl)->item_list,
- REPORT_EXCEPT_NOT_FOUND)) !=
+ &counter,
+ REPORT_EXCEPT_NOT_FOUND)) !=
(Item **)not_found_item)
break;
if ((tmp= find_field_in_tables(thd, this,
@@ -980,6 +1029,7 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
// Call to report error
find_item_in_list(this,
*(thd->lex.current_select->get_item_list()),
+ &counter,
REPORT_ALL_ERRORS);
ref= 0;
return 1;
@@ -996,17 +1046,35 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
}
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->add_possible_loop(this);
}
}
else if (!ref)
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;
maybe_null= (*ref)->maybe_null;
decimals= (*ref)->decimals;
}
+
if (((*ref)->with_sum_func &&
(depended_from ||
!(thd->lex.current_select->linkage != GLOBAL_OPTIONS_TYPE &&
diff --git a/sql/item.h b/sql/item.h
index 4dff0591c09..900315a3bf6 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -50,6 +50,8 @@ public:
// alloc & destruct is done as start of select using sql_alloc
Item();
+ // copy constructor used by Item_field, Item_ref & agregate (sum) functions
+ Item(Item &item);
virtual ~Item() { name=0; } /*lint -e1509 */
void set_name(const char *str,uint length=0);
void init_make_field(Send_field *tmp_field,enum enum_field_types type);
@@ -67,7 +69,8 @@ public:
virtual longlong val_int()=0;
virtual String *val_str(String*)=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 double val_result() { return val(); }
virtual longlong val_int_result() { return val_int(); }
@@ -82,12 +85,14 @@ public:
virtual bool const_item() const { return used_tables() == 0; }
virtual void print(String *str_arg) { str_arg->append(full_name()); }
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_time(TIME *ltime);
virtual bool is_null() { return 0; };
virtual bool check_loop(uint id);
virtual void top_level_item() {}
+ virtual Item * get_same() { return this; }
+ virtual Item * get_tmp_table_item() { return get_same(); }
virtual bool binary() const
{ return str_value.charset()->state & MY_CS_BINSORT ? 1 : 0 ; }
@@ -159,11 +164,14 @@ public:
const char *table_name;
const char *field_name;
st_select_lex *depended_from;
+
Item_ident(const char *db_name_par,const char *table_name_par,
const char *field_name_par)
:db_name(db_name_par),table_name(table_name_par),
field_name(field_name_par), depended_from(0)
{ name = (char*) field_name_par; }
+ // copy constructor used by Item_field & Item_ref
+ Item_ident(Item_ident &item);
const char *full_name() const;
};
@@ -179,6 +187,8 @@ public:
const char *field_name_par)
: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);
enum Type type() const { return FIELD_ITEM; }
bool eq(const Item *item, bool binary_cmp) const;
@@ -202,10 +212,12 @@ public:
{
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_time(TIME *ltime);
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 */
public:
Field *result_field; /* Save result here */
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 */
- 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; }
virtual void fix_length_and_dec()=0;
};
@@ -463,6 +480,8 @@ public:
: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_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; }
bool eq(const Item *item, bool binary_cmp) const
{ return ref && (*ref)->eq(item, binary_cmp); }
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index dd8d1aeff02..f1859e48206 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -1175,16 +1175,20 @@ void Item_func_in::update_used_tables()
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)
- item->split_sum_func(fields);
+ item->split_sum_func(ref_pointer_array, fields);
else if (item->used_tables() || item->type() == SUM_FUNC_ITEM)
{
+ uint el= fields.elements;
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)
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);
Item *item;
@@ -1290,11 +1294,13 @@ void Item_cond::split_sum_func(List<Item> &fields)
while ((item=li++))
{
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)
{
+ uint el= fields.elements;
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();
used_tables_cache|=item->used_tables();
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index b4f4872bd95..adab7a042c5 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -509,7 +509,7 @@ class Item_func_in :public Item_int_func
enum Functype functype() const { return IN_FUNC; }
const char *func_name() const { return " IN "; }
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)
{
DBUG_ENTER("Item_func_in::check_loop");
@@ -656,7 +656,7 @@ public:
table_map used_tables() const;
void update_used_tables();
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);
bool check_loop(uint id);
void top_level_item() { abort_on_null=1; }
diff --git a/sql/item_func.cc b/sql/item_func.cc
index c84b554b522..1d4d26d799e 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -146,17 +146,19 @@ bool Item_func::check_loop(uint id)
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;
for (arg=args, arg_end=args+arg_count; arg != arg_end ; arg++)
{
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)
{
+ uint el= fields.elements;
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
return 1;
}
-
Field *Item_func::tmp_table_field(TABLE *t_arg)
{
Field *res;
LINT_INIT(res);
- if (!t_arg)
- return result_field;
switch (result_type()) {
case INT_RESULT:
if (max_length > 11)
@@ -303,6 +302,16 @@ void Item_func::fix_num_length_and_dec()
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)
{
longlong nr=val_int();
diff --git a/sql/item_func.h b/sql/item_func.h
index 98e56af368c..dab42f1b336 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -118,7 +118,7 @@ public:
inline Item **arguments() const { return args; }
inline uint argument_count() const { return arg_count; }
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_op(String *str);
void fix_num_length_and_dec();
@@ -132,8 +132,10 @@ public:
}
bool is_null() { (void) val_int(); return null_value; }
friend class udf_handler;
+ Field *tmp_table_field() { return result_field; }
Field *tmp_table_field(TABLE *t_arg);
bool check_loop(uint id);
+ Item * get_tmp_table_item();
};
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index e087664e060..f397379b5be 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -288,6 +288,8 @@ void Item_in_subselect::single_value_transformer(st_select_lex *select_lex,
compare_func_creator func)
{
DBUG_ENTER("Item_in_subselect::single_value_transformer");
+ THD *thd= current_thd;
+
for (SELECT_LEX * sl= select_lex; sl; sl= sl->next_select())
{
Item *item;
@@ -301,12 +303,16 @@ void Item_in_subselect::single_value_transformer(st_select_lex *select_lex,
Item *expr= new Item_outer_select_context_saver(left_expr);
- if (sl->having || sl->with_sum_func || sl->group_list.first ||
- sl->order_list.first)
+ if (sl->having || sl->with_sum_func || sl->group_list.elements ||
+ sl->order_list.elements)
{
sl->item_list.push_back(item);
- item= (*func)(expr, new Item_ref(sl->item_list.head_ref(),
- 0, (char*)"<result>"));
+ 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>"));
if (sl->having || sl->with_sum_func || sl->group_list.first)
if (sl->having)
sl->having= new Item_cond_and(sl->having, item);
@@ -348,7 +354,6 @@ void Item_in_subselect::single_value_transformer(st_select_lex *select_lex,
// it is single select without tables => possible optimization
item= (*func)(left_expr, item);
substitution= item;
- THD *thd= current_thd;
if (thd->lex.describe)
{
char warn_buff[MYSQL_ERRMSG_SIZE];
@@ -424,8 +429,12 @@ int subselect_single_select_engine::prepare()
prepared= 1;
SELECT_LEX_NODE *save_select= thd->lex.current_select;
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->order_list.elements +
+ select_lex->group_list.elements,
(ORDER*) select_lex->order_list.first,
(ORDER*) select_lex->group_list.first,
select_lex->having,
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index a1f772f4d46..7e40dc9a94c 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -41,9 +41,22 @@ Item_sum::Item_sum(List<Item> &list)
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()
{
- current_thd->lex.current_select->with_sum_func=1;
+ current_thd->lex.current_select->with_sum_func++;
with_sum_func= 1;
}
@@ -90,6 +103,26 @@ void Item_sum::fix_num_length_and_dec()
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 *
Item_sum_num::val_str(String *str)
@@ -933,7 +966,7 @@ int dump_leaf(byte* key, uint32 count __attribute__((unused)),
The first item->rec_offset bytes are taken care of with
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 != HA_ERR_FOUND_DUPP_KEY &&
@@ -946,11 +979,14 @@ int dump_leaf(byte* key, uint32 count __attribute__((unused)),
Item_sum_count_distinct::~Item_sum_count_distinct()
{
- if (table)
- free_tmp_table(current_thd, table);
- delete tmp_table_param;
- if (use_tree)
- delete_tree(&tree);
+ if (!original)
+ {
+ if (table)
+ free_tmp_table(current_thd, table);
+ delete tmp_table_param;
+ if (use_tree)
+ delete_tree(tree);
+ }
}
@@ -1072,8 +1108,8 @@ bool Item_sum_count_distinct::setup(THD *thd)
}
}
- init_tree(&tree, min(thd->variables.max_heap_table_size,
- thd->variables.sortbuff_size/16), 0,
+ init_tree(tree, min(thd->variables.max_heap_table_size,
+ thd->variables.sortbuff_size/16), 0,
key_length, compare_key, 0, NULL, cmp_arg);
use_tree = 1;
@@ -1085,6 +1121,12 @@ bool Item_sum_count_distinct::setup(THD *thd)
*/
max_elements_in_tree = ((key_length) ?
thd->variables.max_heap_table_size/key_length : 1);
+
+ }
+ if (original)
+ {
+ original->table= table;
+ original->use_tree= use_tree;
}
return 0;
}
@@ -1094,10 +1136,10 @@ int Item_sum_count_distinct::tree_to_myisam()
{
if (create_myisam_from_heap(current_thd, table, tmp_table_param,
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))
return 1;
- delete_tree(&tree);
+ delete_tree(tree);
use_tree = 0;
return 0;
}
@@ -1105,7 +1147,7 @@ int Item_sum_count_distinct::tree_to_myisam()
void Item_sum_count_distinct::reset()
{
if (use_tree)
- reset_tree(&tree);
+ reset_tree(tree);
else if (table)
{
table->file->extra(HA_EXTRA_NO_CACHE);
@@ -1133,13 +1175,13 @@ bool Item_sum_count_distinct::add()
If the tree got too big, convert to MyISAM, otherwise insert into the
tree.
*/
- if (tree.elements_in_tree > max_elements_in_tree)
+ if (tree->elements_in_tree > max_elements_in_tree)
{
if (tree_to_myisam())
return 1;
}
- else if (!tree_insert(&tree, table->record[0] + rec_offset, 0,
- tree.custom_arg))
+ else if (!tree_insert(tree, table->record[0] + rec_offset, 0,
+ tree->custom_arg))
return 1;
}
else if ((error=table->file->write_row(table->record[0])))
@@ -1161,7 +1203,7 @@ longlong Item_sum_count_distinct::val_int()
if (!table) // Empty query
return LL(0);
if (use_tree)
- return tree.elements_in_tree;
+ return tree->elements_in_tree;
table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
return table->file->records;
}
diff --git a/sql/item_sum.h b/sql/item_sum.h
index 23b8482d41a..5e561a05e64 100644
--- a/sql/item_sum.h
+++ b/sql/item_sum.h
@@ -54,6 +54,8 @@ public:
mark_as_sum_func();
}
Item_sum(List<Item> &list);
+ //Copy constructor, need to perform subselects with temporary tables
+ Item_sum(Item_sum &item);
~Item_sum() { result_field=0; }
enum Type type() const { return SUM_FUNC_ITEM; }
@@ -75,6 +77,7 @@ public:
void print(String *str);
void fix_num_length_and_dec();
virtual bool setup(THD *thd) {return 0;}
+ Item * get_tmp_table_item();
};
@@ -85,6 +88,7 @@ public:
Item_sum_num(Item *item_par) :Item_sum(item_par) {}
Item_sum_num(Item *a, Item* b) :Item_sum(a,b) {}
Item_sum_num(List<Item> &list) :Item_sum(list) {}
+ Item_sum_num(Item_sum_num &item) :Item_sum(item) {}
bool fix_fields(THD *, TABLE_LIST *, Item **);
longlong val_int() { return (longlong) val(); } /* Real as default */
String *val_str(String*str);
@@ -100,6 +104,7 @@ class Item_sum_int :public Item_sum_num
public:
Item_sum_int(Item *item_par) :Item_sum_num(item_par) {}
Item_sum_int(List<Item> &list) :Item_sum_num(list) {}
+ Item_sum_int(Item_sum_int &item) :Item_sum_num(item) {}
double val() { return (double) val_int(); }
String *val_str(String*str);
enum Item_result result_type () const { return INT_RESULT; }
@@ -113,6 +118,7 @@ class Item_sum_sum :public Item_sum_num
public:
Item_sum_sum(Item *item_par) :Item_sum_num(item_par),sum(0.0) {}
+ Item_sum_sum(Item_sum_sum &item) :Item_sum_num(item), sum(item.sum) {}
enum Sumfunctype sum_func () const {return SUM_FUNC;}
void reset();
bool add();
@@ -120,6 +126,7 @@ class Item_sum_sum :public Item_sum_num
void reset_field();
void update_field(int offset);
const char *func_name() const { return "sum"; }
+ Item * get_same() { return new Item_sum_sum(*this); }
};
@@ -132,6 +139,10 @@ class Item_sum_count :public Item_sum_int
Item_sum_count(Item *item_par)
:Item_sum_int(item_par),count(0),used_table_cache(~(table_map) 0)
{}
+ Item_sum_count(Item_sum_count &item): Item_sum_int(item),
+ count(item.count),
+ used_table_cache(item.used_table_cache)
+ {}
table_map used_tables() const { return used_table_cache; }
bool const_item() const { return !used_table_cache; }
enum Sumfunctype sum_func () const { return COUNT_FUNC; }
@@ -142,6 +153,7 @@ class Item_sum_count :public Item_sum_int
void reset_field();
void update_field(int offset);
const char *func_name() const { return "count"; }
+ Item * get_same() { return new Item_sum_count(*this); }
};
@@ -154,7 +166,14 @@ class Item_sum_count_distinct :public Item_sum_int
bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref);
uint32 *field_lengths;
TMP_TABLE_PARAM *tmp_table_param;
- TREE tree;
+ TREE tree_base;
+ TREE *tree;
+ /*
+ Following is 0 normal object and pointer to original one for copy
+ (to correctly free resources)
+ */
+ Item_sum_count_distinct *original;
+
uint key_length;
// calculated based on max_heap_table_size. If reached,
@@ -180,9 +199,19 @@ class Item_sum_count_distinct :public Item_sum_int
public:
Item_sum_count_distinct(List<Item> &list)
- :Item_sum_int(list),table(0),used_table_cache(~(table_map) 0),
- tmp_table_param(0),use_tree(0),always_null(0)
- { quick_group=0; }
+ :Item_sum_int(list), table(0), used_table_cache(~(table_map) 0),
+ tmp_table_param(0), tree(&tree_base), original(0), use_tree(0),
+ always_null(0)
+ { quick_group= 0; }
+ Item_sum_count_distinct(Item_sum_count_distinct &item):
+ Item_sum_int(item), table(item.table),
+ used_table_cache(item.used_table_cache),
+ field_lengths(item.field_lengths), tmp_table_param(item.tmp_table_param),
+ tree(item.tree), original(&item), key_length(item.key_length),
+ max_elements_in_tree(item.max_elements_in_tree),
+ rec_offset(item.rec_offset), use_tree(item.use_tree),
+ always_null(item.always_null)
+ {}
~Item_sum_count_distinct();
table_map used_tables() const { return used_table_cache; }
enum Sumfunctype sum_func () const { return COUNT_DISTINCT_FUNC; }
@@ -193,6 +222,7 @@ class Item_sum_count_distinct :public Item_sum_int
void update_field(int offset) { return ; } // Never called
const char *func_name() const { return "count_distinct"; }
bool setup(THD *thd);
+ Item * get_same() { return new Item_sum_count_distinct(*this); }
};
@@ -224,6 +254,8 @@ class Item_sum_avg :public Item_sum_num
public:
Item_sum_avg(Item *item_par) :Item_sum_num(item_par),count(0) {}
+ Item_sum_avg(Item_sum_avg &item)
+ :Item_sum_num(item), sum(item.sum), count(item.count) {}
enum Sumfunctype sum_func () const {return AVG_FUNC;}
void reset();
bool add();
@@ -233,6 +265,7 @@ class Item_sum_avg :public Item_sum_num
Item *result_item(Field *field)
{ return new Item_avg_field(this); }
const char *func_name() const { return "avg"; }
+ Item * get_same() { return new Item_sum_avg(*this); }
};
class Item_sum_std;
@@ -260,6 +293,9 @@ class Item_sum_std :public Item_sum_num
public:
Item_sum_std(Item *item_par) :Item_sum_num(item_par),count(0) {}
+ Item_sum_std(Item_sum_std &item):
+ Item_sum_num(item), sum(item.sum), sum_sqr(item.sum_sqr),
+ count(item.count) {}
enum Sumfunctype sum_func () const { return STD_FUNC; }
void reset();
bool add();
@@ -269,6 +305,7 @@ class Item_sum_std :public Item_sum_num
Item *result_item(Field *field)
{ return new Item_std_field(this); }
const char *func_name() const { return "std"; }
+ Item * get_same() { return new Item_sum_std(*this); }
};
@@ -288,6 +325,10 @@ class Item_sum_hybrid :public Item_sum
Item_sum_hybrid(Item *item_par,int sign) :Item_sum(item_par),cmp_sign(sign),
used_table_cache(~(table_map) 0)
{}
+ Item_sum_hybrid(Item_sum_hybrid &item):
+ Item_sum(item), value(item.value), tmp_value(item.tmp_value),
+ sum(item.sum), sum_int(item.sum_int), hybrid_type(item.hybrid_type),
+ cmp_sign(item.cmp_sign), used_table_cache(used_table_cache) {}
bool fix_fields(THD *, TABLE_LIST *, Item **);
table_map used_tables() const { return used_table_cache; }
bool const_item() const { return !used_table_cache; }
@@ -318,10 +359,12 @@ class Item_sum_min :public Item_sum_hybrid
{
public:
Item_sum_min(Item *item_par) :Item_sum_hybrid(item_par,1) {}
+ Item_sum_min(Item_sum_min &item) :Item_sum_hybrid(item) {}
enum Sumfunctype sum_func () const {return MIN_FUNC;}
bool add();
const char *func_name() const { return "min"; }
+ Item * get_same() { return new Item_sum_min(*this); }
};
@@ -329,10 +372,12 @@ class Item_sum_max :public Item_sum_hybrid
{
public:
Item_sum_max(Item *item_par) :Item_sum_hybrid(item_par,-1) {}
+ Item_sum_max(Item_sum_max &item) :Item_sum_hybrid(item) {}
enum Sumfunctype sum_func () const {return MAX_FUNC;}
bool add();
const char *func_name() const { return "max"; }
+ Item * get_same() { return new Item_sum_max(*this); }
};
@@ -344,6 +389,8 @@ class Item_sum_bit :public Item_sum_int
public:
Item_sum_bit(Item *item_par,ulonglong reset_arg)
:Item_sum_int(item_par),reset_bits(reset_arg),bits(reset_arg) {}
+ Item_sum_bit(Item_sum_bit &item):
+ Item_sum_int(item), reset_bits(item.reset_bits), bits(item.bits) {}
enum Sumfunctype sum_func () const {return SUM_BIT_FUNC;}
void reset();
longlong val_int();
@@ -355,9 +402,11 @@ class Item_sum_or :public Item_sum_bit
{
public:
Item_sum_or(Item *item_par) :Item_sum_bit(item_par,LL(0)) {}
+ Item_sum_or(Item_sum_or &item) :Item_sum_bit(item) {}
bool add();
void update_field(int offset);
const char *func_name() const { return "bit_or"; }
+ Item * get_same() { return new Item_sum_or(*this); }
};
@@ -365,9 +414,11 @@ class Item_sum_and :public Item_sum_bit
{
public:
Item_sum_and(Item *item_par) :Item_sum_bit(item_par, ~(ulonglong) LL(0)) {}
+ Item_sum_and(Item_sum_and &item) :Item_sum_bit(item) {}
bool add();
void update_field(int offset);
const char *func_name() const { return "bit_and"; }
+ Item * get_same() { return new Item_sum_and(*this); }
};
/*
@@ -385,6 +436,7 @@ public:
Item_udf_sum( udf_func *udf_arg, List<Item> &list )
:Item_sum( list ), udf(udf_arg)
{ quick_group=0;}
+ Item_udf_sum(Item_udf_sum &item) :Item_sum(item), udf(item.udf) {}
~Item_udf_sum() {}
const char *func_name() const { return udf.name(); }
bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
@@ -408,11 +460,13 @@ class Item_sum_udf_float :public Item_udf_sum
Item_sum_udf_float(udf_func *udf_arg) :Item_udf_sum(udf_arg) {}
Item_sum_udf_float(udf_func *udf_arg, List<Item> &list)
:Item_udf_sum(udf_arg,list) {}
+ Item_sum_udf_float(Item_sum_udf_float &item): Item_udf_sum(item) {}
~Item_sum_udf_float() {}
longlong val_int() { return (longlong) Item_sum_udf_float::val(); }
double val();
String *val_str(String*str);
void fix_length_and_dec() { fix_num_length_and_dec(); }
+ Item * get_same() { return new Item_sum_udf_float(*this); }
};
@@ -422,12 +476,14 @@ public:
Item_sum_udf_int(udf_func *udf_arg) :Item_udf_sum(udf_arg) {}
Item_sum_udf_int(udf_func *udf_arg, List<Item> &list)
:Item_udf_sum(udf_arg,list) {}
+ Item_sum_udf_int(Item_sum_udf_int &item): Item_udf_sum(item) {}
~Item_sum_udf_int() {}
longlong val_int();
double val() { return (double) Item_sum_udf_int::val_int(); }
String *val_str(String*str);
enum Item_result result_type () const { return INT_RESULT; }
void fix_length_and_dec() { decimals=0; max_length=21; }
+ Item * get_same() { return new Item_sum_udf_int(*this); }
};
@@ -437,6 +493,7 @@ public:
Item_sum_udf_str(udf_func *udf_arg) :Item_udf_sum(udf_arg) {}
Item_sum_udf_str(udf_func *udf_arg, List<Item> &list)
:Item_udf_sum(udf_arg,list) {}
+ Item_sum_udf_str(Item_sum_udf_str &item): Item_udf_sum(item) {}
~Item_sum_udf_str() {}
String *val_str(String *);
double val()
@@ -451,6 +508,7 @@ public:
}
enum Item_result result_type () const { return STRING_RESULT; }
void fix_length_and_dec();
+ Item * get_same() { return new Item_sum_udf_str(*this); }
};
#else /* Dummy functions to get sql_yacc.cc compiled */
@@ -460,12 +518,14 @@ class Item_sum_udf_float :public Item_sum_num
public:
Item_sum_udf_float(udf_func *udf_arg) :Item_sum_num() {}
Item_sum_udf_float(udf_func *udf_arg, List<Item> &list) :Item_sum_num() {}
+ Item_sum_udf_float(Item_sum_udf_float &item): Item_sum_num(item) {}
~Item_sum_udf_float() {}
enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; }
double val() { return 0.0; }
void reset() {}
bool add() { return 0; }
void update_field(int offset) {}
+ Item * get_same() { return new Item_sum_udf_float(*this); }
};
@@ -474,6 +534,7 @@ class Item_sum_udf_int :public Item_sum_num
public:
Item_sum_udf_int(udf_func *udf_arg) :Item_sum_num() {}
Item_sum_udf_int(udf_func *udf_arg, List<Item> &list) :Item_sum_num() {}
+ Item_sum_udf_int(Item_sum_udf_int &item): Item_sum_num(item) {}
~Item_sum_udf_int() {}
enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; }
longlong val_int() { return 0; }
@@ -481,6 +542,7 @@ public:
void reset() {}
bool add() { return 0; }
void update_field(int offset) {}
+ Item * get_same() { return new Item_sum_udf_int(*this); }
};
@@ -489,6 +551,7 @@ class Item_sum_udf_str :public Item_sum_num
public:
Item_sum_udf_str(udf_func *udf_arg) :Item_sum_num() {}
Item_sum_udf_str(udf_func *udf_arg, List<Item> &list) :Item_sum_num() {}
+ Item_sum_udf_str(Item_sum_udf_str &item): Item_sum_num(item) {}
~Item_sum_udf_str() {}
String *val_str(String *) { null_value=1; return 0; }
double val() { null_value=1; return 0.0; }
@@ -499,6 +562,7 @@ public:
void reset() {}
bool add() { return 0; }
void update_field(int offset) {}
+ Item * get_same() { return new Item_sum_udf_str(*this); }
};
#endif /* HAVE_DLOPEN */
diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h
index 40397351c18..5b968ed80eb 100644
--- a/sql/item_timefunc.h
+++ b/sql/item_timefunc.h
@@ -330,9 +330,10 @@ public:
{
init_make_field(tmp_field,FIELD_TYPE_DATE);
}
+ Field *tmp_table_field() { return result_field; }
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 @@ public:
{
init_make_field(tmp_field,FIELD_TYPE_DATETIME);
}
+ Field *tmp_table_field() { return result_field; }
Field *tmp_table_field(TABLE *t_arg)
{
- return (!t_arg) ? result_field : new Field_datetime(maybe_null, name,
- t_arg, thd_charset());
+ return (new Field_datetime(maybe_null, name, t_arg, thd_charset()));
}
};
@@ -373,10 +374,10 @@ public:
{
init_make_field(tmp_field,FIELD_TYPE_TIME);
}
+ Field *tmp_table_field() { return result_field; }
Field *tmp_table_field(TABLE *t_arg)
{
- return (!t_arg) ? result_field :
- new Field_time(maybe_null, name, t_arg, thd_charset());
+ return (new Field_time(maybe_null, name, t_arg, thd_charset()));
}
};
@@ -475,10 +476,10 @@ public:
{
init_make_field(tmp_field,FIELD_TYPE_TIME);
}
+ Field *tmp_table_field() { return result_field; }
Field *tmp_table_field(TABLE *t_arg)
{
- return (!t_arg) ? result_field :
- new Field_time(maybe_null, name, t_arg, thd_charset());
+ return (new Field_time(maybe_null, name, t_arg, thd_charset()));
}
};
@@ -570,10 +571,10 @@ public:
{
init_make_field(tmp_field,FIELD_TYPE_DATE);
}
+ Field *tmp_table_field() { return result_field; }
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()));
}
};
@@ -587,10 +588,10 @@ public:
{
init_make_field(tmp_field,FIELD_TYPE_TIME);
}
+ Field *tmp_table_field() { return result_field; }
Field *tmp_table_field(TABLE *t_arg)
{
- return (!t_arg) ? result_field :
- new Field_time(maybe_null, name, t_arg, thd_charset());
+ return (new Field_time(maybe_null, name, t_arg, thd_charset()));
}
};
@@ -604,9 +605,9 @@ public:
{
init_make_field(tmp_field,FIELD_TYPE_DATETIME);
}
+ Field *tmp_table_field() { return result_field; }
Field *tmp_table_field(TABLE *t_arg)
{
- return (!t_arg) ? result_field : new Field_datetime(maybe_null, name,
- t_arg, thd_charset());
+ return (new Field_datetime(maybe_null, name, t_arg, thd_charset()));
}
};
diff --git a/sql/item_uniq.h b/sql/item_uniq.h
index 2004be63de2..9098dfe7d41 100644
--- a/sql/item_uniq.h
+++ b/sql/item_uniq.h
@@ -37,6 +37,7 @@ class Item_sum_unique_users :public Item_sum_num
public:
Item_sum_unique_users(Item *name_arg,int start,int end,Item *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; }
enum Sumfunctype sum_func () const {return UNIQUE_USERS_FUNC;}
void reset() {}
@@ -48,4 +49,5 @@ public:
fixed= 1;
return 0;
}
+ Item_sum * get_same() { return new Item_sum_unique_users(*this); }
};
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 771d105a1c7..b9cd99624ea 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -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);
SORT_FIELD * make_unireg_sortorder(ORDER *order, uint *length);
-int setup_order(THD *thd,TABLE_LIST *tables, List<Item> &fields,
- List <Item> &all_fields, ORDER *order);
-int setup_group(THD *thd,TABLE_LIST *tables,List<Item> &fields,
- List<Item> &all_fields, ORDER *order,
+int setup_ref_array(THD *thd, Item ***rref_pointer_array, uint elements);
+int setup_order(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
+ List<Item> &fields, 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);
int handle_select(THD *thd, LEX *lex, select_result *result);
-int mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &list,COND *conds,
- ORDER *order, ORDER *group,Item *having,ORDER *proc_param,
- ulong select_type,select_result *result,
- SELECT_LEX_UNIT *unit, SELECT_LEX *select_lex,
- bool fake_select_lex);
+int mysql_select(THD *thd, Item ***rref_pointer_array,
+ TABLE_LIST *tables, uint wild_num, List<Item> &list,
+ COND *conds, uint og_num, ORDER *order, ORDER *group,
+ Item *having, ORDER *proc_param, ulong select_type,
+ 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);
int mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit,
select_result *result);
@@ -440,7 +443,7 @@ int mysql_alter_table(THD *thd, char *new_db, char *new_name,
List<create_field> &fields,
List<Key> &keys,List<Alter_drop> &drop_list,
List<Alter_column> &alter_list,
- ORDER *order,
+ uint order_num, ORDER *order,
bool drop_primary,
enum enum_duplicates handle_duplicates,
enum enum_enable_or_disable keys_onoff=LEAVE_AS_IS,
@@ -456,7 +459,7 @@ int mysql_drop_index(THD *thd, TABLE_LIST *table_list,
List<Alter_drop> &drop_list);
int mysql_update(THD *thd,TABLE_LIST *tables,List<Item> &fields,
List<Item> &values,COND *conds,
- ORDER *order, ha_rows limit,
+ uint order_num, ORDER *order, ha_rows limit,
enum enum_duplicates handle_duplicates);
int mysql_multi_update(THD *thd, TABLE_LIST *table_list,
List<Item> *fields, List<Item> *values,
@@ -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,
IGNORE_ERRORS};
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);
bool insert_fields(THD *thd,TABLE_LIST *tables,
const char *db_name, const char *table_name,
List_iterator<Item> *it);
bool setup_tables(TABLE_LIST *tables);
-int setup_fields(THD *thd,TABLE_LIST *tables,List<Item> &item,
- bool set_query_id,List<Item> *sum_func_list,
- bool allow_sum_func);
+int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
+ List<Item> *sum_func_list, uint wild_num);
+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_ftfuncs(SELECT_LEX* select);
int init_ftfuncs(THD *thd, SELECT_LEX* select, bool no_order);
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index e2b36106fb0..870c341c148 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -2012,11 +2012,15 @@ const Item **not_found_item= (const Item**) 0x1;
/*
Find Item in list of items (find_field_in_tables analog)
-
+
+ TODO
+ is it better return only counter?
+
SYNOPSIS
find_item_in_list()
find - item to find
items - list of items
+ counter - to return number of found item
report_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
@@ -2033,7 +2037,7 @@ const Item **not_found_item= (const Item**) 0x1;
*/
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)
{
List_iterator<Item> li(items);
@@ -2046,8 +2050,10 @@ find_item_in_list(Item *find, List<Item> &items,
table_name= ((Item_ident*) find)->table_name;
}
+ uint i= 0;
while ((item=li++))
{
+ i++;
if (field_name && item->type() == Item::FIELD_ITEM)
{
if (!my_strcasecmp(system_charset_info,
@@ -2064,11 +2070,13 @@ find_item_in_list(Item *find, List<Item> &items,
find->full_name(), current_thd->where);
return (Item**) 0;
}
- found=li.ref();
+ found= li.ref();
+ *counter= i;
}
else if (!strcmp(((Item_field*) item)->table_name,table_name))
{
- found=li.ref();
+ found= li.ref();
+ *counter= i;
break;
}
}
@@ -2078,7 +2086,8 @@ find_item_in_list(Item *find, List<Item> &items,
!my_strcasecmp(system_charset_info,
item->name,find->name)))
{
- found=li.ref();
+ found= li.ref();
+ *counter= i;
break;
}
}
@@ -2096,30 +2105,26 @@ find_item_in_list(Item *find, List<Item> &items,
}
/****************************************************************************
-** Check that all given fields exists and fill struct with current data
+** Expand all '*' in given fields
****************************************************************************/
-int setup_fields(THD *thd, TABLE_LIST *tables, List<Item> &fields,
- bool set_query_id, List<Item> *sum_func_list,
- bool allow_sum_func)
+int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
+ List<Item> *sum_func_list,
+ uint wild_num)
{
+ if (!wild_num)
+ return 0;
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";
-
- while ((item=it++))
- {
+ while ( wild_num && (item= it++))
+ {
if (item->type() == Item::FIELD_ITEM && ((Item_field*) item)->field_name &&
((Item_field*) item)->field_name[0] == '*')
{
uint elem= fields.elements;
if (insert_fields(thd,tables,((Item_field*) item)->db_name,
((Item_field*) item)->table_name, &it))
- DBUG_RETURN(-1); /* purecov: inspected */
+ return (-1);
if (sum_func_list)
{
/*
@@ -2129,22 +2134,43 @@ int setup_fields(THD *thd, TABLE_LIST *tables, List<Item> &fields,
*/
sum_func_list->elements+= fields.elements - elem;
}
- }
- else
- {
- if (item->check_cols(1) ||
- item->fix_fields(thd, tables, it.ref()))
- DBUG_RETURN(-1); /* purecov: inspected */
- item= *(it.ref()); //Item can be chenged in fix fields
- if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM &&
- sum_func_list)
- item->split_sum_func(*sum_func_list);
- thd->used_tables|=item->used_tables();
+ wild_num--;
}
}
- DBUG_RETURN(test(thd->fatal_error || thd->net.report_error));
+ return 0;
}
+/****************************************************************************
+** Check that all given fields exists and fill struct with current data
+****************************************************************************/
+
+int setup_fields(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
+ List<Item> &fields, bool set_query_id,
+ List<Item> *sum_func_list, bool allow_sum_func)
+{
+ reg2 Item *item;
+ List_iterator<Item> it(fields);
+ DBUG_ENTER("setup_fields");
+
+ thd->set_query_id=set_query_id;
+ thd->allow_sum_func= allow_sum_func;
+ thd->where="field list";
+
+ for (uint i= 0; (item= it++); i++)
+ {
+ if (item->check_cols(1) ||
+ item->fix_fields(thd, tables, it.ref()))
+ DBUG_RETURN(-1); /* purecov: inspected */
+ item= *(it.ref()); //Item can be chenged in fix fields
+ if (ref_pointer_array)
+ ref_pointer_array[i]= item;
+ if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM &&
+ sum_func_list)
+ item->split_sum_func(ref_pointer_array, *sum_func_list);
+ thd->used_tables|=item->used_tables();
+ }
+ DBUG_RETURN(test(thd->fatal_error || thd->net.report_error));
+}
/*
Remap table numbers if INSERT ... SELECT
@@ -2459,7 +2485,7 @@ int mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys)
create_info.table_charset=default_charset_info;
DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->real_name,
&create_info, table_list,
- fields, keys, drop, alter, (ORDER*)0, FALSE,
+ fields, keys, drop, alter, 0, (ORDER*)0, FALSE,
DUP_ERROR));
}
@@ -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;
DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->real_name,
&create_info, table_list,
- fields, keys, drop, alter, (ORDER*)0, FALSE,
+ fields, keys, drop, alter, 0, (ORDER*)0, FALSE,
DUP_ERROR));
}
diff --git a/sql/sql_class.h b/sql/sql_class.h
index ca56d2dcdf5..38a96d1af66 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -376,7 +376,7 @@ struct system_variables
CONVERT *convert_set;
};
-
+void free_tmp_table(THD *thd, TABLE *entry);
/*
For each client connection we create a separate thread with THD serving as
a thread/connection descriptor
@@ -486,6 +486,7 @@ public:
CHARSET_INFO *db_charset;
CHARSET_INFO *thd_charset;
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;
uint warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_END];
uint total_warn_count, old_total_warn_count;
@@ -640,6 +641,17 @@ public:
net.report_error= 0;
}
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();
+ }
+ }
};
/*
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index 88da3e2505c..bb1eb1e1dd2 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -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)
{
delete select;
+ free_ulderlayed_joins(thd, &thd->lex.select_lex);
send_ok(thd,0L);
DBUG_RETURN(0); // Nothing to delete
}
@@ -103,6 +104,7 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order,
if (safe_update && !using_limit)
{
delete select;
+ free_ulderlayed_joins(thd, &thd->lex.select_lex);
send_error(thd,ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE);
DBUG_RETURN(1);
}
@@ -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),
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)) ||
(table->found_records = filesort(thd, table, sortorder, length,
(SQL_SELECT *) 0, HA_POS_ERROR,
@@ -132,6 +134,7 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order,
== HA_POS_ERROR)
{
delete select;
+ free_ulderlayed_joins(thd, &thd->lex.select_lex);
DBUG_RETURN(-1); // This will force out message
}
}
@@ -207,6 +210,7 @@ cleanup:
thd->lock=0;
}
delete select;
+ free_ulderlayed_joins(thd, &thd->lex.select_lex);
if (error >= 0 || thd->net.report_error)
send_error(thd,thd->killed ? ER_SERVER_SHUTDOWN: 0);
else
diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc
index f0df6811133..2949dae3985 100644
--- a/sql/sql_derived.cc
+++ b/sql/sql_derived.cc
@@ -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 (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;
goto exit;
@@ -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;
lex->current_select= sl;
- res= mysql_select(thd, tables, sl->item_list,
- sl->where, (ORDER *) sl->order_list.first,
- (ORDER*) sl->group_list.first,
+ res= mysql_select(thd, &sl->ref_pointer_array, tables, sl->with_wild,
+ sl->item_list, sl->where,
+ sl->order_list.elements+sl->group_list.elements,
+ (ORDER *) sl->order_list.first,
+ (ORDER *) sl->group_list.first,
sl->having, (ORDER*) NULL,
sl->options | thd->options | SELECT_NO_UNLOCK,
derived_result, unit, sl, 0);
@@ -122,6 +125,8 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
}
if (res)
free_tmp_table(thd,table);
+ else
+ thd->temporary_tables_should_be_free.push_front(table);
exit:
close_thread_tables(thd);
}
diff --git a/sql/sql_do.cc b/sql/sql_do.cc
index 2eef088da5b..f25c4632e1e 100644
--- a/sql/sql_do.cc
+++ b/sql/sql_do.cc
@@ -25,7 +25,7 @@ int mysql_do(THD *thd, List<Item> &values)
List_iterator<Item> li(values);
Item *value;
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);
while ((value = li++))
value->val_int();
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index f45e09cf0bf..8d5727d9eb1 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -81,7 +81,7 @@ check_insert_fields(THD *thd,TABLE *table,List<Item> &fields,
thd->dupp_field=0;
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;
if (thd->dupp_field)
{
@@ -171,10 +171,10 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
values= its++;
if (check_insert_fields(thd,table,fields,*values,1) ||
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 &&
- (setup_fields(thd, 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_fields, 0, 0, 0) ||
+ setup_fields(thd, 0, insert_table_list, update_values, 0, 0, 0))))
goto abort;
if (find_real_table_in_list(table_list->next,
table_list->db, table_list->real_name))
@@ -194,7 +194,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
MYF(0),counter);
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;
}
its.rewind ();
@@ -381,11 +381,13 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
thd->cuted_fields);
::send_ok(thd,info.copied+info.deleted,(ulonglong)id,buff);
}
+ free_ulderlayed_joins(thd, &thd->lex.select_lex);
DBUG_RETURN(0);
abort:
if (lock_type == TL_WRITE_DELAYED)
end_delayed_insert(thd);
+ free_ulderlayed_joins(thd, &thd->lex.select_lex);
DBUG_RETURN(-1);
}
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 833f36dbe9f..0da47b12649 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -944,6 +944,7 @@ void st_select_lex_node::init_query()
next= master= slave= link_next= 0;
prev= link_prev= 0;
dependent= 0;
+ ref_pointer_array= 0;
}
void st_select_lex_node::init_select()
@@ -967,6 +968,8 @@ void st_select_lex_unit::init_query()
union_option= 0;
prepared= optimized= executed= 0;
item= 0;
+ union_result= 0;
+ table= 0;
}
void st_select_lex::init_query()
@@ -979,6 +982,7 @@ void st_select_lex::init_query()
join= 0;
olap= UNSPECIFIED_OLAP_TYPE;
having_fix_field= 0;
+ with_wild= 0;
}
void st_select_lex::init_select()
@@ -1105,12 +1109,12 @@ bool st_select_lex_node::add_item_to_list(THD *thd, Item *item)
bool st_select_lex_node::add_group_to_list(THD *thd, Item *item, bool asc)
{
- return 1;
+ return 1;
}
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)
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 0c761baffa3..a8d55ec91d5 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -208,8 +208,11 @@ public:
List<List_item> expr_list;
List<List_item> when_list; /* WHEN clause (expression) */
ha_rows select_limit, offset_limit; /* LIMIT clause parameters */
- bool with_sum_func;
- bool create_refs;
+ // 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 dependent; /* dependent from outer select subselect */
static void *operator new(size_t size)
@@ -269,11 +272,10 @@ class select_union;
class st_select_lex_unit: public st_select_lex_node {
protected:
List<Item> item_list;
- List<JOIN*> joins; /* list of *JOINs, to delete it in cleanup() */
TABLE_LIST result_table_list;
select_union *union_result;
TABLE *table; /* temporary table using for appending UNION results */
- THD *thd;
+
select_result *result;
int res;
bool describe, found_rows_for_union,
@@ -290,6 +292,8 @@ public:
ha_rows select_limit_cnt, offset_limit_cnt;
/* not NULL if union used in subselect, point to subselect item */
Item_subselect *item;
+ THD *thd;
+
uint union_option;
void init_query();
@@ -336,6 +340,7 @@ public:
const char *type; /* type of select for EXPLAIN */
uint in_sum_expr;
uint select_number; /* number of select (used for EXPLAIN) */
+ uint with_wild; /* item list contain '*' */
bool braces; /* SELECT ... UNION (SELECT ... ) <- this braces */
/* TRUE when having fix field called in processing of this SELECT */
bool having_fix_field;
diff --git a/sql/sql_list.h b/sql/sql_list.h
index 56e6528f214..c9f569accf6 100644
--- a/sql/sql_list.h
+++ b/sql/sql_list.h
@@ -147,12 +147,20 @@ protected:
class base_list_iterator
{
+protected:
base_list *list;
list_node **el,**prev,*current;
+ void sublist(base_list &ls, uint elm)
+ {
+ ls.first= *el;
+ ls.last= list->last;
+ ls.elements= elm;
+ }
public:
- base_list_iterator(base_list &list_par) :list(&list_par),el(&list_par.first),
- prev(0),current(0)
+ base_list_iterator(base_list &list_par)
+ :list(&list_par), el(&list_par.first), prev(0), current(0)
{}
+
inline void *next(void)
{
prev=el;
@@ -212,7 +220,6 @@ public:
friend class error_list_iterator;
};
-
template <class T> class List :public base_list
{
public:
@@ -260,6 +267,10 @@ public:
List_iterator_fast(List<T> &a) : base_list_iterator(a) {}
inline T* operator++(int) { return (T*) base_list_iterator::next_fast(); }
inline void rewind(void) { base_list_iterator::rewind(); }
+ void sublist(List<T> &list, uint el)
+ {
+ base_list_iterator::sublist(list, el);
+ }
};
diff --git a/sql/sql_load.cc b/sql/sql_load.cc
index 00450a3b86c..2e059612014 100644
--- a/sql/sql_load.cc
+++ b/sql/sql_load.cc
@@ -117,7 +117,8 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
else
{ // Part field list
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);
if (thd->dupp_field)
{
diff --git a/sql/sql_olap.cc b/sql/sql_olap.cc
index 6eb4fbcaaf6..93dff84bf0b 100644
--- a/sql/sql_olap.cc
+++ b/sql/sql_olap.cc
@@ -164,8 +164,10 @@ int handle_olaps(LEX *lex, SELECT_LEX *select_lex)
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,(TABLE_LIST *)select_lex->table_list.first,item_list_copy,1,&all_fields,1))
+ setup_fields(lex->thd, 0, (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,
+ item_list_copy, 1, &all_fields, 1))
return -1;
if (select_lex->olap == CUBE_TYPE)
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 90568bfcc5e..b608221e7f0 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -1915,6 +1915,7 @@ mysql_execute_command(THD *thd)
&lex->create_info,
tables, lex->create_list,
lex->key_list, lex->drop_list, lex->alter_list,
+ select_lex->order_list.elements,
(ORDER *) select_lex->order_list.first,
lex->drop_primary, lex->duplicates,
lex->alter_keys_onoff, lex->simple_alter);
@@ -2026,8 +2027,8 @@ mysql_execute_command(THD *thd)
res= mysql_alter_table(thd, NullS, NullS, &create_info,
tables, lex->create_list,
lex->key_list, lex->drop_list, lex->alter_list,
- (ORDER *) 0,
- 0,DUP_ERROR);
+ 0, (ORDER *) 0,
+ 0, DUP_ERROR);
}
else
res = mysql_optimize_table(thd, tables, &lex->check_opt);
@@ -2047,6 +2048,7 @@ mysql_execute_command(THD *thd)
select_lex->item_list,
lex->value_list,
select_lex->where,
+ select_lex->order_list.elements,
(ORDER *) select_lex->order_list.first,
select_lex->select_limit,
lex->duplicates);
@@ -2246,10 +2248,12 @@ mysql_execute_command(THD *thd)
if (!thd->fatal_error && (result= new multi_delete(thd,aux_tables,
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->where,
- (ORDER *)NULL,(ORDER *)NULL,(Item *)NULL,
+ 0, (ORDER *)NULL, (ORDER *)NULL, (Item *)NULL,
(ORDER *)NULL,
select_lex->options | thd->options |
SELECT_NO_JOIN_CACHE,
@@ -2741,6 +2745,7 @@ mysql_execute_command(THD *thd)
send_ok(thd);
break;
}
+ thd->free_tmp_tables();
thd->proc_info="query end"; // QQ
if (res < 0)
send_error(thd,thd->killed ? ER_SERVER_SHUTDOWN : 0);
@@ -2988,6 +2993,7 @@ mysql_init_query(THD *thd)
LEX *lex=&thd->lex;
lex->unit.init_query();
lex->unit.init_select();
+ lex->unit.thd= thd;
lex->select_lex.init_query();
lex->value_list.empty();
lex->param_list.empty();
@@ -3044,6 +3050,7 @@ mysql_new_select(LEX *lex, bool move_down)
return 1;
unit->init_query();
unit->init_select();
+ unit->thd= lex->thd;
unit->include_down(lex->current_select);
select_lex->include_down(unit);
}
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 9d6e6d75ade..6af2528074c 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -365,7 +365,7 @@ static int check_prepare_fields(THD *thd,TABLE *table, List<Item> &fields,
thd->dupp_field=0;
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;
if (thd->dupp_field)
{
@@ -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)))
DBUG_RETURN(1);
- if (setup_tables(table_list) || setup_fields(thd,table_list,fields,1,0,0) ||
- setup_conds(thd,table_list,&conds))
+ if (setup_tables(table_list) ||
+ setup_fields(thd, 0, table_list, fields, 1, 0, 0) ||
+ setup_conds(thd, table_list, &conds))
DBUG_RETURN(1);
/*
@@ -488,10 +489,11 @@ static bool mysql_test_select_fields(PREP_STMT *stmt, TABLE_LIST *tables,
thd->used_tables=0; // Updated by setup_fields
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_order(thd,tables,fields,all_fields,order) ||
- setup_group(thd,tables,fields,all_fields,group,&hidden_group_fields))
+ setup_order(thd, 0, tables, fields, all_fields, order) ||
+ setup_group(thd, 0, tables, fields, all_fields, group,
+ &hidden_group_fields))
DBUG_RETURN(1);
if (having)
@@ -502,7 +504,7 @@ static bool mysql_test_select_fields(PREP_STMT *stmt, TABLE_LIST *tables,
|| thd->fatal_error)
DBUG_RETURN(1);
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))
DBUG_RETURN(1);
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 5b8e2085982..50bea2376c3 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -58,7 +58,7 @@ static bool make_simple_join(JOIN *join,TABLE *tmp_table);
static bool make_join_select(JOIN *join,SQL_SELECT *select,COND *item);
static void make_join_readinfo(JOIN *join,uint options);
static void join_free(JOIN *join, bool full);
-static bool only_eq_ref_tables(JOIN *join,ORDER *order,table_map tables);
+static bool only_eq_ref_tables(JOIN *join, ORDER *order, table_map tables);
static void update_depend_map(JOIN *join);
static void update_depend_map(JOIN *join, ORDER *order);
static ORDER *remove_const(JOIN *join,ORDER *first_order,COND *cond,
@@ -140,8 +140,16 @@ static TABLE *get_sort_by_table(ORDER *a,ORDER *b,TABLE_LIST *tables);
static void calc_group_buffer(JOIN *join,ORDER *group);
static bool alloc_group_fields(JOIN *join,ORDER *group);
static bool make_sum_func_list(JOIN *join,List<Item> &fields);
-static bool change_to_use_tmp_fields(List<Item> &func);
-static bool change_refs_to_tmp_fields(THD *thd, List<Item> &func);
+// Create list for using with tempory table
+static bool change_to_use_tmp_fields(Item **ref_pointer_array,
+ List<Item> &new_list1,
+ List<Item> &new_list2,
+ uint elements, List<Item> &items);
+// Create list for using with tempory table
+static bool change_refs_to_tmp_fields(THD *thd, Item **ref_pointer_array,
+ List<Item> &new_list1,
+ List<Item> &new_list2,
+ uint elements, List<Item> &items);
static void init_tmptable_sum_functions(Item_sum **func);
static void update_tmptable_sum_func(Item_sum **func,TABLE *tmp_table);
static void copy_sum_funcs(Item_sum **func_ptr);
@@ -164,17 +172,21 @@ int handle_select(THD *thd, LEX *lex, select_result *result)
if (select_lex->next_select())
res=mysql_union(thd,lex,result);
else
- res=mysql_select(thd,(TABLE_LIST*) select_lex->table_list.first,
- select_lex->item_list,
- select_lex->where,
- (ORDER*) select_lex->order_list.first,
- (ORDER*) select_lex->group_list.first,
- select_lex->having,
- (ORDER*) lex->proc_list.first,
- select_lex->options | thd->options,
- result, &(lex->unit), &(lex->select_lex), 0);
+ res= mysql_select(thd, &select_lex->ref_pointer_array,
+ (TABLE_LIST*) select_lex->table_list.first,
+ select_lex->with_wild, select_lex->item_list,
+ select_lex->where,
+ select_lex->order_list.elements +
+ select_lex->group_list.elements,
+ (ORDER*) select_lex->order_list.first,
+ (ORDER*) select_lex->group_list.first,
+ select_lex->having,
+ (ORDER*) lex->proc_list.first,
+ select_lex->options | thd->options,
+ result, &(lex->unit), &(lex->select_lex), 0);
if (res && result)
result->abort();
+
if (res || thd->net.report_error)
{
send_error(thd, 0, NullS);
@@ -204,7 +216,8 @@ void fix_tables_pointers(SELECT_LEX *select_lex)
/*
Inline function to setup clauses without sum functions
*/
-inline int setup_without_group(THD *thd, TABLE_LIST *tables,
+inline int setup_without_group(THD *thd, Item **ref_pointer_array,
+ TABLE_LIST *tables,
List<Item> &fields,
List<Item> &all_fields,
COND **conds,
@@ -213,10 +226,11 @@ inline int setup_without_group(THD *thd, TABLE_LIST *tables,
{
bool save_allow_sum_func= thd->allow_sum_func;
thd->allow_sum_func= 0;
- int res= (setup_conds(thd,tables, conds) ||
- setup_order(thd,tables, fields, all_fields, order) ||
- setup_group(thd,tables, fields, all_fields, group,
- hidden_group_fields));
+ int res= (setup_conds(thd, tables, conds) ||
+ setup_order(thd, ref_pointer_array, tables, fields, all_fields,
+ order) ||
+ setup_group(thd, ref_pointer_array, tables, fields, all_fields,
+ group, hidden_group_fields));
thd->allow_sum_func= save_allow_sum_func;
return res;
}
@@ -232,8 +246,10 @@ inline int setup_without_group(THD *thd, TABLE_LIST *tables,
0 on success
*/
int
-JOIN::prepare(TABLE_LIST *tables_init,
- COND *conds_init, ORDER *order_init, ORDER *group_init,
+JOIN::prepare(Item ***rref_pointer_array,
+ TABLE_LIST *tables_init,
+ uint wild_num, COND *conds_init, uint og_num,
+ ORDER *order_init, ORDER *group_init,
Item *having_init,
ORDER *proc_param_init, SELECT_LEX *select,
SELECT_LEX_UNIT *unit, bool fake_select_lex)
@@ -254,11 +270,19 @@ JOIN::prepare(TABLE_LIST *tables_init,
/* Check that all tables, fields, conds and order are ok */
if (setup_tables(tables_list) ||
- setup_fields(thd,tables_list,fields_list,1,&all_fields,1) ||
- setup_without_group(thd, tables_list, fields_list, all_fields,
- &conds, order, group_list, &hidden_group_fields))
+ setup_wild(thd, tables_list, fields_list, &all_fields, wild_num) ||
+ setup_ref_array(thd, rref_pointer_array, (fields_list.elements +
+ select_lex->with_sum_func +
+ og_num)) ||
+ setup_fields(thd, (*rref_pointer_array), tables_list, fields_list, 1,
+ &all_fields, 1) ||
+ setup_without_group(thd, (*rref_pointer_array), tables_list, fields_list,
+ all_fields, &conds, order, group_list,
+ &hidden_group_fields))
DBUG_RETURN(-1); /* purecov: inspected */
+ ref_pointer_array= *rref_pointer_array;
+
if (having)
{
thd->where="having clause";
@@ -270,7 +294,7 @@ JOIN::prepare(TABLE_LIST *tables_init,
if (having_fix_rc || thd->net.report_error)
DBUG_RETURN(-1); /* purecov: inspected */
if (having->with_sum_func)
- having->split_sum_func(all_fields);
+ having->split_sum_func(ref_pointer_array, all_fields);
}
if (setup_ftfuncs(select_lex)) /* should be after having->fix_fields */
DBUG_RETURN(-1);
@@ -303,7 +327,7 @@ JOIN::prepare(TABLE_LIST *tables_init,
for (table=tables_list ; table ; table=table->next)
tables++;
}
- procedure=setup_procedure(thd,proc_param,result,fields_list,&error);
+ procedure= setup_procedure(thd, proc_param, result, fields_list, &error);
if (error)
DBUG_RETURN(-1); /* purecov: inspected */
if (procedure)
@@ -378,6 +402,9 @@ int
JOIN::optimize()
{
DBUG_ENTER("JOIN::optimize");
+ if (optimized)
+ DBUG_RETURN(0);
+ optimized= 1;
#ifdef HAVE_REF_TO_FIELDS // Not done yet
/* Add HAVING to WHERE if possible */
@@ -638,7 +665,7 @@ JOIN::optimize()
we must add the removed reference to the select for the table.
We only need to do this when we have a simple_order or simple_group
as in other cases the join is done before the sort.
- */
+ */
if ((order || group_list) && join_tab[const_tables].type != JT_ALL &&
join_tab[const_tables].type != JT_FT &&
(order && simple_order || group_list && simple_group))
@@ -658,19 +685,117 @@ JOIN::optimize()
{
need_tmp=1; simple_order=simple_group=0; // Force tmp table without sort
}
+
+ if (select_options & SELECT_DESCRIBE)
+ DBUG_RETURN(0);
+
+ tmp_having= having;
+ having= 0;
+
+ /* Perform FULLTEXT search before all regular searches */
+ init_ftfuncs(thd, select_lex, test(order));
+ /* Create a tmp table if distinct or if the sort is too complicated */
+ if (need_tmp)
+ {
+ DBUG_PRINT("info",("Creating tmp table"));
+ thd->proc_info="Creating tmp table";
+
+ init_items_ref_array();
+
+ tmp_table_param.hidden_field_count= (all_fields.elements -
+ fields_list.elements);
+ if (!(exec_tmp_table1 =
+ create_tmp_table(thd, &tmp_table_param, all_fields,
+ ((!simple_group && !procedure &&
+ !(test_flags & TEST_NO_KEY_GROUP)) ?
+ group_list : (ORDER*) 0),
+ group_list ? 0 : select_distinct,
+ group_list && simple_group,
+ select_options,
+ (order == 0 || skip_sort_order) ? select_limit :
+ HA_POS_ERROR)))
+ DBUG_RETURN(1);
+
+ //thd->temporary_tables_should_be_free.push_front(exec_tmp_table1);
+ if (having &&
+ (sort_and_group || (exec_tmp_table1->distinct && !group_list)))
+ having= tmp_having;
+
+ /* if group or order on first table, sort first */
+ if (group_list && simple_group)
+ {
+ DBUG_PRINT("info",("Sorting for group"));
+ thd->proc_info="Sorting for group";
+ if (create_sort_index(thd, &join_tab[const_tables], group_list,
+ HA_POS_ERROR, HA_POS_ERROR) ||
+ make_sum_func_list(this, all_fields) ||
+ alloc_group_fields(this, group_list))
+ DBUG_RETURN(1);
+ group_list=0;
+ }
+ else
+ {
+ if (make_sum_func_list(this, all_fields))
+ DBUG_RETURN(1);
+ if (!group_list && ! exec_tmp_table1->distinct && order && simple_order)
+ {
+ DBUG_PRINT("info",("Sorting for order"));
+ thd->proc_info="Sorting for order";
+ if (create_sort_index(thd, &join_tab[const_tables], order,
+ HA_POS_ERROR, HA_POS_ERROR))
+ DBUG_RETURN(1);
+ order=0;
+ }
+ }
+
+ /*
+ Optimize distinct when used on some of the tables
+ SELECT DISTINCT t1.a FROM t1,t2 WHERE t1.b=t2.b
+ In this case we can stop scanning t2 when we have found one t1.a
+ */
+
+ if (exec_tmp_table1->distinct)
+ {
+ table_map used_tables= thd->used_tables;
+ JOIN_TAB *join_tab= this->join_tab+tables-1;
+ do
+ {
+ if (used_tables & join_tab->table->map)
+ break;
+ join_tab->not_used_in_distinct=1;
+ } while (join_tab-- != this->join_tab);
+ /* Optimize "select distinct b from t1 order by key_part_1 limit #" */
+ if (order && skip_sort_order)
+ {
+ /* Should always succeed */
+ if (test_if_skip_sort_order(&this->join_tab[const_tables],
+ order, unit->select_limit_cnt, 0))
+ order=0;
+ }
+ }
+
+ if (select_lex != &thd->lex.select_lex &&
+ select_lex->linkage != DERIVED_TABLE_TYPE)
+ {
+ if (!(tmp_join= (JOIN*)thd->alloc(sizeof(JOIN))))
+ DBUG_RETURN(-1);
+ restore_tmp();
+ }
+ }
+
DBUG_RETURN(0);
}
/*
- Global optimization (with subselect) must be here (TODO)
+ Restore values in temporary join
*/
-int
-JOIN::global_optimize()
+void JOIN::restore_tmp()
{
- return 0;
+ memcpy(tmp_join, this, (size_t) sizeof(JOIN));
}
+
int
JOIN::reinit()
{
@@ -695,6 +820,28 @@ JOIN::reinit()
func->null_value= 1;
}
+ if (exec_tmp_table1)
+ {
+ exec_tmp_table1->file->extra(HA_EXTRA_RESET_STATE);
+ exec_tmp_table1->file->delete_all_rows();
+ free_io_cache(exec_tmp_table1);
+ memcpy(ref_pointer_array, items0, ref_pointer_array_size);
+ }
+ if (exec_tmp_table2)
+ {
+ exec_tmp_table2->file->extra(HA_EXTRA_RESET_STATE);
+ exec_tmp_table2->file->delete_all_rows();
+ free_io_cache(exec_tmp_table2);
+ }
+ if (items0)
+ memcpy(ref_pointer_array, items0, ref_pointer_array_size);
+
+ tmp_table_param.copy_funcs.empty();
+ tmp_table_param.copy_field= tmp_table_param.copy_field_end= 0;
+
+ if (tmp_join)
+ restore_tmp();
+
DBUG_RETURN(0);
}
@@ -743,14 +890,11 @@ JOIN::exec()
!group_list,
select_options,
zero_result_cause,
- having,procedure,
+ having, procedure,
unit);
DBUG_VOID_RETURN;
}
- Item *having_list = having;
- having = 0;
-
if (select_options & SELECT_DESCRIBE)
{
if (!order && !no_order)
@@ -761,6 +905,7 @@ JOIN::exec()
test_if_skip_sort_order(&join_tab[const_tables], order,
select_limit, 0))))
order=0;
+ having= tmp_having;
select_describe(this, need_tmp,
order != 0 && !skip_sort_order,
select_distinct);
@@ -769,120 +914,85 @@ JOIN::exec()
}
/* Perform FULLTEXT search before all regular searches */
- init_ftfuncs(thd, select_lex, test(order));
+ //init_ftfuncs(thd, select_lex, test(order));
+
+ JOIN *curr_join= this;
+ List<Item> *curr_all_fields= &all_fields;
+ List<Item> *curr_fields_list= &fields_list;
+ TABLE *curr_tmp_table= 0;
/* Create a tmp table if distinct or if the sort is too complicated */
if (need_tmp)
{
- DBUG_PRINT("info",("Creating tmp table"));
- thd->proc_info="Creating tmp table";
-
- tmp_table_param.hidden_field_count= (all_fields.elements -
- fields_list.elements);
- if (!(exec_tmp_table =
- create_tmp_table(thd, &tmp_table_param, all_fields,
- ((!simple_group && !procedure &&
- !(test_flags & TEST_NO_KEY_GROUP)) ?
- group_list : (ORDER*) 0),
- group_list ? 0 : select_distinct,
- group_list && simple_group,
- select_options,
- (order == 0 || skip_sort_order) ? select_limit :
- HA_POS_ERROR)))
- DBUG_VOID_RETURN;
-
- if (having_list &&
- (sort_and_group || (exec_tmp_table->distinct && !group_list)))
- having=having_list;
-
- /* if group or order on first table, sort first */
- if (group_list && simple_group)
- {
- DBUG_PRINT("info",("Sorting for group"));
- thd->proc_info="Sorting for group";
- if (create_sort_index(thd, &join_tab[const_tables], group_list,
- HA_POS_ERROR, HA_POS_ERROR) ||
- make_sum_func_list(this, all_fields) ||
- alloc_group_fields(this, group_list))
- DBUG_VOID_RETURN;
- group_list=0;
- }
- else
- {
- if (make_sum_func_list(this, all_fields))
- DBUG_VOID_RETURN;
- if (!group_list && ! exec_tmp_table->distinct && order && simple_order)
- {
- DBUG_PRINT("info",("Sorting for order"));
- thd->proc_info="Sorting for order";
- if (create_sort_index(thd, &join_tab[const_tables], order,
- HA_POS_ERROR, HA_POS_ERROR))
- DBUG_VOID_RETURN;
- order=0;
- }
- }
-
- /*
- Optimize distinct when used on some of the tables
- SELECT DISTINCT t1.a FROM t1,t2 WHERE t1.b=t2.b
- In this case we can stop scanning t2 when we have found one t1.a
- */
-
- if (exec_tmp_table->distinct)
- {
- table_map used_tables= thd->used_tables;
- JOIN_TAB *join_tab= this->join_tab+tables-1;
- do
- {
- if (used_tables & join_tab->table->map)
- break;
- join_tab->not_used_in_distinct=1;
- } while (join_tab-- != this->join_tab);
- /* Optimize "select distinct b from t1 order by key_part_1 limit #" */
- if (order && skip_sort_order)
- {
- /* Should always succeed */
- if (test_if_skip_sort_order(&this->join_tab[const_tables],
- order, unit->select_limit_cnt, 0))
- order=0;
- }
- }
-
+ if (tmp_join)
+ curr_join= tmp_join;
+ curr_tmp_table= exec_tmp_table1;
/* Copy data to the temporary table */
thd->proc_info= "Copying to tmp table";
- if ((tmp_error= do_select(this, (List<Item> *) 0, exec_tmp_table, 0)))
+
+ if ((tmp_error= do_select(curr_join, (List<Item> *) 0, curr_tmp_table, 0)))
{
error= tmp_error;
DBUG_VOID_RETURN;
}
- if (having)
- having= having_list= 0; // Allready done
-
+ curr_tmp_table->file->info(HA_STATUS_VARIABLE);
+
+ if (curr_join->having)
+ curr_join->having= curr_join->tmp_having= 0; // Allready done
+
/* Change sum_fields reference to calculated fields in tmp_table */
- if (sort_and_group || exec_tmp_table->group)
+ curr_join->all_fields= *curr_all_fields;
+ if (!items1)
{
- if (change_to_use_tmp_fields(all_fields))
- DBUG_VOID_RETURN;
- tmp_table_param.field_count+= tmp_table_param.sum_func_count+
- tmp_table_param.func_count;
- tmp_table_param.sum_func_count= tmp_table_param.func_count= 0;
+ items1= items0 + all_fields.elements;
+ if (sort_and_group || curr_tmp_table->group)
+ {
+ if (change_to_use_tmp_fields(items1,
+ tmp_fields_list1, tmp_all_fields1,
+ fields_list.elements, all_fields))
+ DBUG_VOID_RETURN;
+ }
+ else
+ {
+ if (change_refs_to_tmp_fields(thd, items1,
+ tmp_fields_list1, tmp_all_fields1,
+ fields_list.elements, all_fields))
+ DBUG_VOID_RETURN;
+ }
+ curr_join->tmp_all_fields1= tmp_all_fields1;
+ curr_join->tmp_fields_list1= tmp_fields_list1;
+ curr_join->items1= items1;
+ }
+ curr_all_fields= &tmp_all_fields1;
+ curr_fields_list= &tmp_fields_list1;
+ memcpy(ref_pointer_array, items1, ref_pointer_array_size);
+
+ if (sort_and_group || curr_tmp_table->group)
+ {
+ curr_join->tmp_table_param.field_count+=
+ curr_join->tmp_table_param.sum_func_count+
+ curr_join->tmp_table_param.func_count;
+ curr_join->tmp_table_param.sum_func_count=
+ curr_join->tmp_table_param.func_count= 0;
}
else
{
- if (change_refs_to_tmp_fields(thd,all_fields))
- DBUG_VOID_RETURN;
- tmp_table_param.field_count+= tmp_table_param.func_count;
- tmp_table_param.func_count= 0;
+ curr_join->tmp_table_param.field_count+=
+ curr_join->tmp_table_param.func_count;
+ curr_join->tmp_table_param.func_count= 0;
}
+
+ // procedure can't be used inside subselect => we do nothing special for it
if (procedure)
procedure->update_refs();
- if (exec_tmp_table->group)
+
+ if (curr_tmp_table->group)
{ // Already grouped
- if (!order && !no_order)
- order= group_list; /* order by group */
- group_list= 0;
+ if (!curr_join->order && !curr_join->no_order)
+ curr_join->order= curr_join->group_list; /* order by group */
+ curr_join->group_list= 0;
}
-
+
/*
If we have different sort & group then we must sort the data by group
and copy it to another tmp table
@@ -891,142 +1001,199 @@ JOIN::exec()
like SEC_TO_TIME(SUM(...)).
*/
- if (group_list && (!test_if_subpart(group_list,order) ||
- select_distinct) ||
- (select_distinct &&
- tmp_table_param.using_indirect_summary_function))
+ if (curr_join->group_list && (!test_if_subpart(curr_join->group_list,
+ curr_join->order) ||
+ curr_join->select_distinct) ||
+ (curr_join->select_distinct &&
+ curr_join->tmp_table_param.using_indirect_summary_function))
{ /* Must copy to another table */
- TABLE *tmp_table2;
DBUG_PRINT("info",("Creating group table"));
-
+
/* Free first data from old join */
- join_free(this, 0);
- if (make_simple_join(this, exec_tmp_table))
- DBUG_VOID_RETURN;
- calc_group_buffer(this, group_list);
- count_field_types(&tmp_table_param, all_fields,
- select_distinct && !group_list);
- tmp_table_param.hidden_field_count= (all_fields.elements-
- fields_list.elements);
-
- /* group data to new table */
- if (!(tmp_table2 = create_tmp_table(thd, &tmp_table_param, all_fields,
- (ORDER*) 0,
- select_distinct && !group_list,
- 1, select_options, HA_POS_ERROR)))
+ join_free(curr_join, 0);
+ if (make_simple_join(curr_join, curr_tmp_table))
DBUG_VOID_RETURN;
+ calc_group_buffer(curr_join, group_list);
+ count_field_types(&curr_join->tmp_table_param, curr_join->tmp_all_fields1,
+ curr_join->select_distinct && !curr_join->group_list);
+ curr_join->tmp_table_param.hidden_field_count=
+ (curr_join->tmp_all_fields1.elements-
+ curr_join->tmp_fields_list1.elements);
+
+
+ if (exec_tmp_table2)
+ curr_tmp_table= exec_tmp_table2;
+ else
+ {
+ /* group data to new table */
+ if (!(curr_tmp_table=
+ exec_tmp_table2= create_tmp_table(thd,
+ &curr_join->tmp_table_param,
+ *curr_all_fields,
+ (ORDER*) 0,
+ curr_join->select_distinct &&
+ !curr_join->group_list,
+ 1, curr_join->select_options,
+ HA_POS_ERROR)))
+ DBUG_VOID_RETURN;
+ //thd->temporary_tables_should_be_free.push_front(exec_tmp_table2);
+ curr_join->exec_tmp_table2= exec_tmp_table2;
+ }
if (group_list)
{
- thd->proc_info="Creating sort index";
- if (create_sort_index(thd, join_tab, group_list, HA_POS_ERROR,
- HA_POS_ERROR) ||
- alloc_group_fields(this, group_list))
+ thd->proc_info= "Creating sort index";
+ if (create_sort_index(thd, curr_join->join_tab, curr_join->group_list,
+ HA_POS_ERROR, HA_POS_ERROR) ||
+ alloc_group_fields(curr_join, curr_join->group_list))
{
- free_tmp_table(thd,tmp_table2); /* purecov: inspected */
DBUG_VOID_RETURN;
}
- group_list= 0;
+ curr_join->group_list= 0;
}
+
thd->proc_info="Copying to group table";
tmp_error= -1;
- if (make_sum_func_list(this, all_fields) ||
- (tmp_error=do_select(this, (List<Item> *) 0,tmp_table2,0)))
+ if (make_sum_func_list(curr_join, *curr_all_fields) ||
+ (tmp_error= do_select(curr_join, (List<Item> *) 0, curr_tmp_table,
+ 0)))
{
- error=tmp_error;
- free_tmp_table(thd,tmp_table2);
+ error= tmp_error;
DBUG_VOID_RETURN;
}
- end_read_record(&join_tab->read_record);
- free_tmp_table(thd,exec_tmp_table);
- const_tables= tables; // Mark free for join_free()
- exec_tmp_table= tmp_table2;
- join_tab[0].table= 0; // Table is freed
-
- if (change_to_use_tmp_fields(all_fields)) // No sum funcs anymore
- DBUG_VOID_RETURN;
- tmp_table_param.field_count+= tmp_table_param.sum_func_count;
- tmp_table_param.sum_func_count= 0;
- }
-
- if (exec_tmp_table->distinct)
- select_distinct=0; /* Each row is unique */
-
- join_free(this, 0); /* Free quick selects */
+ end_read_record(&curr_join->join_tab->read_record);
+ curr_join->const_tables= curr_join->tables; // Mark free for join_free()
+ curr_join->join_tab[0].table= 0; // Table is freed
+
+ // No sum funcs anymore
+ if (!items2)
+ {
+ items2= items1 + all_fields.elements;
+ if (change_to_use_tmp_fields(items2,
+ tmp_fields_list2, tmp_all_fields2,
+ fields_list.elements, tmp_all_fields1))
+ DBUG_VOID_RETURN;
+ curr_join->tmp_fields_list2= tmp_fields_list2;
+ curr_join->tmp_all_fields2= tmp_all_fields2;
+ }
+ curr_fields_list= &curr_join->tmp_fields_list2;
+ curr_all_fields= &curr_join->tmp_all_fields2;
+ memcpy(ref_pointer_array, items2, ref_pointer_array_size);
+ curr_join->tmp_table_param.field_count+=
+ curr_join->tmp_table_param.sum_func_count;
+ curr_join->tmp_table_param.sum_func_count= 0;
+ }
+ if (curr_tmp_table->distinct)
+ curr_join->select_distinct=0; /* Each row is unique */
+
+ join_free(curr_join, 0); /* Free quick selects */
if (select_distinct && ! group_list)
{
thd->proc_info="Removing duplicates";
- if (having_list)
- having_list->update_used_tables();
- if (remove_duplicates(this, exec_tmp_table, fields_list, having_list))
+ if (curr_join->tmp_having)
+ curr_join->tmp_having->update_used_tables();
+ if (remove_duplicates(curr_join, curr_tmp_table,
+ curr_join->fields_list, curr_join->tmp_having))
DBUG_VOID_RETURN;
- having_list=0;
- select_distinct=0;
+ curr_join->tmp_having=0;
+ curr_join->select_distinct=0;
}
- exec_tmp_table->reginfo.lock_type=TL_UNLOCK;
- if (make_simple_join(this, exec_tmp_table))
+ curr_tmp_table->reginfo.lock_type= TL_UNLOCK;
+ if (make_simple_join(curr_join, curr_tmp_table))
DBUG_VOID_RETURN;
- calc_group_buffer(this, group_list);
- count_field_types(&tmp_table_param, all_fields, 0);
+ calc_group_buffer(curr_join, curr_join->group_list);
+ count_field_types(&curr_join->tmp_table_param, *curr_all_fields, 0);
+
}
if (procedure)
{
- if (procedure->change_columns(fields_list) ||
- result->prepare(fields_list, unit))
+ if (procedure->change_columns(*curr_fields_list) ||
+ result->prepare(*curr_fields_list, unit))
DBUG_VOID_RETURN;
- count_field_types(&tmp_table_param, all_fields, 0);
+ count_field_types(&curr_join->tmp_table_param, *curr_all_fields, 0);
}
- if (group || tmp_table_param.sum_func_count ||
+
+ if (curr_join->group || curr_join->tmp_table_param.sum_func_count ||
(procedure && (procedure->flags & PROC_GROUP)))
{
- alloc_group_fields(this, group_list);
- setup_copy_fields(thd, &tmp_table_param,all_fields);
- if (make_sum_func_list(this, all_fields) || thd->fatal_error)
+ alloc_group_fields(curr_join, curr_join->group_list);
+ if (!items3)
+ {
+ if (!items0)
+ init_items_ref_array();
+ items3= ref_pointer_array + (all_fields.elements*4);
+ setup_copy_fields(thd, &curr_join->tmp_table_param,
+ items3, tmp_fields_list3, tmp_all_fields3,
+ curr_fields_list->elements, *curr_all_fields);
+ tmp_table_param.save_copy_funcs= curr_join->tmp_table_param.copy_funcs;
+ tmp_table_param.save_copy_field= curr_join->tmp_table_param.copy_field;
+ tmp_table_param.save_copy_field_end=
+ curr_join->tmp_table_param.copy_field_end;
+ curr_join->tmp_all_fields3= tmp_all_fields3;
+ curr_join->tmp_fields_list3= tmp_fields_list3;
+ }
+ else
+ {
+ curr_join->tmp_table_param.copy_funcs= tmp_table_param.save_copy_funcs;
+ curr_join->tmp_table_param.copy_field= tmp_table_param.save_copy_field;
+ curr_join->tmp_table_param.copy_field_end=
+ tmp_table_param.save_copy_field_end;
+ }
+ curr_fields_list= &tmp_fields_list3;
+ curr_all_fields= &tmp_all_fields3;
+ memcpy(ref_pointer_array, items3, ref_pointer_array_size);
+
+ if (make_sum_func_list(curr_join, *curr_all_fields) ||
+ thd->fatal_error)
DBUG_VOID_RETURN;
}
- if (group_list || order)
+ if (curr_join->group_list || curr_join->order)
{
DBUG_PRINT("info",("Sorting for send_fields"));
thd->proc_info="Sorting result";
/* If we have already done the group, add HAVING to sorted table */
- if (having_list && ! group_list && ! sort_and_group)
+ if (curr_join->tmp_having && ! curr_join->group_list &&
+ ! curr_join->sort_and_group)
{
- having_list->update_used_tables(); // Some tables may have been const
- JOIN_TAB *table= &join_tab[const_tables];
- table_map used_tables= const_table_map | table->table->map;
+ // Some tables may have been const
+ curr_join->tmp_having->update_used_tables();
+ JOIN_TAB *table= &curr_join->join_tab[const_tables];
+ table_map used_tables= curr_join->const_table_map | table->table->map;
- Item* sort_table_cond= make_cond_for_table(having_list, used_tables,
+ Item* sort_table_cond= make_cond_for_table(curr_join->tmp_having,
+ used_tables,
used_tables);
if (sort_table_cond)
{
if (!table->select)
- if (!(table->select=new SQL_SELECT))
+ if (!(table->select= new SQL_SELECT))
DBUG_VOID_RETURN;
if (!table->select->cond)
- table->select->cond=sort_table_cond;
+ table->select->cond= sort_table_cond;
else // This should never happen
- if (!(table->select->cond=new Item_cond_and(table->select->cond,
- sort_table_cond)))
+ if (!(table->select->cond= new Item_cond_and(table->select->cond,
+ sort_table_cond)))
DBUG_VOID_RETURN;
table->select_cond=table->select->cond;
table->select_cond->top_level_item();
DBUG_EXECUTE("where",print_where(table->select->cond,
"select and having"););
- having_list= make_cond_for_table(having_list, ~ (table_map) 0,
- ~used_tables);
+ curr_join->tmp_having= make_cond_for_table(curr_join->tmp_having,
+ ~ (table_map) 0,
+ ~used_tables);
DBUG_EXECUTE("where",print_where(conds,"having after sort"););
}
}
{
if (group)
- select_limit= HA_POS_ERROR;
+ curr_join->select_limit= HA_POS_ERROR;
else
{
/*
We can abort sorting after thd->select_limit rows if we there is no
WHERE clause for any tables after the sorted one.
*/
- JOIN_TAB *table= &join_tab[const_tables+1];
- JOIN_TAB *end_table= &join_tab[tables];
+ JOIN_TAB *table= &curr_join->join_tab[const_tables+1];
+ JOIN_TAB *end_table= &curr_join->join_tab[tables];
for (; table < end_table ; table++)
{
/*
@@ -1038,21 +1205,22 @@ JOIN::exec()
if (table->select_cond || (table->keyuse && !table->on_expr))
{
/* We have to sort all rows */
- select_limit= HA_POS_ERROR;
+ curr_join->select_limit= HA_POS_ERROR;
break;
}
}
}
- if (create_sort_index(thd, &join_tab[const_tables],
- group_list ? group_list : order,
- select_limit, unit->select_limit_cnt))
- DBUG_VOID_RETURN;
+ if (create_sort_index(thd, &curr_join->join_tab[curr_join->const_tables],
+ curr_join->group_list ?
+ curr_join->group_list : curr_join->order,
+ curr_join->select_limit, unit->select_limit_cnt))
+ DBUG_VOID_RETURN;
}
}
- having=having_list; // Actually a parameter
+ curr_join->having= curr_join->tmp_having;
thd->proc_info="Sending data";
error= thd->net.report_error ||
- do_select(this, &fields_list, NULL, procedure);
+ do_select(curr_join, curr_fields_list, NULL, procedure);
DBUG_VOID_RETURN;
}
@@ -1065,10 +1233,18 @@ JOIN::cleanup(THD *thd)
{
DBUG_ENTER("JOIN::cleanup");
+ select_lex->join= 0;
+
+ if (tmp_join)
+ memcpy(this, tmp_join, sizeof(tmp_join));
+
+
lock=0; // It's faster to unlock later
join_free(this, 1);
- if (exec_tmp_table)
- free_tmp_table(thd, exec_tmp_table);
+ if (exec_tmp_table1)
+ free_tmp_table(thd, exec_tmp_table1);
+ if (exec_tmp_table2)
+ free_tmp_table(thd, exec_tmp_table2);
delete select;
delete_dynamic(&keyuse);
delete procedure;
@@ -1076,18 +1252,7 @@ JOIN::cleanup(THD *thd)
unit != 0;
unit= unit->next_unit())
{
- for (SELECT_LEX *sl= unit->first_select();
- sl != 0;
- sl= sl->next_select())
- {
- if (sl->join)
- {
- int err= sl->join->cleanup(thd);
- if (err)
- error= err;
- sl->join= 0;
- }
- }
+ error|= unit->cleanup();
}
DBUG_RETURN(error);
}
@@ -1111,11 +1276,12 @@ bool JOIN::check_loop(uint id)
}
int
-mysql_select(THD *thd, TABLE_LIST *tables, List<Item> &fields, COND *conds,
- ORDER *order, ORDER *group,Item *having, ORDER *proc_param,
- ulong select_options, select_result *result,
- SELECT_LEX_UNIT *unit, SELECT_LEX *select_lex,
- bool fake_select_lex)
+mysql_select(THD *thd, Item ***rref_pointer_array,
+ TABLE_LIST *tables, uint wild_num, List<Item> &fields,
+ COND *conds, uint og_num, ORDER *order, ORDER *group,
+ Item *having, ORDER *proc_param, ulong select_options,
+ select_result *result, SELECT_LEX_UNIT *unit,
+ SELECT_LEX *select_lex, bool fake_select_lex)
{
int err;
bool free_join= 1;
@@ -1140,7 +1306,8 @@ mysql_select(THD *thd, TABLE_LIST *tables, List<Item> &fields, COND *conds,
thd->proc_info="init";
thd->used_tables=0; // Updated by setup_fields
- if (join->prepare(tables, conds, order, group, having, proc_param,
+ if (join->prepare(rref_pointer_array, tables, wild_num,
+ conds, og_num, order, group, having, proc_param,
select_lex, unit, fake_select_lex))
{
DBUG_RETURN(-1);
@@ -1172,7 +1339,7 @@ mysql_select(THD *thd, TABLE_LIST *tables, List<Item> &fields, COND *conds,
goto err; // 1
}
- if (thd->net.report_error || (free_join && join->global_optimize()))
+ if (thd->net.report_error)
goto err;
join->exec();
@@ -1180,10 +1347,14 @@ mysql_select(THD *thd, TABLE_LIST *tables, List<Item> &fields, COND *conds,
err:
if (free_join)
{
- thd->limit_found_rows = join->send_records;
- thd->examined_row_count = join->examined_rows;
+ JOIN *curr_join= (join->need_tmp&&join->tmp_join?
+ (join->tmp_join->error=join->error,join->tmp_join):
+ join);
+
+ thd->limit_found_rows= curr_join->send_records;
+ thd->examined_row_count= curr_join->examined_rows;
thd->proc_info="end";
- err= (fake_select_lex ? join->error : join->cleanup(thd));
+ err= (fake_select_lex ? curr_join->error : join->cleanup(thd));
if (thd->net.report_error)
err= -1;
delete join;
@@ -3068,6 +3239,7 @@ join_free(JOIN *join, bool full)
delete tab->select;
delete tab->quick;
x_free(tab->cache.buff);
+ tab->cache.buff= 0;
if (tab->table)
{
if (tab->table->key_read)
@@ -3094,9 +3266,12 @@ join_free(JOIN *join, bool full)
mysql_unlock_read_tables(join->thd, join->lock);// Don't free join->lock
join->lock=0;
}
- join->group_fields.delete_elements();
- join->tmp_table_param.copy_funcs.delete_elements();
- join->tmp_table_param.cleanup();
+ if (full)
+ {
+ join->group_fields.delete_elements();
+ join->tmp_table_param.copy_funcs.delete_elements();
+ join->tmp_table_param.cleanup();
+ }
DBUG_VOID_RETURN;
}
@@ -4124,9 +4299,11 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
{
uint alloc_length=ALIGN_SIZE(reclength+MI_UNIQUE_HASH_LENGTH+1);
table->rec_buff_length=alloc_length;
- if (!(table->record[0]= (byte *) my_malloc(alloc_length*3, MYF(MY_WME))))
+ byte * t;
+ if (!(t= table->record[0]= (byte *) my_malloc(alloc_length*3, MYF(MY_WME))))
goto err;
- table->record[1]= table->record[0]+alloc_length;
+ table->record[1]= t+alloc_length;
+ //table->record[1]= table->record[0]+alloc_length;
table->record[2]= table->record[1]+alloc_length;
}
copy_func[0]=0; // End marker
@@ -6752,31 +6929,32 @@ cp_buffer_from_ref(TABLE_REF *ref)
*/
static int
-find_order_in_list(THD *thd,TABLE_LIST *tables,ORDER *order,List<Item> &fields,
+find_order_in_list(THD *thd, Item **ref_pointer_array,
+ TABLE_LIST *tables,ORDER *order, List<Item> &fields,
List<Item> &all_fields)
{
if ((*order->item)->type() == Item::INT_ITEM)
{ /* Order by position */
Item *item=0;
- List_iterator<Item> li(fields);
- for (uint count= (uint) ((Item_int*) (*order->item))->value ;
- count-- && (item=li++) ;) ;
- if (!item)
+ uint count= (uint) ((Item_int*) (*order->item))->value;
+ if (count > fields.elements)
{
my_printf_error(ER_BAD_FIELD_ERROR,ER(ER_BAD_FIELD_ERROR),
MYF(0),(*order->item)->full_name(),
thd->where);
return 1;
}
- order->item=li.ref();
- order->in_field_list=1;
+ order->item= ref_pointer_array + count-1;
+ order->in_field_list= 1;
return 0;
}
- Item **item= find_item_in_list(*order->item, fields, IGNORE_ERRORS);
+ uint counter= 0;
+ Item **item= find_item_in_list(*order->item, fields, &counter,
+ IGNORE_ERRORS);
if (item)
{
- order->item=item; // use it
+ order->item= ref_pointer_array + counter-1;
order->in_field_list=1;
return 0;
}
@@ -6785,24 +6963,43 @@ find_order_in_list(THD *thd,TABLE_LIST *tables,ORDER *order,List<Item> &fields,
if (it->check_cols(1) || it->fix_fields(thd, tables, order->item) ||
thd->fatal_error)
return 1; // Wrong field
- all_fields.push_front(*order->item); // Add new field to field list
- order->item=(Item**) all_fields.head_ref();
+ uint el= all_fields.elements;
+ all_fields.push_front(it); // Add new field to field list
+ ref_pointer_array[el]= it;
+ order->item= ref_pointer_array + el;
return 0;
}
+/*
+ Allocate array of references to address all_fileds list elements
+*/
+
+int setup_ref_array(THD* thd, Item ***rref_pointer_array, uint elements)
+{
+ if (*rref_pointer_array)
+ return 0;
+
+ /* TODO: may be better allocate only one and all other on demand? */
+ if (!(*rref_pointer_array=
+ (Item **)thd->alloc(sizeof(Item*) * elements * 5)))
+ return -1;
+ else
+ return 0;
+}
/*
Change order to point at item in select list. If item isn't a number
and doesn't exits in the select list, add it the the field list.
*/
-int setup_order(THD *thd,TABLE_LIST *tables,List<Item> &fields,
- List<Item> &all_fields, ORDER *order)
+int setup_order(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
+ List<Item> &fields, List<Item> &all_fields, ORDER *order)
{
thd->where="order clause";
for (; order; order=order->next)
{
- if (find_order_in_list(thd,tables,order,fields,all_fields))
+ if (find_order_in_list(thd, ref_pointer_array, tables, order, fields,
+ all_fields))
return 1;
}
return 0;
@@ -6810,8 +7007,9 @@ int setup_order(THD *thd,TABLE_LIST *tables,List<Item> &fields,
int
-setup_group(THD *thd,TABLE_LIST *tables,List<Item> &fields,
- List<Item> &all_fields, ORDER *order, bool *hidden_group_fields)
+setup_group(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
+ List<Item> &fields, List<Item> &all_fields, ORDER *order,
+ bool *hidden_group_fields)
{
*hidden_group_fields=0;
if (!order)
@@ -6829,7 +7027,8 @@ setup_group(THD *thd,TABLE_LIST *tables,List<Item> &fields,
thd->where="group statement";
for (; order; order=order->next)
{
- if (find_order_in_list(thd,tables,order,fields,all_fields))
+ if (find_order_in_list(thd, ref_pointer_array, tables, order, fields,
+ all_fields))
return 1;
(*order->item)->marker=1; /* Mark found */
if ((*order->item)->with_sum_func)
@@ -6873,9 +7072,11 @@ setup_new_fields(THD *thd,TABLE_LIST *tables,List<Item> &fields,
DBUG_ENTER("setup_new_fields");
thd->set_query_id=1; // Not really needed, but...
+ uint counter= 0;
for (; new_field ; new_field= new_field->next)
{
- if ((item= find_item_in_list(*new_field->item, fields, IGNORE_ERRORS)))
+ if ((item= find_item_in_list(*new_field->item, fields, &counter,
+ IGNORE_ERRORS)))
new_field->item=item; /* Change to shared Item */
else
{
@@ -7126,41 +7327,55 @@ test_if_group_changed(List<Item_buff> &list)
*/
bool
-setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields)
+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)
{
Item *pos;
- List_iterator<Item> li(fields);
+ List_iterator_fast<Item> li(fields);
Copy_field *copy;
DBUG_ENTER("setup_copy_fields");
+ new_list1.empty();
+ new_list2.empty();
+ List_iterator_fast<Item> itr(new_list2);
+
+ uint i, border= fields.elements - elements;
if (!(copy=param->copy_field= new Copy_field[param->field_count]))
goto err2;
param->copy_funcs.empty();
- while ((pos=li++))
+ for (i= 0; (pos= li++); i++)
{
if (pos->type() == Item::FIELD_ITEM)
{
- Item_field *item=(Item_field*) pos;
+ Item_field *item;
+ if (!(item= new Item_field(*((Item_field*) pos))))
+ goto err;
+ pos= item;
if (item->field->flags & BLOB_FLAG)
{
- if (!(pos=new Item_copy_string(pos)))
+ if (!(pos= new Item_copy_string(pos)))
goto err;
- VOID(li.replace(pos));
if (param->copy_funcs.push_back(pos))
goto err;
- continue;
}
-
- /* set up save buffer and change result_field to point at saved value */
- Field *field= item->field;
- item->result_field=field->new_field(&thd->mem_root,field->table);
- char *tmp=(char*) sql_alloc(field->pack_length()+1);
- if (!tmp)
- goto err;
- copy->set(tmp, item->result_field);
- item->result_field->move_field(copy->to_ptr,copy->to_null_ptr,1);
- copy++;
+ else
+ {
+ /*
+ set up save buffer and change result_field to point at
+ saved value
+ */
+ Field *field= item->field;
+ item->result_field=field->new_field(&thd->mem_root,field->table);
+ char *tmp=(char*) sql_alloc(field->pack_length()+1);
+ if (!tmp)
+ goto err;
+ copy->set(tmp, item->result_field);
+ item->result_field->move_field(copy->to_ptr,copy->to_null_ptr,1);
+ copy++;
+ }
}
else if ((pos->type() == Item::FUNC_ITEM ||
pos->type() == Item::COND_ITEM) &&
@@ -7174,12 +7389,18 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields)
*/
if (!(pos=new Item_copy_string(pos)))
goto err;
- VOID(li.replace(pos));
if (param->copy_funcs.push_back(pos))
goto err;
}
+ new_list2.push_back(pos);
+ ref_pointer_array[((i < border)? fields.elements-i-1 : i-border)]=
+ pos;
}
param->copy_field_end= copy;
+
+ for (i= 0; i < border; i++)
+ itr++;
+ itr.sublist(new_list1, elements);
DBUG_RETURN(0);
err:
@@ -7244,51 +7465,63 @@ make_sum_func_list(JOIN *join,List<Item> &fields)
/*
- Change all funcs and sum_funcs to fields in tmp table
+ Change all funcs and sum_funcs to fields in tmp table, and create
+ new list of all items
*/
static bool
-change_to_use_tmp_fields(List<Item> &items)
+change_to_use_tmp_fields(Item **ref_pointer_array,
+ List<Item> &new_list1, List<Item> &new_list2,
+ uint elements, List<Item> &items)
{
- List_iterator<Item> it(items);
+ List_iterator_fast<Item> it(items);
Item *item_field,*item;
+ new_list1.empty();
+ new_list2.empty();
- while ((item=it++))
+ uint i, border= items.elements - elements;
+ for (i= 0; (item= it++); i++)
{
Field *field;
+
if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM)
- continue;
- if (item->type() == Item::FIELD_ITEM)
- {
- ((Item_field*) item)->field=
- ((Item_field*) item)->result_field;
- }
- else if ((field=item->tmp_table_field()))
- {
- if (item->type() == Item::SUM_FUNC_ITEM && field->table->group)
- item_field=((Item_sum*) item)->result_item(field);
- else
- item_field=(Item*) new Item_field(field);
- if (!item_field)
- return TRUE; // Fatal error
- item_field->name=item->name; /*lint -e613 */
-#ifndef DBUG_OFF
- if (_db_on_ && !item_field->name)
+ item_field= item;
+ else
+ if (item->type() == Item::FIELD_ITEM)
{
- char buff[256];
- String str(buff,sizeof(buff),default_charset_info);
- str.length(0);
- item->print(&str);
- item_field->name=sql_strmake(str.ptr(),str.length());
+ item_field= item->get_tmp_table_item();
}
+ else if ((field= item->tmp_table_field()))
+ {
+ if (item->type() == Item::SUM_FUNC_ITEM && field->table->group)
+ item_field= ((Item_sum*) item)->result_item(field);
+ else
+ item_field= (Item*) new Item_field(field);
+ if (!item_field)
+ return TRUE; // Fatal error
+ item_field->name= item->name; /*lint -e613 */
+#ifndef DBUG_OFF
+ if (_db_on_ && !item_field->name)
+ {
+ char buff[256];
+ String str(buff,sizeof(buff),default_charset_info);
+ str.length(0);
+ item->print(&str);
+ item_field->name= sql_strmake(str.ptr(),str.length());
+ }
#endif
-#ifdef DELETE_ITEMS
- delete it.replace(item_field); /*lint -e613 */
-#else
- (void) it.replace(item_field); /*lint -e613 */
-#endif
- }
+ }
+ else
+ item_field= item;
+ new_list2.push_back(item_field);
+ ref_pointer_array[((i < border)? items.elements-i-1 : i-border)]=
+ item_field;
}
+
+ List_iterator_fast<Item> itr(new_list2);
+ for (i= 0; i < border; i++)
+ itr++;
+ itr.sublist(new_list1, elements);
return FALSE;
}
@@ -7299,52 +7532,29 @@ change_to_use_tmp_fields(List<Item> &items)
*/
static bool
-change_refs_to_tmp_fields(THD *thd,List<Item> &items)
+change_refs_to_tmp_fields(THD *thd, Item **ref_pointer_array,
+ List<Item> &new_list1,
+ List<Item> &new_list2, uint elements,
+ List<Item> &items)
{
- List_iterator<Item> it(items);
- Item *item;
+ List_iterator_fast<Item> it(items);
+ Item *item, *new_item;
+ new_list1.empty();
+ new_list2.empty();
- while ((item= it++))
+ uint i, border= items.elements - elements;
+ for (i= 0; (item= it++); i++)
{
- if (item->type() == Item::SUM_FUNC_ITEM)
- {
- if (!item->const_item())
- {
- Item_sum *sum_item= (Item_sum*) item;
- if (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++);
- }
- }
- }
- }
- }
- else if (item->with_sum_func)
- continue;
- else if ((item->type() == Item::FUNC_ITEM ||
- item->type() == Item::COND_ITEM) &&
- !item->const_item())
- { /* All funcs are stored */
-#ifdef DELETE_ITEMS
- delete it.replace(new Item_field(((Item_func*) item)->result_field));
-#else
- (void) it.replace(new Item_field(((Item_func*) item)->result_field));
-#endif
- }
- else if (item->type() == Item::FIELD_ITEM) /* Change refs */
- {
- ((Item_field*)item)->field=((Item_field*) item)->result_field;
- }
+ new_list2.push_back(new_item= item->get_tmp_table_item());
+ ref_pointer_array[((i < border)? items.elements-i-1 : i-border)]=
+ new_item;
}
+
+ List_iterator_fast<Item> itr(new_list2);
+ for (i= 0; i < border; i++)
+ itr++;
+ itr.sublist(new_list1, elements);
+
return thd->fatal_error;
}
@@ -7683,9 +7893,12 @@ int mysql_explain_select(THD *thd, SELECT_LEX *select_lex, char const *type,
select_lex->type= type;
thd->lex.current_select= select_lex;
SELECT_LEX_UNIT *unit= select_lex->master_unit();
- int res= mysql_select(thd,(TABLE_LIST*) select_lex->table_list.first,
- select_lex->item_list,
+ int res= mysql_select(thd, &select_lex->ref_pointer_array,
+ (TABLE_LIST*) select_lex->table_list.first,
+ select_lex->with_wild, select_lex->item_list,
select_lex->where,
+ select_lex->order_list.elements +
+ select_lex->group_list.elements,
(ORDER*) select_lex->order_list.first,
(ORDER*) select_lex->group_list.first,
select_lex->having,
@@ -7694,4 +7907,17 @@ int mysql_explain_select(THD *thd, SELECT_LEX *select_lex, char const *type,
result, unit, select_lex, 0);
DBUG_RETURN(res);
}
+
+/*
+*/
+
+void free_ulderlayed_joins(THD *thd, SELECT_LEX *select)
+{
+ for (SELECT_LEX_UNIT *unit= select->first_inner_unit();
+ unit;
+ unit= unit->next_unit())
+ unit->cleanup();
+}
+
+
diff --git a/sql/sql_select.h b/sql/sql_select.h
index 1fbe2052831..20972635d33 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -119,8 +119,10 @@ class TMP_TABLE_PARAM :public Sql_alloc
{
public:
List<Item> copy_funcs;
+ List<Item> save_copy_funcs;
List_iterator_fast<Item> copy_funcs_it;
Copy_field *copy_field, *copy_field_end;
+ Copy_field *save_copy_field, *save_copy_field_end;
byte *group_buff;
Item_result_field **funcs;
MI_COLUMNDEF *recinfo,*start_recinfo;
@@ -166,10 +168,13 @@ class JOIN :public Sql_alloc
List<Item> *fields;
List<Item_buff> group_fields;
TABLE *tmp_table;
+ // used to store 2 possible tmp table of SELECT
+ TABLE *exec_tmp_table1, *exec_tmp_table2;
THD *thd;
Item_sum **sum_funcs;
Procedure *procedure;
Item *having;
+ Item *tmp_having; // To store Having when processed tenporary table
uint select_options;
select_result *result;
TMP_TABLE_PARAM tmp_table_param;
@@ -178,6 +183,8 @@ class JOIN :public Sql_alloc
SELECT_LEX_UNIT *unit;
// select that processed
SELECT_LEX *select_lex;
+
+ JOIN *tmp_join; // copy of this JOIN to be used with temporary tables
bool select_distinct, //Is select distinct?
no_order, simple_order, simple_group,
@@ -186,7 +193,11 @@ class JOIN :public Sql_alloc
buffer_result;
DYNAMIC_ARRAY keyuse;
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
int error;
@@ -194,11 +205,14 @@ class JOIN :public Sql_alloc
COND *conds; // ---"---
TABLE_LIST *tables_list; //hold 'tables' parameter of mysql_selec
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
- 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,
ulong select_options, select_result *result):
@@ -208,14 +222,16 @@ class JOIN :public Sql_alloc
sort_and_group(0), first_record(0),
do_send_rows(1),
send_records(0), found_records(0), examined_rows(0),
+ exec_tmp_table1(0), exec_tmp_table2(0),
thd(thd),
sum_funcs(0),
procedure(0),
- having(0),
+ having(0), tmp_having(0),
select_options(select_options),
result(result),
lock(thd->lock),
select_lex(0), //for safety
+ tmp_join(0),
select_distinct(test(select_options & SELECT_DISTINCT)),
no_order(0), simple_order(0), simple_group(0), skip_sort_order(0),
need_tmp(0),
@@ -226,8 +242,10 @@ class JOIN :public Sql_alloc
fields_list(fields),
error(0),
select(0),
- exec_tmp_table(0),
- zero_result_cause(0)
+ ref_pointer_array(0), items0(0), items1(0), items2(0), items3(0),
+ ref_pointer_array_size(0),
+ zero_result_cause(0),
+ optimized(0)
{
fields_list = fields;
bzero((char*) &keyuse,sizeof(keyuse));
@@ -235,16 +253,23 @@ class JOIN :public Sql_alloc
tmp_table_param.end_write_records= HA_POS_ERROR;
}
- int prepare(TABLE_LIST *tables,
- COND *conds, ORDER *order, ORDER *group, Item *having,
- ORDER *proc_param, SELECT_LEX *select, SELECT_LEX_UNIT *unit,
- bool fake_select_lex);
+ int prepare(Item ***rref_pointer_array, TABLE_LIST *tables, uint wind_num,
+ COND *conds, uint og_num, ORDER *order, ORDER *group,
+ Item *having, ORDER *proc_param, SELECT_LEX *select,
+ SELECT_LEX_UNIT *unit, bool fake_select_lex);
int optimize();
- int global_optimize();
int reinit();
void exec();
int cleanup(THD *thd);
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,
void free_tmp_table(THD *thd, TABLE *entry);
void count_field_types(TMP_TABLE_PARAM *param, List<Item> &fields,
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_funcs(Item_result_field **func_ptr);
bool create_myisam_from_heap(THD *thd, TABLE *table, TMP_TABLE_PARAM *param,
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index d343ccd39f5..072e0de0432 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -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,
List<create_field> &create,
enum enum_duplicates handle_duplicates,
- ORDER *order,
+ uint order_num, ORDER *order,
ha_rows *copied,ha_rows *deleted);
/*****************************************************************************
@@ -1415,7 +1415,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
List<create_field> &fields,
List<Key> &keys,List<Alter_drop> &drop_list,
List<Alter_column> &alter_list,
- ORDER *order,
+ uint order_num, ORDER *order,
bool drop_primary,
enum enum_duplicates handle_duplicates,
enum enum_enable_or_disable keys_onoff,
@@ -1877,7 +1877,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
if (!new_table->is_view)
error=copy_data_between_tables(table,new_table,create_list,
handle_duplicates,
- order, &copied, &deleted);
+ order_num, order, &copied, &deleted);
thd->last_insert_id=next_insert_id; // Needed for correct log
thd->count_cuted_fields=0; // Don`t calc cuted fields
new_table->time_stamp=save_time_stamp;
@@ -2090,7 +2090,7 @@ static int
copy_data_between_tables(TABLE *from,TABLE *to,
List<create_field> &create,
enum enum_duplicates handle_duplicates,
- ORDER *order,
+ uint order_num, ORDER *order,
ha_rows *copied,
ha_rows *deleted)
{
@@ -2138,7 +2138,10 @@ copy_data_between_tables(TABLE *from,TABLE *to,
tables.db = from->table_cache_key;
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)) ||
(from->found_records = filesort(thd, from, sortorder, length,
(SQL_SELECT *) 0, HA_POS_ERROR,
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index 6e8c2ebdb5c..70eb39007d2 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -108,7 +108,6 @@ bool select_union::flush()
return 0;
}
-typedef JOIN * JOIN_P;
int st_select_lex_unit::prepare(THD *thd, select_result *result)
{
DBUG_ENTER("st_select_lex_unit::prepare");
@@ -116,11 +115,9 @@ int st_select_lex_unit::prepare(THD *thd, select_result *result)
if (prepared)
DBUG_RETURN(0);
prepared= 1;
- union_result=0;
res= 0;
found_rows_for_union= 0;
TMP_TABLE_PARAM tmp_table_param;
- this->thd= thd;
this->result= result;
SELECT_LEX_NODE *lex_select_save= thd->lex.current_select;
SELECT_LEX *sl;
@@ -143,7 +140,9 @@ int st_select_lex_unit::prepare(THD *thd, select_result *result)
while ((item= it++))
if (item_list.push_back(item))
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;
}
@@ -169,13 +168,11 @@ int st_select_lex_unit::prepare(THD *thd, select_result *result)
union_result->tmp_table_param=&tmp_table_param;
// prepare selects
- joins.empty();
for (sl= first_select(); sl; sl= sl->next_select())
{
JOIN *join= new JOIN(thd, sl->item_list,
sl->options | thd->options | SELECT_NO_UNLOCK,
union_result);
- joins.push_back(new JOIN_P(join));
thd->lex.current_select= sl;
offset_limit_cnt= 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)
if (select_limit_cnt == HA_POS_ERROR)
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->braces) ? sl->order_list.elements : 0) +
+ sl->group_list.elements,
(sl->braces) ?
(ORDER *)sl->order_list.first : (ORDER *) 0,
(ORDER*) sl->group_list.first,
@@ -286,8 +286,9 @@ int st_select_lex_unit::exec()
select_limit_cnt= HA_POS_ERROR; // no limit
if (select_limit_cnt == HA_POS_ERROR)
thd->options&= ~OPTION_FOUND_ROWS;
- res= mysql_select(thd,&result_table_list,
- item_list, NULL,
+ res= mysql_select(thd, &ref_pointer_array, &result_table_list,
+ 0, item_list, NULL,
+ global_parameters->order_list.elements,
(ORDER*)global_parameters->order_list.first,
(ORDER*) NULL, NULL, (ORDER*) NULL,
thd->options, result, this, first_select(), 1);
@@ -303,20 +304,24 @@ int st_select_lex_unit::exec()
int st_select_lex_unit::cleanup()
{
DBUG_ENTER("st_select_lex_unit::cleanup");
+
+ int error= 0;
+
if (union_result)
{
delete union_result;
- free_tmp_table(thd,table);
+ if (table)
+ free_tmp_table(thd, table);
table= 0; // Safety
}
- List_iterator<JOIN*> j(joins);
- JOIN** join;
- while ((join= j++))
+ for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select())
{
- (*join)->cleanup(thd);
- delete *join;
- delete join;
+ JOIN *join;
+ if ((join= sl->join))
+ {
+ error|= sl->join->cleanup(thd);
+ delete join;
+ }
}
- joins.empty();
- DBUG_RETURN(0);
+ DBUG_RETURN(error);
}
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index de5cb9ef45b..f32260f97f6 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -50,7 +50,7 @@ int mysql_update(THD *thd,
List<Item> &fields,
List<Item> &values,
COND *conds,
- ORDER *order,
+ uint order_num, ORDER *order,
ha_rows limit,
enum enum_duplicates handle_duplicates)
{
@@ -109,7 +109,7 @@ int mysql_update(THD *thd,
/* Check the fields we are going to modify */
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 */
if (table->timestamp_field)
{
@@ -122,8 +122,9 @@ int mysql_update(THD *thd,
/* Check values */
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 */
}
@@ -134,6 +135,7 @@ int mysql_update(THD *thd,
(select && select->check_quick(safe_update, limit)) || !limit)
{
delete select;
+ free_ulderlayed_joins(thd, &thd->lex.select_lex);
if (error)
{
DBUG_RETURN(-1); // Error in where
@@ -148,6 +150,7 @@ int mysql_update(THD *thd,
if (safe_update && !using_limit)
{
delete select;
+ free_ulderlayed_joins(thd, &thd->lex.select_lex);
send_error(thd,ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE);
DBUG_RETURN(1);
}
@@ -175,6 +178,7 @@ int mysql_update(THD *thd,
DISK_BUFFER_SIZE, MYF(MY_WME)))
{
delete select; /* purecov: inspected */
+ free_ulderlayed_joins(thd, &thd->lex.select_lex);
DBUG_RETURN(-1);
}
if (old_used_keys & ((key_map) 1 << used_index))
@@ -197,7 +201,10 @@ int mysql_update(THD *thd,
table->io_cache = (IO_CACHE *) my_malloc(sizeof(IO_CACHE),
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)) ||
(table->found_records = filesort(thd, table, sortorder, length,
(SQL_SELECT *) 0,
@@ -205,6 +212,7 @@ int mysql_update(THD *thd,
== HA_POS_ERROR)
{
delete select;
+ free_ulderlayed_joins(thd, &thd->lex.select_lex);
DBUG_RETURN(-1);
}
}
@@ -258,6 +266,7 @@ int mysql_update(THD *thd,
if (error >= 0)
{
delete select;
+ free_ulderlayed_joins(thd, &thd->lex.select_lex);
DBUG_RETURN(-1);
}
}
@@ -343,6 +352,7 @@ int mysql_update(THD *thd,
}
delete select;
+ free_ulderlayed_joins(thd, &thd->lex.select_lex);
if (error >= 0)
send_error(thd,thd->killed ? ER_SERVER_SHUTDOWN : 0); /* purecov: inspected */
else
@@ -357,6 +367,7 @@ int mysql_update(THD *thd,
}
thd->count_cuted_fields=0; /* calc cuted fields */
free_io_cache(table);
+
DBUG_RETURN(0);
}
@@ -388,7 +399,7 @@ int mysql_multi_update(THD *thd,
DBUG_RETURN(res);
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);
/*
@@ -411,8 +422,9 @@ int mysql_multi_update(THD *thd,
DBUG_RETURN(-1);
List<Item> total_list;
- res= mysql_select(thd,table_list,total_list,
- conds, (ORDER *) NULL, (ORDER *)NULL, (Item *) NULL,
+ res= mysql_select(thd, &select_lex->ref_pointer_array,
+ table_list, select_lex->with_wild, total_list,
+ conds, 0, (ORDER *) NULL, (ORDER *)NULL, (Item *) NULL,
(ORDER *)NULL,
options | SELECT_NO_JOIN_CACHE,
result, unit, select_lex, 0);
@@ -467,7 +479,7 @@ int multi_update::prepare(List<Item> &not_used_values, SELECT_LEX_UNIT *unit)
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);
/*
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index ed8e8f0fb51..de20d8c2b6e 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -1760,8 +1760,10 @@ select_item_list:
| 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;
+ (thd->lex.current_select->select_lex()->with_wild)++;
};
@@ -3631,10 +3633,19 @@ insert_ident:
| table_wild { $$=$1; };
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 '.' '*'
- { $$ = 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:
expr { $$=$1; };