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
This commit is contained in:
unknown 2003-01-25 13:19:46 +02:00
commit fbd882fca6
33 changed files with 1145 additions and 590 deletions

View File

@ -155,21 +155,18 @@ select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1);
a b a b
1 7 1 7
2 7 2 7
(select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)) (select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)) union (select * from t4 order by a limit 2) limit 3;
union (select * from t4 order by a limit 2) limit 3;
a b a b
1 7 1 7
2 7 2 7
3 8 3 8
(select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)) (select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)) union (select * from t4 where t4.b=(select max(t2.a)*4 from t2) order by a);
union (select * from t4 where t4.b=(select max(t2.a)*4 from t2) order by a);
a b a b
1 7 1 7
2 7 2 7
3 8 3 8
4 8 4 8
explain (select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)) explain (select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)) union (select * from t4 where t4.b=(select max(t2.a)*4 from t2) order by a);
union (select * from t4 where t4.b=(select max(t2.a)*4 from t2) order by a);
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Using where 1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Using where
2 SUBSELECT t3 ALL NULL NULL NULL NULL 3 Using filesort 2 SUBSELECT t3 ALL NULL NULL NULL NULL 3 Using filesort
@ -403,19 +400,15 @@ Unknown column 'a' in 'having clause'
SELECT * from t2 where topic IN (SELECT topic FROM t2 GROUP BY date); SELECT * from t2 where topic IN (SELECT topic FROM t2 GROUP BY date);
mot topic date pseudo mot topic date pseudo
joce 40143 2002-10-22 joce joce 40143 2002-10-22 joce
joce 43506 2002-10-22 joce
SELECT * from t2 where topic IN (SELECT topic FROM t2 GROUP BY date HAVING topic < 4100); SELECT * from t2 where topic IN (SELECT topic FROM t2 GROUP BY date HAVING topic < 4100);
mot topic date pseudo mot topic date pseudo
joce 43506 2002-10-22 joce
SELECT * from t2 where topic IN (SELECT SUM(topic) FROM t1); SELECT * from t2 where topic IN (SELECT SUM(topic) FROM t1);
mot topic date pseudo mot topic date pseudo
SELECT * from t2 where topic = any (SELECT topic FROM t2 GROUP BY date); SELECT * from t2 where topic = any (SELECT topic FROM t2 GROUP BY date);
mot topic date pseudo mot topic date pseudo
joce 40143 2002-10-22 joce joce 40143 2002-10-22 joce
joce 43506 2002-10-22 joce
SELECT * from t2 where topic = any (SELECT topic FROM t2 GROUP BY date HAVING topic < 4100); SELECT * from t2 where topic = any (SELECT topic FROM t2 GROUP BY date HAVING topic < 4100);
mot topic date pseudo mot topic date pseudo
joce 43506 2002-10-22 joce
SELECT * from t2 where topic = any (SELECT SUM(topic) FROM t1); SELECT * from t2 where topic = any (SELECT SUM(topic) FROM t1);
mot topic date pseudo mot topic date pseudo
SELECT * from t2 where topic = all (SELECT topic FROM t2 GROUP BY date); SELECT * from t2 where topic = all (SELECT topic FROM t2 GROUP BY date);
@ -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); SELECT * from t2 where topic = all (SELECT topic FROM t2 GROUP BY date HAVING topic < 4100);
mot topic date pseudo mot topic date pseudo
joce 40143 2002-10-22 joce joce 40143 2002-10-22 joce
joce 43506 2002-10-22 joce
SELECT * from t2 where topic = all (SELECT SUM(topic) FROM t2); SELECT * from t2 where topic = all (SELECT SUM(topic) FROM t2);
mot topic date pseudo mot topic date pseudo
SELECT * from t2 where topic <> any (SELECT SUM(topic) FROM t2); SELECT * from t2 where topic <> any (SELECT SUM(topic) FROM t2);

View File

@ -70,12 +70,9 @@ select (select a from t3), a from t2;
select * from t2 where t2.a=(select a from t1); select * from t2 where t2.a=(select a from t1);
insert into t3 values (6),(7),(3); insert into t3 values (6),(7),(3);
select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1); select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1);
(select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)) (select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)) union (select * from t4 order by a limit 2) limit 3;
union (select * from t4 order by a limit 2) limit 3; (select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)) union (select * from t4 where t4.b=(select max(t2.a)*4 from t2) order by a);
(select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)) explain (select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)) union (select * from t4 where t4.b=(select max(t2.a)*4 from t2) order by a);
union (select * from t4 where t4.b=(select max(t2.a)*4 from t2) order by a);
explain (select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1))
union (select * from t4 where t4.b=(select max(t2.a)*4 from t2) order by a);
select (select a from t3 where a<t2.a*4 order by 1 desc limit 1), a from t2; select (select a from t3 where a<t2.a*4 order by 1 desc limit 1), a from t2;
select (select t3.a from t3 where a<8 order by 1 desc limit 1), a from select (select t3.a from t3 where a<8 order by 1 desc limit 1), a from
(select * from t2 where a>1) as tt; (select * from t2 where a>1) as tt;
@ -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 topic FROM t2 GROUP BY date HAVING topic < 4100);
SELECT * from t2 where topic = any (SELECT SUM(topic) FROM t1); SELECT * from t2 where topic = any (SELECT SUM(topic) FROM t1);
SELECT * from t2 where topic = all (SELECT topic FROM t2 GROUP BY date); SELECT * from t2 where topic = all (SELECT topic FROM t2 GROUP BY date);
SELECT topic FROM t2 GROUP BY date;
SELECT topic FROM t2 GROUP BY date HAVING topic < 4100;
SELECT * from t2 where topic = all (SELECT topic FROM t2 GROUP BY date HAVING topic < 4100); SELECT * from t2 where topic = all (SELECT topic FROM t2 GROUP BY date HAVING topic < 4100);
SELECT *, date as fff from t2 where not (SELECT date FROM t2 GROUP BY date HAVING topic < 4100 and fff!=date);
SELECT * from t2 where topic = all (SELECT SUM(topic) FROM t2); SELECT * from t2 where topic = all (SELECT SUM(topic) FROM t2);
SELECT * from t2 where topic <> any (SELECT SUM(topic) FROM t2); SELECT * from t2 where topic <> any (SELECT SUM(topic) FROM t2);
drop table t1,t2; drop table t1,t2;

View File

@ -46,6 +46,30 @@ Item::Item():
loop_id= 0; loop_id= 0;
} }
Item::Item(Item &item):
loop_id(0),
str_value(item.str_value),
name(item.name),
max_length(item.max_length),
marker(item.marker),
decimals(item.decimals),
maybe_null(item.maybe_null),
null_value(item.null_value),
unsigned_flag(item.unsigned_flag),
with_sum_func(item.with_sum_func),
fixed(item.fixed)
{
next=current_thd->free_list; // Put in free list
current_thd->free_list= this;
}
Item_ident::Item_ident(Item_ident &item):
Item(item),
db_name(item.db_name),
table_name(item.table_name),
field_name(item.field_name),
depended_from(item.depended_from)
{}
bool Item::check_loop(uint id) bool Item::check_loop(uint id)
{ {
@ -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 fixed= 1; // This item is not needed in fix_fields
} }
Item_field::Item_field(Item_field &item):
Item_ident(item),
field(item.field),
result_field(item.result_field)
{}
void Item_field::set_field(Field *field_par) void Item_field::set_field(Field *field_par)
{ {
@ -265,6 +294,13 @@ table_map Item_field::used_tables() const
return field->table->map; return field->table->map;
} }
Item * Item_field::get_tmp_table_item()
{
Item_field *new_item= new Item_field(*this);
if (new_item)
new_item->field= new_item->result_field;
return new_item;
}
String *Item_int::val_str(String *str) String *Item_int::val_str(String *str)
{ {
@ -600,6 +636,7 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
thd->net.last_errno= 0; thd->net.last_errno= 0;
#endif #endif
Item **refer= (Item **)not_found_item; Item **refer= (Item **)not_found_item;
uint counter= 0;
// Prevent using outer fields in subselects, that is not supported now // Prevent using outer fields in subselects, that is not supported now
SELECT_LEX *cursel=(SELECT_LEX *) thd->lex.current_select; SELECT_LEX *cursel=(SELECT_LEX *) thd->lex.current_select;
if (cursel->master_unit()->first_select()->linkage != DERIVED_TABLE_TYPE) 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, (last= sl)->get_table_list(), &where,
0)) != not_found_field) 0)) != not_found_field)
break; break;
if ((refer= find_item_in_list(this, sl->item_list, if ((refer= find_item_in_list(this, sl->item_list, &counter,
REPORT_EXCEPT_NOT_FOUND)) != REPORT_EXCEPT_NOT_FOUND)) !=
(Item **)not_found_item) (Item **)not_found_item)
break; break;
@ -631,8 +668,16 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
} }
else if (refer != (Item **)not_found_item) else if (refer != (Item **)not_found_item)
{ {
if (!(*refer)->fixed)
{
my_error(ER_ILLEGAL_REFERENCE, MYF(0), name,
"forward reference in item list");
return -1;
}
Item_ref *r; Item_ref *r;
*ref= r= new Item_ref(refer, (char *)table_name, *ref= r= new Item_ref(last->ref_pointer_array + counter-1
, (char *)table_name,
(char *)field_name); (char *)field_name);
if (!r) if (!r)
return 1; return 1;
@ -1045,6 +1090,7 @@ bool Item_field::send(Protocol *protocol, String *buffer)
bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
{ {
uint counter= 0;
if (!ref) if (!ref)
{ {
TABLE_LIST *where= 0; TABLE_LIST *where= 0;
@ -1059,6 +1105,7 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
if (outer_resolving || if (outer_resolving ||
(ref= find_item_in_list(this, (ref= find_item_in_list(this,
*(thd->lex.current_select->get_item_list()), *(thd->lex.current_select->get_item_list()),
&counter,
((sl && ((sl &&
thd->lex.current_select->master_unit()-> thd->lex.current_select->master_unit()->
first_select()->linkage != first_select()->linkage !=
@ -1081,6 +1128,7 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
for ( ; sl ; sl= sl->outer_select()) for ( ; sl ; sl= sl->outer_select())
{ {
if ((ref= find_item_in_list(this, (last= sl)->item_list, if ((ref= find_item_in_list(this, (last= sl)->item_list,
&counter,
REPORT_EXCEPT_NOT_FOUND)) != REPORT_EXCEPT_NOT_FOUND)) !=
(Item **)not_found_item) (Item **)not_found_item)
break; break;
@ -1102,6 +1150,7 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
// Call to report error // Call to report error
find_item_in_list(this, find_item_in_list(this,
*(thd->lex.current_select->get_item_list()), *(thd->lex.current_select->get_item_list()),
&counter,
REPORT_ALL_ERRORS); REPORT_ALL_ERRORS);
ref= 0; ref= 0;
return 1; return 1;
@ -1118,17 +1167,35 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
} }
else else
{ {
depended_from= last; if (!(*ref)->fixed)
{
my_error(ER_ILLEGAL_REFERENCE, MYF(0), name,
"forward reference in item list");
return -1;
}
ref= (depended_from= last)->ref_pointer_array + counter-1;
thd->lex.current_select->mark_as_dependent(last); thd->lex.current_select->mark_as_dependent(last);
thd->add_possible_loop(this); thd->add_possible_loop(this);
} }
} }
else if (!ref) else if (!ref)
return 1; return 1;
else
{
if (!(*ref)->fixed)
{
my_error(ER_ILLEGAL_REFERENCE, MYF(0), name,
"forward reference in item list");
return -1;
}
ref= thd->lex.current_select->ref_pointer_array + counter-1;
}
max_length= (*ref)->max_length; max_length= (*ref)->max_length;
maybe_null= (*ref)->maybe_null; maybe_null= (*ref)->maybe_null;
decimals= (*ref)->decimals; decimals= (*ref)->decimals;
} }
if (((*ref)->with_sum_func && if (((*ref)->with_sum_func &&
(depended_from || (depended_from ||
!(thd->lex.current_select->linkage != GLOBAL_OPTIONS_TYPE && !(thd->lex.current_select->linkage != GLOBAL_OPTIONS_TYPE &&

View File

@ -52,6 +52,8 @@ public:
// alloc & destruct is done as start of select using sql_alloc // alloc & destruct is done as start of select using sql_alloc
Item(); Item();
// copy constructor used by Item_field, Item_ref & agregate (sum) functions
Item(Item &item);
virtual ~Item() { name=0; } /*lint -e1509 */ virtual ~Item() { name=0; } /*lint -e1509 */
void set_name(const char *str,uint length=0); void set_name(const char *str,uint length=0);
void init_make_field(Send_field *tmp_field,enum enum_field_types type); void init_make_field(Send_field *tmp_field,enum enum_field_types type);
@ -70,7 +72,8 @@ public:
virtual double val()=0; virtual double val()=0;
virtual longlong val_int()=0; virtual longlong val_int()=0;
virtual String *val_str(String*)=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 const char *full_name() const { return name ? name : "???"; }
virtual double val_result() { return val(); } virtual double val_result() { return val(); }
virtual longlong val_int_result() { return val_int(); } virtual longlong val_int_result() { return val_int(); }
@ -84,12 +87,14 @@ public:
virtual bool const_item() const { return used_tables() == 0; } virtual bool const_item() const { return used_tables() == 0; }
virtual void print(String *str_arg) { str_arg->append(full_name()); } virtual void print(String *str_arg) { str_arg->append(full_name()); }
virtual void update_used_tables() {} virtual void update_used_tables() {}
virtual void split_sum_func(List<Item> &fields) {} virtual void split_sum_func(Item **ref_pointer_array, List<Item> &fields) {}
virtual bool get_date(TIME *ltime,bool fuzzydate); virtual bool get_date(TIME *ltime,bool fuzzydate);
virtual bool get_time(TIME *ltime); virtual bool get_time(TIME *ltime);
virtual bool is_null() { return 0; }; virtual bool is_null() { return 0; };
virtual bool check_loop(uint id); virtual bool check_loop(uint id);
virtual void top_level_item() {} virtual void top_level_item() {}
virtual Item * get_same() { return this; }
virtual Item * get_tmp_table_item() { return get_same(); }
virtual bool binary() const virtual bool binary() const
{ return str_value.charset()->state & MY_CS_BINSORT ? 1 : 0 ; } { return str_value.charset()->state & MY_CS_BINSORT ? 1 : 0 ; }
@ -124,6 +129,8 @@ public:
:db_name(db_name_par), table_name(table_name_par), :db_name(db_name_par), table_name(table_name_par),
field_name(field_name_par), depended_from(0), outer_resolving(0) field_name(field_name_par), depended_from(0), outer_resolving(0)
{ name = (char*) field_name_par; } { name = (char*) field_name_par; }
// copy constructor used by Item_field & Item_ref
Item_ident(Item_ident &item);
const char *full_name() const; const char *full_name() const;
void set_outer_resolving() { outer_resolving= 1; } void set_outer_resolving() { outer_resolving= 1; }
}; };
@ -140,6 +147,8 @@ public:
const char *field_name_par) const char *field_name_par)
:Item_ident(db_par,table_name_par,field_name_par),field(0),result_field(0) :Item_ident(db_par,table_name_par,field_name_par),field(0),result_field(0)
{} {}
// copy constructor need to process subselect with temporary tables
Item_field(Item_field &item);
Item_field(Field *field); Item_field(Field *field);
enum Type type() const { return FIELD_ITEM; } enum Type type() const { return FIELD_ITEM; }
bool eq(const Item *item, bool binary_cmp) const; bool eq(const Item *item, bool binary_cmp) const;
@ -163,10 +172,12 @@ public:
{ {
return field->type(); 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_date(TIME *ltime,bool fuzzydate);
bool get_time(TIME *ltime); bool get_time(TIME *ltime);
bool is_null() { return field->is_null(); } bool is_null() { return field->is_null(); }
Item * get_tmp_table_item();
}; };
@ -446,8 +457,13 @@ class Item_result_field :public Item /* Item with result field */
public: public:
Field *result_field; /* Save result here */ Field *result_field; /* Save result here */
Item_result_field() :result_field(0) {} Item_result_field() :result_field(0) {}
Item_result_field(Item_result_field &item): Item(item)
{
result_field= item.result_field;
}
~Item_result_field() {} /* Required with gcc 2.95 */ ~Item_result_field() {} /* Required with gcc 2.95 */
Field *tmp_table_field(TABLE *t_arg=(TABLE *)0) { return result_field; } Field *tmp_table_field() { return result_field; }
Field *tmp_table_field(TABLE *t_arg) { return result_field; }
table_map used_tables() const { return 1; } table_map used_tables() const { return 1; }
virtual void fix_length_and_dec()=0; virtual void fix_length_and_dec()=0;
}; };
@ -461,6 +477,8 @@ public:
:Item_ident(db_par,table_name_par,field_name_par),ref(0) {} :Item_ident(db_par,table_name_par,field_name_par),ref(0) {}
Item_ref(Item **item, char *table_name_par,char *field_name_par) Item_ref(Item **item, char *table_name_par,char *field_name_par)
:Item_ident(NullS,table_name_par,field_name_par),ref(item) {} :Item_ident(NullS,table_name_par,field_name_par),ref(item) {}
// copy constructor need to process subselect with temporary tables
Item_ref(Item_ref &item): Item_ident(item), ref(item.ref) {}
enum Type type() const { return REF_ITEM; } enum Type type() const { return REF_ITEM; }
bool eq(const Item *item, bool binary_cmp) const bool eq(const Item *item, bool binary_cmp) const
{ return ref && (*ref)->eq(item, binary_cmp); } { return ref && (*ref)->eq(item, binary_cmp); }

View File

@ -1396,16 +1396,20 @@ void Item_func_in::update_used_tables()
const_item_cache&=item->const_item(); const_item_cache&=item->const_item();
} }
void Item_func_in::split_sum_func(List<Item> &fields) void Item_func_in::split_sum_func(Item **ref_pointer_array, List<Item> &fields)
{ {
if (item->with_sum_func && item->type() != SUM_FUNC_ITEM) if (item->with_sum_func && item->type() != SUM_FUNC_ITEM)
item->split_sum_func(fields); item->split_sum_func(ref_pointer_array, fields);
else if (item->used_tables() || item->type() == SUM_FUNC_ITEM) else if (item->used_tables() || item->type() == SUM_FUNC_ITEM)
{ {
uint el= fields.elements;
fields.push_front(item); fields.push_front(item);
item=new Item_ref((Item**) fields.head_ref(),0,item->name); ref_pointer_array[el]= item;
item=new Item_ref(ref_pointer_array + el,
0, item->name);
} }
Item_func::split_sum_func(fields); Item_func::split_sum_func(ref_pointer_array, fields);
} }
@ -1511,7 +1515,7 @@ void Item_cond::set_outer_resolving()
item->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); List_iterator<Item> li(list);
Item *item; Item *item;
@ -1520,11 +1524,13 @@ void Item_cond::split_sum_func(List<Item> &fields)
while ((item=li++)) while ((item=li++))
{ {
if (item->with_sum_func && item->type() != SUM_FUNC_ITEM) if (item->with_sum_func && item->type() != SUM_FUNC_ITEM)
item->split_sum_func(fields); item->split_sum_func(ref_pointer_array, fields);
else if (item->used_tables() || item->type() == SUM_FUNC_ITEM) else if (item->used_tables() || item->type() == SUM_FUNC_ITEM)
{ {
uint el= fields.elements;
fields.push_front(item); fields.push_front(item);
li.replace(new Item_ref((Item**) fields.head_ref(),0,item->name)); ref_pointer_array[el]= item;
li.replace(new Item_ref(ref_pointer_array + el, 0, item->name));
} }
item->update_used_tables(); item->update_used_tables();
used_tables_cache|=item->used_tables(); used_tables_cache|=item->used_tables();

View File

@ -650,7 +650,7 @@ class Item_func_in :public Item_int_func
enum Functype functype() const { return IN_FUNC; } enum Functype functype() const { return IN_FUNC; }
const char *func_name() const { return " IN "; } const char *func_name() const { return " IN "; }
void update_used_tables(); void update_used_tables();
void split_sum_func(List<Item> &fields); void split_sum_func(Item **ref_pointer_array, List<Item> &fields);
bool check_loop(uint id) bool check_loop(uint id)
{ {
DBUG_ENTER("Item_func_in::check_loop"); DBUG_ENTER("Item_func_in::check_loop");
@ -801,7 +801,7 @@ public:
table_map used_tables() const; table_map used_tables() const;
void update_used_tables(); void update_used_tables();
void print(String *str); void print(String *str);
void split_sum_func(List<Item> &fields); void split_sum_func(Item **ref_pointer_array, List<Item> &fields);
friend int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds); friend int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds);
bool check_loop(uint id); bool check_loop(uint id);
void top_level_item() { abort_on_null=1; } void top_level_item() { abort_on_null=1; }

View File

@ -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; Item **arg,**arg_end;
for (arg=args, arg_end=args+arg_count; arg != arg_end ; arg++) for (arg=args, arg_end=args+arg_count; arg != arg_end ; arg++)
{ {
if ((*arg)->with_sum_func && (*arg)->type() != SUM_FUNC_ITEM) if ((*arg)->with_sum_func && (*arg)->type() != SUM_FUNC_ITEM)
(*arg)->split_sum_func(fields); (*arg)->split_sum_func(ref_pointer_array, fields);
else if ((*arg)->used_tables() || (*arg)->type() == SUM_FUNC_ITEM) else if ((*arg)->used_tables() || (*arg)->type() == SUM_FUNC_ITEM)
{ {
uint el= fields.elements;
fields.push_front(*arg); fields.push_front(*arg);
*arg=new Item_ref((Item**) fields.head_ref(),0,(*arg)->name); ref_pointer_array[el]= *arg;
*arg=new Item_ref(ref_pointer_array + el, 0, (*arg)->name);
} }
} }
} }
@ -234,14 +236,11 @@ bool Item_func::eq(const Item *item, bool binary_cmp) const
return 1; return 1;
} }
Field *Item_func::tmp_table_field(TABLE *t_arg) Field *Item_func::tmp_table_field(TABLE *t_arg)
{ {
Field *res; Field *res;
LINT_INIT(res); LINT_INIT(res);
if (!t_arg)
return result_field;
switch (result_type()) { switch (result_type()) {
case INT_RESULT: case INT_RESULT:
if (max_length > 11) if (max_length > 11)
@ -312,6 +311,16 @@ void Item_func::fix_num_length_and_dec()
max_length=float_length(decimals); max_length=float_length(decimals);
} }
Item * Item_func::get_tmp_table_item()
{
if (!with_sum_func && !const_item())
{
return new Item_field(result_field);
}
else
return get_same();
}
String *Item_int_func::val_str(String *str) String *Item_int_func::val_str(String *str)
{ {
longlong nr=val_int(); longlong nr=val_int();

View File

@ -117,7 +117,7 @@ public:
inline Item **arguments() const { return args; } inline Item **arguments() const { return args; }
inline uint argument_count() const { return arg_count; } inline uint argument_count() const { return arg_count; }
inline void remove_arguments() { arg_count=0; } inline void remove_arguments() { arg_count=0; }
virtual void split_sum_func(List<Item> &fields); virtual void split_sum_func(Item **ref_pointer_array, List<Item> &fields);
void print(String *str); void print(String *str);
void print_op(String *str); void print_op(String *str);
void fix_num_length_and_dec(); void fix_num_length_and_dec();
@ -131,9 +131,11 @@ public:
} }
bool is_null() { (void) val_int(); return null_value; } bool is_null() { (void) val_int(); return null_value; }
friend class udf_handler; friend class udf_handler;
Field *tmp_table_field() { return result_field; }
Field *tmp_table_field(TABLE *t_arg); Field *tmp_table_field(TABLE *t_arg);
bool check_loop(uint id); bool check_loop(uint id);
void set_outer_resolving(); void set_outer_resolving();
Item * get_tmp_table_item();
}; };

View File

@ -439,6 +439,8 @@ void Item_in_subselect::single_value_transformer(THD *thd,
compare_func_creator func) compare_func_creator func)
{ {
DBUG_ENTER("Item_in_subselect::single_value_transformer"); DBUG_ENTER("Item_in_subselect::single_value_transformer");
THD *thd= current_thd;
if (unit->global_parameters->select_limit != HA_POS_ERROR) if (unit->global_parameters->select_limit != HA_POS_ERROR)
{ {
my_error(ER_NOT_SUPPORTED_YET, MYF(0), 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 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); 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, item= (*func)(expr, new Item_ref_null_helper(this,
sl->item_list.head_ref(), sl->ref_pointer_array,
(char *)"<no matter>", (char *)"<no matter>",
(char*)"<result>")); (char*)"<result>"));
sl->having= and_items(sl->having, item); sl->having= and_items(sl->having, item);
@ -678,8 +684,12 @@ int subselect_single_select_engine::prepare()
prepared= 1; prepared= 1;
SELECT_LEX_NODE *save_select= thd->lex.current_select; SELECT_LEX_NODE *save_select= thd->lex.current_select;
thd->lex.current_select= select_lex; thd->lex.current_select= select_lex;
if (join->prepare((TABLE_LIST*) select_lex->table_list.first, if (join->prepare(&select_lex->ref_pointer_array,
(TABLE_LIST*) select_lex->table_list.first,
select_lex->with_wild,
select_lex->where, select_lex->where,
select_lex->order_list.elements +
select_lex->group_list.elements,
(ORDER*) select_lex->order_list.first, (ORDER*) select_lex->order_list.first,
(ORDER*) select_lex->group_list.first, (ORDER*) select_lex->group_list.first,
select_lex->having, select_lex->having,

View File

@ -41,9 +41,22 @@ Item_sum::Item_sum(List<Item> &list)
list.empty(); // Fields are used list.empty(); // Fields are used
} }
Item_sum::Item_sum(Item_sum &item):
Item_result_field(item), quick_group(item.quick_group)
{
arg_count= item.arg_count;
if (arg_count <= 2)
args=tmp_args;
else
if (!(args=(Item**) sql_alloc(sizeof(Item*)*arg_count)))
return;
for(uint i= 0; i < arg_count; i++)
args[i]= item.args[i];
}
void Item_sum::mark_as_sum_func() void Item_sum::mark_as_sum_func()
{ {
current_thd->lex.current_select->with_sum_func=1; current_thd->lex.current_select->with_sum_func++;
with_sum_func= 1; with_sum_func= 1;
} }
@ -83,6 +96,26 @@ void Item_sum::fix_num_length_and_dec()
max_length=float_length(decimals); max_length=float_length(decimals);
} }
Item * Item_sum::get_tmp_table_item()
{
Item_sum* sum_item= (Item_sum *) get_same();
if (sum_item && sum_item->result_field) // If not a const sum func
{
Field *result_field= sum_item->result_field;
for (uint i=0 ; i < sum_item->arg_count ; i++)
{
Item *arg= sum_item->args[i];
if (!arg->const_item())
{
if (arg->type() == Item::FIELD_ITEM)
((Item_field*) arg)->field= result_field++;
else
sum_item->args[i]= new Item_field(result_field++);
}
}
}
return sum_item;
}
String * String *
Item_sum_num::val_str(String *str) Item_sum_num::val_str(String *str)
@ -952,7 +985,7 @@ int dump_leaf(byte* key, uint32 count __attribute__((unused)),
The first item->rec_offset bytes are taken care of with The first item->rec_offset bytes are taken care of with
restore_record(table,2) in setup() restore_record(table,2) in setup()
*/ */
memcpy(buf + item->rec_offset, key, item->tree.size_of_element); memcpy(buf + item->rec_offset, key, item->tree->size_of_element);
if ((error = item->table->file->write_row(buf))) if ((error = item->table->file->write_row(buf)))
{ {
if (error != HA_ERR_FOUND_DUPP_KEY && if (error != HA_ERR_FOUND_DUPP_KEY &&
@ -964,12 +997,15 @@ int dump_leaf(byte* key, uint32 count __attribute__((unused)),
Item_sum_count_distinct::~Item_sum_count_distinct() Item_sum_count_distinct::~Item_sum_count_distinct()
{
if (!original)
{ {
if (table) if (table)
free_tmp_table(current_thd, table); free_tmp_table(current_thd, table);
delete tmp_table_param; delete tmp_table_param;
if (use_tree) if (use_tree)
delete_tree(&tree); delete_tree(tree);
}
} }
@ -1100,7 +1136,7 @@ bool Item_sum_count_distinct::setup(THD *thd)
} }
} }
init_tree(&tree, min(thd->variables.max_heap_table_size, init_tree(tree, min(thd->variables.max_heap_table_size,
thd->variables.sortbuff_size/16), 0, thd->variables.sortbuff_size/16), 0,
key_length, compare_key, 0, NULL, cmp_arg); key_length, compare_key, 0, NULL, cmp_arg);
use_tree = 1; use_tree = 1;
@ -1113,6 +1149,12 @@ bool Item_sum_count_distinct::setup(THD *thd)
*/ */
max_elements_in_tree = ((key_length) ? max_elements_in_tree = ((key_length) ?
thd->variables.max_heap_table_size/key_length : 1); thd->variables.max_heap_table_size/key_length : 1);
}
if (original)
{
original->table= table;
original->use_tree= use_tree;
} }
return 0; return 0;
} }
@ -1122,10 +1164,10 @@ int Item_sum_count_distinct::tree_to_myisam()
{ {
if (create_myisam_from_heap(current_thd, table, tmp_table_param, if (create_myisam_from_heap(current_thd, table, tmp_table_param,
HA_ERR_RECORD_FILE_FULL, 1) || HA_ERR_RECORD_FILE_FULL, 1) ||
tree_walk(&tree, (tree_walk_action)&dump_leaf, (void*)this, tree_walk(tree, (tree_walk_action)&dump_leaf, (void*)this,
left_root_right)) left_root_right))
return 1; return 1;
delete_tree(&tree); delete_tree(tree);
use_tree = 0; use_tree = 0;
return 0; return 0;
} }
@ -1133,7 +1175,7 @@ int Item_sum_count_distinct::tree_to_myisam()
void Item_sum_count_distinct::reset() void Item_sum_count_distinct::reset()
{ {
if (use_tree) if (use_tree)
reset_tree(&tree); reset_tree(tree);
else if (table) else if (table)
{ {
table->file->extra(HA_EXTRA_NO_CACHE); table->file->extra(HA_EXTRA_NO_CACHE);
@ -1161,13 +1203,13 @@ bool Item_sum_count_distinct::add()
If the tree got too big, convert to MyISAM, otherwise insert into the If the tree got too big, convert to MyISAM, otherwise insert into the
tree. tree.
*/ */
if (tree.elements_in_tree > max_elements_in_tree) if (tree->elements_in_tree > max_elements_in_tree)
{ {
if (tree_to_myisam()) if (tree_to_myisam())
return 1; return 1;
} }
else if (!tree_insert(&tree, table->record[0] + rec_offset, 0, else if (!tree_insert(tree, table->record[0] + rec_offset, 0,
tree.custom_arg)) tree->custom_arg))
return 1; return 1;
} }
else if ((error=table->file->write_row(table->record[0]))) else if ((error=table->file->write_row(table->record[0])))
@ -1189,7 +1231,7 @@ longlong Item_sum_count_distinct::val_int()
if (!table) // Empty query if (!table) // Empty query
return LL(0); return LL(0);
if (use_tree) if (use_tree)
return tree.elements_in_tree; return tree->elements_in_tree;
table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK); table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
return table->file->records; return table->file->records;
} }

View File

@ -54,6 +54,8 @@ public:
mark_as_sum_func(); mark_as_sum_func();
} }
Item_sum(List<Item> &list); Item_sum(List<Item> &list);
//Copy constructor, need to perform subselects with temporary tables
Item_sum(Item_sum &item);
~Item_sum() { result_field=0; } ~Item_sum() { result_field=0; }
enum Type type() const { return SUM_FUNC_ITEM; } enum Type type() const { return SUM_FUNC_ITEM; }
@ -75,6 +77,7 @@ public:
void print(String *str); void print(String *str);
void fix_num_length_and_dec(); void fix_num_length_and_dec();
virtual bool setup(THD *thd) {return 0;} 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 *item_par) :Item_sum(item_par) {}
Item_sum_num(Item *a, Item* b) :Item_sum(a,b) {} Item_sum_num(Item *a, Item* b) :Item_sum(a,b) {}
Item_sum_num(List<Item> &list) :Item_sum(list) {} 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 **); bool fix_fields(THD *, TABLE_LIST *, Item **);
longlong val_int() { return (longlong) val(); } /* Real as default */ longlong val_int() { return (longlong) val(); } /* Real as default */
String *val_str(String*str); String *val_str(String*str);
@ -100,6 +104,7 @@ class Item_sum_int :public Item_sum_num
public: public:
Item_sum_int(Item *item_par) :Item_sum_num(item_par) {} Item_sum_int(Item *item_par) :Item_sum_num(item_par) {}
Item_sum_int(List<Item> &list) :Item_sum_num(list) {} 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(); } double val() { return (double) val_int(); }
String *val_str(String*str); String *val_str(String*str);
enum Item_result result_type () const { return INT_RESULT; } enum Item_result result_type () const { return INT_RESULT; }
@ -113,6 +118,7 @@ class Item_sum_sum :public Item_sum_num
public: public:
Item_sum_sum(Item *item_par) :Item_sum_num(item_par),sum(0.0) {} 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;} enum Sumfunctype sum_func () const {return SUM_FUNC;}
void reset(); void reset();
bool add(); bool add();
@ -120,6 +126,7 @@ class Item_sum_sum :public Item_sum_num
void reset_field(); void reset_field();
void update_field(int offset); void update_field(int offset);
const char *func_name() const { return "sum"; } 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_count(Item *item_par)
:Item_sum_int(item_par),count(0),used_table_cache(~(table_map) 0) :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; } table_map used_tables() const { return used_table_cache; }
bool const_item() const { return !used_table_cache; } bool const_item() const { return !used_table_cache; }
enum Sumfunctype sum_func () const { return COUNT_FUNC; } enum Sumfunctype sum_func () const { return COUNT_FUNC; }
@ -142,6 +153,7 @@ class Item_sum_count :public Item_sum_int
void reset_field(); void reset_field();
void update_field(int offset); void update_field(int offset);
const char *func_name() const { return "count"; } 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); bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref);
uint32 *field_lengths; uint32 *field_lengths;
TMP_TABLE_PARAM *tmp_table_param; 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; uint key_length;
CHARSET_INFO *key_charset; CHARSET_INFO *key_charset;
@ -184,8 +203,18 @@ class Item_sum_count_distinct :public Item_sum_int
public: public:
Item_sum_count_distinct(List<Item> &list) Item_sum_count_distinct(List<Item> &list)
:Item_sum_int(list), table(0), used_table_cache(~(table_map) 0), :Item_sum_int(list), table(0), used_table_cache(~(table_map) 0),
tmp_table_param(0),use_tree(0),always_null(0) tmp_table_param(0), tree(&tree_base), original(0), use_tree(0),
always_null(0)
{ quick_group= 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(); ~Item_sum_count_distinct();
table_map used_tables() const { return used_table_cache; } table_map used_tables() const { return used_table_cache; }
enum Sumfunctype sum_func () const { return COUNT_DISTINCT_FUNC; } 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 void update_field(int offset) { return ; } // Never called
const char *func_name() const { return "count_distinct"; } const char *func_name() const { return "count_distinct"; }
bool setup(THD *thd); 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: public:
Item_sum_avg(Item *item_par) :Item_sum_num(item_par),count(0) {} 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;} enum Sumfunctype sum_func () const {return AVG_FUNC;}
void reset(); void reset();
bool add(); bool add();
@ -236,6 +268,7 @@ class Item_sum_avg :public Item_sum_num
Item *result_item(Field *field) Item *result_item(Field *field)
{ return new Item_avg_field(this); } { return new Item_avg_field(this); }
const char *func_name() const { return "avg"; } const char *func_name() const { return "avg"; }
Item * get_same() { return new Item_sum_avg(*this); }
}; };
class Item_sum_variance; class Item_sum_variance;
@ -276,6 +309,9 @@ class Item_sum_variance : public Item_sum_num
public: public:
Item_sum_variance(Item *item_par) :Item_sum_num(item_par),count(0) {} 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; } enum Sumfunctype sum_func () const { return VARIANCE_FUNC; }
void reset(); void reset();
bool add(); bool add();
@ -285,6 +321,7 @@ class Item_sum_variance : public Item_sum_num
Item *result_item(Field *field) Item *result_item(Field *field)
{ return new Item_variance_field(this); } { return new Item_variance_field(this); }
const char *func_name() const { return "variance"; } const char *func_name() const { return "variance"; }
Item * get_same() { return new Item_sum_variance(*this); }
}; };
class Item_sum_std; class Item_sum_std;
@ -295,22 +332,6 @@ public:
Item_std_field(Item_sum_std *item); Item_std_field(Item_sum_std *item);
enum Type type() const { return FIELD_STD_ITEM; } enum Type type() const { return FIELD_STD_ITEM; }
double val(); 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 // 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), Item_sum_hybrid(Item *item_par,int sign) :Item_sum(item_par),cmp_sign(sign),
used_table_cache(~(table_map) 0) 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 **); bool fix_fields(THD *, TABLE_LIST *, Item **);
table_map used_tables() const { return used_table_cache; } table_map used_tables() const { return used_table_cache; }
bool const_item() 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: public:
Item_sum_min(Item *item_par) :Item_sum_hybrid(item_par,1) {} 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;} enum Sumfunctype sum_func () const {return MIN_FUNC;}
bool add(); bool add();
const char *func_name() const { return "min"; } 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: public:
Item_sum_max(Item *item_par) :Item_sum_hybrid(item_par,-1) {} 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;} enum Sumfunctype sum_func () const {return MAX_FUNC;}
bool add(); bool add();
const char *func_name() const { return "max"; } 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: public:
Item_sum_bit(Item *item_par,ulonglong reset_arg) Item_sum_bit(Item *item_par,ulonglong reset_arg)
:Item_sum_int(item_par),reset_bits(reset_arg),bits(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;} enum Sumfunctype sum_func () const {return SUM_BIT_FUNC;}
void reset(); void reset();
longlong val_int(); longlong val_int();
@ -397,9 +428,11 @@ class Item_sum_or :public Item_sum_bit
{ {
public: public:
Item_sum_or(Item *item_par) :Item_sum_bit(item_par,LL(0)) {} 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(); bool add();
void update_field(int offset); void update_field(int offset);
const char *func_name() const { return "bit_or"; } 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: public:
Item_sum_and(Item *item_par) :Item_sum_bit(item_par, ~(ulonglong) LL(0)) {} 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(); bool add();
void update_field(int offset); void update_field(int offset);
const char *func_name() const { return "bit_and"; } 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_udf_sum( udf_func *udf_arg, List<Item> &list )
:Item_sum( list ), udf(udf_arg) :Item_sum( list ), udf(udf_arg)
{ quick_group=0;} { quick_group=0;}
Item_udf_sum(Item_udf_sum &item) :Item_sum(item), udf(item.udf) {}
~Item_udf_sum() {} ~Item_udf_sum() {}
const char *func_name() const { return udf.name(); } const char *func_name() const { return udf.name(); }
bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) 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) :Item_udf_sum(udf_arg) {}
Item_sum_udf_float(udf_func *udf_arg, List<Item> &list) Item_sum_udf_float(udf_func *udf_arg, List<Item> &list)
:Item_udf_sum(udf_arg,list) {} :Item_udf_sum(udf_arg,list) {}
Item_sum_udf_float(Item_sum_udf_float &item): Item_udf_sum(item) {}
~Item_sum_udf_float() {} ~Item_sum_udf_float() {}
longlong val_int() { return (longlong) Item_sum_udf_float::val(); } longlong val_int() { return (longlong) Item_sum_udf_float::val(); }
double val(); double val();
String *val_str(String*str); String *val_str(String*str);
void fix_length_and_dec() { fix_num_length_and_dec(); } 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) :Item_udf_sum(udf_arg) {}
Item_sum_udf_int(udf_func *udf_arg, List<Item> &list) Item_sum_udf_int(udf_func *udf_arg, List<Item> &list)
:Item_udf_sum(udf_arg,list) {} :Item_udf_sum(udf_arg,list) {}
Item_sum_udf_int(Item_sum_udf_int &item): Item_udf_sum(item) {}
~Item_sum_udf_int() {} ~Item_sum_udf_int() {}
longlong val_int(); longlong val_int();
double val() { return (double) Item_sum_udf_int::val_int(); } double val() { return (double) Item_sum_udf_int::val_int(); }
String *val_str(String*str); String *val_str(String*str);
enum Item_result result_type () const { return INT_RESULT; } enum Item_result result_type () const { return INT_RESULT; }
void fix_length_and_dec() { decimals=0; max_length=21; } 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) :Item_udf_sum(udf_arg) {}
Item_sum_udf_str(udf_func *udf_arg, List<Item> &list) Item_sum_udf_str(udf_func *udf_arg, List<Item> &list)
:Item_udf_sum(udf_arg,list) {} :Item_udf_sum(udf_arg,list) {}
Item_sum_udf_str(Item_sum_udf_str &item): Item_udf_sum(item) {}
~Item_sum_udf_str() {} ~Item_sum_udf_str() {}
String *val_str(String *); String *val_str(String *);
double val() double val()
@ -496,6 +537,7 @@ public:
} }
enum Item_result result_type () const { return STRING_RESULT; } enum Item_result result_type () const { return STRING_RESULT; }
void fix_length_and_dec(); void fix_length_and_dec();
Item * get_same() { return new Item_sum_udf_str(*this); }
}; };
#else /* Dummy functions to get sql_yacc.cc compiled */ #else /* Dummy functions to get sql_yacc.cc compiled */
@ -505,12 +547,14 @@ class Item_sum_udf_float :public Item_sum_num
public: public:
Item_sum_udf_float(udf_func *udf_arg) :Item_sum_num() {} 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(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() {} ~Item_sum_udf_float() {}
enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; } enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; }
double val() { return 0.0; } double val() { return 0.0; }
void reset() {} void reset() {}
bool add() { return 0; } bool add() { return 0; }
void update_field(int offset) {} 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: public:
Item_sum_udf_int(udf_func *udf_arg) :Item_sum_num() {} 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(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() {} ~Item_sum_udf_int() {}
enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; } enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; }
longlong val_int() { return 0; } longlong val_int() { return 0; }
@ -526,6 +571,7 @@ public:
void reset() {} void reset() {}
bool add() { return 0; } bool add() { return 0; }
void update_field(int offset) {} 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: public:
Item_sum_udf_str(udf_func *udf_arg) :Item_sum_num() {} 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(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() {} ~Item_sum_udf_str() {}
String *val_str(String *) { null_value=1; return 0; } String *val_str(String *) { null_value=1; return 0; }
double val() { null_value=1; return 0.0; } double val() { null_value=1; return 0.0; }
@ -544,6 +591,7 @@ public:
void reset() {} void reset() {}
bool add() { return 0; } bool add() { return 0; }
void update_field(int offset) {} void update_field(int offset) {}
Item * get_same() { return new Item_sum_udf_str(*this); }
}; };
#endif /* HAVE_DLOPEN */ #endif /* HAVE_DLOPEN */

View File

@ -327,9 +327,10 @@ public:
max_length=10*thd_charset()->mbmaxlen; max_length=10*thd_charset()->mbmaxlen;
} }
int save_in_field(Field *to, bool no_conversions); int save_in_field(Field *to, bool no_conversions);
Field *tmp_table_field() { return result_field; }
Field *tmp_table_field(TABLE *t_arg) Field *tmp_table_field(TABLE *t_arg)
{ {
return (!t_arg) ? result_field : new Field_date(maybe_null, name, t_arg, thd_charset()); return (new Field_date(maybe_null, name, t_arg, thd_charset()));
} }
}; };
@ -341,10 +342,10 @@ public:
Item_date_func(Item *a) :Item_str_func(a) {} Item_date_func(Item *a) :Item_str_func(a) {}
Item_date_func(Item *a,Item *b) :Item_str_func(a,b) {} Item_date_func(Item *a,Item *b) :Item_str_func(a,b) {}
enum_field_types field_type() const { return MYSQL_TYPE_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) Field *tmp_table_field(TABLE *t_arg)
{ {
return (!t_arg) ? result_field : new Field_datetime(maybe_null, name, return (new Field_datetime(maybe_null, name, t_arg, thd_charset()));
t_arg, thd_charset());
} }
}; };
@ -364,10 +365,10 @@ public:
String *val_str(String *str); String *val_str(String *str);
const char *func_name() const { return "curtime"; } const char *func_name() const { return "curtime"; }
void fix_length_and_dec(); void fix_length_and_dec();
Field *tmp_table_field() { return result_field; }
Field *tmp_table_field(TABLE *t_arg) Field *tmp_table_field(TABLE *t_arg)
{ {
return (!t_arg) ? result_field : return (new Field_time(maybe_null, name, t_arg, thd_charset()));
new Field_time(maybe_null, name, t_arg, thd_charset());
} }
}; };
@ -462,10 +463,10 @@ public:
} }
enum_field_types field_type() const { return MYSQL_TYPE_TIME; } enum_field_types field_type() const { return MYSQL_TYPE_TIME; }
const char *func_name() const { return "sec_to_time"; } const char *func_name() const { return "sec_to_time"; }
Field *tmp_table_field() { return result_field; }
Field *tmp_table_field(TABLE *t_arg) Field *tmp_table_field(TABLE *t_arg)
{ {
return (!t_arg) ? result_field : return (new Field_time(maybe_null, name, t_arg, thd_charset()));
new Field_time(maybe_null, name, t_arg, thd_charset());
} }
}; };
@ -556,10 +557,10 @@ public:
Item_date_typecast(Item *a) :Item_typecast(a) {} Item_date_typecast(Item *a) :Item_typecast(a) {}
const char *func_name() const { return "date"; } const char *func_name() const { return "date"; }
enum_field_types field_type() const { return MYSQL_TYPE_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) Field *tmp_table_field(TABLE *t_arg)
{ {
return (!t_arg) ? result_field : return (new Field_date(maybe_null, name, t_arg, thd_charset()));
new Field_date(maybe_null, name, t_arg, thd_charset());
} }
}; };
@ -570,10 +571,10 @@ public:
Item_time_typecast(Item *a) :Item_typecast(a) {} Item_time_typecast(Item *a) :Item_typecast(a) {}
const char *func_name() const { return "time"; } const char *func_name() const { return "time"; }
enum_field_types field_type() const { return MYSQL_TYPE_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) Field *tmp_table_field(TABLE *t_arg)
{ {
return (!t_arg) ? result_field : return (new Field_time(maybe_null, name, t_arg, thd_charset()));
new Field_time(maybe_null, name, t_arg, thd_charset());
} }
}; };
@ -584,9 +585,9 @@ public:
Item_datetime_typecast(Item *a) :Item_typecast(a) {} Item_datetime_typecast(Item *a) :Item_typecast(a) {}
const char *func_name() const { return "datetime"; } const char *func_name() const { return "datetime"; }
enum_field_types field_type() const { return MYSQL_TYPE_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) Field *tmp_table_field(TABLE *t_arg)
{ {
return (!t_arg) ? result_field : new Field_datetime(maybe_null, name, return (new Field_datetime(maybe_null, name, t_arg, thd_charset()));
t_arg, thd_charset());
} }
}; };

View File

@ -37,6 +37,7 @@ class Item_sum_unique_users :public Item_sum_num
public: public:
Item_sum_unique_users(Item *name_arg,int start,int end,Item *item_arg) Item_sum_unique_users(Item *name_arg,int start,int end,Item *item_arg)
:Item_sum_num(item_arg) {} :Item_sum_num(item_arg) {}
Item_sum_unique_users(Item_sum_unique_users &item): Item_sum_num(item) {}
double val() { return 0.0; } double val() { return 0.0; }
enum Sumfunctype sum_func () const {return UNIQUE_USERS_FUNC;} enum Sumfunctype sum_func () const {return UNIQUE_USERS_FUNC;}
void reset() {} void reset() {}
@ -48,4 +49,5 @@ public:
fixed= 1; fixed= 1;
return 0; return 0;
} }
Item_sum * get_same() { return new Item_sum_unique_users(*this); }
}; };

View File

@ -390,18 +390,21 @@ int mysql_optimize_table(THD* thd, TABLE_LIST* table_list,
bool check_simple_select(); bool check_simple_select();
SORT_FIELD * make_unireg_sortorder(ORDER *order, uint *length); SORT_FIELD * make_unireg_sortorder(ORDER *order, uint *length);
int setup_order(THD *thd,TABLE_LIST *tables, List<Item> &fields, int setup_ref_array(THD *thd, Item ***rref_pointer_array, uint elements);
List <Item> &all_fields, ORDER *order); int setup_order(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
int setup_group(THD *thd,TABLE_LIST *tables,List<Item> &fields, List<Item> &fields, List <Item> &all_fields, ORDER *order);
List<Item> &all_fields, ORDER *order, int setup_group(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
List<Item> &fields, List<Item> &all_fields, ORDER *order,
bool *hidden_group_fields); bool *hidden_group_fields);
int handle_select(THD *thd, LEX *lex, select_result *result); int handle_select(THD *thd, LEX *lex, select_result *result);
int mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &list,COND *conds, int mysql_select(THD *thd, Item ***rref_pointer_array,
ORDER *order, ORDER *group,Item *having,ORDER *proc_param, TABLE_LIST *tables, uint wild_num, List<Item> &list,
ulong select_type,select_result *result, COND *conds, uint og_num, ORDER *order, ORDER *group,
SELECT_LEX_UNIT *unit, SELECT_LEX *select_lex, Item *having, ORDER *proc_param, ulong select_type,
bool fake_select_lex); select_result *result, SELECT_LEX_UNIT *unit,
SELECT_LEX *select_lex, bool fake_select_lex);
void free_ulderlayed_joins(THD *thd, SELECT_LEX *select);
void fix_tables_pointers(SELECT_LEX *select_lex); void fix_tables_pointers(SELECT_LEX *select_lex);
int mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, int mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit,
select_result *result); select_result *result);
@ -428,7 +431,7 @@ int mysql_alter_table(THD *thd, char *new_db, char *new_name,
List<create_field> &fields, List<create_field> &fields,
List<Key> &keys,List<Alter_drop> &drop_list, List<Key> &keys,List<Alter_drop> &drop_list,
List<Alter_column> &alter_list, List<Alter_column> &alter_list,
ORDER *order, uint order_num, ORDER *order,
bool drop_primary, bool drop_primary,
enum enum_duplicates handle_duplicates, enum enum_duplicates handle_duplicates,
enum enum_enable_or_disable keys_onoff=LEAVE_AS_IS, enum enum_enable_or_disable keys_onoff=LEAVE_AS_IS,
@ -447,7 +450,7 @@ int mysql_drop_index(THD *thd, TABLE_LIST *table_list,
List<Alter_drop> &drop_list); List<Alter_drop> &drop_list);
int mysql_update(THD *thd,TABLE_LIST *tables,List<Item> &fields, int mysql_update(THD *thd,TABLE_LIST *tables,List<Item> &fields,
List<Item> &values,COND *conds, List<Item> &values,COND *conds,
ORDER *order, ha_rows limit, uint order_num, ORDER *order, ha_rows limit,
enum enum_duplicates handle_duplicates); enum enum_duplicates handle_duplicates);
int mysql_multi_update(THD *thd, TABLE_LIST *table_list, int mysql_multi_update(THD *thd, TABLE_LIST *table_list,
List<Item> *fields, List<Item> *values, List<Item> *fields, List<Item> *values,
@ -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, enum find_item_error_report_type {REPORT_ALL_ERRORS, REPORT_EXCEPT_NOT_FOUND,
IGNORE_ERRORS}; IGNORE_ERRORS};
extern const Item **not_found_item; extern const Item **not_found_item;
Item ** find_item_in_list(Item *item, List<Item> &items, Item ** find_item_in_list(Item *item, List<Item> &items, uint *counter,
find_item_error_report_type report_error); find_item_error_report_type report_error);
bool insert_fields(THD *thd,TABLE_LIST *tables, bool insert_fields(THD *thd,TABLE_LIST *tables,
const char *db_name, const char *table_name, const char *db_name, const char *table_name,
List_iterator<Item> *it); List_iterator<Item> *it);
bool setup_tables(TABLE_LIST *tables); bool setup_tables(TABLE_LIST *tables);
int setup_fields(THD *thd,TABLE_LIST *tables,List<Item> &item, int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
bool set_query_id,List<Item> *sum_func_list, List<Item> *sum_func_list, uint wild_num);
bool allow_sum_func); int setup_fields(THD *thd, Item** ref_pointer_array, TABLE_LIST *tables,
List<Item> &item, bool set_query_id,
List<Item> *sum_func_list, bool allow_sum_func);
int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds); int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds);
int setup_ftfuncs(SELECT_LEX* select); int setup_ftfuncs(SELECT_LEX* select);
int init_ftfuncs(THD *thd, SELECT_LEX* select, bool no_order); int init_ftfuncs(THD *thd, SELECT_LEX* select, bool no_order);

View File

@ -1808,10 +1808,14 @@ const Item **not_found_item= (const Item**) 0x1;
/* /*
Find Item in list of items (find_field_in_tables analog) Find Item in list of items (find_field_in_tables analog)
TODO
is it better return only counter?
SYNOPSIS SYNOPSIS
find_item_in_list() find_item_in_list()
find - item to find find - item to find
items - list of items items - list of items
counter - to return number of found item
report_error report_error
REPORT_ALL_ERRORS - report errors, return 0 if error REPORT_ALL_ERRORS - report errors, return 0 if error
REPORT_EXCEPT_NOT_FOUND - do not report 'not found' error and return not_ found_item, report other errors, return 0 REPORT_EXCEPT_NOT_FOUND - do not report 'not found' error and return not_ found_item, report other errors, return 0
@ -1828,7 +1832,7 @@ const Item **not_found_item= (const Item**) 0x1;
*/ */
Item ** Item **
find_item_in_list(Item *find, List<Item> &items, find_item_in_list(Item *find, List<Item> &items, uint *counter,
find_item_error_report_type report_error) find_item_error_report_type report_error)
{ {
List_iterator<Item> li(items); List_iterator<Item> li(items);
@ -1841,8 +1845,10 @@ find_item_in_list(Item *find, List<Item> &items,
table_name= ((Item_ident*) find)->table_name; table_name= ((Item_ident*) find)->table_name;
} }
uint i= 0;
while ((item=li++)) while ((item=li++))
{ {
i++;
if (field_name && item->type() == Item::FIELD_ITEM) if (field_name && item->type() == Item::FIELD_ITEM)
{ {
if (!my_strcasecmp(system_charset_info, if (!my_strcasecmp(system_charset_info,
@ -1860,10 +1866,12 @@ find_item_in_list(Item *find, List<Item> &items,
return (Item**) 0; return (Item**) 0;
} }
found= li.ref(); found= li.ref();
*counter= i;
} }
else if (!strcmp(((Item_field*) item)->table_name,table_name)) else if (!strcmp(((Item_field*) item)->table_name,table_name))
{ {
found= li.ref(); found= li.ref();
*counter= i;
break; break;
} }
} }
@ -1874,6 +1882,7 @@ find_item_in_list(Item *find, List<Item> &items,
item->name,find->name))) item->name,find->name)))
{ {
found= li.ref(); found= li.ref();
*counter= i;
break; break;
} }
} }
@ -1891,22 +1900,18 @@ find_item_in_list(Item *find, List<Item> &items,
} }
/**************************************************************************** /****************************************************************************
** Check that all given fields exists and fill struct with current data ** Expand all '*' in given fields
****************************************************************************/ ****************************************************************************/
int setup_fields(THD *thd, TABLE_LIST *tables, List<Item> &fields, int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
bool set_query_id, List<Item> *sum_func_list, List<Item> *sum_func_list,
bool allow_sum_func) uint wild_num)
{ {
if (!wild_num)
return 0;
reg2 Item *item; reg2 Item *item;
List_iterator<Item> it(fields); List_iterator<Item> it(fields);
DBUG_ENTER("setup_fields"); while ( wild_num && (item= it++))
thd->set_query_id=set_query_id;
thd->allow_sum_func= allow_sum_func;
thd->where="field list";
while ((item=it++))
{ {
if (item->type() == Item::FIELD_ITEM && ((Item_field*) item)->field_name && if (item->type() == Item::FIELD_ITEM && ((Item_field*) item)->field_name &&
((Item_field*) item)->field_name[0] == '*') ((Item_field*) item)->field_name[0] == '*')
@ -1914,7 +1919,7 @@ int setup_fields(THD *thd, TABLE_LIST *tables, List<Item> &fields,
uint elem= fields.elements; uint elem= fields.elements;
if (insert_fields(thd,tables,((Item_field*) item)->db_name, if (insert_fields(thd,tables,((Item_field*) item)->db_name,
((Item_field*) item)->table_name, &it)) ((Item_field*) item)->table_name, &it))
DBUG_RETURN(-1); /* purecov: inspected */ return (-1);
if (sum_func_list) if (sum_func_list)
{ {
/* /*
@ -1924,22 +1929,44 @@ int setup_fields(THD *thd, TABLE_LIST *tables, List<Item> &fields,
*/ */
sum_func_list->elements+= fields.elements - elem; sum_func_list->elements+= fields.elements - elem;
} }
wild_num--;
} }
else }
return 0;
}
/****************************************************************************
** Check that all given fields exists and fill struct with current data
****************************************************************************/
int setup_fields(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
List<Item> &fields, bool set_query_id,
List<Item> *sum_func_list, bool allow_sum_func)
{ {
if (item->fix_fields(thd, tables, it.ref()) || item->check_cols(1)) 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 */ DBUG_RETURN(-1); /* purecov: inspected */
item= *(it.ref()); //Item can be chenged in fix fields item= *(it.ref()); //Item can be chenged in fix fields
if (ref_pointer_array)
ref_pointer_array[i]= item;
if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM && if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM &&
sum_func_list) sum_func_list)
item->split_sum_func(*sum_func_list); item->split_sum_func(ref_pointer_array, *sum_func_list);
thd->used_tables|=item->used_tables(); thd->used_tables|=item->used_tables();
} }
}
DBUG_RETURN(test(thd->fatal_error || thd->net.report_error)); DBUG_RETURN(test(thd->fatal_error || thd->net.report_error));
} }
/* /*
Remap table numbers if INSERT ... SELECT Remap table numbers if INSERT ... SELECT
Check also that the 'used keys' and 'ignored keys' exists and set up the Check also that the 'used keys' and 'ignored keys' exists and set up the
@ -2254,7 +2281,7 @@ int mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys)
create_info.table_charset=default_charset_info; create_info.table_charset=default_charset_info;
DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->real_name, DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->real_name,
&create_info, table_list, &create_info, table_list,
fields, keys, drop, alter, (ORDER*)0, FALSE, fields, keys, drop, alter, 0, (ORDER*)0, FALSE,
DUP_ERROR)); DUP_ERROR));
} }
@ -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; create_info.table_charset=default_charset_info;
DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->real_name, DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->real_name,
&create_info, table_list, &create_info, table_list,
fields, keys, drop, alter, (ORDER*)0, FALSE, fields, keys, drop, alter, 0, (ORDER*)0, FALSE,
DUP_ERROR)); DUP_ERROR));
} }

View File

@ -394,7 +394,7 @@ struct system_variables
CHARSET_INFO *thd_charset; 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 For each client connection we create a separate thread with THD serving as
a thread/connection descriptor a thread/connection descriptor
@ -507,6 +507,7 @@ public:
USER_CONN *user_connect; USER_CONN *user_connect;
CHARSET_INFO *db_charset; CHARSET_INFO *db_charset;
List<Item> *possible_loops; // Items that may cause loops in subselects List<Item> *possible_loops; // Items that may cause loops in subselects
List<TABLE> temporary_tables_should_be_free; // list of temporary tables
List <MYSQL_ERROR> warn_list; List <MYSQL_ERROR> warn_list;
uint warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_END]; uint warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_END];
uint total_warn_count, old_total_warn_count; uint total_warn_count, old_total_warn_count;
@ -662,6 +663,17 @@ public:
#endif #endif
void add_possible_loop(Item *); void add_possible_loop(Item *);
void free_tmp_tables()
{
if (temporary_tables_should_be_free.elements)
{
List_iterator_fast<TABLE> lt(temporary_tables_should_be_free);
TABLE *table;
while ((table= lt++))
free_tmp_table(this,table);
temporary_tables_should_be_free.empty();
}
}
}; };
/* /*

View File

@ -92,6 +92,7 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order,
if ((select && select->check_quick(safe_update, limit)) || !limit) if ((select && select->check_quick(safe_update, limit)) || !limit)
{ {
delete select; delete select;
free_ulderlayed_joins(thd, &thd->lex.select_lex);
send_ok(thd,0L); send_ok(thd,0L);
DBUG_RETURN(0); // Nothing to delete DBUG_RETURN(0); // Nothing to delete
} }
@ -103,6 +104,7 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order,
if (safe_update && !using_limit) if (safe_update && !using_limit)
{ {
delete select; delete select;
free_ulderlayed_joins(thd, &thd->lex.select_lex);
send_error(thd,ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE); send_error(thd,ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE);
DBUG_RETURN(1); DBUG_RETURN(1);
} }
@ -124,7 +126,7 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order,
table->io_cache = (IO_CACHE *) my_malloc(sizeof(IO_CACHE), table->io_cache = (IO_CACHE *) my_malloc(sizeof(IO_CACHE),
MYF(MY_FAE | MY_ZEROFILL)); MYF(MY_FAE | MY_ZEROFILL));
if (setup_order(thd, &tables, fields, all_fields, order) || if (setup_order(thd, 0, &tables, fields, all_fields, order) ||
!(sortorder=make_unireg_sortorder(order, &length)) || !(sortorder=make_unireg_sortorder(order, &length)) ||
(table->found_records = filesort(thd, table, sortorder, length, (table->found_records = filesort(thd, table, sortorder, length,
(SQL_SELECT *) 0, HA_POS_ERROR, (SQL_SELECT *) 0, HA_POS_ERROR,
@ -132,6 +134,7 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order,
== HA_POS_ERROR) == HA_POS_ERROR)
{ {
delete select; delete select;
free_ulderlayed_joins(thd, &thd->lex.select_lex);
DBUG_RETURN(-1); // This will force out message DBUG_RETURN(-1); // This will force out message
} }
} }
@ -207,6 +210,7 @@ cleanup:
thd->lock=0; thd->lock=0;
} }
delete select; delete select;
free_ulderlayed_joins(thd, &thd->lex.select_lex);
if (error >= 0 || thd->net.report_error) if (error >= 0 || thd->net.report_error)
send_error(thd,thd->killed ? ER_SERVER_SHUTDOWN: 0); send_error(thd,thd->killed ? ER_SERVER_SHUTDOWN: 0);
else else

View File

@ -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 (!(res=open_and_lock_tables(thd,tables)))
{ {
if (is_union) if (setup_wild(thd, tables, item_list, 0, sl->with_wild) ||
{ setup_fields(thd, 0, tables, item_list, 0, 0, 1))
/*
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))
{ {
res= -1; res= -1;
goto exit; goto exit;
@ -144,8 +131,10 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
if (is_union) if (is_union)
res= mysql_union(thd,lex,derived_result,unit); res= mysql_union(thd,lex,derived_result,unit);
else else
res= mysql_select(thd, tables, sl->item_list, res= mysql_select(thd, &sl->ref_pointer_array, tables, sl->with_wild,
sl->where, (ORDER *) sl->order_list.first, sl->item_list, sl->where,
sl->order_list.elements+sl->group_list.elements,
(ORDER *) sl->order_list.first,
(ORDER *) sl->group_list.first, (ORDER *) sl->group_list.first,
sl->having, (ORDER*) NULL, sl->having, (ORDER*) NULL,
sl->options | thd->options | SELECT_NO_UNLOCK, sl->options | thd->options | SELECT_NO_UNLOCK,
@ -181,12 +170,12 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
delete derived_result; delete derived_result;
} }
if (res) if (res)
free_tmp_table(thd, table); mp_table(thd, table);
else
{
table->next= thd->derived_tables; >next= thd->derived_tables
thd->derived_tables= table; erived_tables= table;
}
exit: exit:
lex->current_select= save_current_select; lex->current_select= save_current_select;
close_thread_tables(thd, 0, 1); close_thread_tables(thd, 0, 1);

View File

@ -25,7 +25,7 @@ int mysql_do(THD *thd, List<Item> &values)
List_iterator<Item> li(values); List_iterator<Item> li(values);
Item *value; Item *value;
DBUG_ENTER("mysql_do"); DBUG_ENTER("mysql_do");
if (setup_fields(thd,0, values, 0, 0, 0)) if (setup_fields(thd, 0, 0, values, 0, 0, 0))
DBUG_RETURN(-1); DBUG_RETURN(-1);
while ((value = li++)) while ((value = li++))
value->val_int(); value->val_int();

View File

@ -81,7 +81,7 @@ check_insert_fields(THD *thd,TABLE *table,List<Item> &fields,
thd->dupp_field=0; thd->dupp_field=0;
if (setup_tables(&table_list) || if (setup_tables(&table_list) ||
setup_fields(thd,&table_list,fields,1,0,0)) setup_fields(thd, 0, &table_list,fields,1,0,0))
return -1; return -1;
if (thd->dupp_field) if (thd->dupp_field)
{ {
@ -171,10 +171,10 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
values= its++; values= its++;
if (check_insert_fields(thd,table,fields,*values,1) || if (check_insert_fields(thd,table,fields,*values,1) ||
setup_tables(insert_table_list) || setup_tables(insert_table_list) ||
setup_fields(thd, insert_table_list, *values, 0, 0, 0) || setup_fields(thd, 0, insert_table_list, *values, 0, 0, 0) ||
(duplic == DUP_UPDATE && (duplic == DUP_UPDATE &&
(setup_fields(thd, insert_table_list, update_fields, 0, 0, 0) || (setup_fields(thd, 0, insert_table_list, update_fields, 0, 0, 0) ||
setup_fields(thd, insert_table_list, update_values, 0, 0, 0)))) setup_fields(thd, 0, insert_table_list, update_values, 0, 0, 0))))
goto abort; goto abort;
if (find_real_table_in_list(table_list->next, if (find_real_table_in_list(table_list->next,
table_list->db, table_list->real_name)) table_list->db, table_list->real_name))
@ -194,7 +194,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
MYF(0),counter); MYF(0),counter);
goto abort; goto abort;
} }
if (setup_fields(thd,insert_table_list,*values,0,0,0)) if (setup_fields(thd, 0, insert_table_list, *values, 0, 0, 0))
goto abort; goto abort;
} }
its.rewind (); its.rewind ();
@ -376,11 +376,13 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
thd->cuted_fields); thd->cuted_fields);
::send_ok(thd,info.copied+info.deleted,(ulonglong)id,buff); ::send_ok(thd,info.copied+info.deleted,(ulonglong)id,buff);
} }
free_ulderlayed_joins(thd, &thd->lex.select_lex);
DBUG_RETURN(0); DBUG_RETURN(0);
abort: abort:
if (lock_type == TL_WRITE_DELAYED) if (lock_type == TL_WRITE_DELAYED)
end_delayed_insert(thd); end_delayed_insert(thd);
free_ulderlayed_joins(thd, &thd->lex.select_lex);
DBUG_RETURN(-1); DBUG_RETURN(-1);
} }

View File

@ -996,6 +996,7 @@ int yylex(void *arg, void *yythd)
void st_select_lex_node::init_query() void st_select_lex_node::init_query()
{ {
no_table_names_allowed= dependent= 0; no_table_names_allowed= dependent= 0;
ref_pointer_array= 0;
} }
void st_select_lex_node::init_select() void st_select_lex_node::init_select()
@ -1019,6 +1020,8 @@ void st_select_lex_unit::init_query()
union_option= 0; union_option= 0;
prepared= optimized= executed= 0; prepared= optimized= executed= 0;
item= 0; item= 0;
union_result= 0;
table= 0;
} }
void st_select_lex::init_query() void st_select_lex::init_query()
@ -1031,6 +1034,7 @@ void st_select_lex::init_query()
join= 0; join= 0;
olap= UNSPECIFIED_OLAP_TYPE; olap= UNSPECIFIED_OLAP_TYPE;
having_fix_field= 0; having_fix_field= 0;
with_wild= 0;
} }
void st_select_lex::init_select() void st_select_lex::init_select()

View File

@ -210,7 +210,10 @@ public:
List<List_item> expr_list; List<List_item> expr_list;
List<List_item> when_list; /* WHEN clause (expression) */ List<List_item> when_list; /* WHEN clause (expression) */
ha_rows select_limit, offset_limit; /* LIMIT clause parameters */ ha_rows select_limit, offset_limit; /* LIMIT clause parameters */
bool with_sum_func; // Arrays of pointers to top elements of all_fields list
Item **ref_pointer_array;
uint with_sum_func; /* sum function indicator and number of it */
bool create_refs; bool create_refs;
bool dependent; /* dependent from outer select subselect */ bool dependent; /* dependent from outer select subselect */
bool no_table_names_allowed; /* used for global order by */ 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 { class st_select_lex_unit: public st_select_lex_node {
protected: protected:
List<Item> item_list; List<Item> item_list;
List<JOIN*> joins; /* list of *JOINs, to delete it in cleanup() */
TABLE_LIST result_table_list; TABLE_LIST result_table_list;
select_union *union_result; select_union *union_result;
TABLE *table; /* temporary table using for appending UNION results */ TABLE *table; /* temporary table using for appending UNION results */
THD *thd;
select_result *result; select_result *result;
int res; int res;
bool describe, found_rows_for_union, bool describe, found_rows_for_union,
@ -295,6 +297,8 @@ public:
ha_rows select_limit_cnt, offset_limit_cnt; ha_rows select_limit_cnt, offset_limit_cnt;
/* not NULL if union used in subselect, point to subselect item */ /* not NULL if union used in subselect, point to subselect item */
Item_subselect *item; Item_subselect *item;
THD *thd;
uint union_option; uint union_option;
void init_query(); void init_query();
@ -342,6 +346,7 @@ public:
ulong table_join_options; ulong table_join_options;
uint in_sum_expr; uint in_sum_expr;
uint select_number; /* number of select (used for EXPLAIN) */ uint select_number; /* number of select (used for EXPLAIN) */
uint with_wild; /* item list contain '*' */
bool braces; /* SELECT ... UNION (SELECT ... ) <- this braces */ bool braces; /* SELECT ... UNION (SELECT ... ) <- this braces */
/* TRUE when having fix field called in processing of this SELECT */ /* TRUE when having fix field called in processing of this SELECT */
bool having_fix_field; bool having_fix_field;

View File

@ -155,12 +155,20 @@ protected:
class base_list_iterator class base_list_iterator
{ {
protected:
base_list *list; base_list *list;
list_node **el,**prev,*current; list_node **el,**prev,*current;
void sublist(base_list &ls, uint elm)
{
ls.first= *el;
ls.last= list->last;
ls.elements= elm;
}
public: public:
base_list_iterator(base_list &list_par) :list(&list_par),el(&list_par.first), base_list_iterator(base_list &list_par)
prev(0),current(0) :list(&list_par), el(&list_par.first), prev(0), current(0)
{} {}
inline void *next(void) inline void *next(void)
{ {
prev=el; prev=el;
@ -220,7 +228,6 @@ public:
friend class error_list_iterator; friend class error_list_iterator;
}; };
template <class T> class List :public base_list template <class T> class List :public base_list
{ {
public: public:
@ -268,6 +275,10 @@ public:
List_iterator_fast(List<T> &a) : base_list_iterator(a) {} List_iterator_fast(List<T> &a) : base_list_iterator(a) {}
inline T* operator++(int) { return (T*) base_list_iterator::next_fast(); } inline T* operator++(int) { return (T*) base_list_iterator::next_fast(); }
inline void rewind(void) { base_list_iterator::rewind(); } inline void rewind(void) { base_list_iterator::rewind(); }
void sublist(List<T> &list, uint el)
{
base_list_iterator::sublist(list, el);
}
}; };

View File

@ -119,7 +119,8 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
else else
{ // Part field list { // Part field list
thd->dupp_field=0; thd->dupp_field=0;
if (setup_tables(table_list) || setup_fields(thd,table_list,fields,1,0,0)) if (setup_tables(table_list) ||
setup_fields(thd, 0, table_list, fields, 1, 0, 0))
DBUG_RETURN(-1); DBUG_RETURN(-1);
if (thd->dupp_field) if (thd->dupp_field)
{ {

View File

@ -164,8 +164,10 @@ int handle_olaps(LEX *lex, SELECT_LEX *select_lex)
if (setup_tables((TABLE_LIST *)select_lex->table_list.first) || if (setup_tables((TABLE_LIST *)select_lex->table_list.first) ||
setup_fields(lex->thd,(TABLE_LIST *)select_lex->table_list.first,select_lex->item_list,1,&all_fields,1) || setup_fields(lex->thd, 0, (TABLE_LIST *)select_lex->table_list.first,
setup_fields(lex->thd,(TABLE_LIST *)select_lex->table_list.first,item_list_copy,1,&all_fields,1)) select_lex->item_list, 1, &all_fields,1) ||
setup_fields(lex->thd, 0, (TABLE_LIST *)select_lex->table_list.first,
item_list_copy, 1, &all_fields, 1))
return -1; return -1;
if (select_lex->olap == CUBE_TYPE) if (select_lex->olap == CUBE_TYPE)

View File

@ -2041,6 +2041,7 @@ mysql_execute_command(THD *thd)
&lex->create_info, &lex->create_info,
tables, lex->create_list, tables, lex->create_list,
lex->key_list, lex->drop_list, lex->alter_list, lex->key_list, lex->drop_list, lex->alter_list,
select_lex->order_list.elements,
(ORDER *) select_lex->order_list.first, (ORDER *) select_lex->order_list.first,
lex->drop_primary, lex->duplicates, lex->drop_primary, lex->duplicates,
lex->alter_keys_onoff, lex->simple_alter); lex->alter_keys_onoff, lex->simple_alter);
@ -2154,7 +2155,7 @@ mysql_execute_command(THD *thd)
res= mysql_alter_table(thd, NullS, NullS, &create_info, res= mysql_alter_table(thd, NullS, NullS, &create_info,
tables, lex->create_list, tables, lex->create_list,
lex->key_list, lex->drop_list, lex->alter_list, lex->key_list, lex->drop_list, lex->alter_list,
(ORDER *) 0, 0, (ORDER *) 0,
0, DUP_ERROR); 0, DUP_ERROR);
} }
else else
@ -2175,6 +2176,7 @@ mysql_execute_command(THD *thd)
select_lex->item_list, select_lex->item_list,
lex->value_list, lex->value_list,
select_lex->where, select_lex->where,
select_lex->order_list.elements,
(ORDER *) select_lex->order_list.first, (ORDER *) select_lex->order_list.first,
select_lex->select_limit, select_lex->select_limit,
lex->duplicates); lex->duplicates);
@ -2376,10 +2378,12 @@ mysql_execute_command(THD *thd)
if (!thd->fatal_error && (result= new multi_delete(thd,aux_tables, if (!thd->fatal_error && (result= new multi_delete(thd,aux_tables,
table_count))) table_count)))
{ {
res= mysql_select(thd,select_lex->get_table_list(), res= mysql_select(thd, &select_lex->ref_pointer_array,
select_lex->get_table_list(),
select_lex->with_wild,
select_lex->item_list, select_lex->item_list,
select_lex->where, select_lex->where,
(ORDER *)NULL,(ORDER *)NULL,(Item *)NULL, 0, (ORDER *)NULL, (ORDER *)NULL, (Item *)NULL,
(ORDER *)NULL, (ORDER *)NULL,
select_lex->options | thd->options | select_lex->options | thd->options |
SELECT_NO_JOIN_CACHE, SELECT_NO_JOIN_CACHE,
@ -2883,6 +2887,7 @@ mysql_execute_command(THD *thd)
send_ok(thd); send_ok(thd);
break; break;
} }
thd->free_tmp_tables();
thd->proc_info="query end"; // QQ thd->proc_info="query end"; // QQ
if (res < 0) if (res < 0)
send_error(thd,thd->killed ? ER_SERVER_SHUTDOWN : 0); send_error(thd,thd->killed ? ER_SERVER_SHUTDOWN : 0);
@ -3130,6 +3135,7 @@ mysql_init_query(THD *thd)
LEX *lex=&thd->lex; LEX *lex=&thd->lex;
lex->unit.init_query(); lex->unit.init_query();
lex->unit.init_select(); lex->unit.init_select();
lex->unit.thd= thd;
lex->select_lex.init_query(); lex->select_lex.init_query();
lex->value_list.empty(); lex->value_list.empty();
lex->param_list.empty(); lex->param_list.empty();
@ -3191,6 +3197,7 @@ mysql_new_select(LEX *lex, bool move_down)
return 1; return 1;
unit->init_query(); unit->init_query();
unit->init_select(); unit->init_select();
unit->thd= lex->thd;
unit->include_down(lex->current_select); unit->include_down(lex->current_select);
unit->link_next= 0; unit->link_next= 0;
unit->link_prev= 0; unit->link_prev= 0;

View File

@ -437,6 +437,7 @@ static bool setup_params_data(PREP_STMT *stmt)
} }
/* /*
Validate the following information for INSERT statement: Validate the following information for INSERT statement:
- field existance - field existance
- fields count - fields count
@ -504,7 +505,8 @@ static bool mysql_test_upd_fields(PREP_STMT *stmt, TABLE_LIST *table_list,
if (open_and_lock_tables(thd, table_list)) if (open_and_lock_tables(thd, table_list))
DBUG_RETURN(1); DBUG_RETURN(1);
if (setup_tables(table_list) || setup_fields(thd,table_list,fields,1,0,0) || if (setup_tables(table_list) ||
setup_fields(thd, 0, table_list, fields, 1, 0, 0) ||
setup_conds(thd, table_list, &conds) || thd->net.report_error) setup_conds(thd, table_list, &conds) || thd->net.report_error)
DBUG_RETURN(1); DBUG_RETURN(1);

File diff suppressed because it is too large Load Diff

View File

@ -119,8 +119,10 @@ class TMP_TABLE_PARAM :public Sql_alloc
{ {
public: public:
List<Item> copy_funcs; List<Item> copy_funcs;
List<Item> save_copy_funcs;
List_iterator_fast<Item> copy_funcs_it; List_iterator_fast<Item> copy_funcs_it;
Copy_field *copy_field, *copy_field_end; Copy_field *copy_field, *copy_field_end;
Copy_field *save_copy_field, *save_copy_field_end;
byte *group_buff; byte *group_buff;
Item_result_field **funcs; Item_result_field **funcs;
MI_COLUMNDEF *recinfo,*start_recinfo; MI_COLUMNDEF *recinfo,*start_recinfo;
@ -166,10 +168,13 @@ class JOIN :public Sql_alloc
List<Item> *fields; List<Item> *fields;
List<Item_buff> group_fields; List<Item_buff> group_fields;
TABLE *tmp_table; TABLE *tmp_table;
// used to store 2 possible tmp table of SELECT
TABLE *exec_tmp_table1, *exec_tmp_table2;
THD *thd; THD *thd;
Item_sum **sum_funcs; Item_sum **sum_funcs;
Procedure *procedure; Procedure *procedure;
Item *having; Item *having;
Item *tmp_having; // To store Having when processed tenporary table
uint select_options; uint select_options;
select_result *result; select_result *result;
TMP_TABLE_PARAM tmp_table_param; TMP_TABLE_PARAM tmp_table_param;
@ -179,6 +184,8 @@ class JOIN :public Sql_alloc
// select that processed // select that processed
SELECT_LEX *select_lex; SELECT_LEX *select_lex;
JOIN *tmp_join; // copy of this JOIN to be used with temporary tables
bool select_distinct, //Is select distinct? bool select_distinct, //Is select distinct?
no_order, simple_order, simple_group, no_order, simple_order, simple_group,
skip_sort_order, need_tmp, skip_sort_order, need_tmp,
@ -186,7 +193,11 @@ class JOIN :public Sql_alloc
buffer_result; buffer_result;
DYNAMIC_ARRAY keyuse; DYNAMIC_ARRAY keyuse;
Item::cond_result cond_value; Item::cond_result cond_value;
List<Item> all_fields; List<Item> all_fields; // to store all fields that used in query
//Above list changed to use temporary table
List<Item> tmp_all_fields1, tmp_all_fields2, tmp_all_fields3;
//Part, shared with list above, emulate following list
List<Item> tmp_fields_list1, tmp_fields_list2, tmp_fields_list3;
List<Item> & fields_list; // hold field list passed to mysql_select List<Item> & fields_list; // hold field list passed to mysql_select
int error; int error;
@ -194,11 +205,14 @@ class JOIN :public Sql_alloc
COND *conds; // ---"--- COND *conds; // ---"---
TABLE_LIST *tables_list; //hold 'tables' parameter of mysql_selec TABLE_LIST *tables_list; //hold 'tables' parameter of mysql_selec
SQL_SELECT *select; //created in optimisation phase SQL_SELECT *select; //created in optimisation phase
TABLE *exec_tmp_table; //used in 'exec' to hold temporary Item **ref_pointer_array; //used pointer reference for this select
// Copy of above to be used with different lists
Item **items0, **items1, **items2, **items3;
uint ref_pointer_array_size; // size of above in bytes
const char *zero_result_cause; // not 0 if exec must return zero result const char *zero_result_cause; // not 0 if exec must return zero result
my_bool union_part; // this subselect is part of union bool union_part; // this subselect is part of union
bool optimized; // flag to avoid double optimization in EXPLAIN
JOIN(THD *thd, List<Item> &fields, JOIN(THD *thd, List<Item> &fields,
ulong select_options, select_result *result): ulong select_options, select_result *result):
@ -208,14 +222,16 @@ class JOIN :public Sql_alloc
sort_and_group(0), first_record(0), sort_and_group(0), first_record(0),
do_send_rows(1), do_send_rows(1),
send_records(0), found_records(0), examined_rows(0), send_records(0), found_records(0), examined_rows(0),
exec_tmp_table1(0), exec_tmp_table2(0),
thd(thd), thd(thd),
sum_funcs(0), sum_funcs(0),
procedure(0), procedure(0),
having(0), having(0), tmp_having(0),
select_options(select_options), select_options(select_options),
result(result), result(result),
lock(thd->lock), lock(thd->lock),
select_lex(0), //for safety select_lex(0), //for safety
tmp_join(0),
select_distinct(test(select_options & SELECT_DISTINCT)), select_distinct(test(select_options & SELECT_DISTINCT)),
no_order(0), simple_order(0), simple_group(0), skip_sort_order(0), no_order(0), simple_order(0), simple_group(0), skip_sort_order(0),
need_tmp(0), need_tmp(0),
@ -226,8 +242,10 @@ class JOIN :public Sql_alloc
fields_list(fields), fields_list(fields),
error(0), error(0),
select(0), select(0),
exec_tmp_table(0), ref_pointer_array(0), items0(0), items1(0), items2(0), items3(0),
zero_result_cause(0) ref_pointer_array_size(0),
zero_result_cause(0),
optimized(0)
{ {
fields_list = fields; fields_list = fields;
bzero((char*) &keyuse,sizeof(keyuse)); bzero((char*) &keyuse,sizeof(keyuse));
@ -235,16 +253,23 @@ class JOIN :public Sql_alloc
tmp_table_param.end_write_records= HA_POS_ERROR; tmp_table_param.end_write_records= HA_POS_ERROR;
} }
int prepare(TABLE_LIST *tables, int prepare(Item ***rref_pointer_array, TABLE_LIST *tables, uint wind_num,
COND *conds, ORDER *order, ORDER *group, Item *having, COND *conds, uint og_num, ORDER *order, ORDER *group,
ORDER *proc_param, SELECT_LEX *select, SELECT_LEX_UNIT *unit, Item *having, ORDER *proc_param, SELECT_LEX *select,
bool fake_select_lex); SELECT_LEX_UNIT *unit, bool fake_select_lex);
int optimize(); int optimize();
int global_optimize();
int reinit(); int reinit();
void exec(); void exec();
int cleanup(THD *thd); int cleanup(THD *thd);
bool check_loop(uint id); bool check_loop(uint id);
void restore_tmp();
inline void init_items_ref_array()
{
items0= ref_pointer_array + all_fields.elements;
ref_pointer_array_size= all_fields.elements*sizeof(Item*);
memcpy(items0, ref_pointer_array, ref_pointer_array_size);
}
}; };
@ -263,7 +288,10 @@ TABLE *create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
void free_tmp_table(THD *thd, TABLE *entry); void free_tmp_table(THD *thd, TABLE *entry);
void count_field_types(TMP_TABLE_PARAM *param, List<Item> &fields, void count_field_types(TMP_TABLE_PARAM *param, List<Item> &fields,
bool reset_with_sum_func); bool reset_with_sum_func);
bool setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param,List<Item> &fields); bool setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param,
Item **ref_pointer_array,
List<Item> &new_list1, List<Item> &new_list2,
uint elements, List<Item> &fields);
void copy_fields(TMP_TABLE_PARAM *param); void copy_fields(TMP_TABLE_PARAM *param);
void copy_funcs(Item_result_field **func_ptr); void copy_funcs(Item_result_field **func_ptr);
bool create_myisam_from_heap(THD *thd, TABLE *table, TMP_TABLE_PARAM *param, bool create_myisam_from_heap(THD *thd, TABLE *table, TMP_TABLE_PARAM *param,

View File

@ -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, static int copy_data_between_tables(TABLE *from,TABLE *to,
List<create_field> &create, List<create_field> &create,
enum enum_duplicates handle_duplicates, enum enum_duplicates handle_duplicates,
ORDER *order, uint order_num, ORDER *order,
ha_rows *copied,ha_rows *deleted); ha_rows *copied,ha_rows *deleted);
/***************************************************************************** /*****************************************************************************
@ -1572,7 +1572,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
List<create_field> &fields, List<create_field> &fields,
List<Key> &keys,List<Alter_drop> &drop_list, List<Key> &keys,List<Alter_drop> &drop_list,
List<Alter_column> &alter_list, List<Alter_column> &alter_list,
ORDER *order, uint order_num, ORDER *order,
bool drop_primary, bool drop_primary,
enum enum_duplicates handle_duplicates, enum enum_duplicates handle_duplicates,
enum enum_enable_or_disable keys_onoff, enum enum_enable_or_disable keys_onoff,
@ -2034,7 +2034,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
if (!new_table->is_view) if (!new_table->is_view)
error=copy_data_between_tables(table,new_table,create_list, error=copy_data_between_tables(table,new_table,create_list,
handle_duplicates, handle_duplicates,
order, &copied, &deleted); order_num, order, &copied, &deleted);
thd->last_insert_id=next_insert_id; // Needed for correct log thd->last_insert_id=next_insert_id; // Needed for correct log
thd->count_cuted_fields=0; // Don`t calc cuted fields thd->count_cuted_fields=0; // Don`t calc cuted fields
new_table->time_stamp=save_time_stamp; new_table->time_stamp=save_time_stamp;
@ -2244,7 +2244,7 @@ static int
copy_data_between_tables(TABLE *from,TABLE *to, copy_data_between_tables(TABLE *from,TABLE *to,
List<create_field> &create, List<create_field> &create,
enum enum_duplicates handle_duplicates, enum enum_duplicates handle_duplicates,
ORDER *order, uint order_num, ORDER *order,
ha_rows *copied, ha_rows *copied,
ha_rows *deleted) ha_rows *deleted)
{ {
@ -2292,7 +2292,10 @@ copy_data_between_tables(TABLE *from,TABLE *to,
tables.db = from->table_cache_key; tables.db = from->table_cache_key;
error=1; error=1;
if (setup_order(thd, &tables, fields, all_fields, order) || if (setup_ref_array(thd, &thd->lex.select_lex.ref_pointer_array,
order_num)||
setup_order(thd, thd->lex.select_lex.ref_pointer_array,
&tables, fields, all_fields, order) ||
!(sortorder=make_unireg_sortorder(order, &length)) || !(sortorder=make_unireg_sortorder(order, &length)) ||
(from->found_records = filesort(thd, from, sortorder, length, (from->found_records = filesort(thd, from, sortorder, length,
(SQL_SELECT *) 0, HA_POS_ERROR, (SQL_SELECT *) 0, HA_POS_ERROR,

View File

@ -107,7 +107,6 @@ bool select_union::flush()
return 0; return 0;
} }
typedef JOIN * JOIN_P;
int st_select_lex_unit::prepare(THD *thd, select_result *result) int st_select_lex_unit::prepare(THD *thd, select_result *result)
{ {
DBUG_ENTER("st_select_lex_unit::prepare"); DBUG_ENTER("st_select_lex_unit::prepare");
@ -115,11 +114,9 @@ int st_select_lex_unit::prepare(THD *thd, select_result *result)
if (prepared) if (prepared)
DBUG_RETURN(0); DBUG_RETURN(0);
prepared= 1; prepared= 1;
union_result=0;
res= 0; res= 0;
found_rows_for_union= 0; found_rows_for_union= 0;
TMP_TABLE_PARAM tmp_table_param; TMP_TABLE_PARAM tmp_table_param;
this->thd= thd;
this->result= result; this->result= result;
SELECT_LEX_NODE *lex_select_save= thd->lex.current_select; SELECT_LEX_NODE *lex_select_save= thd->lex.current_select;
SELECT_LEX *sl; SELECT_LEX *sl;
@ -143,7 +140,9 @@ int st_select_lex_unit::prepare(THD *thd, select_result *result)
while ((item= it++)) while ((item= it++))
if (item_list.push_back(item)) if (item_list.push_back(item))
goto err; goto err;
if (setup_fields(thd,first_table,item_list,0,0,1)) if (setup_wild(thd, first_table, item_list, 0,
first_select()->with_wild) ||
setup_fields(thd, 0, first_table, item_list, 0, 0, 1))
goto err; goto err;
} }
@ -169,13 +168,11 @@ int st_select_lex_unit::prepare(THD *thd, select_result *result)
union_result->tmp_table_param=&tmp_table_param; union_result->tmp_table_param=&tmp_table_param;
// prepare selects // prepare selects
joins.empty();
for (sl= first_select(); sl; sl= sl->next_select()) for (sl= first_select(); sl; sl= sl->next_select())
{ {
JOIN *join= new JOIN(thd, sl->item_list, JOIN *join= new JOIN(thd, sl->item_list,
sl->options | thd->options | SELECT_NO_UNLOCK, sl->options | thd->options | SELECT_NO_UNLOCK,
union_result); union_result);
joins.push_back(new JOIN_P(join));
thd->lex.current_select= sl; thd->lex.current_select= sl;
offset_limit_cnt= sl->offset_limit; offset_limit_cnt= sl->offset_limit;
select_limit_cnt= sl->select_limit+sl->offset_limit; select_limit_cnt= sl->select_limit+sl->offset_limit;
@ -184,8 +181,11 @@ int st_select_lex_unit::prepare(THD *thd, select_result *result)
if (select_limit_cnt == HA_POS_ERROR) if (select_limit_cnt == HA_POS_ERROR)
sl->options&= ~OPTION_FOUND_ROWS; sl->options&= ~OPTION_FOUND_ROWS;
res= join->prepare((TABLE_LIST*) sl->table_list.first, res= join->prepare(&sl->ref_pointer_array,
(TABLE_LIST*) sl->table_list.first, sl->with_wild,
sl->where, sl->where,
((sl->braces) ? sl->order_list.elements : 0) +
sl->group_list.elements,
(sl->braces) ? (sl->braces) ?
(ORDER *)sl->order_list.first : (ORDER *) 0, (ORDER *)sl->order_list.first : (ORDER *) 0,
(ORDER*) sl->group_list.first, (ORDER*) sl->group_list.first,
@ -287,8 +287,9 @@ int st_select_lex_unit::exec()
select_limit_cnt= HA_POS_ERROR; // no limit select_limit_cnt= HA_POS_ERROR; // no limit
if (select_limit_cnt == HA_POS_ERROR) if (select_limit_cnt == HA_POS_ERROR)
thd->options&= ~OPTION_FOUND_ROWS; thd->options&= ~OPTION_FOUND_ROWS;
res= mysql_select(thd,&result_table_list, res= mysql_select(thd, &ref_pointer_array, &result_table_list,
item_list, NULL, 0, item_list, NULL,
global_parameters->order_list.elements,
(ORDER*)global_parameters->order_list.first, (ORDER*)global_parameters->order_list.first,
(ORDER*) NULL, NULL, (ORDER*) NULL, (ORDER*) NULL, NULL, (ORDER*) NULL,
thd->options, result, this, first_select(), 1); thd->options, result, this, first_select(), 1);
@ -304,20 +305,24 @@ int st_select_lex_unit::exec()
int st_select_lex_unit::cleanup() int st_select_lex_unit::cleanup()
{ {
DBUG_ENTER("st_select_lex_unit::cleanup"); DBUG_ENTER("st_select_lex_unit::cleanup");
int error= 0;
if (union_result) if (union_result)
{ {
delete union_result; delete union_result;
if (table)
free_tmp_table(thd, table); free_tmp_table(thd, table);
table= 0; // Safety table= 0; // Safety
} }
List_iterator<JOIN*> j(joins); for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select())
JOIN** join;
while ((join= j++))
{ {
(*join)->cleanup(thd); JOIN *join;
delete *join; if ((join= sl->join))
{
error|= sl->join->cleanup(thd);
delete join; delete join;
} }
joins.empty(); }
DBUG_RETURN(0); DBUG_RETURN(error);
} }

View File

@ -50,7 +50,7 @@ int mysql_update(THD *thd,
List<Item> &fields, List<Item> &fields,
List<Item> &values, List<Item> &values,
COND *conds, COND *conds,
ORDER *order, uint order_num, ORDER *order,
ha_rows limit, ha_rows limit,
enum enum_duplicates handle_duplicates) enum enum_duplicates handle_duplicates)
{ {
@ -109,7 +109,7 @@ int mysql_update(THD *thd,
/* Check the fields we are going to modify */ /* Check the fields we are going to modify */
table->grant.want_privilege=want_privilege; table->grant.want_privilege=want_privilege;
if (setup_fields(thd,update_table_list,fields,1,0,0)) if (setup_fields(thd, 0, update_table_list, fields, 1, 0, 0))
DBUG_RETURN(-1); /* purecov: inspected */ DBUG_RETURN(-1); /* purecov: inspected */
if (table->timestamp_field) if (table->timestamp_field)
{ {
@ -122,8 +122,9 @@ int mysql_update(THD *thd,
/* Check values */ /* Check values */
table->grant.want_privilege=(SELECT_ACL & ~table->grant.privilege); table->grant.want_privilege=(SELECT_ACL & ~table->grant.privilege);
if (setup_fields(thd,update_table_list,values,0,0,0)) if (setup_fields(thd, 0, update_table_list, values, 0, 0, 0))
{ {
free_ulderlayed_joins(thd, &thd->lex.select_lex);
DBUG_RETURN(-1); /* purecov: inspected */ DBUG_RETURN(-1); /* purecov: inspected */
} }
@ -134,6 +135,7 @@ int mysql_update(THD *thd,
(select && select->check_quick(safe_update, limit)) || !limit) (select && select->check_quick(safe_update, limit)) || !limit)
{ {
delete select; delete select;
free_ulderlayed_joins(thd, &thd->lex.select_lex);
if (error) if (error)
{ {
DBUG_RETURN(-1); // Error in where DBUG_RETURN(-1); // Error in where
@ -148,6 +150,7 @@ int mysql_update(THD *thd,
if (safe_update && !using_limit) if (safe_update && !using_limit)
{ {
delete select; delete select;
free_ulderlayed_joins(thd, &thd->lex.select_lex);
send_error(thd,ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE); send_error(thd,ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE);
DBUG_RETURN(1); DBUG_RETURN(1);
} }
@ -175,6 +178,7 @@ int mysql_update(THD *thd,
DISK_BUFFER_SIZE, MYF(MY_WME))) DISK_BUFFER_SIZE, MYF(MY_WME)))
{ {
delete select; /* purecov: inspected */ delete select; /* purecov: inspected */
free_ulderlayed_joins(thd, &thd->lex.select_lex);
DBUG_RETURN(-1); DBUG_RETURN(-1);
} }
if (old_used_keys & ((key_map) 1 << used_index)) if (old_used_keys & ((key_map) 1 << used_index))
@ -197,7 +201,10 @@ int mysql_update(THD *thd,
table->io_cache = (IO_CACHE *) my_malloc(sizeof(IO_CACHE), table->io_cache = (IO_CACHE *) my_malloc(sizeof(IO_CACHE),
MYF(MY_FAE | MY_ZEROFILL)); MYF(MY_FAE | MY_ZEROFILL));
if (setup_order(thd, &tables, fields, all_fields, order) || if (setup_ref_array(thd, &thd->lex.select_lex.ref_pointer_array,
order_num)||
setup_order(thd, thd->lex.select_lex.ref_pointer_array,
&tables, fields, all_fields, order) ||
!(sortorder=make_unireg_sortorder(order, &length)) || !(sortorder=make_unireg_sortorder(order, &length)) ||
(table->found_records = filesort(thd, table, sortorder, length, (table->found_records = filesort(thd, table, sortorder, length,
(SQL_SELECT *) 0, (SQL_SELECT *) 0,
@ -205,6 +212,7 @@ int mysql_update(THD *thd,
== HA_POS_ERROR) == HA_POS_ERROR)
{ {
delete select; delete select;
free_ulderlayed_joins(thd, &thd->lex.select_lex);
DBUG_RETURN(-1); DBUG_RETURN(-1);
} }
} }
@ -259,6 +267,7 @@ int mysql_update(THD *thd,
if (error >= 0) if (error >= 0)
{ {
delete select; delete select;
free_ulderlayed_joins(thd, &thd->lex.select_lex);
DBUG_RETURN(-1); DBUG_RETURN(-1);
} }
} }
@ -344,6 +353,7 @@ int mysql_update(THD *thd,
} }
delete select; delete select;
free_ulderlayed_joins(thd, &thd->lex.select_lex);
if (error >= 0) if (error >= 0)
send_error(thd,thd->killed ? ER_SERVER_SHUTDOWN : 0); /* purecov: inspected */ send_error(thd,thd->killed ? ER_SERVER_SHUTDOWN : 0); /* purecov: inspected */
else else
@ -358,6 +368,7 @@ int mysql_update(THD *thd,
} }
thd->count_cuted_fields=0; /* calc cuted fields */ thd->count_cuted_fields=0; /* calc cuted fields */
free_io_cache(table); free_io_cache(table);
DBUG_RETURN(0); DBUG_RETURN(0);
} }
@ -389,7 +400,7 @@ int mysql_multi_update(THD *thd,
DBUG_RETURN(res); DBUG_RETURN(res);
thd->select_limit=HA_POS_ERROR; thd->select_limit=HA_POS_ERROR;
if (setup_fields(thd, table_list, *fields, 1, 0, 0)) if (setup_fields(thd, 0, table_list, *fields, 1, 0, 0))
DBUG_RETURN(-1); DBUG_RETURN(-1);
/* /*
@ -412,8 +423,9 @@ int mysql_multi_update(THD *thd,
DBUG_RETURN(-1); DBUG_RETURN(-1);
List<Item> total_list; List<Item> total_list;
res= mysql_select(thd,table_list,total_list, res= mysql_select(thd, &select_lex->ref_pointer_array,
conds, (ORDER *) NULL, (ORDER *)NULL, (Item *) NULL, table_list, select_lex->with_wild, total_list,
conds, 0, (ORDER *) NULL, (ORDER *)NULL, (Item *) NULL,
(ORDER *)NULL, (ORDER *)NULL,
options | SELECT_NO_JOIN_CACHE, options | SELECT_NO_JOIN_CACHE,
result, unit, select_lex, 0); result, unit, select_lex, 0);
@ -466,7 +478,7 @@ int multi_update::prepare(List<Item> &not_used_values, SELECT_LEX_UNIT *unit)
reference tables reference tables
*/ */
if (setup_fields(thd, all_tables, *values, 1,0,0)) if (setup_fields(thd, 0, all_tables, *values, 1, 0, 0))
DBUG_RETURN(1); DBUG_RETURN(1);
/* /*

View File

@ -1825,8 +1825,10 @@ select_item_list:
| select_item | select_item
| '*' | '*'
{ {
if (add_item_to_list(YYTHD, new Item_field(NULL,NULL,"*"))) THD *thd= YYTHD;
if (add_item_to_list(thd, new Item_field(NULL, NULL, "*")))
YYABORT; YYABORT;
(thd->lex.current_select->select_lex()->with_wild)++;
}; };
@ -3732,10 +3734,19 @@ insert_ident:
| table_wild { $$=$1; }; | table_wild { $$=$1; };
table_wild: table_wild:
ident '.' '*' { $$ = new Item_field(NullS,$1.str,"*"); } ident '.' '*'
{
$$ = new Item_field(NullS,$1.str,"*");
Lex->current_select->select_lex()->with_wild++;
}
| ident '.' ident '.' '*' | ident '.' ident '.' '*'
{ $$ = new Item_field((YYTHD->client_capabilities & {
CLIENT_NO_SCHEMA ? NullS : $1.str),$3.str,"*"); }; $$ = new Item_field((YYTHD->client_capabilities &
CLIENT_NO_SCHEMA ? NullS : $1.str),
$3.str,"*");
Lex->current_select->select_lex()->with_wild++;
}
;
order_ident: order_ident:
expr { $$=$1; }; expr { $$=$1; };