summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <bell@sanja.is.com.ua>2003-01-25 13:19:46 +0200
committerunknown <bell@sanja.is.com.ua>2003-01-25 13:19:46 +0200
commit4b260ea42ede6a0c30fa45a4aab6e56788538d25 (patch)
tree088681536e968628003ae711fd14a8df01b404ac
parenta76f62bb0ff3364c8e1cafd443ded508f972f252 (diff)
parentd94eecbb92305f366983d938f3de586a7832a3c3 (diff)
downloadmariadb-git-4b260ea42ede6a0c30fa45a4aab6e56788538d25.tar.gz
merging
sql/item.cc: Auto merged sql/item_cmpfunc.cc: Auto merged sql/item_cmpfunc.h: Auto merged sql/item_sum.cc: Auto merged sql/mysql_priv.h: Auto merged sql/sql_class.h: Auto merged sql/sql_delete.cc: Auto merged sql/sql_insert.cc: Auto merged sql/sql_lex.h: Auto merged sql/sql_list.h: Auto merged sql/sql_load.cc: Auto merged sql/sql_olap.cc: Auto merged sql/sql_parse.cc: Auto merged sql/sql_select.h: Auto merged sql/sql_table.cc: Auto merged sql/sql_union.cc: Auto merged sql/sql_update.cc: Auto merged sql/sql_yacc.yy: Auto merged
-rw-r--r--mysql-test/r/subselect.result14
-rw-r--r--mysql-test/t/subselect.test12
-rw-r--r--sql/item.cc75
-rw-r--r--sql/item.h26
-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.cc16
-rw-r--r--sql/item_sum.cc74
-rw-r--r--sql/item_sum.h88
-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.cc89
-rw-r--r--sql/sql_class.h14
-rw-r--r--sql/sql_delete.cc6
-rw-r--r--sql/sql_derived.cc43
-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.cc6
-rw-r--r--sql/sql_select.cc928
-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, 1146 insertions, 591 deletions
diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result
index 2bbbd71f4cd..03308ca7dc4 100644
--- a/mysql-test/r/subselect.result
+++ b/mysql-test/r/subselect.result
@@ -155,21 +155,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
@@ -403,19 +400,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);
@@ -424,6 +417,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 b506baa9fdd..e715cd1d09f 100644
--- a/mysql-test/t/subselect.test
+++ b/mysql-test/t/subselect.test
@@ -70,12 +70,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;
@@ -216,7 +213,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 359ba486a71..34eae344af9 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -46,6 +46,30 @@ 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)
{
@@ -154,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)
{
@@ -265,6 +294,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)
{
@@ -600,6 +636,7 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
thd->net.last_errno= 0;
#endif
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->master_unit()->first_select()->linkage != DERIVED_TABLE_TYPE)
@@ -611,7 +648,7 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
(last= sl)->get_table_list(), &where,
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;
@@ -631,8 +668,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;
@@ -1045,6 +1090,7 @@ bool Item_field::send(Protocol *protocol, String *buffer)
bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
{
+ uint counter= 0;
if (!ref)
{
TABLE_LIST *where= 0;
@@ -1059,6 +1105,7 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
if (outer_resolving ||
(ref= find_item_in_list(this,
*(thd->lex.current_select->get_item_list()),
+ &counter,
((sl &&
thd->lex.current_select->master_unit()->
first_select()->linkage !=
@@ -1081,7 +1128,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,
@@ -1102,6 +1150,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;
@@ -1118,17 +1167,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 25cc2601281..788d37be491 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -52,6 +52,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);
@@ -70,7 +72,8 @@ public:
virtual double val()=0;
virtual longlong val_int()=0;
virtual String *val_str(String*)=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(); }
@@ -84,12 +87,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 ; }
@@ -124,6 +129,8 @@ public:
:db_name(db_name_par), table_name(table_name_par),
field_name(field_name_par), depended_from(0), outer_resolving(0)
{ name = (char*) field_name_par; }
+ // copy constructor used by Item_field & Item_ref
+ Item_ident(Item_ident &item);
const char *full_name() const;
void set_outer_resolving() { outer_resolving= 1; }
};
@@ -140,6 +147,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;
@@ -163,10 +172,12 @@ public:
{
return field->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();
};
@@ -446,8 +457,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;
};
@@ -461,6 +477,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 1c579708503..4310fbebaf7 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -1396,16 +1396,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);
}
@@ -1511,7 +1515,7 @@ void Item_cond::set_outer_resolving()
item->set_outer_resolving();
}
-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;
@@ -1520,11 +1524,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 8641ab410b3..d1557f022d2 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -650,7 +650,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");
@@ -801,7 +801,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 477b759be61..3f231c73585 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -155,17 +155,19 @@ void Item_func::set_outer_resolving()
}
}
-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);
}
}
}
@@ -234,14 +236,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)
@@ -312,6 +311,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 ec361cce4c5..5ca3bed1322 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -117,7 +117,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();
@@ -131,9 +131,11 @@ 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);
void set_outer_resolving();
+ Item * get_tmp_table_item();
};
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index 4ee851c2f84..e337f9c0c40 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -439,6 +439,8 @@ void Item_in_subselect::single_value_transformer(THD *thd,
compare_func_creator func)
{
DBUG_ENTER("Item_in_subselect::single_value_transformer");
+ THD *thd= current_thd;
+
if (unit->global_parameters->select_limit != HA_POS_ERROR)
{
my_error(ER_NOT_SUPPORTED_YET, MYF(0),
@@ -482,11 +484,15 @@ void Item_in_subselect::single_value_transformer(THD *thd,
sl->order_list.empty(); // no sense in ORDER BY without LIMIT
- if (sl->having || sl->with_sum_func || sl->group_list.first)
+ if (sl->having || sl->with_sum_func || sl->group_list.elements)
{
sl->item_list.push_back(item);
+ 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_null_helper(this,
- sl->item_list.head_ref(),
+ sl->ref_pointer_array,
(char *)"<no matter>",
(char*)"<result>"));
sl->having= and_items(sl->having, item);
@@ -678,8 +684,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 273c5a3c1c3..13e70358b05 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;
}
@@ -83,6 +96,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)
@@ -952,7 +985,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 &&
@@ -965,11 +998,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);
+ }
}
@@ -1100,8 +1136,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;
@@ -1113,6 +1149,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;
}
@@ -1122,10 +1164,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;
}
@@ -1133,7 +1175,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);
@@ -1161,13 +1203,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])))
@@ -1189,7 +1231,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 c49311082e8..311e7778be6 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;
CHARSET_INFO *key_charset;
@@ -183,9 +202,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; }
@@ -196,6 +225,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); }
};
@@ -227,6 +257,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();
@@ -236,6 +268,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_variance;
@@ -276,6 +309,9 @@ class Item_sum_variance : public Item_sum_num
public:
Item_sum_variance(Item *item_par) :Item_sum_num(item_par),count(0) {}
+ Item_sum_variance(Item_sum_variance &item):
+ Item_sum_num(item), sum(item.sum), sum_sqr(item.sum_sqr),
+ count(item.count) {}
enum Sumfunctype sum_func () const { return VARIANCE_FUNC; }
void reset();
bool add();
@@ -285,6 +321,7 @@ class Item_sum_variance : public Item_sum_num
Item *result_item(Field *field)
{ return new Item_variance_field(this); }
const char *func_name() const { return "variance"; }
+ Item * get_same() { return new Item_sum_variance(*this); }
};
class Item_sum_std;
@@ -295,22 +332,6 @@ public:
Item_std_field(Item_sum_std *item);
enum Type type() const { return FIELD_STD_ITEM; }
double val();
-};
-
-/*
- standard_deviation(a) = sqrt(variance(a))
-*/
-
-class Item_sum_std :public Item_sum_variance
-{
- public:
- Item_sum_std(Item *item_par) :Item_sum_variance(item_par){}
- enum Sumfunctype sum_func () const { return STD_FUNC; }
- double val();
- Item *result_item(Field *field)
- { return new Item_std_field(this); }
- const char *func_name() const { return "std"; }
-};
// This class is a string or number function depending on num_func
@@ -329,6 +350,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; }
@@ -360,10 +385,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); }
};
@@ -371,10 +398,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); }
};
@@ -386,6 +415,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();
@@ -397,9 +428,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); }
};
@@ -407,9 +440,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); }
};
/*
@@ -427,6 +462,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)
@@ -450,11 +486,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); }
};
@@ -464,12 +502,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); }
};
@@ -479,6 +519,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()
@@ -496,6 +537,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 */
@@ -505,12 +547,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); }
};
@@ -519,6 +563,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; }
@@ -526,6 +571,7 @@ public:
void reset() {}
bool add() { return 0; }
void update_field(int offset) {}
+ Item * get_same() { return new Item_sum_udf_int(*this); }
};
@@ -534,6 +580,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; }
@@ -544,6 +591,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 aa075e1a91d..03180793d8a 100644
--- a/sql/item_timefunc.h
+++ b/sql/item_timefunc.h
@@ -327,9 +327,10 @@ public:
max_length=10*thd_charset()->mbmaxlen;
}
int save_in_field(Field *to, bool no_conversions);
+ 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()));
}
};
@@ -341,10 +342,10 @@ public:
Item_date_func(Item *a) :Item_str_func(a) {}
Item_date_func(Item *a,Item *b) :Item_str_func(a,b) {}
enum_field_types field_type() const { return MYSQL_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()));
}
};
@@ -364,10 +365,10 @@ public:
String *val_str(String *str);
const char *func_name() const { return "curtime"; }
void fix_length_and_dec();
+ 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()));
}
};
@@ -462,10 +463,10 @@ public:
}
enum_field_types field_type() const { return MYSQL_TYPE_TIME; }
const char *func_name() const { return "sec_to_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()));
}
};
@@ -556,10 +557,10 @@ public:
Item_date_typecast(Item *a) :Item_typecast(a) {}
const char *func_name() const { return "date"; }
enum_field_types field_type() const { return MYSQL_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()));
}
};
@@ -570,10 +571,10 @@ public:
Item_time_typecast(Item *a) :Item_typecast(a) {}
const char *func_name() const { return "time"; }
enum_field_types field_type() const { return MYSQL_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()));
}
};
@@ -584,9 +585,9 @@ public:
Item_datetime_typecast(Item *a) :Item_typecast(a) {}
const char *func_name() const { return "datetime"; }
enum_field_types field_type() const { return MYSQL_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 feb6675e787..b1507a1e6f6 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -390,18 +390,21 @@ int mysql_optimize_table(THD* thd, TABLE_LIST* table_list,
bool check_simple_select();
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);
@@ -428,7 +431,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,
@@ -447,7 +450,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,
@@ -567,15 +570,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 847617d6462..6bbec63c258 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -1807,11 +1807,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
@@ -1828,7 +1832,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);
@@ -1841,8 +1845,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,
@@ -1859,11 +1865,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;
}
}
@@ -1873,7 +1881,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;
}
}
@@ -1891,30 +1900,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)
{
/*
@@ -1924,21 +1929,43 @@ int setup_fields(THD *thd, TABLE_LIST *tables, List<Item> &fields,
*/
sum_func_list->elements+= fields.elements - elem;
}
- }
- else
- {
- if (item->fix_fields(thd, tables, it.ref()) || item->check_cols(1))
- 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->fix_fields(thd, tables, it.ref()) ||
+ item->check_cols(1))
+ 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
@@ -2254,7 +2281,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));
}
@@ -2271,7 +2298,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 216720da801..e33ccb82cff 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -394,7 +394,7 @@ struct system_variables
CHARSET_INFO *thd_charset;
};
-
+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
@@ -507,6 +507,7 @@ public:
USER_CONN *user_connect;
CHARSET_INFO *db_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;
@@ -662,6 +663,17 @@ public:
#endif
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 cfa7170fd0a..808d3b6fc54 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 f4c3979a34a..9296625dfdb 100644
--- a/sql/sql_derived.cc
+++ b/sql/sql_derived.cc
@@ -99,21 +99,8 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
if (!(res=open_and_lock_tables(thd,tables)))
{
- if (is_union)
- {
- /*
- The following code is a re-do of fix_tables_pointers() found
- in sql_select.cc for UNION's within derived tables. The only
- difference is in navigation, as in derived tables we care for
- this level only.
-
- */
- for (SELECT_LEX *sel= sl; sel; sel= sel->next_select())
- relink_tables(sel);
- }
-
- lex->current_select= sl;
- 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;
@@ -144,12 +131,14 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
if (is_union)
res= mysql_union(thd,lex,derived_result,unit);
else
- res= mysql_select(thd, tables, sl->item_list,
- sl->where, (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);
+ 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);
if (!res)
{
@@ -181,12 +170,12 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
delete derived_result;
}
if (res)
- free_tmp_table(thd, table);
- else
- {
- table->next= thd->derived_tables;
- thd->derived_tables= table;
- }
+mp_table(thd, table);
+
+
+>next= thd->derived_tables
+erived_tables= table;
+
exit:
lex->current_select= save_current_select;
close_thread_tables(thd, 0, 1);
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 e76e982adea..1c3e97a0b8e 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 ();
@@ -376,11 +376,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 716e37b5cb7..764b7650f1d 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -996,6 +996,7 @@ int yylex(void *arg, void *yythd)
void st_select_lex_node::init_query()
{
no_table_names_allowed= dependent= 0;
+ ref_pointer_array= 0;
}
void st_select_lex_node::init_select()
@@ -1019,6 +1020,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()
@@ -1031,6 +1034,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()
@@ -1160,12 +1164,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 85a171e9fe4..a77f0ce76eb 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -210,8 +210,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 */
bool no_table_names_allowed; /* used for global order by */
@@ -274,11 +277,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,
@@ -295,6 +297,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();
@@ -342,6 +346,7 @@ public:
ulong table_join_options;
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 1711a340cae..505ea994d42 100644
--- a/sql/sql_list.h
+++ b/sql/sql_list.h
@@ -155,12 +155,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;
@@ -220,7 +228,6 @@ public:
friend class error_list_iterator;
};
-
template <class T> class List :public base_list
{
public:
@@ -268,6 +275,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 71d8a3e181b..49b4f2f7c2f 100644
--- a/sql/sql_load.cc
+++ b/sql/sql_load.cc
@@ -119,7 +119,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 1f22073f556..a5f164e1e38 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 ac79f4ebcf6..c0b38cec254 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -2041,6 +2041,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);
@@ -2154,8 +2155,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);
@@ -2175,6 +2176,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);
@@ -2376,10 +2378,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,
@@ -2883,6 +2887,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);
@@ -3130,6 +3135,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();
@@ -3191,6 +3197,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);
unit->link_next= 0;
unit->link_prev= 0;
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 758054a6e48..7c9e4b27564 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -437,6 +437,7 @@ static bool setup_params_data(PREP_STMT *stmt)
}
/*
+
Validate the following information for INSERT statement:
- field existance
- fields count
@@ -504,8 +505,9 @@ static bool mysql_test_upd_fields(PREP_STMT *stmt, TABLE_LIST *table_list,
if (open_and_lock_tables(thd, table_list))
DBUG_RETURN(1);
- if (setup_tables(table_list) || setup_fields(thd,table_list,fields,1,0,0) ||
- setup_conds(thd,table_list,&conds) || thd->net.report_error)
+ if (setup_tables(table_list) ||
+ setup_fields(thd, 0, table_list, fields, 1, 0, 0) ||
+ setup_conds(thd, table_list, &conds) || thd->net.report_error)
DBUG_RETURN(1);
/*
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 4de4b2299f2..f33433c6c37 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -57,7 +57,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,
@@ -139,8 +139,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);
@@ -163,17 +171,21 @@ int handle_select(THD *thd, LEX *lex, select_result *result)
if (select_lex->next_select())
res=mysql_union(thd,lex,result,&lex->unit);
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);
@@ -209,8 +221,8 @@ void fix_tables_pointers(SELECT_LEX *select_lex)
/*
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,
@@ -219,10 +231,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;
}
@@ -238,8 +251,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)
@@ -260,11 +275,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";
@@ -276,7 +299,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);
@@ -309,7 +332,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)
@@ -384,6 +407,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 */
@@ -644,7 +670,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))
@@ -664,19 +690,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()
{
@@ -701,6 +825,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);
}
@@ -755,14 +901,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)
@@ -773,6 +916,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);
@@ -781,29 +925,21 @@ 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 (tmp_join)
+ curr_join= tmp_join;
+ curr_tmp_table= exec_tmp_table1;
/*
+ TODO: move this comment on its place
We don't have to store rows in temp table that doesn't match HAVING if:
- we are sorting the table and writing complete group rows to the
temp table.
@@ -813,98 +949,72 @@ JOIN::exec()
If having is not handled here, it will be checked before the row
is sent to the client.
*/
- 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;
- }
- }
-
/* 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
@@ -913,139 +1023,196 @@ 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)
{
- 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++)
{
/*
@@ -1057,21 +1224,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;
}
@@ -1084,10 +1252,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;
@@ -1095,18 +1271,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);
}
@@ -1130,11 +1295,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;
@@ -1159,7 +1325,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);
@@ -1191,7 +1358,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();
@@ -1199,10 +1366,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;
@@ -3109,6 +3280,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)
@@ -3140,9 +3312,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;
}
@@ -4173,9 +4348,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
@@ -6906,31 +7083,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;
}
@@ -6939,24 +7117,43 @@ find_order_in_list(THD *thd,TABLE_LIST *tables,ORDER *order,List<Item> &fields,
if (it->fix_fields(thd, tables, order->item) || it->check_cols(1) ||
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;
@@ -6964,8 +7161,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)
@@ -6983,7 +7181,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)
@@ -7027,9 +7226,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
{
@@ -7280,41 +7481,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) &&
@@ -7328,12 +7543,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:
@@ -7398,51 +7619,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;
}
@@ -7453,52 +7686,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;
}
@@ -7843,9 +8053,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,
@@ -7854,4 +8067,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 e30bba830eb..934a3b72734 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 3f443c34287..931d3ab4512 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -36,7 +36,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);
/*****************************************************************************
@@ -1572,7 +1572,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,
@@ -2034,7 +2034,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;
@@ -2244,7 +2244,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)
{
@@ -2292,7 +2292,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 cdd34977e5a..ffd6ac48c2c 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -107,7 +107,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");
@@ -115,11 +114,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,
@@ -287,8 +287,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);
@@ -304,20 +305,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 3aae6f6f411..f2f1c0da0d9 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);
}
}
@@ -259,6 +267,7 @@ int mysql_update(THD *thd,
if (error >= 0)
{
delete select;
+ free_ulderlayed_joins(thd, &thd->lex.select_lex);
DBUG_RETURN(-1);
}
}
@@ -344,6 +353,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
@@ -358,6 +368,7 @@ int mysql_update(THD *thd,
}
thd->count_cuted_fields=0; /* calc cuted fields */
free_io_cache(table);
+
DBUG_RETURN(0);
}
@@ -389,7 +400,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);
/*
@@ -412,8 +423,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);
@@ -466,7 +478,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 d603748c443..e9e26b06bb4 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -1825,8 +1825,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)++;
};
@@ -3732,10 +3734,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; };