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

merge

parents ea075fbb 934fa2a1
This diff is collapsed.
...@@ -86,10 +86,12 @@ a b ...@@ -86,10 +86,12 @@ a b
1 a 1 a
(select a,b from t1 limit 2) union all (select a,b from t2 order by a limit 1) order by t1.b; (select a,b from t1 limit 2) union all (select a,b from t2 order by a limit 1) order by t1.b;
ERROR 42000: Table 't1' from one of SELECT's can not be used in global ORDER clause ERROR 42000: Table 't1' from one of SELECT's can not be used in global ORDER clause
explain (select a,b from t1 limit 2) union all (select a,b from t2 order by a limit 1) order by b desc; explain extended (select a,b from t1 limit 2) union all (select a,b from t2 order by a limit 1) order by b desc;
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 t1 ALL NULL NULL NULL NULL 4 1 PRIMARY t1 ALL NULL NULL NULL NULL 4
2 UNION t2 ALL NULL NULL NULL NULL 4 Using filesort 2 UNION t2 ALL NULL NULL NULL NULL 4 Using filesort
Warnings:
Note 1003 (select high_priority test.t1.a AS `a`,test.t1.b AS `b` from test.t1 limit 2) union all (select test.t2.a AS `a`,test.t2.b AS `b` from test.t2 order by test.t2.a limit 1) order by b desc
(select sql_calc_found_rows a,b from t1 limit 2) union all (select a,b from t2 order by a) limit 2; (select sql_calc_found_rows a,b from t1 limit 2) union all (select a,b from t2 order by a) limit 2;
a b a b
1 a 1 a
...@@ -463,10 +465,12 @@ create table t1 (a int not null primary key auto_increment, b int, key(b)); ...@@ -463,10 +465,12 @@ create table t1 (a int not null primary key auto_increment, b int, key(b));
create table t2 (a int not null primary key auto_increment, b int); create table t2 (a int not null primary key auto_increment, b int);
insert into t1 (b) values (1),(2),(2),(3); insert into t1 (b) values (1),(2),(2),(3);
insert into t2 (b) values (10),(11),(12),(13); insert into t2 (b) values (10),(11),(12),(13);
explain (select * from t1 where a=1) union (select * from t2 where a=1); explain extended (select * from t1 where a=1) union (select * from t2 where a=1);
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 t1 const PRIMARY PRIMARY 4 const 1 1 PRIMARY t1 const PRIMARY PRIMARY 4 const 1
2 UNION t2 const PRIMARY PRIMARY 4 const 1 2 UNION t2 const PRIMARY PRIMARY 4 const 1
Warnings:
Note 1003 (select high_priority test.t1.a AS `a`,test.t1.b AS `b` from test.t1 where (test.t1.a = 1)) union (select test.t2.a AS `a`,test.t2.b AS `b` from test.t2 where (test.t2.a = 1))
(select * from t1 where a=5) union (select * from t2 where a=1); (select * from t1 where a=5) union (select * from t2 where a=1);
a b a b
1 10 1 10
......
This diff is collapsed.
...@@ -25,7 +25,7 @@ select 't1',b,count(*) from t1 group by b UNION select 't2',b,count(*) from t2 g ...@@ -25,7 +25,7 @@ select 't1',b,count(*) from t1 group by b UNION select 't2',b,count(*) from t2 g
(select a,b from t1 limit 2) union all (select a,b from t2 order by a limit 1) order by b desc; (select a,b from t1 limit 2) union all (select a,b from t2 order by a limit 1) order by b desc;
--error 1249 --error 1249
(select a,b from t1 limit 2) union all (select a,b from t2 order by a limit 1) order by t1.b; (select a,b from t1 limit 2) union all (select a,b from t2 order by a limit 1) order by t1.b;
explain (select a,b from t1 limit 2) union all (select a,b from t2 order by a limit 1) order by b desc; explain extended (select a,b from t1 limit 2) union all (select a,b from t2 order by a limit 1) order by b desc;
(select sql_calc_found_rows a,b from t1 limit 2) union all (select a,b from t2 order by a) limit 2; (select sql_calc_found_rows a,b from t1 limit 2) union all (select a,b from t2 order by a) limit 2;
select found_rows(); select found_rows();
select sql_calc_found_rows a,b from t1 union all select a,b from t2 limit 2; select sql_calc_found_rows a,b from t1 union all select a,b from t2 limit 2;
...@@ -275,7 +275,7 @@ create table t2 (a int not null primary key auto_increment, b int); ...@@ -275,7 +275,7 @@ create table t2 (a int not null primary key auto_increment, b int);
insert into t1 (b) values (1),(2),(2),(3); insert into t1 (b) values (1),(2),(2),(3);
insert into t2 (b) values (10),(11),(12),(13); insert into t2 (b) values (10),(11),(12),(13);
explain (select * from t1 where a=1) union (select * from t2 where a=1); explain extended (select * from t1 where a=1) union (select * from t2 where a=1);
(select * from t1 where a=5) union (select * from t2 where a=1); (select * from t1 where a=5) union (select * from t2 where a=1);
(select * from t1 where a=5 and a=6) union (select * from t2 where a=1); (select * from t1 where a=5 and a=6) union (select * from t2 where a=1);
(select t1.a,t1.b from t1,t2 where t1.a=5) union (select * from t2 where a=1); (select t1.a,t1.b from t1,t2 where t1.a=5) union (select * from t2 where a=1);
......
...@@ -87,6 +87,19 @@ Item::Item(THD *c_thd, Item &item): ...@@ -87,6 +87,19 @@ Item::Item(THD *c_thd, Item &item):
thd->free_list= this; thd->free_list= this;
} }
void Item::print_item_w_name(String *str)
{
print(str);
if (name)
{
str->append(" AS `");
str->append(name);
str->append('`');
}
}
// Constructor used by Item_field & Item_ref (see Item comment) // Constructor used by Item_field & Item_ref (see Item comment)
Item_ident::Item_ident(THD *thd, Item_ident &item): Item_ident::Item_ident(THD *thd, Item_ident &item):
Item(thd, item), Item(thd, item),
...@@ -445,12 +458,8 @@ String *Item_int::val_str(String *str) ...@@ -445,12 +458,8 @@ String *Item_int::val_str(String *str)
void Item_int::print(String *str) void Item_int::print(String *str)
{ {
if (!name) str_value.set(value, default_charset());
{ str->append(str_value);
str_value.set(value, default_charset());
name=str_value.c_ptr();
}
str->append(name);
} }
String *Item_uint::val_str(String *str) String *Item_uint::val_str(String *str)
...@@ -461,12 +470,8 @@ String *Item_uint::val_str(String *str) ...@@ -461,12 +470,8 @@ String *Item_uint::val_str(String *str)
void Item_uint::print(String *str) void Item_uint::print(String *str)
{ {
if (!name) str_value.set((ulonglong) value, default_charset());
{ str->append(str_value);
str_value.set((ulonglong) value, default_charset());
name=str_value.c_ptr();
}
str->append(name);
} }
...@@ -478,8 +483,10 @@ String *Item_real::val_str(String *str) ...@@ -478,8 +483,10 @@ String *Item_real::val_str(String *str)
void Item_string::print(String *str) void Item_string::print(String *str)
{ {
str->append('_');
str->append(collation.collation->csname);
str->append('\''); str->append('\'');
str->append(full_name()); str->append(str_value);
str->append('\''); str->append('\'');
} }
...@@ -777,7 +784,7 @@ static void mark_as_dependent(THD *thd, SELECT_LEX *last, SELECT_LEX *current, ...@@ -777,7 +784,7 @@ static void mark_as_dependent(THD *thd, SELECT_LEX *last, SELECT_LEX *current,
// store pointer on SELECT_LEX from wich item is dependent // store pointer on SELECT_LEX from wich item is dependent
item->depended_from= last; item->depended_from= last;
current->mark_as_dependent(last); current->mark_as_dependent(last);
if (thd->lex.describe) if (thd->lex.describe & DESCRIBE_EXTENDED)
{ {
char warn_buff[MYSQL_ERRMSG_SIZE]; char warn_buff[MYSQL_ERRMSG_SIZE];
sprintf(warn_buff, ER(ER_WARN_FIELD_RESOLVED), sprintf(warn_buff, ER(ER_WARN_FIELD_RESOLVED),
...@@ -1533,6 +1540,34 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) ...@@ -1533,6 +1540,34 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
} }
void Item_ref::print(String *str)
{
if (ref && *ref)
(*ref)->print(str);
else
Item_ident::print(str);
}
void Item_ref_null_helper::print(String *str)
{
str->append("<ref_null_helper>(");
if (ref && *ref)
(*ref)->print(str);
else
str->append('?');
str->append(')');
}
void Item_null_helper::print(String *str)
{
str->append("<null_helper>(");
store->print(str);
str->append(')');
}
bool Item_default_value::eq(const Item *item, bool binary_cmp) const bool Item_default_value::eq(const Item *item, bool binary_cmp) const
{ {
return item->type() == DEFAULT_VALUE_ITEM && return item->type() == DEFAULT_VALUE_ITEM &&
...@@ -1754,6 +1789,34 @@ Item_cache* Item_cache::get_cache(Item_result type) ...@@ -1754,6 +1789,34 @@ Item_cache* Item_cache::get_cache(Item_result type)
} }
} }
void Item_cache::print(String *str)
{
str->append("<cache>(");
if (example)
example->print(str);
else
Item::print(str);
str->append(')');
}
void Item_cache_int::store(Item *item)
{
value= item->val_int_result();
null_value= item->null_value;
collation.set(item->collation);
}
void Item_cache_real::store(Item *item)
{
value= item->val_result();
null_value= item->null_value;
collation.set(item->collation);
}
void Item_cache_str::store(Item *item) void Item_cache_str::store(Item *item)
{ {
value_buff.set(buffer, sizeof(buffer), item->collation.collation); value_buff.set(buffer, sizeof(buffer), item->collation.collation);
...@@ -1804,6 +1867,7 @@ bool Item_cache_row::allocate(uint num) ...@@ -1804,6 +1867,7 @@ bool Item_cache_row::allocate(uint num)
bool Item_cache_row::setup(Item * item) bool Item_cache_row::setup(Item * item)
{ {
example= item;
if (!values && allocate(item->cols())) if (!values && allocate(item->cols()))
return 1; return 1;
for (uint i= 0; i < item_count; i++) for (uint i= 0; i < item_count; i++)
......
...@@ -182,6 +182,7 @@ class Item { ...@@ -182,6 +182,7 @@ class Item {
{ return decimals != NOT_FIXED_DEC ? (DBL_DIG+2+decimals_par) : DBL_DIG+8;} { return decimals != NOT_FIXED_DEC ? (DBL_DIG+2+decimals_par) : DBL_DIG+8;}
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()); }
void print_item_w_name(String *);
virtual void update_used_tables() {} virtual void update_used_tables() {}
virtual void split_sum_func(Item **ref_pointer_array, 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);
...@@ -315,6 +316,7 @@ class Item_null :public Item ...@@ -315,6 +316,7 @@ class Item_null :public Item
bool basic_const_item() const { return 1; } bool basic_const_item() const { return 1; }
Item *new_item() { return new Item_null(name); } Item *new_item() { return new Item_null(name); }
bool is_null() { return 1; } bool is_null() { return 1; }
void print(String *str) { str->append("NULL"); }
}; };
class Item_param :public Item class Item_param :public Item
...@@ -365,6 +367,7 @@ class Item_param :public Item ...@@ -365,6 +367,7 @@ class Item_param :public Item
String *query_val_str(String *str); String *query_val_str(String *str);
enum_field_types field_type() const { return MYSQL_TYPE_STRING; } enum_field_types field_type() const { return MYSQL_TYPE_STRING; }
Item *new_item() { return new Item_param(pos_in_query); } Item *new_item() { return new Item_param(pos_in_query); }
void print(String *str) { str->append('?'); }
}; };
class Item_int :public Item class Item_int :public Item
...@@ -637,6 +640,7 @@ class Item_ref :public Item_ident ...@@ -637,6 +640,7 @@ class Item_ref :public Item_ident
(*ref)->save_in_field(result_field, no_conversions); (*ref)->save_in_field(result_field, no_conversions);
} }
Item *real_item() { return *ref; } Item *real_item() { return *ref; }
void print(String *str);
}; };
class Item_in_subselect; class Item_in_subselect;
...@@ -652,15 +656,7 @@ class Item_ref_null_helper: public Item_ref ...@@ -652,15 +656,7 @@ class Item_ref_null_helper: public Item_ref
longlong val_int(); longlong val_int();
String* val_str(String* s); String* val_str(String* s);
bool get_date(TIME *ltime, bool fuzzydate); bool get_date(TIME *ltime, bool fuzzydate);
void print(String *str) void print(String *str);
{
str->append("ref_null_helper(");
if (ref && *ref)
(*ref)->print(str);
else
str->append('?');
str->append(')');
}
}; };
class Item_null_helper :public Item_ref_null_helper class Item_null_helper :public Item_ref_null_helper
...@@ -672,6 +668,7 @@ class Item_null_helper :public Item_ref_null_helper ...@@ -672,6 +668,7 @@ class Item_null_helper :public Item_ref_null_helper
:Item_ref_null_helper(master, &store, table_name_par, field_name_par), :Item_ref_null_helper(master, &store, table_name_par, field_name_par),
store(item) store(item)
{} {}
void print(String *str);
}; };
/* /*
...@@ -853,14 +850,16 @@ class Item_insert_value : public Item_field ...@@ -853,14 +850,16 @@ class Item_insert_value : public Item_field
class Item_cache: public Item class Item_cache: public Item
{ {
protected:
Item *example;
table_map used_table_map; table_map used_table_map;
public: public:
Item_cache(): used_table_map(0) {fixed= 1; null_value= 1;} Item_cache(): example(0), used_table_map(0) {fixed= 1; null_value= 1;}
void set_used_tables(table_map map) { used_table_map= map; } void set_used_tables(table_map map) { used_table_map= map; }
virtual bool allocate(uint i) { return 0; }; virtual bool allocate(uint i) { return 0; };
virtual bool setup(Item *) { return 0; }; virtual bool setup(Item *item) { example= item; return 0; };
virtual void store(Item *)= 0; virtual void store(Item *)= 0;
void set_len_n_dec(uint32 max_len, uint8 dec) void set_len_n_dec(uint32 max_len, uint8 dec)
{ {
...@@ -870,6 +869,7 @@ class Item_cache: public Item ...@@ -870,6 +869,7 @@ class Item_cache: public Item
enum Type type() const { return CACHE_ITEM; } enum Type type() const { return CACHE_ITEM; }
static Item_cache* get_cache(Item_result type); static Item_cache* get_cache(Item_result type);
table_map used_tables() const { return used_table_map; } table_map used_tables() const { return used_table_map; }
void print(String *str);
}; };
class Item_cache_int: public Item_cache class Item_cache_int: public Item_cache
...@@ -878,12 +878,7 @@ class Item_cache_int: public Item_cache ...@@ -878,12 +878,7 @@ class Item_cache_int: public Item_cache
public: public:
Item_cache_int(): Item_cache() {} Item_cache_int(): Item_cache() {}
void store(Item *item) void store(Item *item);
{
value= item->val_int_result();
null_value= item->null_value;
collation.set(item->collation);
}
double val() { return (double) value; } double val() { return (double) value; }
longlong val_int() { return value; } longlong val_int() { return value; }
String* val_str(String *str) { str->set(value, default_charset()); return str; } String* val_str(String *str) { str->set(value, default_charset()); return str; }
...@@ -896,12 +891,7 @@ class Item_cache_real: public Item_cache ...@@ -896,12 +891,7 @@ class Item_cache_real: public Item_cache
public: public:
Item_cache_real(): Item_cache() {} Item_cache_real(): Item_cache() {}
void store(Item *item) void store(Item *item);
{
value= item->val_result();
null_value= item->null_value;
collation.set(item->collation);
}
double val() { return value; } double val() { return value; }
longlong val_int() { return (longlong) (value+(value > 0 ? 0.5 : -0.5)); } longlong val_int() { return (longlong) (value+(value > 0 ? 0.5 : -0.5)); }
String* val_str(String *str) String* val_str(String *str)
......
...@@ -112,6 +112,14 @@ longlong Item_func_not_all::val_int() ...@@ -112,6 +112,14 @@ longlong Item_func_not_all::val_int()
return (!null_value && value == 0) ? 1 : 0; return (!null_value && value == 0) ? 1 : 0;
} }
void Item_func_not_all::print(String *str)
{
if (show)
Item_func::print(str);
else
args[0]->print(str);
}
/* /*
Convert a constant expression or string to an integer. Convert a constant expression or string to an integer.
This is done when comparing DATE's of different formats and This is done when comparing DATE's of different formats and
...@@ -704,6 +712,18 @@ longlong Item_func_between::val_int() ...@@ -704,6 +712,18 @@ longlong Item_func_between::val_int()
return 0; return 0;
} }
void Item_func_between::print(String *str)
{
str->append('(');
args[0]->print(str);
str->append(" between ");
args[1]->print(str);
str->append(" and ");
args[2]->print(str);
str->append(')');
}
void void
Item_func_ifnull::fix_length_and_dec() Item_func_ifnull::fix_length_and_dec()
{ {
...@@ -1097,7 +1117,27 @@ void Item_func_case::fix_length_and_dec() ...@@ -1097,7 +1117,27 @@ void Item_func_case::fix_length_and_dec()
void Item_func_case::print(String *str) void Item_func_case::print(String *str)
{ {
str->append("case "); // Not yet complete str->append("(case ");
if (first_expr_num != -1)
{
args[first_expr_num]->print(str);
str->append(' ');
}
for (uint i=0 ; i < ncases ; i+=2)
{
str->append("when ");
args[i]->print(str);
str->append(" then ");
args[i+1]->print(str);
str->append(' ');
}
if (else_expr_num != -1)
{
str->append("else ");
args[else_expr_num]->print(str);
str->append(' ');
}
str->append("end)");
} }
/* /*
...@@ -1504,8 +1544,15 @@ void Item_func_in::fix_length_and_dec() ...@@ -1504,8 +1544,15 @@ void Item_func_in::fix_length_and_dec()
void Item_func_in::print(String *str) void Item_func_in::print(String *str)
{ {
str->append('('); str->append('(');
Item_func::print(str); args[0]->print(str);
str->append(')'); str->append(" IN (");
for (uint i=1 ; i < arg_count ; i++)
{
if (i > 1)
str->append(',');
args[i]->print(str);
}
str->append("))");
} }
...@@ -1866,12 +1913,21 @@ void Item_is_not_null_test::update_used_tables() ...@@ -1866,12 +1913,21 @@ void Item_is_not_null_test::update_used_tables()
} }
} }
longlong Item_func_isnotnull::val_int() longlong Item_func_isnotnull::val_int()
{ {
return args[0]->is_null() ? 0 : 1; return args[0]->is_null() ? 0 : 1;
} }
void Item_func_isnotnull::print(String *str)
{
str->append('(');
args[0]->print(str);
str->append(" is not null)");
}
longlong Item_func_like::val_int() longlong Item_func_like::val_int()
{ {
String* res = args[0]->val_str(&tmp_value1); String* res = args[0]->val_str(&tmp_value1);
......
...@@ -105,7 +105,7 @@ class Item_in_optimizer: public Item_bool_func ...@@ -105,7 +105,7 @@ class Item_in_optimizer: public Item_bool_func
Item_in_optimizer return NULL, else it evaluate Item_in_subselect. Item_in_optimizer return NULL, else it evaluate Item_in_subselect.
*/ */
longlong val_int(); longlong val_int();
const char *func_name() const { return "IN_OPTIMIZER"; } const char *func_name() const { return "<in_optimizer>"; }
Item_cache **get_cache() { return &cache; } Item_cache **get_cache() { return &cache; }
}; };
...@@ -160,10 +160,14 @@ class Item_func_not_all :public Item_func_not ...@@ -160,10 +160,14 @@ class Item_func_not_all :public Item_func_not
{ {
bool abort_on_null; bool abort_on_null;
public: public:
Item_func_not_all(Item *a) :Item_func_not(a), abort_on_null(0) {} bool show;
Item_func_not_all(Item *a) :Item_func_not(a), abort_on_null(0), show(0) {}
virtual void top_level_item() { abort_on_null= 1; } virtual void top_level_item() { abort_on_null= 1; }
bool top_level() { return abort_on_null; } bool top_level() { return abort_on_null; }
longlong val_int(); longlong val_int();
const char *func_name() const { return "<not>"; }
void print(String *str);
}; };
class Item_func_eq :public Item_bool_rowready_func2 class Item_func_eq :public Item_bool_rowready_func2
...@@ -262,6 +266,7 @@ class Item_func_between :public Item_int_func ...@@ -262,6 +266,7 @@ class Item_func_between :public Item_int_func
enum Functype functype() const { return BETWEEN; } enum Functype functype() const { return BETWEEN; }
const char *func_name() const { return "between"; } const char *func_name() const { return "between"; }
void fix_length_and_dec(); void fix_length_and_dec();
void print(String *str);
}; };
...@@ -704,7 +709,7 @@ class Item_is_not_null_test :public Item_func_isnull ...@@ -704,7 +709,7 @@ class Item_is_not_null_test :public Item_func_isnull
{} {}
enum Functype functype() const { return ISNOTNULLTEST_FUNC; } enum Functype functype() const { return ISNOTNULLTEST_FUNC; }
longlong val_int(); longlong val_int();
const char *func_name() const { return "is_not_null_test"; } const char *func_name() const { return "<is_not_null_test>"; }
void update_used_tables(); void update_used_tables();
}; };
...@@ -722,6 +727,7 @@ class Item_func_isnotnull :public Item_bool_func ...@@ -722,6 +727,7 @@ class Item_func_isnotnull :public Item_bool_func
const char *func_name() const { return "isnotnull"; } const char *func_name() const { return "isnotnull"; }
optimize_type select_optimize() const { return OPTIMIZE_NULL; } optimize_type select_optimize() const { return OPTIMIZE_NULL; }
table_map not_null_tables() const { return 0; } table_map not_null_tables() const { return 0; }
void print(String *str);
}; };
...@@ -775,6 +781,7 @@ class Item_func_regex :public Item_bool_func ...@@ -775,6 +781,7 @@ class Item_func_regex :public Item_bool_func
longlong val_int(); longlong val_int();
bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref); bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref);
const char *func_name() const { return "regex"; } const char *func_name() const { return "regex"; }
void print(String *str) { print_op(str); }
}; };
#else #else
...@@ -785,6 +792,7 @@ class Item_func_regex :public Item_bool_func ...@@ -785,6 +792,7 @@ class Item_func_regex :public Item_bool_func
Item_func_regex(Item *a,Item *b) :Item_bool_func(a,b) {} Item_func_regex(Item *a,Item *b) :Item_bool_func(a,b) {}
longlong val_int() { return 0;} longlong val_int() { return 0;}
const char *func_name() const { return "regex"; } const char *func_name() const { return "regex"; }
void print(String *str) { print_op(str); }
}; };
#endif /* USE_REGEX */ #endif /* USE_REGEX */
......
...@@ -462,6 +462,24 @@ String *Item_num_op::val_str(String *str) ...@@ -462,6 +462,24 @@ String *Item_num_op::val_str(String *str)
} }
void Item_func_signed::print(String *str)
{
str->append("cast(");
args[0]->print(str);
str->append("as signed)");
}
void Item_func_unsigned::print(String *str)
{
str->append("cast(");
args[0]->print(str);
str->append("as unsigned)");
}
double Item_func_plus::val() double Item_func_plus::val()
{ {
double value=args[0]->val()+args[1]->val(); double value=args[0]->val()+args[1]->val();
...@@ -2820,6 +2838,26 @@ double Item_func_match::val() ...@@ -2820,6 +2838,26 @@ double Item_func_match::val()
DBUG_RETURN(ft_handler->please->find_relevance(ft_handler, record, 0)); DBUG_RETURN(ft_handler->please->find_relevance(ft_handler, record, 0));
} }
void Item_func_match::print(String *str)
{
str->append("(match ");
List_iterator_fast<Item> li(fields);
Item *item;
bool first= 1;
while ((item= li++))
{
if (first)
first= 0;
else
str->append(',');
item->print(str);
}
str->append(" against (");
args[0]->print(str);
if (mode == FT_BOOL)
str->append(" in boolean mode");
str->append("))");
}
longlong Item_func_bit_xor::val_int() longlong Item_func_bit_xor::val_int()
{ {
......
...@@ -214,6 +214,7 @@ class Item_func_signed :public Item_int_func ...@@ -214,6 +214,7 @@ class Item_func_signed :public Item_int_func
longlong val_int() { return args[0]->val_int(); } longlong val_int() { return args[0]->val_int(); }
void fix_length_and_dec() void fix_length_and_dec()
{ max_length=args[0]->max_length; unsigned_flag=0; } { max_length=args[0]->max_length; unsigned_flag=0; }
void print(String *str);
}; };
...@@ -225,6 +226,7 @@ class Item_func_unsigned :public Item_int_func ...@@ -225,6 +226,7 @@ class Item_func_unsigned :public Item_int_func
longlong val_int() { return args[0]->val_int(); } longlong val_int() { return args[0]->val_int(); }
void fix_length_and_dec() void fix_length_and_dec()
{ max_length=args[0]->max_length; unsigned_flag=1; } { max_length=args[0]->max_length; unsigned_flag=1; }
void print(String *str);
}; };
...@@ -662,6 +664,7 @@ class Item_func_bit_or :public Item_int_func ...@@ -662,6 +664,7 @@ class Item_func_bit_or :public Item_int_func
longlong val_int(); longlong val_int();
const char *func_name() const { return "|"; } const char *func_name() const { return "|"; }
void fix_length_and_dec() { unsigned_flag=1; } void fix_length_and_dec() { unsigned_flag=1; }
void print(String *str) { print_op(str); }
}; };
class Item_func_bit_and :public Item_int_func class Item_func_bit_and :public Item_int_func
...@@ -671,6 +674,7 @@ class Item_func_bit_and :public Item_int_func ...@@ -671,6 +674,7 @@ class Item_func_bit_and :public Item_int_func
longlong val_int(); longlong val_int();
const char *func_name() const { return "&"; } const char *func_name() const { return "&"; }
void fix_length_and_dec() { unsigned_flag=1; } void fix_length_and_dec() { unsigned_flag=1; }
void print(String *str) { print_op(str); }
}; };
class Item_func_bit_count :public Item_int_func class Item_func_bit_count :public Item_int_func
...@@ -689,6 +693,7 @@ class Item_func_shift_left :public Item_int_func ...@@ -689,6 +693,7 @@ class Item_func_shift_left :public Item_int_func
longlong val_int(); longlong val_int();
const char *func_name() const { return "<<"; } const char *func_name() const { return "<<"; }
void fix_length_and_dec() { unsigned_flag=1; } void fix_length_and_dec() { unsigned_flag=1; }
void print(String *str) { print_op(str); }
}; };
class Item_func_shift_right :public Item_int_func class Item_func_shift_right :public Item_int_func
...@@ -697,6 +702,7 @@ class Item_func_shift_right :public Item_int_func ...@@ -697,6 +702,7 @@ class Item_func_shift_right :public Item_int_func
Item_func_shift_right(Item *a,Item *b) :Item_int_func(a,b) {} Item_func_shift_right(Item *a,Item *b) :Item_int_func(a,b) {}
longlong val_int(); longlong val_int();
const char *func_name() const { return ">>"; } const char *func_name() const { return ">>"; }
void print(String *str) { print_op(str); }
}; };
class Item_func_bit_neg :public Item_int_func class Item_func_bit_neg :public Item_int_func
...@@ -1005,6 +1011,7 @@ class Item_func_match :public Item_real_func ...@@ -1005,6 +1011,7 @@ class Item_func_match :public Item_real_func
bool eq(const Item *, bool binary_cmp) const; bool eq(const Item *, bool binary_cmp) const;
longlong val_int() { return val()!=0.0; } longlong val_int() { return val()!=0.0; }
double val(); double val();
void print(String *str);
bool fix_index(); bool fix_index();
void init_search(bool no_order); void init_search(bool no_order);
...@@ -1040,6 +1047,7 @@ class Item_func_bit_xor : public Item_int_func ...@@ -1040,6 +1047,7 @@ class Item_func_bit_xor : public Item_int_func
longlong val_int(); longlong val_int();
const char *func_name() const { return "^"; } const char *func_name() const { return "^"; }
void fix_length_xor_dec() { unsigned_flag=1; } void fix_length_xor_dec() { unsigned_flag=1; }
void print(String *str) { print_op(str); }
}; };
class Item_func_is_free_lock :public Item_int_func class Item_func_is_free_lock :public Item_int_func
......
...@@ -118,6 +118,7 @@ class Item_func_spatial_decomp: public Item_str_func ...@@ -118,6 +118,7 @@ class Item_func_spatial_decomp: public Item_str_func
case SP_EXTERIORRING: case SP_EXTERIORRING:
return "exteriorring"; return "exteriorring";
default: default:
DBUG_ASSERT(0); // Should never happened
return "spatial_decomp_unknown"; return "spatial_decomp_unknown";
} }
} }
...@@ -142,6 +143,7 @@ class Item_func_spatial_decomp_n: public Item_str_func ...@@ -142,6 +143,7 @@ class Item_func_spatial_decomp_n: public Item_str_func
case SP_INTERIORRINGN: case SP_INTERIORRINGN:
return "interiorringn"; return "interiorringn";
default: default:
DBUG_ASSERT(0); // Should never happened
return "spatial_decomp_n_unknown"; return "spatial_decomp_n_unknown";
} }
} }
...@@ -210,6 +212,7 @@ class Item_func_spatial_rel: public Item_bool_func2 ...@@ -210,6 +212,7 @@ class Item_func_spatial_rel: public Item_bool_func2
case SP_OVERLAPS_FUNC: case SP_OVERLAPS_FUNC:
return "overlaps"; return "overlaps";
default: default:
DBUG_ASSERT(0); // Should never happened
return "sp_unknown"; return "sp_unknown";
} }
} }
......
...@@ -118,6 +118,18 @@ bool Item_row::check_cols(uint c) ...@@ -118,6 +118,18 @@ bool Item_row::check_cols(uint c)
return 0; return 0;
} }
void Item_row::print(String *str)
{
str->append('(');
for (uint i= 0; i < arg_count; i++)
{
if (i)
str->append(',');
items[i]->print(str);
}
str->append(')');
}
bool Item_row::walk(Item_processor processor, byte *arg) bool Item_row::walk(Item_processor processor, byte *arg)
{ {
for (uint i= 0; i < arg_count; i++) for (uint i= 0; i < arg_count; i++)
......
...@@ -68,6 +68,7 @@ class Item_row: public Item ...@@ -68,6 +68,7 @@ class Item_row: public Item
bool const_item() const { return const_item_cache; }; bool const_item() const { return const_item_cache; };
enum Item_result result_type() const { return ROW_RESULT; } enum Item_result result_type() const { return ROW_RESULT; }
void update_used_tables(); void update_used_tables();
void print(String *str);
bool walk(Item_processor processor, byte *arg); bool walk(Item_processor processor, byte *arg);
......
...@@ -2271,6 +2271,14 @@ String *Item_func_hex::val_str(String *str) ...@@ -2271,6 +2271,14 @@ String *Item_func_hex::val_str(String *str)
} }
void Item_func_binary::print(String *str)
{
str->append("cast(");
args[0]->print(str);
str->append("as binary)");
}
#include <my_dir.h> // For my_stat #include <my_dir.h> // For my_stat
String *Item_load_file::val_str(String *str) String *Item_load_file::val_str(String *str)
......
...@@ -120,6 +120,7 @@ class Item_func_reverse :public Item_str_func ...@@ -120,6 +120,7 @@ class Item_func_reverse :public Item_str_func
Item_func_reverse(Item *a) :Item_str_func(a) {} Item_func_reverse(Item *a) :Item_str_func(a) {}
String *val_str(String *); String *val_str(String *);
void fix_length_and_dec(); void fix_length_and_dec();
const char *func_name() const { return "reverse"; }
}; };
...@@ -324,10 +325,12 @@ class Item_func_encrypt :public Item_str_func ...@@ -324,10 +325,12 @@ class Item_func_encrypt :public Item_str_func
Item_func_encrypt(Item *a, Item *b): Item_str_func(a,b) {} Item_func_encrypt(Item *a, Item *b): Item_str_func(a,b) {}
String *val_str(String *); String *val_str(String *);
void fix_length_and_dec() { maybe_null=1; max_length = 13; } void fix_length_and_dec() { maybe_null=1; max_length = 13; }
const char *func_name() const { return "ecrypt"; }
}; };
#include "sql_crypt.h" #include "sql_crypt.h"
class Item_func_encode :public Item_str_func class Item_func_encode :public Item_str_func
{ {
protected: protected:
...@@ -337,13 +340,16 @@ class Item_func_encode :public Item_str_func ...@@ -337,13 +340,16 @@ class Item_func_encode :public Item_str_func
Item_str_func(a),sql_crypt(seed) {} Item_str_func(a),sql_crypt(seed) {}
String *val_str(String *); String *val_str(String *);
void fix_length_and_dec(); void fix_length_and_dec();
const char *func_name() const { return "encode"; }
}; };
class Item_func_decode :public Item_func_encode class Item_func_decode :public Item_func_encode
{ {
public: public:
Item_func_decode(Item *a, char *seed): Item_func_encode(a,seed) {} Item_func_decode(Item *a, char *seed): Item_func_encode(a,seed) {}
String *val_str(String *); String *val_str(String *);
const char *func_name() const { return "decode"; }
}; };
...@@ -520,7 +526,6 @@ class Item_func_binary :public Item_str_func ...@@ -520,7 +526,6 @@ class Item_func_binary :public Item_str_func
{ {
public: public:
Item_func_binary(Item *a) :Item_str_func(a) {} Item_func_binary(Item *a) :Item_str_func(a) {}
const char *func_name() const { return "binary"; }
String *val_str(String *a) String *val_str(String *a)
{ {
String *tmp=args[0]->val_str(a); String *tmp=args[0]->val_str(a);
...@@ -534,7 +539,7 @@ class Item_func_binary :public Item_str_func ...@@ -534,7 +539,7 @@ class Item_func_binary :public Item_str_func
collation.set(&my_charset_bin); collation.set(&my_charset_bin);
max_length=args[0]->max_length; max_length=args[0]->max_length;
} }
void print(String *str) { print_op(str); } void print(String *str);
}; };
......
...@@ -146,21 +146,25 @@ Item::Type Item_subselect::type() const ...@@ -146,21 +146,25 @@ Item::Type Item_subselect::type() const
return SUBSELECT_ITEM; return SUBSELECT_ITEM;
} }
void Item_subselect::fix_length_and_dec() void Item_subselect::fix_length_and_dec()
{ {
engine->fix_length_and_dec(0); engine->fix_length_and_dec(0);
} }
table_map Item_subselect::used_tables() const table_map Item_subselect::used_tables() const
{ {
return (table_map) (engine->dependent() ? used_tables_cache : 0L); return (table_map) (engine->dependent() ? used_tables_cache : 0L);
} }
bool Item_subselect::const_item() const bool Item_subselect::const_item() const
{ {
return const_item_cache; return const_item_cache;
} }
void Item_subselect::update_used_tables() void Item_subselect::update_used_tables()
{ {
if (!engine->uncacheable()) if (!engine->uncacheable())
...@@ -171,6 +175,15 @@ void Item_subselect::update_used_tables() ...@@ -171,6 +175,15 @@ void Item_subselect::update_used_tables()
} }
} }
void Item_subselect::print(String *str)
{
str->append('(');
engine->print(str);
str->append(')');
}
Item_singlerow_subselect::Item_singlerow_subselect(st_select_lex *select_lex) Item_singlerow_subselect::Item_singlerow_subselect(st_select_lex *select_lex)
:Item_subselect(), value(0) :Item_subselect(), value(0)
{ {
...@@ -184,11 +197,12 @@ Item_singlerow_subselect::Item_singlerow_subselect(st_select_lex *select_lex) ...@@ -184,11 +197,12 @@ Item_singlerow_subselect::Item_singlerow_subselect(st_select_lex *select_lex)
Item_maxmin_subselect::Item_maxmin_subselect(Item_subselect *parent, Item_maxmin_subselect::Item_maxmin_subselect(Item_subselect *parent,
st_select_lex *select_lex, st_select_lex *select_lex,
bool max) bool max_arg)
:Item_singlerow_subselect() :Item_singlerow_subselect()
{ {
DBUG_ENTER("Item_maxmin_subselect::Item_maxmin_subselect"); DBUG_ENTER("Item_maxmin_subselect::Item_maxmin_subselect");
init(select_lex, new select_max_min_finder_subselect(this, max)); max= max_arg;
init(select_lex, new select_max_min_finder_subselect(this, max_arg));
max_columns= 1; max_columns= 1;
maybe_null= 1; maybe_null= 1;
max_columns= 1; max_columns= 1;
...@@ -203,6 +217,12 @@ Item_maxmin_subselect::Item_maxmin_subselect(Item_subselect *parent, ...@@ -203,6 +217,12 @@ Item_maxmin_subselect::Item_maxmin_subselect(Item_subselect *parent,
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
void Item_maxmin_subselect::print(String *str)
{
str->append(max?"<max>":"<min>");
Item_singlerow_subselect::print(str);
}
void Item_singlerow_subselect::reset() void Item_singlerow_subselect::reset()
{ {
null_value= 1; null_value= 1;
...@@ -245,7 +265,7 @@ Item_singlerow_subselect::select_transformer(JOIN *join) ...@@ -245,7 +265,7 @@ Item_singlerow_subselect::select_transformer(JOIN *join)
*/ */
substitution->walk(&Item::remove_dependence_processor, substitution->walk(&Item::remove_dependence_processor,
(byte *) select_lex->outer_select()); (byte *) select_lex->outer_select());
if (select_lex->where || select_lex->having) if (join->conds || join->having)
{ {
Item *cond; Item *cond;
if (!join->having) if (!join->having)
...@@ -365,6 +385,7 @@ String *Item_singlerow_subselect::val_str (String *str) ...@@ -365,6 +385,7 @@ String *Item_singlerow_subselect::val_str (String *str)
} }
} }
Item_exists_subselect::Item_exists_subselect(st_select_lex *select_lex): Item_exists_subselect::Item_exists_subselect(st_select_lex *select_lex):
Item_subselect() Item_subselect()
{ {
...@@ -379,6 +400,14 @@ Item_exists_subselect::Item_exists_subselect(st_select_lex *select_lex): ...@@ -379,6 +400,14 @@ Item_exists_subselect::Item_exists_subselect(st_select_lex *select_lex):
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
void Item_exists_subselect::print(String *str)
{
str->append("exists");
Item_subselect::print(str);
}
bool Item_in_subselect::test_limit(SELECT_LEX_UNIT *unit) bool Item_in_subselect::test_limit(SELECT_LEX_UNIT *unit)
{ {
if (unit->fake_select_lex && if (unit->fake_select_lex &&
...@@ -396,7 +425,7 @@ bool Item_in_subselect::test_limit(SELECT_LEX_UNIT *unit) ...@@ -396,7 +425,7 @@ bool Item_in_subselect::test_limit(SELECT_LEX_UNIT *unit)
Item_in_subselect::Item_in_subselect(Item * left_exp, Item_in_subselect::Item_in_subselect(Item * left_exp,
st_select_lex *select_lex): st_select_lex *select_lex):
Item_exists_subselect(), upper_not(0) Item_exists_subselect(), transformed(0), upper_not(0)
{ {
DBUG_ENTER("Item_in_subselect::Item_in_subselect"); DBUG_ENTER("Item_in_subselect::Item_in_subselect");
left_expr= left_exp; left_expr= left_exp;
...@@ -412,8 +441,9 @@ Item_in_subselect::Item_in_subselect(Item * left_exp, ...@@ -412,8 +441,9 @@ Item_in_subselect::Item_in_subselect(Item * left_exp,
Item_allany_subselect::Item_allany_subselect(Item * left_exp, Item_allany_subselect::Item_allany_subselect(Item * left_exp,
compare_func_creator fn, compare_func_creator fn,
st_select_lex *select_lex) st_select_lex *select_lex,
:Item_in_subselect() bool all_arg)
:Item_in_subselect(), all(all_arg)
{ {
DBUG_ENTER("Item_in_subselect::Item_in_subselect"); DBUG_ENTER("Item_in_subselect::Item_in_subselect");
left_expr= left_exp; left_expr= left_exp;
...@@ -800,6 +830,7 @@ Item_in_subselect::row_value_transformer(JOIN *join, ...@@ -800,6 +830,7 @@ Item_in_subselect::row_value_transformer(JOIN *join,
Item_subselect::trans_res Item_subselect::trans_res
Item_in_subselect::select_transformer(JOIN *join) Item_in_subselect::select_transformer(JOIN *join)
{ {
transformed= 1;
if (left_expr->cols() == 1) if (left_expr->cols() == 1)
return single_value_transformer(join, left_expr, return single_value_transformer(join, left_expr,
&Item_bool_func2::eq_creator); &Item_bool_func2::eq_creator);
...@@ -807,12 +838,82 @@ Item_in_subselect::select_transformer(JOIN *join) ...@@ -807,12 +838,82 @@ Item_in_subselect::select_transformer(JOIN *join)
} }
void Item_in_subselect::print(String *str)
{
if (transformed)
str->append("<exists>");
else
{
left_expr->print(str);
str->append(" in ");
}
Item_subselect::print(str);
}
Item_subselect::trans_res Item_subselect::trans_res
Item_allany_subselect::select_transformer(JOIN *join) Item_allany_subselect::select_transformer(JOIN *join)
{ {
transformed= 1;
if (upper_not)
upper_not->show= 1;
return single_value_transformer(join, left_expr, func); return single_value_transformer(join, left_expr, func);
} }
void Item_allany_subselect::print(String *str)
{
if (transformed)
str->append("<exists>");
else
{
left_expr->print(str);
str->append(' ');
if (all)
{
if (func == &Item_bool_func2::lt_creator)
str->append(">=");
else if (func == &Item_bool_func2::gt_creator)
str->append("<=");
else if (func == &Item_bool_func2::le_creator)
str->append('>');
else if (func == &Item_bool_func2::ge_creator)
str->append('<');
else if (func == &Item_bool_func2::eq_creator)
str->append("<>");
else if (func == &Item_bool_func2::ne_creator)
str->append('=');
else
{
DBUG_ASSERT(0); // Impossible
}
str->append(" all ");
}
else
{
if (func == &Item_bool_func2::lt_creator)
str->append('<');
else if (func == &Item_bool_func2::gt_creator)
str->append('>');
else if (func == &Item_bool_func2::le_creator)
str->append("<=");
else if (func == &Item_bool_func2::ge_creator)
str->append(">=");
else if (func == &Item_bool_func2::eq_creator)
str->append('=');
else if (func == &Item_bool_func2::ne_creator)
str->append("<>");
else
{
DBUG_ASSERT(0); // Impossible
}
str->append(" any ");
}
}
Item_subselect::print(str);
}
subselect_single_select_engine:: subselect_single_select_engine::
subselect_single_select_engine(st_select_lex *select, subselect_single_select_engine(st_select_lex *select,
select_subselect *result, select_subselect *result,
...@@ -1140,11 +1241,13 @@ uint subselect_single_select_engine::cols() ...@@ -1140,11 +1241,13 @@ uint subselect_single_select_engine::cols()
return select_lex->item_list.elements; return select_lex->item_list.elements;
} }
uint subselect_union_engine::cols() uint subselect_union_engine::cols()
{ {
return unit->first_select()->item_list.elements; return unit->first_select()->item_list.elements;
} }
bool subselect_single_select_engine::dependent() bool subselect_single_select_engine::dependent()
{ {
return select_lex->dependent; return select_lex->dependent;
...@@ -1155,16 +1258,19 @@ bool subselect_union_engine::dependent() ...@@ -1155,16 +1258,19 @@ bool subselect_union_engine::dependent()
return unit->dependent; return unit->dependent;
} }
bool subselect_single_select_engine::uncacheable() bool subselect_single_select_engine::uncacheable()
{ {
return select_lex->uncacheable; return select_lex->uncacheable;
} }
bool subselect_union_engine::uncacheable() bool subselect_union_engine::uncacheable()
{ {
return unit->uncacheable; return unit->uncacheable;
} }
void subselect_single_select_engine::exclude() void subselect_single_select_engine::exclude()
{ {
select_lex->master_unit()->exclude_level(); select_lex->master_unit()->exclude_level();
...@@ -1175,6 +1281,7 @@ void subselect_union_engine::exclude() ...@@ -1175,6 +1281,7 @@ void subselect_union_engine::exclude()
unit->exclude_level(); unit->exclude_level();
} }
void subselect_uniquesubquery_engine::exclude() void subselect_uniquesubquery_engine::exclude()
{ {
//this never should be called //this never should be called
...@@ -1201,8 +1308,59 @@ table_map subselect_single_select_engine::upper_select_const_tables() ...@@ -1201,8 +1308,59 @@ table_map subselect_single_select_engine::upper_select_const_tables()
table_list.first); table_list.first);
} }
table_map subselect_union_engine::upper_select_const_tables() table_map subselect_union_engine::upper_select_const_tables()
{ {
return calc_const_tables((TABLE_LIST *) unit->outer_select()-> return calc_const_tables((TABLE_LIST *) unit->outer_select()->
table_list.first); table_list.first);
} }
void subselect_single_select_engine::print(String *str)
{
select_lex->print(thd, str);
}
void subselect_union_engine::print(String *str)
{
unit->print(str);
}
void subselect_uniquesubquery_engine::print(String *str)
{
str->append("<primary_index_lookup>(");
tab->ref.items[0]->print(str);
str->append(" in ");
str->append(tab->table->real_name);
KEY *key_info= tab->table->key_info+ tab->ref.key;
str->append(" on ");
str->append(key_info->name);
if (cond)
{
str->append(" where ");
cond->print(str);
}
str->append(')');
}
void subselect_indexsubquery_engine::print(String *str)
{
str->append("<index_lookup>(");
tab->ref.items[0]->print(str);
str->append(" in ");
str->append(tab->table->real_name);
KEY *key_info= tab->table->key_info+ tab->ref.key;
str->append(" on ");
str->append(key_info->name);
if (check_null)
str->append(" chicking NULL");
if (cond)
{
str->append(" where ");
cond->print(str);
}
str->append(')');
}
...@@ -92,13 +92,7 @@ class Item_subselect :public Item_result_field ...@@ -92,13 +92,7 @@ class Item_subselect :public Item_result_field
inline table_map get_used_tables_cache() { return used_tables_cache; } inline table_map get_used_tables_cache() { return used_tables_cache; }
inline bool get_const_item_cache() { return const_item_cache; } inline bool get_const_item_cache() { return const_item_cache; }
void update_used_tables(); void update_used_tables();
void print(String *str) void print(String *str);
{
if (name)
str->append(name);
else
str->append("-subselect-");
}
bool change_engine(subselect_engine *eng) bool change_engine(subselect_engine *eng)
{ {
engine= eng; engine= eng;
...@@ -147,9 +141,11 @@ class Item_singlerow_subselect :public Item_subselect ...@@ -147,9 +141,11 @@ class Item_singlerow_subselect :public Item_subselect
/* used in static ALL/ANY optimisation */ /* used in static ALL/ANY optimisation */
class Item_maxmin_subselect :public Item_singlerow_subselect class Item_maxmin_subselect :public Item_singlerow_subselect
{ {
bool max;
public: public:
Item_maxmin_subselect(Item_subselect *parent, Item_maxmin_subselect(Item_subselect *parent,
st_select_lex *select_lex, bool max); st_select_lex *select_lex, bool max);
void print(String *str);
}; };
/* exists subselect */ /* exists subselect */
...@@ -174,6 +170,7 @@ class Item_exists_subselect :public Item_subselect ...@@ -174,6 +170,7 @@ class Item_exists_subselect :public Item_subselect
double val(); double val();
String *val_str(String*); String *val_str(String*);
void fix_length_and_dec(); void fix_length_and_dec();
void print(String *str);
friend class select_exists_subselect; friend class select_exists_subselect;
friend class subselect_uniquesubquery_engine; friend class subselect_uniquesubquery_engine;
...@@ -194,12 +191,15 @@ class Item_in_subselect :public Item_exists_subselect ...@@ -194,12 +191,15 @@ class Item_in_subselect :public Item_exists_subselect
Item_in_optimizer *optimizer; Item_in_optimizer *optimizer;
bool was_null; bool was_null;
bool abort_on_null; bool abort_on_null;
bool transformed;
public: public:
Item_func_not_all *upper_not; // point on NOT before ALL subquery Item_func_not_all *upper_not; // point on NOT before ALL subquery
Item_in_subselect(Item * left_expr, st_select_lex *select_lex); Item_in_subselect(Item * left_expr, st_select_lex *select_lex);
Item_in_subselect() Item_in_subselect()
:Item_exists_subselect(), abort_on_null(0), upper_not(0) {} :Item_exists_subselect(), abort_on_null(0), transformed(0), upper_not(0)
{}
subs_type substype() { return IN_SUBS; } subs_type substype() { return IN_SUBS; }
void reset() void reset()
...@@ -219,6 +219,7 @@ class Item_in_subselect :public Item_exists_subselect ...@@ -219,6 +219,7 @@ class Item_in_subselect :public Item_exists_subselect
String *val_str(String*); String *val_str(String*);
void top_level_item() { abort_on_null=1; } void top_level_item() { abort_on_null=1; }
bool test_limit(st_select_lex_unit *unit); bool test_limit(st_select_lex_unit *unit);
void print(String *str);
friend class Item_ref_null_helper; friend class Item_ref_null_helper;
friend class Item_is_not_null_test; friend class Item_is_not_null_test;
...@@ -233,12 +234,15 @@ class Item_allany_subselect :public Item_in_subselect ...@@ -233,12 +234,15 @@ class Item_allany_subselect :public Item_in_subselect
compare_func_creator func; compare_func_creator func;
public: public:
bool all;
Item_allany_subselect(Item * left_expr, compare_func_creator f, Item_allany_subselect(Item * left_expr, compare_func_creator f,
st_select_lex *select_lex); st_select_lex *select_lex, bool all);
// only ALL subquery has upper not // only ALL subquery has upper not
subs_type substype() { return upper_not?ALL_SUBS:ANY_SUBS; } subs_type substype() { return upper_not?ALL_SUBS:ANY_SUBS; }
trans_res select_transformer(JOIN *join); trans_res select_transformer(JOIN *join);
void print(String *str);
}; };
...@@ -276,6 +280,7 @@ class subselect_engine: public Sql_alloc ...@@ -276,6 +280,7 @@ class subselect_engine: public Sql_alloc
bool may_be_null() { return maybe_null; }; bool may_be_null() { return maybe_null; };
virtual table_map upper_select_const_tables()= 0; virtual table_map upper_select_const_tables()= 0;
static table_map calc_const_tables(TABLE_LIST *); static table_map calc_const_tables(TABLE_LIST *);
virtual void print(String *str)= 0;
}; };
...@@ -298,6 +303,7 @@ class subselect_single_select_engine: public subselect_engine ...@@ -298,6 +303,7 @@ class subselect_single_select_engine: public subselect_engine
bool uncacheable(); bool uncacheable();
void exclude(); void exclude();
table_map upper_select_const_tables(); table_map upper_select_const_tables();
void print (String *str);
}; };
...@@ -316,6 +322,7 @@ class subselect_union_engine: public subselect_engine ...@@ -316,6 +322,7 @@ class subselect_union_engine: public subselect_engine
bool uncacheable(); bool uncacheable();
void exclude(); void exclude();
table_map upper_select_const_tables(); table_map upper_select_const_tables();
void print (String *str);
}; };
...@@ -343,6 +350,7 @@ class subselect_uniquesubquery_engine: public subselect_engine ...@@ -343,6 +350,7 @@ class subselect_uniquesubquery_engine: public subselect_engine
bool uncacheable() { return 1; } bool uncacheable() { return 1; }
void exclude(); void exclude();
table_map upper_select_const_tables() { return 0; } table_map upper_select_const_tables() { return 0; }
void print (String *str);
}; };
...@@ -359,4 +367,5 @@ class subselect_indexsubquery_engine: public subselect_uniquesubquery_engine ...@@ -359,4 +367,5 @@ class subselect_indexsubquery_engine: public subselect_uniquesubquery_engine
check_null(chk_null) check_null(chk_null)
{} {}
int exec(); int exec();
void print (String *str);
}; };
...@@ -1366,6 +1366,14 @@ longlong Item_sum_count_distinct::val_int() ...@@ -1366,6 +1366,14 @@ longlong Item_sum_count_distinct::val_int()
return table->file->records; return table->file->records;
} }
void Item_sum_count_distinct::print(String *str)
{
str->append("count(distinct ");
args[0]->print(str);
str->append(')');
}
/**************************************************************************** /****************************************************************************
** Functions to handle dynamic loadable aggregates ** Functions to handle dynamic loadable aggregates
** Original source by: Alexis Mikhailov <root@medinf.chuvashia.su> ** Original source by: Alexis Mikhailov <root@medinf.chuvashia.su>
...@@ -1960,3 +1968,28 @@ String* Item_func_group_concat::val_str(String* str) ...@@ -1960,3 +1968,28 @@ String* Item_func_group_concat::val_str(String* str)
} }
return &result; return &result;
} }
void Item_func_group_concat::print(String *str)
{
str->append("group concat(");
if (distinct)
str->append(" distinct ");
for (uint i= 0; i < arg_count; i++)
{
if (i)
str->append(',');
args[i]->print(str);
}
if (arg_count_order)
{
for (uint i= 0 ; i < arg_count_order ; i++)
{
if (i)
str->append(',');
(*order[i]->item)->print(str);
}
}
str->append(" seperator \'");
str->append(*separator);
str->append("\')");
}
...@@ -238,6 +238,7 @@ class Item_sum_count_distinct :public Item_sum_int ...@@ -238,6 +238,7 @@ class Item_sum_count_distinct :public Item_sum_int
void make_unique(); void make_unique();
Item *copy_or_same(THD* thd); Item *copy_or_same(THD* thd);
void no_rows_in_result() {} void no_rows_in_result() {}
void print(String *str);
}; };
...@@ -748,4 +749,5 @@ class Item_func_group_concat : public Item_sum ...@@ -748,4 +749,5 @@ class Item_func_group_concat : public Item_sum
String* val_str(String* str); String* val_str(String* str);
Item *copy_or_same(THD* thd); Item *copy_or_same(THD* thd);
void no_rows_in_result() {} void no_rows_in_result() {}
void print(String *str);
}; };
...@@ -1644,6 +1644,35 @@ longlong Item_date_add_interval::val_int() ...@@ -1644,6 +1644,35 @@ longlong Item_date_add_interval::val_int()
((date*100L + ltime.hour)*100L+ ltime.minute)*100L + ltime.second; ((date*100L + ltime.hour)*100L+ ltime.minute)*100L + ltime.second;
} }
static const char *interval_names[]=
{
"year", "month", "day", "hour", "minute",
"second", "microsecond", "year_month",
"day_hour", "day_minute", "day_second",
"hour_minute", "hour_second", "minute_second",
"day_microsecond", "hour_microsecond",
"minute_microsecond", "second_microsecond"
};
void Item_date_add_interval::print(String *str)
{
str->append('(');
args[0]->print(str);
str->append(date_sub_interval?" - interval ":" + interval ");
args[1]->print(str);
str->append(interval_names[int_type]);
str->append(')');
}
void Item_extract::print(String *str)
{
str->append("extract(");
str->append(interval_names[int_type]);
str->append(' ');
args[0]->print(str);
str->append(')');
}
void Item_extract::fix_length_and_dec() void Item_extract::fix_length_and_dec()
{ {
value.alloc(32); // alloc buffer value.alloc(32); // alloc buffer
...@@ -1751,10 +1780,31 @@ bool Item_extract::eq(const Item *item, bool binary_cmp) const ...@@ -1751,10 +1780,31 @@ bool Item_extract::eq(const Item *item, bool binary_cmp) const
void Item_typecast::print(String *str) void Item_typecast::print(String *str)
{ {
str->append("CAST("); str->append("cast(");
args[0]->print(str); args[0]->print(str);
str->append(" AS "); str->append(" as ");
str->append(func_name()); str->append(cast_type());
str->append(')');
}
void Item_char_typecast::print(String *str)
{
str->append("cast(");
args[0]->print(str);
str->append(" as char");
if (cast_length >= 0)
{
str->append('(');
char buff[10];
snprintf(buff, 10, "%d", cast_length);
str->append(buff);
str->append(')');
}
if (cast_cs)
{
str->append(" charset ");
str->append(cast_cs->name);
}
str->append(')'); str->append(')');
} }
...@@ -2039,6 +2089,28 @@ String *Item_func_add_time::val_str(String *str) ...@@ -2039,6 +2089,28 @@ String *Item_func_add_time::val_str(String *str)
return 0; return 0;
} }
void Item_func_add_time::print(String *str)
{
if (is_date)
{
DBUG_ASSERT(sign > 0);
str->append("timestamp(");
}
else
{
if (sign > 0)
str->append("addtime(");
else
str->append("subtime(");
}
args[0]->print(str);
str->append(',');
args[0]->print(str);
str->append(')');
}
/* /*
TIMEDIFF(t,s) is a time function that calculates the TIMEDIFF(t,s) is a time function that calculates the
time value between a start and end time. time value between a start and end time.
......
...@@ -544,13 +544,13 @@ class Item_func_sec_to_time :public Item_str_func ...@@ -544,13 +544,13 @@ class Item_func_sec_to_time :public Item_str_func
enum interval_type enum interval_type
{ {
INTERVAL_YEAR, INTERVAL_MONTH, INTERVAL_DAY, INTERVAL_HOUR, INTERVAL_MINUTE, INTERVAL_YEAR, INTERVAL_MONTH, INTERVAL_DAY, INTERVAL_HOUR, INTERVAL_MINUTE,
INTERVAL_SECOND, INTERVAL_MICROSECOND ,INTERVAL_YEAR_MONTH, INTERVAL_DAY_HOUR, INTERVAL_SECOND, INTERVAL_MICROSECOND ,INTERVAL_YEAR_MONTH,
INTERVAL_DAY_MINUTE, INTERVAL_DAY_SECOND, INTERVAL_HOUR_MINUTE, INTERVAL_DAY_HOUR, INTERVAL_DAY_MINUTE, INTERVAL_DAY_SECOND,
INTERVAL_HOUR_SECOND, INTERVAL_MINUTE_SECOND, INTERVAL_DAY_MICROSECOND, INTERVAL_HOUR_MINUTE, INTERVAL_HOUR_SECOND, INTERVAL_MINUTE_SECOND,
INTERVAL_HOUR_MICROSECOND, INTERVAL_MINUTE_MICROSECOND, INTERVAL_SECOND_MICROSECOND INTERVAL_DAY_MICROSECOND, INTERVAL_HOUR_MICROSECOND,
INTERVAL_MINUTE_MICROSECOND, INTERVAL_SECOND_MICROSECOND
}; };
class Item_date_add_interval :public Item_date_func class Item_date_add_interval :public Item_date_func
{ {
const interval_type int_type; const interval_type int_type;
...@@ -568,6 +568,7 @@ class Item_date_add_interval :public Item_date_func ...@@ -568,6 +568,7 @@ class Item_date_add_interval :public Item_date_func
double val() { return (double) val_int(); } double val() { return (double) val_int(); }
longlong val_int(); longlong val_int();
bool get_date(TIME *res,bool fuzzy_date); bool get_date(TIME *res,bool fuzzy_date);
void print(String *str);
}; };
...@@ -583,6 +584,7 @@ class Item_extract :public Item_int_func ...@@ -583,6 +584,7 @@ class Item_extract :public Item_int_func
const char *func_name() const { return "extract"; } const char *func_name() const { return "extract"; }
void fix_length_and_dec(); void fix_length_and_dec();
bool eq(const Item *item, bool binary_cmp) const; bool eq(const Item *item, bool binary_cmp) const;
void print(String *str);
}; };
...@@ -590,7 +592,6 @@ class Item_typecast :public Item_str_func ...@@ -590,7 +592,6 @@ class Item_typecast :public Item_str_func
{ {
public: public:
Item_typecast(Item *a) :Item_str_func(a) {} Item_typecast(Item *a) :Item_str_func(a) {}
const char *func_name() const { return "char"; }
String *val_str(String *a) String *val_str(String *a)
{ {
String *tmp=args[0]->val_str(a); String *tmp=args[0]->val_str(a);
...@@ -604,6 +605,7 @@ class Item_typecast :public Item_str_func ...@@ -604,6 +605,7 @@ class Item_typecast :public Item_str_func
collation.set(default_charset()); collation.set(default_charset());
max_length=args[0]->max_length; max_length=args[0]->max_length;
} }
virtual const char* cast_type() const= 0;
void print(String *str); void print(String *str);
}; };
...@@ -617,8 +619,10 @@ class Item_char_typecast :public Item_typecast ...@@ -617,8 +619,10 @@ class Item_char_typecast :public Item_typecast
public: public:
Item_char_typecast(Item *a, int length_arg, CHARSET_INFO *cs_arg) Item_char_typecast(Item *a, int length_arg, CHARSET_INFO *cs_arg)
:Item_typecast(a), cast_length(length_arg), cast_cs(cs_arg) {} :Item_typecast(a), cast_length(length_arg), cast_cs(cs_arg) {}
const char* cast_type() const { return "char"; };
String *val_str(String *a); String *val_str(String *a);
void fix_length_and_dec(); void fix_length_and_dec();
void print(String *str);
}; };
...@@ -628,7 +632,7 @@ class Item_date_typecast :public Item_typecast ...@@ -628,7 +632,7 @@ class Item_date_typecast :public Item_typecast
Item_date_typecast(Item *a) :Item_typecast(a) {} Item_date_typecast(Item *a) :Item_typecast(a) {}
String *val_str(String *str); String *val_str(String *str);
bool get_date(TIME *ltime, bool fuzzy_date); bool get_date(TIME *ltime, bool fuzzy_date);
const char *func_name() const { return "date"; } const char *cast_type() 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(TABLE *t_arg) Field *tmp_table_field(TABLE *t_arg)
{ {
...@@ -643,7 +647,7 @@ class Item_time_typecast :public Item_typecast ...@@ -643,7 +647,7 @@ class Item_time_typecast :public Item_typecast
Item_time_typecast(Item *a) :Item_typecast(a) {} Item_time_typecast(Item *a) :Item_typecast(a) {}
String *val_str(String *str); String *val_str(String *str);
bool get_time(TIME *ltime); bool get_time(TIME *ltime);
const char *func_name() const { return "time"; } const char *cast_type() 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(TABLE *t_arg) Field *tmp_table_field(TABLE *t_arg)
{ {
...@@ -657,7 +661,7 @@ class Item_datetime_typecast :public Item_typecast ...@@ -657,7 +661,7 @@ class Item_datetime_typecast :public Item_typecast
public: public:
Item_datetime_typecast(Item *a) :Item_typecast(a) {} Item_datetime_typecast(Item *a) :Item_typecast(a) {}
String *val_str(String *str); String *val_str(String *str);
const char *func_name() const { return "datetime"; } const char *cast_type() 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(TABLE *t_arg) Field *tmp_table_field(TABLE *t_arg)
{ {
...@@ -694,7 +698,6 @@ class Item_func_add_time :public Item_str_func ...@@ -694,7 +698,6 @@ class Item_func_add_time :public Item_str_func
Item_func_add_time(Item *a, Item *b, bool type_arg, bool neg_arg) Item_func_add_time(Item *a, Item *b, bool type_arg, bool neg_arg)
:Item_str_func(a, b), is_date(type_arg) { sign= neg_arg ? -1 : 1; } :Item_str_func(a, b), is_date(type_arg) { sign= neg_arg ? -1 : 1; }
String *val_str(String *str); String *val_str(String *str);
const char *func_name() const { return "addtime"; }
enum_field_types field_type() const { return cached_field_type; } enum_field_types field_type() const { return cached_field_type; }
void fix_length_and_dec(); void fix_length_and_dec();
...@@ -711,6 +714,7 @@ class Item_func_add_time :public Item_str_func ...@@ -711,6 +714,7 @@ class Item_func_add_time :public Item_str_func
return (new Field_datetime(maybe_null, name, t_arg, &my_charset_bin)); return (new Field_datetime(maybe_null, name, t_arg, &my_charset_bin));
return (new Field_string(max_length, maybe_null, name, t_arg, &my_charset_bin)); return (new Field_string(max_length, maybe_null, name, t_arg, &my_charset_bin));
} }
void print(String *str);
}; };
class Item_func_timediff :public Item_str_func class Item_func_timediff :public Item_str_func
......
...@@ -29,6 +29,7 @@ class Item_func_unique_users :public Item_real_func ...@@ -29,6 +29,7 @@ class Item_func_unique_users :public Item_real_func
:Item_real_func(list) {} :Item_real_func(list) {}
double val() { return 0.0; } double val() { return 0.0; }
void fix_length_and_dec() { decimals=0; max_length=6; } void fix_length_and_dec() { decimals=0; max_length=6; }
void print(String *str) { str->append("0.0"); }
}; };
...@@ -54,4 +55,5 @@ class Item_sum_unique_users :public Item_sum_num ...@@ -54,4 +55,5 @@ class Item_sum_unique_users :public Item_sum_num
{ {
return new Item_sum_unique_users(thd, *this); return new Item_sum_unique_users(thd, *this);
} }
void print(String *str) { str->append("0.0"); }
}; };
...@@ -199,6 +199,9 @@ extern CHARSET_INFO *national_charset_info, *table_alias_charset; ...@@ -199,6 +199,9 @@ extern CHARSET_INFO *national_charset_info, *table_alias_charset;
#define OPTION_QUOTE_SHOW_CREATE OPTION_QUICK*2 #define OPTION_QUOTE_SHOW_CREATE OPTION_QUICK*2
#define OPTION_INTERNAL_SUBTRANSACTIONS OPTION_QUOTE_SHOW_CREATE*2 #define OPTION_INTERNAL_SUBTRANSACTIONS OPTION_QUOTE_SHOW_CREATE*2
/* options for UNION set by the yacc parser (stored in unit->union_option) */
#define UNION_ALL 1
/* Set if we are updating a non-transaction safe table */ /* Set if we are updating a non-transaction safe table */
#define OPTION_STATUS_NO_TRANS_UPDATE OPTION_INTERNAL_SUBTRANSACTIONS*2 #define OPTION_STATUS_NO_TRANS_UPDATE OPTION_INTERNAL_SUBTRANSACTIONS*2
......
...@@ -222,10 +222,6 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, ...@@ -222,10 +222,6 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit,
else else
unit->exclude_tree(); unit->exclude_tree();
org_table_list->db= (char *)""; org_table_list->db= (char *)"";
#ifndef DBUG_OFF
/* Try to catch errors if this is accessed */
org_table_list->derived=(SELECT_LEX_UNIT *) 1;
#endif
// Force read of table stats in the optimizer // Force read of table stats in the optimizer
table->file->info(HA_STATUS_VARIABLE); table->file->info(HA_STATUS_VARIABLE);
} }
......
...@@ -1471,7 +1471,73 @@ bool st_select_lex::setup_ref_array(THD *thd, uint order_group_num) ...@@ -1471,7 +1471,73 @@ bool st_select_lex::setup_ref_array(THD *thd, uint order_group_num)
order_group_num)* 5)) == 0; order_group_num)* 5)) == 0;
} }
void st_select_lex_unit::print(String *str)
{
for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select())
{
if (sl != first_select())
{
str->append(" union ");
if (union_option & UNION_ALL)
str->append("all ");
}
if (sl->braces)
str->append('(');
sl->print(thd, str);
if (sl->braces)
str->append(')');
}
if (fake_select_lex == global_parameters)
{
if (fake_select_lex->order_list.elements)
{
str->append(" order by ");
fake_select_lex->print_order(str,
(ORDER *) fake_select_lex->
order_list.first);
}
fake_select_lex->print_limit(thd, str);
}
}
void st_select_lex::print_order(String *str, ORDER *order)
{
for (; order; order= order->next)
{
(*order->item)->print(str);
if (!order->asc)
str->append(" desc");
if (order->next)
str->append(',');
}
}
void st_select_lex::print_limit(THD *thd, String *str)
{
if (!thd)
thd= current_thd;
if (select_limit != thd->variables.select_limit ||
select_limit != HA_POS_ERROR ||
offset_limit != 0L)
{
str->append(" limit ");
char buff[21];
snprintf(buff, 21, "%ld", select_limit);
str->append(buff);
if (offset_limit)
{
str->append(',');
snprintf(buff, 21, "%ld", offset_limit);
str->append(buff);
}
}
}
/* /*
There are st_select_lex::add_table_to_list & There are st_select_lex::add_table_to_list &
st_select_lex::set_lock_for_tables in sql_parse.cc st_select_lex::set_lock_for_tables in sql_parse.cc
st_select_lex::print is in sql_select.h
*/ */
...@@ -79,6 +79,10 @@ enum enum_sql_command { ...@@ -79,6 +79,10 @@ enum enum_sql_command {
SQLCOM_END SQLCOM_END
}; };
// describe/explain types
#define DESCRIBE_NORMAL 1
#define DESCRIBE_EXTENDED 2
typedef List<Item> List_item; typedef List<Item> List_item;
typedef struct st_lex_master_info typedef struct st_lex_master_info
...@@ -327,7 +331,9 @@ class st_select_lex_unit: public st_select_lex_node { ...@@ -327,7 +331,9 @@ class st_select_lex_unit: public st_select_lex_node {
int prepare(THD *thd, select_result *result, bool tables_and_fields_initied); int prepare(THD *thd, select_result *result, bool tables_and_fields_initied);
int exec(); int exec();
int cleanup(); int cleanup();
void print(String *str);
friend void mysql_init_query(THD *thd); friend void mysql_init_query(THD *thd);
friend int subselect_union_engine::exec(); friend int subselect_union_engine::exec();
private: private:
...@@ -468,6 +474,9 @@ class st_select_lex: public st_select_lex_node ...@@ -468,6 +474,9 @@ class st_select_lex: public st_select_lex_node
init_select(); init_select();
} }
bool setup_ref_array(THD *thd, uint order_group_num); bool setup_ref_array(THD *thd, uint order_group_num);
void print(THD *thd, String *str);
static void print_order(String *str, ORDER *order);
void print_limit(THD *thd, String *str);
}; };
typedef class st_select_lex SELECT_LEX; typedef class st_select_lex SELECT_LEX;
...@@ -542,9 +551,10 @@ typedef struct st_lex ...@@ -542,9 +551,10 @@ typedef struct st_lex
uint fk_delete_opt, fk_update_opt, fk_match_option; uint fk_delete_opt, fk_update_opt, fk_match_option;
uint param_count; uint param_count;
uint slave_thd_opt; uint slave_thd_opt;
uint8 describe;
bool drop_primary, drop_if_exists, drop_temporary, local_file; bool drop_primary, drop_if_exists, drop_temporary, local_file;
bool in_comment, ignore_space, verbose, simple_alter, no_write_to_binlog; bool in_comment, ignore_space, verbose, simple_alter, no_write_to_binlog;
bool derived_tables, describe; bool derived_tables;
bool safe_to_cache_query; bool safe_to_cache_query;
st_lex() {} st_lex() {}
inline void uncacheable() inline void uncacheable()
......
...@@ -1832,6 +1832,16 @@ mysql_execute_command(THD *thd) ...@@ -1832,6 +1832,16 @@ mysql_execute_command(THD *thd)
res= mysql_explain_union(thd, &thd->lex.unit, result); res= mysql_explain_union(thd, &thd->lex.unit, result);
MYSQL_LOCK *save_lock= thd->lock; MYSQL_LOCK *save_lock= thd->lock;
thd->lock= (MYSQL_LOCK *)0; thd->lock= (MYSQL_LOCK *)0;
if (lex->describe & DESCRIBE_EXTENDED)
{
char buff[1024];
String str(buff,(uint32) sizeof(buff), system_charset_info);
str.length(0);
thd->lex.unit.print(&str);
str.append('\0');
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
ER_YES, str.ptr());
}
result->send_eof(); result->send_eof();
thd->lock= save_lock; thd->lock= save_lock;
} }
......
...@@ -328,6 +328,20 @@ JOIN::prepare(Item ***rref_pointer_array, ...@@ -328,6 +328,20 @@ JOIN::prepare(Item ***rref_pointer_array,
having->split_sum_func(ref_pointer_array, all_fields); having->split_sum_func(ref_pointer_array, all_fields);
} }
#ifndef DEBUG_OFF
{
char buff[256];
String str(buff,(uint32) sizeof(buff), system_charset_info);
str.length(0);
if (select_lex->master_unit()->item)
select_lex->master_unit()->item->print(&str);
else
unit->print(&str);
str.append('\0');
DBUG_PRINT("info", ("(SUB)SELECT: %s", str.ptr()));
}
#endif
// Is it subselect // Is it subselect
{ {
Item_subselect *subselect; Item_subselect *subselect;
...@@ -880,12 +894,12 @@ JOIN::optimize() ...@@ -880,12 +894,12 @@ JOIN::optimize()
need_tmp=1; simple_order=simple_group=0; // Force tmp table without sort need_tmp=1; simple_order=simple_group=0; // Force tmp table without sort
} }
tmp_having= having;
if (select_options & SELECT_DESCRIBE) if (select_options & SELECT_DESCRIBE)
{ {
error= 0; error= 0;
DBUG_RETURN(0); DBUG_RETURN(0);
} }
tmp_having= having;
having= 0; having= 0;
/* Perform FULLTEXT search before all regular searches */ /* Perform FULLTEXT search before all regular searches */
...@@ -1547,11 +1561,23 @@ mysql_select(THD *thd, Item ***rref_pointer_array, ...@@ -1547,11 +1561,23 @@ mysql_select(THD *thd, Item ***rref_pointer_array,
goto err; // 1 goto err; // 1
} }
if (thd->lex.describe & DESCRIBE_EXTENDED)
{
join->conds_history= join->conds;
join->having_history= (join->having?join->having:join->tmp_having);
}
if (thd->net.report_error) if (thd->net.report_error)
goto err; goto err;
join->exec(); join->exec();
if (thd->lex.describe & DESCRIBE_EXTENDED)
{
select_lex->where= join->conds_history;
select_lex->having= join->having_history;
}
err: err:
if (free_join) if (free_join)
{ {
...@@ -8915,3 +8941,159 @@ int mysql_explain_select(THD *thd, SELECT_LEX *select_lex, char const *type, ...@@ -8915,3 +8941,159 @@ int mysql_explain_select(THD *thd, SELECT_LEX *select_lex, char const *type,
result, unit, select_lex, 0); result, unit, select_lex, 0);
DBUG_RETURN(res); DBUG_RETURN(res);
} }
void st_select_lex::print(THD *thd, String *str)
{
if (!thd)
thd= current_thd;
str->append("select ");
//options
if (options & SELECT_STRAIGHT_JOIN)
str->append("straight_join ");
if ((thd->lex.lock_option & TL_READ_HIGH_PRIORITY) &&
(this == &thd->lex.select_lex))
str->append("high_priority ");
if (options & SELECT_DISTINCT)
str->append("distinct ");
if (options & SELECT_SMALL_RESULT)
str->append("small_result ");
if (options & SELECT_BIG_RESULT)
str->append("big_result ");
if (options & OPTION_BUFFER_RESULT)
str->append("buffer_result ");
if (options & OPTION_FOUND_ROWS)
str->append("calc_found_rows ");
if (!thd->lex.safe_to_cache_query)
str->append("no_cache ");
if (options & OPTION_TO_QUERY_CACHE)
str->append("cache ");
//Item List
bool first= 1;
List_iterator_fast<Item> it(item_list);
Item *item;
while ((item= it++))
{
if (first)
first= 0;
else
str->append(',');
item->print_item_w_name(str);
}
/*
from clause
TODO: support USING/FORCE/IGNORE index
*/
if (table_list.elements)
{
str->append(" from ");
Item *next_on= 0;
for (TABLE_LIST *table= (TABLE_LIST *) table_list.first;
table;
table= table->next)
{
if (table->derived)
{
str->append('(');
table->derived->print(str);
str->append(") ");
str->append(table->alias);
}
else
{
str->append(table->db);
str->append('.');
str->append(table->real_name);
if (strcmp(table->real_name, table->alias))
{
str->append(' ');
str->append(table->alias);
}
}
if (table->on_expr && ((table->outer_join & JOIN_TYPE_LEFT) ||
!(table->outer_join & JOIN_TYPE_RIGHT)))
next_on= table->on_expr;
if (next_on)
{
str->append(" on(");
next_on->print(str);
str->append(')');
next_on= 0;
}
TABLE_LIST *next;
if ((next= table->next))
{
if (table->outer_join & JOIN_TYPE_RIGHT)
{
str->append(" right join ");
if (!(table->outer_join & JOIN_TYPE_LEFT) &&
table->on_expr)
next_on= table->on_expr;
}
else if (next->straight)
str->append(" straight_join ");
else if (next->outer_join & JOIN_TYPE_LEFT)
str->append(" left join ");
else
str->append(" join ");
}
}
}
//where
Item *where= this->where;
if (join)
where= join->conds;
if (where)
{
str->append(" where ");
where->print(str);
}
//group by & olap
if (group_list.elements)
{
str->append(" group by ");
print_order(str, (ORDER *) group_list.first);
switch (olap)
{
case CUBE_TYPE:
str->append(" with cube");
break;
case ROLLUP_TYPE:
str->append(" with rollup");
break;
default:
; //satisfy compiler
}
}
//having
Item *having= this->having;
if (join)
having= join->having;
if (having)
{
str->append(" having ");
having->print(str);
}
if (order_list.elements)
{
str->append(" order by ");
print_order(str, (ORDER *) order_list.first);
}
// limit
print_limit(thd, str);
// PROCEDURE unsupported here
}
...@@ -151,7 +151,8 @@ class JOIN :public Sql_alloc ...@@ -151,7 +151,8 @@ class JOIN :public Sql_alloc
Item_sum **sum_funcs2, ***sum_funcs_end2; Item_sum **sum_funcs2, ***sum_funcs_end2;
Procedure *procedure; Procedure *procedure;
Item *having; Item *having;
Item *tmp_having; // To store Having when processed temporary table Item *tmp_having; // To store having when processed temporary table
Item *having_history; // Store having for explain
uint select_options; uint select_options;
select_result *result; select_result *result;
TMP_TABLE_PARAM tmp_table_param; TMP_TABLE_PARAM tmp_table_param;
...@@ -181,6 +182,7 @@ class JOIN :public Sql_alloc ...@@ -181,6 +182,7 @@ class JOIN :public Sql_alloc
ORDER *order, *group_list, *proc_param; //hold parameters of mysql_select ORDER *order, *group_list, *proc_param; //hold parameters of mysql_select
COND *conds; // ---"--- COND *conds; // ---"---
Item *conds_history; // store WHERE for explain
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
Item **ref_pointer_array; //used pointer reference for this select Item **ref_pointer_array; //used pointer reference for this select
...@@ -217,8 +219,7 @@ class JOIN :public Sql_alloc ...@@ -217,8 +219,7 @@ class JOIN :public Sql_alloc
thd= thd_arg; thd= thd_arg;
sum_funcs= sum_funcs2= 0; sum_funcs= sum_funcs2= 0;
procedure= 0; procedure= 0;
having= 0; having= tmp_having= having_history= 0;
tmp_having= 0;
select_options= select_options_arg; select_options= select_options_arg;
result= result_arg; result= result_arg;
lock= thd_arg->lock; lock= thd_arg->lock;
......
...@@ -711,6 +711,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); ...@@ -711,6 +711,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
union_clause union_list union_option union_clause union_list union_option
precision subselect_start opt_and charset precision subselect_start opt_and charset
subselect_end select_var_list select_var_list_init help opt_len subselect_end select_var_list select_var_list_init help opt_len
opt_extended_describe
END_OF_INPUT END_OF_INPUT
%type <NONE> %type <NONE>
...@@ -2878,17 +2879,19 @@ opt_gconcat_separator: ...@@ -2878,17 +2879,19 @@ opt_gconcat_separator:
opt_gorder_clause: opt_gorder_clause:
/* empty */ /* empty */
{ {
LEX *lex=Lex; LEX *lex=Lex;
lex->gorder_list = NULL; lex->gorder_list = NULL;
} }
| order_clause | order_clause
{ {
LEX *lex=Lex; LEX *lex=Lex;
lex->gorder_list= (SQL_LIST*) sql_memdup((char*) &lex->current_select->order_list,sizeof(st_sql_list)); lex->gorder_list=
lex->current_select->order_list.empty(); (SQL_LIST*) sql_memdup((char*) &lex->current_select->order_list,
}; sizeof(st_sql_list));
lex->current_select->order_list.empty();
};
in_sum_expr: in_sum_expr:
...@@ -4027,7 +4030,9 @@ describe: ...@@ -4027,7 +4030,9 @@ describe:
YYABORT; YYABORT;
} }
opt_describe_column {} opt_describe_column {}
| describe_command { Lex->describe=1; } select | describe_command opt_extended_describe
{ Lex->describe|= DESCRIBE_NORMAL; }
select
{ {
LEX *lex=Lex; LEX *lex=Lex;
lex->select_lex.options|= SELECT_DESCRIBE; lex->select_lex.options|= SELECT_DESCRIBE;
...@@ -4038,6 +4043,11 @@ describe_command: ...@@ -4038,6 +4043,11 @@ describe_command:
DESC DESC
| DESCRIBE; | DESCRIBE;
opt_extended_describe:
/* empty */ {}
| EXTENDED_SYM { Lex->describe|= DESCRIBE_EXTENDED; }
;
opt_describe_column: opt_describe_column:
/* empty */ {} /* empty */ {}
| text_string { Lex->wild= $1; } | text_string { Lex->wild= $1; }
...@@ -4293,8 +4303,9 @@ literal: ...@@ -4293,8 +4303,9 @@ literal:
{ {
Item *tmp= new Item_varbinary($2.str,$2.length); Item *tmp= new Item_varbinary($2.str,$2.length);
String *str= tmp ? tmp->val_str((String*) 0) : (String*) 0; String *str= tmp ? tmp->val_str((String*) 0) : (String*) 0;
$$ = new Item_string(str ? str->ptr() : "", str ? str->length() : $$= new Item_string(str ? str->ptr() : "",
0, Lex->charset); str ? str->length() : 0,
Lex->charset);
} }
| DATE_SYM text_literal { $$ = $2; } | DATE_SYM text_literal { $$ = $2; }
| TIME_SYM text_literal { $$ = $2; } | TIME_SYM text_literal { $$ = $2; }
...@@ -5352,7 +5363,7 @@ order_or_limit: ...@@ -5352,7 +5363,7 @@ order_or_limit:
union_option: union_option:
/* empty */ {} /* empty */ {}
| ALL {Select->master_unit()->union_option= 1;}; | ALL {Select->master_unit()->union_option|= UNION_ALL;};
singlerow_subselect: singlerow_subselect:
subselect_start singlerow_subselect_init subselect_start singlerow_subselect_init
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment