Commit 10508712 authored by unknown's avatar unknown

Merge sanja.is.com.ua:/home/bell/mysql/bk/mysql-4.1

into sanja.is.com.ua:/home/bell/mysql/bk/work-union-4.1


sql/item.cc:
  Auto merged
sql/item.h:
  Auto merged
parents c1dd9540 3e21b667
...@@ -53,7 +53,7 @@ select 0,'#' union select a,b from t1 union all select a,b from t2 union select ...@@ -53,7 +53,7 @@ select 0,'#' union select a,b from t1 union all select a,b from t2 union select
4 d 4 d
5 f 5 f
6 e 6 e
7 g 7 gg
select a,b from t1 union select a,b from t1; select a,b from t1 union select a,b from t1;
a b a b
1 a 1 a
...@@ -449,10 +449,10 @@ INSERT INTO t2 (id, id_master, text1, text2) VALUES("4", "1", ...@@ -449,10 +449,10 @@ INSERT INTO t2 (id, id_master, text1, text2) VALUES("4", "1",
SELECT 1 AS id_master, 1 AS id, NULL AS text1, 'ABCDE' AS text2 UNION SELECT id_master, t2.id, text1, text2 FROM t1 LEFT JOIN t2 ON t1.id = t2.id_master; SELECT 1 AS id_master, 1 AS id, NULL AS text1, 'ABCDE' AS text2 UNION SELECT id_master, t2.id, text1, text2 FROM t1 LEFT JOIN t2 ON t1.id = t2.id_master;
id_master id text1 text2 id_master id text1 text2
1 1 NULL ABCDE 1 1 NULL ABCDE
1 1 bar1 1 1 foo1 bar1
1 2 bar2 1 2 foo2 bar2
1 3 NULL bar3 1 3 NULL bar3
1 4 bar4 1 4 foo4 bar4
SELECT 1 AS id_master, 1 AS id, 'ABCDE' AS text1, 'ABCDE' AS text2 UNION SELECT id_master, t2.id, text1, text2 FROM t1 LEFT JOIN t2 ON t1.id = t2.id_master; SELECT 1 AS id_master, 1 AS id, 'ABCDE' AS text1, 'ABCDE' AS text2 UNION SELECT id_master, t2.id, text1, text2 FROM t1 LEFT JOIN t2 ON t1.id = t2.id_master;
id_master id text1 text2 id_master id text1 text2
1 1 ABCDE ABCDE 1 1 ABCDE ABCDE
...@@ -523,3 +523,204 @@ pla_id matintnum ...@@ -523,3 +523,204 @@ pla_id matintnum
105 c 105 c
0 0 0 0
drop table t1, t2; drop table t1, t2;
create table t1 SELECT "a" as a UNION select "aa" as a;
select * from t1;
a
a
aa
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` char(2) NOT NULL default ''
) TYPE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 SELECT 12 as a UNION select "aa" as a;
select * from t1;
a
12
aa
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` char(2) NOT NULL default ''
) TYPE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 SELECT 12 as a UNION select 12.2 as a;
select * from t1;
a
12.0
12.2
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` double(4,1) NOT NULL default '0.0'
) TYPE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t2 (it1 tinyint, it2 tinyint not null, i int not null, f float, d double, y year, da date, dt datetime, sc char(10), sv varchar(10), b blob);
insert into t2 values (NULL, 1, 3, 1.5, 2.5, 1972, '1972-10-22', '1972-10-22 11:50', 'testc', 'testv', 'tetetetetest');
create table t1 SELECT it2 from t2 UNION select it1 from t2;
select * from t1;
it2
1
NULL
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`it2` tinyint(4) default NULL
) TYPE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 SELECT it2 from t2 UNION select i from t2;
select * from t1;
it2
1
3
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`it2` int(11) NOT NULL default '0'
) TYPE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 SELECT i from t2 UNION select f from t2;
select * from t1;
i
3
1.5
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`i` float default NULL
) TYPE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 SELECT f from t2 UNION select d from t2;
select * from t1;
f
1.5
2.5
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`f` double default NULL
) TYPE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 SELECT f from t2 UNION select y from t2;
select * from t1;
f
1.5
1972
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`f` double default NULL
) TYPE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 SELECT f from t2 UNION select da from t2;
select * from t1;
f
1.5
1972-10-22
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`f` char(12) binary default NULL
) TYPE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 SELECT y from t2 UNION select da from t2;
select * from t1;
y
1972
1972-10-22
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`y` char(10) binary default NULL
) TYPE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 SELECT y from t2 UNION select dt from t2;
select * from t1;
y
1972
1972-10-22 11:50:00
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`y` char(19) binary default NULL
) TYPE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 SELECT da from t2 UNION select dt from t2;
select * from t1;
da
1972-10-22 00:00:00
1972-10-22 11:50:00
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`da` datetime default NULL
) TYPE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 SELECT dt from t2 UNION select sc from t2;
select * from t1;
dt
1972-10-22 11:50:00
testc
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`dt` char(19) default NULL
) TYPE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 SELECT dt from t2 UNION select sv from t2;
select * from t1;
dt
1972-10-22 11:50:00
testv
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`dt` char(19) default NULL
) TYPE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 SELECT sc from t2 UNION select sv from t2;
select * from t1;
sc
testc
testv
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`sc` varchar(10) default NULL
) TYPE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 SELECT dt from t2 UNION select b from t2;
select * from t1;
dt
1972-10-22 11:50:00
tetetetetest
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`dt` blob
) TYPE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 SELECT sv from t2 UNION select b from t2;
select * from t1;
sv
testv
tetetetetest
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`sv` blob
) TYPE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 SELECT i from t2 UNION select d from t2 UNION select b from t2;
select * from t1;
i
3
2.5
tetetetetest
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`i` blob
) TYPE=MyISAM DEFAULT CHARSET=latin1
drop table t1,t2;
...@@ -302,3 +302,85 @@ insert into t1 values (NULL, 'a', 1), (NULL, 'b', 2), (NULL, 'c', 3), (NULL, 'd' ...@@ -302,3 +302,85 @@ insert into t1 values (NULL, 'a', 1), (NULL, 'b', 2), (NULL, 'c', 3), (NULL, 'd'
insert into t2 values (1, 100), (1, 101), (1, 102), (2, 100), (2, 103), (2, 104), (3, 101), (3, 102), (3, 105); insert into t2 values (1, 100), (1, 101), (1, 102), (2, 100), (2, 103), (2, 104), (3, 101), (3, 102), (3, 105);
SELECT mp.pla_id, MIN(m1.matintnum) AS matintnum FROM t2 mp INNER JOIN t1 m1 ON mp.mat_id=m1.mat_id GROUP BY mp.pla_id union SELECT 0, 0; SELECT mp.pla_id, MIN(m1.matintnum) AS matintnum FROM t2 mp INNER JOIN t1 m1 ON mp.mat_id=m1.mat_id GROUP BY mp.pla_id union SELECT 0, 0;
drop table t1, t2; drop table t1, t2;
#
# types conversions
#
create table t1 SELECT "a" as a UNION select "aa" as a;
select * from t1;
show create table t1;
drop table t1;
create table t1 SELECT 12 as a UNION select "aa" as a;
select * from t1;
show create table t1;
drop table t1;
create table t1 SELECT 12 as a UNION select 12.2 as a;
select * from t1;
show create table t1;
drop table t1;
create table t2 (it1 tinyint, it2 tinyint not null, i int not null, f float, d double, y year, da date, dt datetime, sc char(10), sv varchar(10), b blob);
insert into t2 values (NULL, 1, 3, 1.5, 2.5, 1972, '1972-10-22', '1972-10-22 11:50', 'testc', 'testv', 'tetetetetest');
create table t1 SELECT it2 from t2 UNION select it1 from t2;
select * from t1;
show create table t1;
drop table t1;
create table t1 SELECT it2 from t2 UNION select i from t2;
select * from t1;
show create table t1;
drop table t1;
create table t1 SELECT i from t2 UNION select f from t2;
select * from t1;
show create table t1;
drop table t1;
create table t1 SELECT f from t2 UNION select d from t2;
select * from t1;
show create table t1;
drop table t1;
create table t1 SELECT f from t2 UNION select y from t2;
select * from t1;
show create table t1;
drop table t1;
create table t1 SELECT f from t2 UNION select da from t2;
select * from t1;
show create table t1;
drop table t1;
create table t1 SELECT y from t2 UNION select da from t2;
select * from t1;
show create table t1;
drop table t1;
create table t1 SELECT y from t2 UNION select dt from t2;
select * from t1;
show create table t1;
drop table t1;
create table t1 SELECT da from t2 UNION select dt from t2;
select * from t1;
show create table t1;
drop table t1;
create table t1 SELECT dt from t2 UNION select sc from t2;
select * from t1;
show create table t1;
drop table t1;
create table t1 SELECT dt from t2 UNION select sv from t2;
select * from t1;
show create table t1;
drop table t1;
create table t1 SELECT sc from t2 UNION select sv from t2;
select * from t1;
show create table t1;
drop table t1;
create table t1 SELECT dt from t2 UNION select b from t2;
select * from t1;
show create table t1;
drop table t1;
create table t1 SELECT sv from t2 UNION select b from t2;
select * from t1;
show create table t1;
drop table t1;
create table t1 SELECT i from t2 UNION select d from t2 UNION select b from t2;
select * from t1;
show create table t1;
drop table t1,t2;
...@@ -230,6 +230,24 @@ class Field ...@@ -230,6 +230,24 @@ class Field
virtual bool has_charset(void) const { return FALSE; } virtual bool has_charset(void) const { return FALSE; }
virtual void set_charset(CHARSET_INFO *charset) { } virtual void set_charset(CHARSET_INFO *charset) { }
void set_warning(const unsigned int level, const unsigned int code); void set_warning(const unsigned int level, const unsigned int code);
/*
number which describe preferences of field type converion,
for example, if we have int and float, float is prefered as more general
ennumiration begins from:
100 for int types
300 for float point
500 time/date
700 string
*/
virtual uint convert_order()= 0;
/*
Is this type is compatible with given
(given can be stored in it)
Should take care only of types 'less' then current
*/
virtual bool convert_order_compatible(uint order) { return 0; }
friend bool reopen_table(THD *,struct st_table *,bool); friend bool reopen_table(THD *,struct st_table *,bool);
friend int cre_myisam(my_string name, register TABLE *form, uint options, friend int cre_myisam(my_string name, register TABLE *form, uint options,
ulonglong auto_increment_value); ulonglong auto_increment_value);
...@@ -334,6 +352,7 @@ class Field_decimal :public Field_num { ...@@ -334,6 +352,7 @@ class Field_decimal :public Field_num {
void overflow(bool negative); void overflow(bool negative);
bool zero_pack() const { return 0; } bool zero_pack() const { return 0; }
void sql_type(String &str) const; void sql_type(String &str) const;
uint convert_order() { return 130; }
}; };
...@@ -369,6 +388,7 @@ class Field_tiny :public Field_num { ...@@ -369,6 +388,7 @@ class Field_tiny :public Field_num {
void sort_string(char *buff,uint length); void sort_string(char *buff,uint length);
uint32 pack_length() const { return 1; } uint32 pack_length() const { return 1; }
void sql_type(String &str) const; void sql_type(String &str) const;
uint convert_order() { return 100; }
}; };
...@@ -404,6 +424,7 @@ class Field_short :public Field_num { ...@@ -404,6 +424,7 @@ class Field_short :public Field_num {
void sort_string(char *buff,uint length); void sort_string(char *buff,uint length);
uint32 pack_length() const { return 2; } uint32 pack_length() const { return 2; }
void sql_type(String &str) const; void sql_type(String &str) const;
uint convert_order() { return 101; }
}; };
...@@ -434,6 +455,7 @@ class Field_medium :public Field_num { ...@@ -434,6 +455,7 @@ class Field_medium :public Field_num {
void sort_string(char *buff,uint length); void sort_string(char *buff,uint length);
uint32 pack_length() const { return 3; } uint32 pack_length() const { return 3; }
void sql_type(String &str) const; void sql_type(String &str) const;
uint convert_order() { return 102; }
}; };
...@@ -469,6 +491,7 @@ class Field_long :public Field_num { ...@@ -469,6 +491,7 @@ class Field_long :public Field_num {
void sort_string(char *buff,uint length); void sort_string(char *buff,uint length);
uint32 pack_length() const { return 4; } uint32 pack_length() const { return 4; }
void sql_type(String &str) const; void sql_type(String &str) const;
uint convert_order() { return 103; }
}; };
...@@ -507,6 +530,7 @@ class Field_longlong :public Field_num { ...@@ -507,6 +530,7 @@ class Field_longlong :public Field_num {
uint32 pack_length() const { return 8; } uint32 pack_length() const { return 8; }
void sql_type(String &str) const; void sql_type(String &str) const;
bool store_for_compare() { return 1; } bool store_for_compare() { return 1; }
uint convert_order() { return 104; }
}; };
#endif #endif
...@@ -540,6 +564,7 @@ class Field_float :public Field_num { ...@@ -540,6 +564,7 @@ class Field_float :public Field_num {
void sort_string(char *buff,uint length); void sort_string(char *buff,uint length);
uint32 pack_length() const { return sizeof(float); } uint32 pack_length() const { return sizeof(float); }
void sql_type(String &str) const; void sql_type(String &str) const;
uint convert_order() { return 300; }
}; };
...@@ -573,6 +598,7 @@ class Field_double :public Field_num { ...@@ -573,6 +598,7 @@ class Field_double :public Field_num {
void sort_string(char *buff,uint length); void sort_string(char *buff,uint length);
uint32 pack_length() const { return sizeof(double); } uint32 pack_length() const { return sizeof(double); }
void sql_type(String &str) const; void sql_type(String &str) const;
uint convert_order() { return 301; }
}; };
...@@ -606,6 +632,7 @@ class Field_null :public Field_str { ...@@ -606,6 +632,7 @@ class Field_null :public Field_str {
uint32 pack_length() const { return 0; } uint32 pack_length() const { return 0; }
void sql_type(String &str) const; void sql_type(String &str) const;
uint size_of() const { return sizeof(*this); } uint size_of() const { return sizeof(*this); }
uint convert_order() { return 0; }
}; };
...@@ -649,6 +676,8 @@ class Field_timestamp :public Field_str { ...@@ -649,6 +676,8 @@ class Field_timestamp :public Field_str {
} }
bool get_date(TIME *ltime,uint fuzzydate); bool get_date(TIME *ltime,uint fuzzydate);
bool get_time(TIME *ltime); bool get_time(TIME *ltime);
uint convert_order() { return 520; }
bool convert_order_compatible(uint ord) { return ord<520; }
}; };
...@@ -674,6 +703,8 @@ class Field_year :public Field_tiny { ...@@ -674,6 +703,8 @@ class Field_year :public Field_tiny {
String *val_str(String*,String *); String *val_str(String*,String *);
bool send_binary(Protocol *protocol); bool send_binary(Protocol *protocol);
void sql_type(String &str) const; void sql_type(String &str) const;
uint convert_order() { return 501; }
bool convert_order_compatible(uint ord) { return ord<520; }
}; };
...@@ -706,6 +737,8 @@ class Field_date :public Field_str { ...@@ -706,6 +737,8 @@ class Field_date :public Field_str {
void sql_type(String &str) const; void sql_type(String &str) const;
bool store_for_compare() { return 1; } bool store_for_compare() { return 1; }
bool zero_pack() const { return 1; } bool zero_pack() const { return 1; }
uint convert_order() { return 502; }
bool convert_order_compatible(uint ord) { return ord<520; }
}; };
class Field_newdate :public Field_str { class Field_newdate :public Field_str {
...@@ -737,6 +770,8 @@ class Field_newdate :public Field_str { ...@@ -737,6 +770,8 @@ class Field_newdate :public Field_str {
bool zero_pack() const { return 1; } bool zero_pack() const { return 1; }
bool get_date(TIME *ltime,uint fuzzydate); bool get_date(TIME *ltime,uint fuzzydate);
bool get_time(TIME *ltime); bool get_time(TIME *ltime);
uint convert_order() { return 503; }
bool convert_order_compatible(uint ord) { return ord<520; }
}; };
...@@ -770,6 +805,8 @@ class Field_time :public Field_str { ...@@ -770,6 +805,8 @@ class Field_time :public Field_str {
void sql_type(String &str) const; void sql_type(String &str) const;
bool store_for_compare() { return 1; } bool store_for_compare() { return 1; }
bool zero_pack() const { return 1; } bool zero_pack() const { return 1; }
uint convert_order() { return 504; }
bool convert_order_compatible(uint ord) { return ord<520; }
}; };
...@@ -807,6 +844,8 @@ class Field_datetime :public Field_str { ...@@ -807,6 +844,8 @@ class Field_datetime :public Field_str {
bool zero_pack() const { return 1; } bool zero_pack() const { return 1; }
bool get_date(TIME *ltime,uint fuzzydate); bool get_date(TIME *ltime,uint fuzzydate);
bool get_time(TIME *ltime); bool get_time(TIME *ltime);
uint convert_order() { return 530; }
bool convert_order_compatible(uint ord) { return ord<=501; }
}; };
...@@ -851,6 +890,7 @@ class Field_string :public Field_str { ...@@ -851,6 +890,7 @@ class Field_string :public Field_str {
uint size_of() const { return sizeof(*this); } uint size_of() const { return sizeof(*this); }
enum_field_types real_type() const { return FIELD_TYPE_STRING; } enum_field_types real_type() const { return FIELD_TYPE_STRING; }
bool has_charset(void) const { return TRUE; } bool has_charset(void) const { return TRUE; }
uint convert_order() { return 700; }
}; };
...@@ -894,6 +934,7 @@ class Field_varstring :public Field_str { ...@@ -894,6 +934,7 @@ class Field_varstring :public Field_str {
uint size_of() const { return sizeof(*this); } uint size_of() const { return sizeof(*this); }
enum_field_types real_type() const { return FIELD_TYPE_VAR_STRING; } enum_field_types real_type() const { return FIELD_TYPE_VAR_STRING; }
bool has_charset(void) const { return TRUE; } bool has_charset(void) const { return TRUE; }
uint convert_order() { return 701; }
}; };
...@@ -983,6 +1024,7 @@ class Field_blob :public Field_str { ...@@ -983,6 +1024,7 @@ class Field_blob :public Field_str {
uint size_of() const { return sizeof(*this); } uint size_of() const { return sizeof(*this); }
bool has_charset(void) const bool has_charset(void) const
{ return charset() == &my_charset_bin ? FALSE : TRUE; } { return charset() == &my_charset_bin ? FALSE : TRUE; }
uint convert_order() { return 701; }
}; };
...@@ -1011,6 +1053,8 @@ class Field_geom :public Field_blob { ...@@ -1011,6 +1053,8 @@ class Field_geom :public Field_blob {
void get_key_image(char *buff,uint length, CHARSET_INFO *cs,imagetype type); void get_key_image(char *buff,uint length, CHARSET_INFO *cs,imagetype type);
void set_key_image(char *buff,uint length, CHARSET_INFO *cs); void set_key_image(char *buff,uint length, CHARSET_INFO *cs);
uint convert_order() { return 750; }
bool convert_order_compatible(uint ord) { return ord < 750; };
}; };
...@@ -1052,6 +1096,8 @@ class Field_enum :public Field_str { ...@@ -1052,6 +1096,8 @@ class Field_enum :public Field_str {
bool optimize_range(uint idx) { return 0; } bool optimize_range(uint idx) { return 0; }
bool eq_def(Field *field); bool eq_def(Field *field);
bool has_charset(void) const { return TRUE; } bool has_charset(void) const { return TRUE; }
uint convert_order() { return 30; }
bool convert_order_compatible(uint ord) { return ord < 30; };
}; };
...@@ -1077,6 +1123,8 @@ class Field_set :public Field_enum { ...@@ -1077,6 +1123,8 @@ class Field_set :public Field_enum {
void sql_type(String &str) const; void sql_type(String &str) const;
enum_field_types real_type() const { return FIELD_TYPE_SET; } enum_field_types real_type() const { return FIELD_TYPE_SET; }
bool has_charset(void) const { return TRUE; } bool has_charset(void) const { return TRUE; }
uint convert_order() { return 40; }
bool convert_order_compatible(uint ord) { return ord < 40; };
}; };
......
...@@ -312,7 +312,7 @@ void Item_field::set_field(Field *field_par) ...@@ -312,7 +312,7 @@ void Item_field::set_field(Field *field_par)
const char *Item_ident::full_name() const const char *Item_ident::full_name() const
{ {
char *tmp; char *tmp;
if (!table_name) if (!table_name || !field_name)
return field_name ? field_name : name ? name : "tmp_field"; return field_name ? field_name : name ? name : "tmp_field";
if (db_name && db_name[0]) if (db_name && db_name[0])
{ {
...@@ -1881,6 +1881,8 @@ void Item_cache_str::store(Item *item) ...@@ -1881,6 +1881,8 @@ void Item_cache_str::store(Item *item)
} }
collation.set(item->collation); collation.set(item->collation);
} }
double Item_cache_str::val() double Item_cache_str::val()
{ {
int err; int err;
...@@ -1890,6 +1892,8 @@ double Item_cache_str::val() ...@@ -1890,6 +1892,8 @@ double Item_cache_str::val()
else else
return (double)0; return (double)0;
} }
longlong Item_cache_str::val_int() longlong Item_cache_str::val_int()
{ {
int err; int err;
...@@ -1900,6 +1904,7 @@ longlong Item_cache_str::val_int() ...@@ -1900,6 +1904,7 @@ longlong Item_cache_str::val_int()
return (longlong)0; return (longlong)0;
} }
bool Item_cache_row::allocate(uint num) bool Item_cache_row::allocate(uint num)
{ {
item_count= num; item_count= num;
...@@ -1908,6 +1913,7 @@ bool Item_cache_row::allocate(uint num) ...@@ -1908,6 +1913,7 @@ bool Item_cache_row::allocate(uint num)
(Item_cache **) thd->calloc(sizeof(Item_cache *)*item_count))); (Item_cache **) thd->calloc(sizeof(Item_cache *)*item_count)));
} }
bool Item_cache_row::setup(Item * item) bool Item_cache_row::setup(Item * item)
{ {
example= item; example= item;
...@@ -1924,6 +1930,7 @@ bool Item_cache_row::setup(Item * item) ...@@ -1924,6 +1930,7 @@ bool Item_cache_row::setup(Item * item)
return 0; return 0;
} }
void Item_cache_row::store(Item * item) void Item_cache_row::store(Item * item)
{ {
null_value= 0; null_value= 0;
...@@ -1935,6 +1942,7 @@ void Item_cache_row::store(Item * item) ...@@ -1935,6 +1942,7 @@ void Item_cache_row::store(Item * item)
} }
} }
void Item_cache_row::illegal_method_call(const char *method) void Item_cache_row::illegal_method_call(const char *method)
{ {
DBUG_ENTER("Item_cache_row::illegal_method_call"); DBUG_ENTER("Item_cache_row::illegal_method_call");
...@@ -1944,6 +1952,7 @@ void Item_cache_row::illegal_method_call(const char *method) ...@@ -1944,6 +1952,7 @@ void Item_cache_row::illegal_method_call(const char *method)
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
bool Item_cache_row::check_cols(uint c) bool Item_cache_row::check_cols(uint c)
{ {
if (c != item_count) if (c != item_count)
...@@ -1954,6 +1963,7 @@ bool Item_cache_row::check_cols(uint c) ...@@ -1954,6 +1963,7 @@ bool Item_cache_row::check_cols(uint c)
return 0; return 0;
} }
bool Item_cache_row::null_inside() bool Item_cache_row::null_inside()
{ {
for (uint i= 0; i < item_count; i++) for (uint i= 0; i < item_count; i++)
...@@ -1973,6 +1983,7 @@ bool Item_cache_row::null_inside() ...@@ -1973,6 +1983,7 @@ bool Item_cache_row::null_inside()
return 0; return 0;
} }
void Item_cache_row::bring_value() void Item_cache_row::bring_value()
{ {
for (uint i= 0; i < item_count; i++) for (uint i= 0; i < item_count; i++)
...@@ -1980,6 +1991,114 @@ void Item_cache_row::bring_value() ...@@ -1980,6 +1991,114 @@ void Item_cache_row::bring_value()
return; return;
} }
Item_type_holder::Item_type_holder(THD *thd, Item *item)
:Item(thd, *item), item_type(item->result_type())
{
DBUG_ASSERT(item->fixed);
if (item->type() == Item::FIELD_ITEM)
{
Item_field *fitem= (Item_field*) item;
field_example= (Field*) thd->memdup((const char*)fitem->field,
fitem->field->size_of());
}
else
field_example= 0;
}
// STRING_RESULT, REAL_RESULT, INT_RESULT, ROW_RESULT
static Item_result type_convertor[4][4]=
{{STRING_RESULT, STRING_RESULT, STRING_RESULT, ROW_RESULT},
{STRING_RESULT, REAL_RESULT, REAL_RESULT, ROW_RESULT},
{STRING_RESULT, REAL_RESULT, INT_RESULT, ROW_RESULT},
{ROW_RESULT, ROW_RESULT, ROW_RESULT, ROW_RESULT}};
void Item_type_holder::join_types(THD *thd, Item *item)
{
bool change_field= 0, skip_store_field= 0;
Item_result new_type= type_convertor[item_type][item->result_type()];
// we have both fields
if (field_example && item->type() == Item::FIELD_ITEM)
{
Field *field= ((Item_field *)item)->field;
// is new field better
if ((change_field=
field_example->convert_order() < field->convert_order()))
{
// is it compatible?
if (field->convert_order_compatible(field_example->convert_order()))
skip_store_field= 1;
}
else
{
/*
if old field can't store value of 'worse' new field we will make
decision about result field tipe based only on Item result type
*/
if (field_example->convert_order_compatible(field->convert_order()))
skip_store_field= 1;
}
}
// size/type should be changed
if (change_field ||
(new_type != item_type) ||
(max_length < item->max_length) ||
((new_type == INT_RESULT) &&
(decimals < item->decimals)) ||
(!maybe_null && item->maybe_null))
{
// new field has some parameters worse then current
skip_store_field|= (change_field &&
(max_length > item->max_length) ||
((new_type == INT_RESULT) &&
(decimals > item->decimals)) ||
(maybe_null && !item->maybe_null));
if (skip_store_field || item->type() != Item::FIELD_ITEM)
field_example= 0;
else
{
/*
we do not need following, because we use mem_root
if (field_example)
thd->free(field_example)
*/
Item_field *fitem= (Item_field*) item;
field_example= (Field*) thd->memdup((const char*)fitem->field,
fitem->field->size_of());
}
max_length= max(max_length, item->max_length);
decimals= max(decimals, item->decimals);
maybe_null|= item->maybe_null;
item_type= new_type;
}
DBUG_ASSERT(item_type != ROW_RESULT);
}
double Item_type_holder::val()
{
DBUG_ASSERT(0); // should never be called
return 0.0;
}
longlong Item_type_holder::val_int()
{
DBUG_ASSERT(0); // should never be called
return 0;
}
String *Item_type_holder::val_str(String*)
{
DBUG_ASSERT(0); // should never be called
return 0;
}
/***************************************************************************** /*****************************************************************************
** Instantiate templates ** Instantiate templates
*****************************************************************************/ *****************************************************************************/
......
...@@ -98,7 +98,7 @@ class Item { ...@@ -98,7 +98,7 @@ class Item {
COPY_STR_ITEM, FIELD_AVG_ITEM, DEFAULT_VALUE_ITEM, COPY_STR_ITEM, FIELD_AVG_ITEM, DEFAULT_VALUE_ITEM,
PROC_ITEM,COND_ITEM, REF_ITEM, FIELD_STD_ITEM, PROC_ITEM,COND_ITEM, REF_ITEM, FIELD_STD_ITEM,
FIELD_VARIANCE_ITEM, INSERT_VALUE_ITEM, FIELD_VARIANCE_ITEM, INSERT_VALUE_ITEM,
SUBSELECT_ITEM, ROW_ITEM, CACHE_ITEM}; SUBSELECT_ITEM, ROW_ITEM, CACHE_ITEM, TYPE_HOLDER};
enum cond_result { COND_UNDEF,COND_OK,COND_TRUE,COND_FALSE }; enum cond_result { COND_UNDEF,COND_OK,COND_TRUE,COND_FALSE };
...@@ -390,17 +390,17 @@ class Item_int :public Item ...@@ -390,17 +390,17 @@ class Item_int :public Item
public: public:
const longlong value; const longlong value;
Item_int(int32 i,uint length=11) :value((longlong) i) Item_int(int32 i,uint length=11) :value((longlong) i)
{ max_length=length;} { max_length=length; fixed= 1; }
#ifdef HAVE_LONG_LONG #ifdef HAVE_LONG_LONG
Item_int(longlong i,uint length=21) :value(i) Item_int(longlong i,uint length=21) :value(i)
{ max_length=length;} { max_length=length; fixed= 1;}
#endif #endif
Item_int(const char *str_arg,longlong i,uint length) :value(i) Item_int(const char *str_arg,longlong i,uint length) :value(i)
{ max_length=length; name=(char*) str_arg;} { max_length=length; name=(char*) str_arg; fixed= 1; }
Item_int(const char *str_arg) : Item_int(const char *str_arg) :
value(str_arg[0] == '-' ? strtoll(str_arg,(char**) 0,10) : value(str_arg[0] == '-' ? strtoll(str_arg,(char**) 0,10) :
(longlong) strtoull(str_arg,(char**) 0,10)) (longlong) strtoull(str_arg,(char**) 0,10))
{ max_length= (uint) strlen(str_arg); name=(char*) str_arg;} { max_length= (uint) strlen(str_arg); name=(char*) str_arg; fixed= 1; }
enum Type type() const { return INT_ITEM; } enum Type type() const { return INT_ITEM; }
enum Item_result result_type () const { return INT_RESULT; } enum Item_result result_type () const { return INT_RESULT; }
enum_field_types field_type() const { return MYSQL_TYPE_LONGLONG; } enum_field_types field_type() const { return MYSQL_TYPE_LONGLONG; }
...@@ -988,6 +988,28 @@ class Item_cache_row: public Item_cache ...@@ -988,6 +988,28 @@ class Item_cache_row: public Item_cache
void bring_value(); void bring_value();
}; };
/*
Used to store type. name, length of Item for UNIONS & derived table
*/
class Item_type_holder: public Item
{
protected:
Item_result item_type;
Field *field_example;
public:
Item_type_holder(THD*, Item*);
Item_result result_type () const { return item_type; }
enum Type type() const { return TYPE_HOLDER; }
double val();
longlong val_int();
String *val_str(String*);
void join_types(THD *thd, Item *);
Field *example() { return field_example; }
};
extern Item_buff *new_Item_buff(Item *item); extern Item_buff *new_Item_buff(Item *item);
extern Item_result item_cmp_type(Item_result a,Item_result b); extern Item_result item_cmp_type(Item_result a,Item_result b);
extern Item *resolve_const_item(Item *item,Item *cmp_item); extern Item *resolve_const_item(Item *item,Item *cmp_item);
......
...@@ -924,7 +924,7 @@ int subselect_single_select_engine::prepare() ...@@ -924,7 +924,7 @@ int subselect_single_select_engine::prepare()
(ORDER*) select_lex->group_list.first, (ORDER*) select_lex->group_list.first,
select_lex->having, select_lex->having,
(ORDER*) 0, select_lex, (ORDER*) 0, select_lex,
select_lex->master_unit(), 0)) select_lex->master_unit()))
return 1; return 1;
thd->lex.current_select= save_select; thd->lex.current_select= save_select;
return 0; return 0;
...@@ -932,7 +932,7 @@ int subselect_single_select_engine::prepare() ...@@ -932,7 +932,7 @@ int subselect_single_select_engine::prepare()
int subselect_union_engine::prepare() int subselect_union_engine::prepare()
{ {
return unit->prepare(thd, result, 0); return unit->prepare(thd, result);
} }
int subselect_uniquesubquery_engine::prepare() int subselect_uniquesubquery_engine::prepare()
...@@ -942,12 +942,12 @@ int subselect_uniquesubquery_engine::prepare() ...@@ -942,12 +942,12 @@ int subselect_uniquesubquery_engine::prepare()
return 1; return 1;
} }
static Item_result set_row(SELECT_LEX *select_lex, Item * item, static Item_result set_row(List<Item> &item_list, Item *item,
Item_cache **row, bool *maybe_null) Item_cache **row, bool *maybe_null)
{ {
Item_result res_type= STRING_RESULT; Item_result res_type= STRING_RESULT;
Item *sel_item; Item *sel_item;
List_iterator_fast<Item> li(select_lex->item_list); List_iterator_fast<Item> li(item_list);
for (uint i= 0; (sel_item= li++); i++) for (uint i= 0; (sel_item= li++); i++)
{ {
item->max_length= sel_item->max_length; item->max_length= sel_item->max_length;
...@@ -962,7 +962,7 @@ static Item_result set_row(SELECT_LEX *select_lex, Item * item, ...@@ -962,7 +962,7 @@ static Item_result set_row(SELECT_LEX *select_lex, Item * item,
row[i]->collation.set(sel_item->collation); row[i]->collation.set(sel_item->collation);
} }
} }
if (select_lex->item_list.elements > 1) if (item_list.elements > 1)
res_type= ROW_RESULT; res_type= ROW_RESULT;
return res_type; return res_type;
} }
...@@ -970,7 +970,7 @@ static Item_result set_row(SELECT_LEX *select_lex, Item * item, ...@@ -970,7 +970,7 @@ static Item_result set_row(SELECT_LEX *select_lex, Item * item,
void subselect_single_select_engine::fix_length_and_dec(Item_cache **row) void subselect_single_select_engine::fix_length_and_dec(Item_cache **row)
{ {
DBUG_ASSERT(row || select_lex->item_list.elements==1); DBUG_ASSERT(row || select_lex->item_list.elements==1);
res_type= set_row(select_lex, item, row, &maybe_null); res_type= set_row(select_lex->item_list, item, row, &maybe_null);
item->collation.set(row[0]->collation); item->collation.set(row[0]->collation);
if (cols() != 1) if (cols() != 1)
maybe_null= 0; maybe_null= 0;
...@@ -981,44 +981,11 @@ void subselect_union_engine::fix_length_and_dec(Item_cache **row) ...@@ -981,44 +981,11 @@ void subselect_union_engine::fix_length_and_dec(Item_cache **row)
DBUG_ASSERT(row || unit->first_select()->item_list.elements==1); DBUG_ASSERT(row || unit->first_select()->item_list.elements==1);
if (unit->first_select()->item_list.elements == 1) if (unit->first_select()->item_list.elements == 1)
{ res_type= set_row(unit->types, item, row, &maybe_null);
uint32 mlen= 0, len;
Item *sel_item= 0;
for (SELECT_LEX *sl= unit->first_select(); sl; sl= sl->next_select())
{
List_iterator_fast<Item> li(sl->item_list);
Item *s_item= li++;
if ((len= s_item->max_length) > mlen)
mlen= len;
if (!sel_item)
sel_item= s_item;
maybe_null= s_item->maybe_null;
}
item->max_length= mlen;
res_type= sel_item->result_type();
item->decimals= sel_item->decimals;
if (row)
{
if (!(row[0]= Item_cache::get_cache(res_type)))
return;
row[0]->set_len_n_dec(mlen, sel_item->decimals);
}
}
else else
{ {
SELECT_LEX *sl= unit->first_select();
bool fake= 0; bool fake= 0;
res_type= set_row(sl, item, row, &fake); res_type= set_row(unit->types, item, row, &fake);
for (sl= sl->next_select(); sl; sl= sl->next_select())
{
List_iterator_fast<Item> li(sl->item_list);
Item *sel_item;
for (uint i= 0; (sel_item= li++); i++)
{
if (sel_item->max_length > row[i]->max_length)
row[i]->max_length= sel_item->max_length;
}
}
} }
} }
......
...@@ -482,7 +482,7 @@ int mysql_select(THD *thd, Item ***rref_pointer_array, ...@@ -482,7 +482,7 @@ int mysql_select(THD *thd, Item ***rref_pointer_array,
COND *conds, uint og_num, ORDER *order, ORDER *group, COND *conds, uint og_num, ORDER *order, ORDER *group,
Item *having, ORDER *proc_param, ulong select_type, Item *having, ORDER *proc_param, ulong select_type,
select_result *result, SELECT_LEX_UNIT *unit, select_result *result, SELECT_LEX_UNIT *unit,
SELECT_LEX *select_lex, bool tables_and_fields_initied); SELECT_LEX *select_lex);
void free_underlaid_joins(THD *thd, SELECT_LEX *select); void free_underlaid_joins(THD *thd, SELECT_LEX *select);
void fix_tables_pointers(SELECT_LEX *select_lex); void fix_tables_pointers(SELECT_LEX *select_lex);
void fix_tables_pointers(SELECT_LEX_UNIT *select_lex); void fix_tables_pointers(SELECT_LEX_UNIT *select_lex);
...@@ -491,7 +491,7 @@ int mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, ...@@ -491,7 +491,7 @@ int mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit,
int mysql_explain_select(THD *thd, SELECT_LEX *sl, char const *type, int mysql_explain_select(THD *thd, SELECT_LEX *sl, char const *type,
select_result *result); select_result *result);
int mysql_union(THD *thd, LEX *lex, select_result *result, int mysql_union(THD *thd, LEX *lex, select_result *result,
SELECT_LEX_UNIT *unit, bool tables_and_fields_initied); SELECT_LEX_UNIT *unit);
int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *s, TABLE_LIST *t); int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *s, TABLE_LIST *t);
Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
Item ***copy_func, Field **from_field, Item ***copy_func, Field **from_field,
...@@ -675,7 +675,6 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields, ...@@ -675,7 +675,6 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
int setup_fields(THD *thd, Item** ref_pointer_array, TABLE_LIST *tables, int setup_fields(THD *thd, Item** ref_pointer_array, TABLE_LIST *tables,
List<Item> &item, bool set_query_id, List<Item> &item, bool set_query_id,
List<Item> *sum_func_list, bool allow_sum_func); List<Item> *sum_func_list, bool allow_sum_func);
void unfix_item_list(List<Item> item_list);
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);
......
...@@ -2023,20 +2023,6 @@ int setup_fields(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables, ...@@ -2023,20 +2023,6 @@ int setup_fields(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
DBUG_RETURN(test(thd->net.report_error)); DBUG_RETURN(test(thd->net.report_error));
} }
/*
Mark all items in list as not fixed (0 assigned to 'fixed' field)
SYNOPSYS
unfix_item_list()
item_list - list of items
*/
void unfix_item_list(List<Item> item_list)
{
Item *item;
List_iterator_fast<Item> it(item_list);
while ((item= it++))
item->walk(&Item::remove_fixed, 0);
}
/* /*
Remap table numbers if INSERT ... SELECT Remap table numbers if INSERT ... SELECT
......
...@@ -946,6 +946,7 @@ class select_union :public select_result { ...@@ -946,6 +946,7 @@ class select_union :public select_result {
bool send_data(List<Item> &items); bool send_data(List<Item> &items);
bool send_eof(); bool send_eof();
bool flush(); bool flush();
void set_table(TABLE *tbl) { table= tbl; }
}; };
/* Base subselect interface class */ /* Base subselect interface class */
......
...@@ -62,16 +62,15 @@ ...@@ -62,16 +62,15 @@
int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit,
TABLE_LIST *org_table_list) TABLE_LIST *org_table_list)
{ {
SELECT_LEX *select_cursor= unit->first_select(); SELECT_LEX *first_select= unit->first_select();
List<Item> item_list;
TABLE *table; TABLE *table;
int res; int res;
select_union *derived_result; select_union *derived_result;
TABLE_LIST *tables= (TABLE_LIST *)select_cursor->table_list.first; TABLE_LIST *tables= (TABLE_LIST *)first_select->table_list.first;
TMP_TABLE_PARAM tmp_table_param; TMP_TABLE_PARAM tmp_table_param;
bool is_union= select_cursor->next_select() && bool is_union= first_select->next_select() &&
select_cursor->next_select()->linkage == UNION_TYPE; first_select->next_select()->linkage == UNION_TYPE;
bool is_subsel= select_cursor->first_inner_unit() ? 1: 0; bool is_subsel= first_select->first_inner_unit() ? 1: 0;
SELECT_LEX *save_current_select= lex->current_select; SELECT_LEX *save_current_select= lex->current_select;
DBUG_ENTER("mysql_derived"); DBUG_ENTER("mysql_derived");
...@@ -112,16 +111,12 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, ...@@ -112,16 +111,12 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit,
fix_tables_pointers(unit); fix_tables_pointers(unit);
} }
lex->current_select= select_cursor; if(!(derived_result= new select_union(0)))
TABLE_LIST *first_table= (TABLE_LIST*) select_cursor->table_list.first; DBUG_RETURN(1); // out of memory
/* Setting up. A must if a join or IGNORE, USE or similar are utilised */
if (setup_tables(first_table) || // st_select_lex_unit::prepare coppectly work for single select
setup_wild(thd, first_table, select_cursor->item_list, 0, if ((res= unit->prepare(thd, derived_result)))
select_cursor->with_wild))
{
res= -1;
goto exit; goto exit;
}
/* /*
This is done in order to redo all field optimisations when any of the This is done in order to redo all field optimisations when any of the
...@@ -133,30 +128,16 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, ...@@ -133,30 +128,16 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit,
cursor->table->clear_query_id= 1; cursor->table->clear_query_id= 1;
} }
item_list= select_cursor->item_list;
select_cursor->with_wild= 0;
if (select_cursor->setup_ref_array(thd,
select_cursor->order_list.elements +
select_cursor->group_list.elements) ||
setup_fields(thd, select_cursor->ref_pointer_array, first_table,
item_list, 0, 0, 1))
{
res= -1;
goto exit;
}
// Item list should be fix_fielded yet another time in JOIN::prepare
unfix_item_list(item_list);
bzero((char*) &tmp_table_param,sizeof(tmp_table_param)); bzero((char*) &tmp_table_param,sizeof(tmp_table_param));
tmp_table_param.field_count= item_list.elements; tmp_table_param.field_count= unit->types.elements;
/* /*
Temp table is created so that it hounours if UNION without ALL is to be Temp table is created so that it hounours if UNION without ALL is to be
processed processed
*/ */
if (!(table= create_tmp_table(thd, &tmp_table_param, item_list, if (!(table= create_tmp_table(thd, &tmp_table_param, unit->types,
(ORDER*) 0, (ORDER*) 0,
is_union && !unit->union_option, 1, is_union && !unit->union_option, 1,
(select_cursor->options | thd->options | (first_select->options | thd->options |
TMP_TABLE_ALL_COLUMNS), TMP_TABLE_ALL_COLUMNS),
HA_POS_ERROR, HA_POS_ERROR,
org_table_list->alias))) org_table_list->alias)))
...@@ -164,70 +145,69 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, ...@@ -164,70 +145,69 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit,
res= -1; res= -1;
goto exit; goto exit;
} }
derived_result->set_table(table);
if ((derived_result=new select_union(table))) derived_result->tmp_table_param=tmp_table_param;
unit->offset_limit_cnt= first_select->offset_limit;
unit->select_limit_cnt= first_select->select_limit+
first_select->offset_limit;
if (unit->select_limit_cnt < first_select->select_limit)
unit->select_limit_cnt= HA_POS_ERROR;
if (unit->select_limit_cnt == HA_POS_ERROR)
first_select->options&= ~OPTION_FOUND_ROWS;
if (is_union)
res= mysql_union(thd, lex, derived_result, unit);
else
res= mysql_select(thd, &first_select->ref_pointer_array,
(TABLE_LIST*) first_select->table_list.first,
first_select->with_wild,
first_select->item_list, first_select->where,
(first_select->order_list.elements+
first_select->group_list.elements),
(ORDER *) first_select->order_list.first,
(ORDER *) first_select->group_list.first,
first_select->having, (ORDER*) NULL,
(first_select->options | thd->options |
SELECT_NO_UNLOCK),
derived_result, unit, first_select);
if (!res)
{ {
derived_result->tmp_table_param=tmp_table_param; /*
unit->offset_limit_cnt= select_cursor->offset_limit; Here we entirely fix both TABLE_LIST and list of SELECT's as
unit->select_limit_cnt= select_cursor->select_limit+ there were no derived tables
select_cursor->offset_limit; */
if (unit->select_limit_cnt < select_cursor->select_limit) if (derived_result->flush())
unit->select_limit_cnt= HA_POS_ERROR; res= 1;
if (unit->select_limit_cnt == HA_POS_ERROR)
select_cursor->options&= ~OPTION_FOUND_ROWS;
if (is_union)
res= mysql_union(thd, lex, derived_result, unit, 1);
else else
res= mysql_select(thd, &select_cursor->ref_pointer_array,
(TABLE_LIST*) select_cursor->table_list.first,
select_cursor->with_wild,
select_cursor->item_list, select_cursor->where,
(select_cursor->order_list.elements+
select_cursor->group_list.elements),
(ORDER *) select_cursor->order_list.first,
(ORDER *) select_cursor->group_list.first,
select_cursor->having, (ORDER*) NULL,
(select_cursor->options | thd->options |
SELECT_NO_UNLOCK),
derived_result, unit, select_cursor, 1);
if (!res)
{ {
/* org_table_list->real_name=table->real_name;
Here we entirely fix both TABLE_LIST and list of SELECT's as org_table_list->table=table;
there were no derived tables table->derived_select_number= first_select->select_number;
*/ table->tmp_table= TMP_TABLE;
if (derived_result->flush())
res= 1;
else
{
org_table_list->real_name=table->real_name;
org_table_list->table=table;
table->derived_select_number= select_cursor->select_number;
table->tmp_table= TMP_TABLE;
#ifndef NO_EMBEDDED_ACCESS_CHECKS #ifndef NO_EMBEDDED_ACCESS_CHECKS
org_table_list->grant.privilege= SELECT_ACL; org_table_list->grant.privilege= SELECT_ACL;
#endif #endif
if (lex->describe) if (lex->describe)
{
// to fix a problem in EXPLAIN
if (tables)
{ {
// to fix a problem in EXPLAIN for (TABLE_LIST *cursor= tables; cursor; cursor= cursor->next)
if (tables) if (cursor->table_list)
{ cursor->table_list->table=cursor->table;
for (TABLE_LIST *cursor= tables; cursor; cursor= cursor->next)
if (cursor->table_list)
cursor->table_list->table=cursor->table;
}
} }
else
unit->exclude_tree();
org_table_list->db= (char *)"";
// Force read of table stats in the optimizer
table->file->info(HA_STATUS_VARIABLE);
} }
else
unit->exclude_tree();
org_table_list->db= (char *)"";
// Force read of table stats in the optimizer
table->file->info(HA_STATUS_VARIABLE);
} }
delete derived_result;
} }
delete derived_result;
if (res) if (res)
free_tmp_table(thd, table); free_tmp_table(thd, table);
else else
......
...@@ -295,7 +295,6 @@ class JOIN; ...@@ -295,7 +295,6 @@ class JOIN;
class select_union; 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;
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 */
...@@ -305,9 +304,13 @@ class st_select_lex_unit: public st_select_lex_node { ...@@ -305,9 +304,13 @@ class st_select_lex_unit: public st_select_lex_node {
ulong found_rows_for_union; ulong found_rows_for_union;
bool prepared, // prepare phase already performed for UNION (unit) bool prepared, // prepare phase already performed for UNION (unit)
optimized, // optimize phase already performed for UNION (unit) optimized, // optimize phase already performed for UNION (unit)
executed, // already executed executed; // already executed
t_and_f; // used for transferring tables_and_fields_initied UNIT:: methods
public: public:
// list of fields which points to temporary table for union
List<Item> item_list;
// list of types of items inside union (used for union & derived tables)
List<Item> types;
/* /*
Pointer to 'last' select or pointer to unit where stored Pointer to 'last' select or pointer to unit where stored
global parameters for union global parameters for union
...@@ -342,7 +345,7 @@ class st_select_lex_unit: public st_select_lex_node { ...@@ -342,7 +345,7 @@ class st_select_lex_unit: public st_select_lex_node {
void exclude_tree(); void exclude_tree();
/* UNION methods */ /* UNION methods */
int prepare(THD *thd, select_result *result, bool tables_and_fields_initied); int prepare(THD *thd, select_result *result);
int exec(); int exec();
int cleanup(); int cleanup();
......
...@@ -2716,7 +2716,7 @@ mysql_execute_command(THD *thd) ...@@ -2716,7 +2716,7 @@ mysql_execute_command(THD *thd)
(ORDER *)NULL, (ORDER *)NULL,
select_lex->options | thd->options | select_lex->options | thd->options |
SELECT_NO_JOIN_CACHE | SELECT_NO_UNLOCK, SELECT_NO_JOIN_CACHE | SELECT_NO_UNLOCK,
result, unit, select_lex, 0); result, unit, select_lex);
if (thd->net.report_error) if (thd->net.report_error)
res= -1; res= -1;
delete result; delete result;
......
...@@ -682,7 +682,7 @@ static bool mysql_test_select_fields(PREP_STMT *stmt, TABLE_LIST *tables, ...@@ -682,7 +682,7 @@ static bool mysql_test_select_fields(PREP_STMT *stmt, TABLE_LIST *tables,
if (join->prepare(&select_lex->ref_pointer_array, tables, if (join->prepare(&select_lex->ref_pointer_array, tables,
wild_num, conds, og_num, order, group, having, proc, wild_num, conds, og_num, order, group, having, proc,
select_lex, unit, 0)) select_lex, unit))
DBUG_RETURN(1); DBUG_RETURN(1);
if (send_prep_stmt(stmt, fields.elements) || if (send_prep_stmt(stmt, fields.elements) ||
thd->protocol_simple.send_fields(&fields, 0) || thd->protocol_simple.send_fields(&fields, 0) ||
......
This diff is collapsed.
...@@ -266,7 +266,7 @@ class JOIN :public Sql_alloc ...@@ -266,7 +266,7 @@ class JOIN :public Sql_alloc
int prepare(Item ***rref_pointer_array, TABLE_LIST *tables, uint wind_num, int prepare(Item ***rref_pointer_array, TABLE_LIST *tables, uint wind_num,
COND *conds, uint og_num, ORDER *order, ORDER *group, COND *conds, uint og_num, ORDER *order, ORDER *group,
Item *having, ORDER *proc_param, SELECT_LEX *select, Item *having, ORDER *proc_param, SELECT_LEX *select,
SELECT_LEX_UNIT *unit, bool tables_and_fields_initied); SELECT_LEX_UNIT *unit);
int optimize(); int optimize();
int reinit(); int reinit();
void exec(); void exec();
......
...@@ -25,11 +25,11 @@ ...@@ -25,11 +25,11 @@
#include "sql_select.h" #include "sql_select.h"
int mysql_union(THD *thd, LEX *lex, select_result *result, int mysql_union(THD *thd, LEX *lex, select_result *result,
SELECT_LEX_UNIT *unit, bool tables_and_fields_initied) SELECT_LEX_UNIT *unit)
{ {
DBUG_ENTER("mysql_union"); DBUG_ENTER("mysql_union");
int res= 0; int res= 0;
if (!(res= unit->prepare(thd, result, tables_and_fields_initied))) if (!(res= unit->prepare(thd, result)))
res= unit->exec(); res= unit->exec();
res|= unit->cleanup(); res|= unit->cleanup();
DBUG_RETURN(res); DBUG_RETURN(res);
...@@ -59,12 +59,6 @@ select_union::~select_union() ...@@ -59,12 +59,6 @@ select_union::~select_union()
int select_union::prepare(List<Item> &list, SELECT_LEX_UNIT *u) int select_union::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
{ {
unit= u; unit= u;
if (not_describe && list.elements != table->fields)
{
my_message(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT,
ER(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT),MYF(0));
return -1;
}
return 0; return 0;
} }
...@@ -112,11 +106,11 @@ bool select_union::flush() ...@@ -112,11 +106,11 @@ bool select_union::flush()
} }
int st_select_lex_unit::prepare(THD *thd, select_result *sel_result, int st_select_lex_unit::prepare(THD *thd, select_result *sel_result)
bool tables_and_fields_initied)
{ {
SELECT_LEX *lex_select_save= thd->lex.current_select; SELECT_LEX *lex_select_save= thd->lex.current_select;
SELECT_LEX *select_cursor,*sl; SELECT_LEX *sl, *first_select;
select_result *tmp_result;
DBUG_ENTER("st_select_lex_unit::prepare"); DBUG_ENTER("st_select_lex_unit::prepare");
/* /*
...@@ -129,74 +123,33 @@ int st_select_lex_unit::prepare(THD *thd, select_result *sel_result, ...@@ -129,74 +123,33 @@ int st_select_lex_unit::prepare(THD *thd, select_result *sel_result,
DBUG_RETURN(0); DBUG_RETURN(0);
prepared= 1; prepared= 1;
res= 0; res= 0;
found_rows_for_union= first_select_in_union()->options & OPTION_FOUND_ROWS;
TMP_TABLE_PARAM tmp_table_param; TMP_TABLE_PARAM tmp_table_param;
t_and_f= tables_and_fields_initied;
bzero((char *)&tmp_table_param,sizeof(TMP_TABLE_PARAM)); bzero((char *)&tmp_table_param,sizeof(TMP_TABLE_PARAM));
thd->lex.current_select= sl= select_cursor= first_select_in_union(); thd->lex.current_select= sl= first_select= first_select_in_union();
found_rows_for_union= first_select->options & OPTION_FOUND_ROWS;
/* Global option */ /* Global option */
if (t_and_f)
if (first_select->next_select())
{ {
// Item list and tables will be initialized by mysql_derived if (!(tmp_result= union_result= new select_union(0)))
item_list= select_cursor->item_list; goto err;
union_result->not_describe= 1;
union_result->tmp_table_param= tmp_table_param;
} }
else else
{ {
item_list.empty(); tmp_result= sel_result;
TABLE_LIST *first_table= (TABLE_LIST*) select_cursor->table_list.first; // single select should be processed like select in p[arantses
first_select->braces= 1;
if (setup_tables(first_table) ||
setup_wild(thd, first_table, select_cursor->item_list, 0,
select_cursor->with_wild))
goto err;
List_iterator<Item> it(select_cursor->item_list);
Item *item;
item_list= select_cursor->item_list;
select_cursor->with_wild= 0;
if (select_cursor->setup_ref_array(thd,
select_cursor->order_list.elements +
select_cursor->group_list.elements) ||
setup_fields(thd, select_cursor->ref_pointer_array, first_table,
item_list, 0, 0, 1))
goto err;
// Item list should be fix_fielded yet another time in JOIN::prepare
unfix_item_list(item_list);
t_and_f= 1;
while((item=it++))
{
item->maybe_null=1;
if (item->type() == Item::FIELD_ITEM)
((class Item_field *)item)->field->table->maybe_null=1;
}
} }
tmp_table_param.field_count=item_list.elements;
if (!(table= create_tmp_table(thd, &tmp_table_param, item_list,
(ORDER*) 0, !union_option,
1, (select_cursor->options | thd->options |
TMP_TABLE_ALL_COLUMNS),
HA_POS_ERROR, (char*) "")))
goto err;
table->file->extra(HA_EXTRA_WRITE_CACHE);
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
bzero((char*) &result_table_list,sizeof(result_table_list));
result_table_list.db= (char*) "";
result_table_list.real_name=result_table_list.alias= (char*) "union";
result_table_list.table=table;
if (!(union_result=new select_union(table)))
goto err;
union_result->not_describe=1;
union_result->tmp_table_param=tmp_table_param;
for (;sl; sl= sl->next_select()) for (;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); tmp_result);
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;
...@@ -215,27 +168,76 @@ int st_select_lex_unit::prepare(THD *thd, select_result *sel_result, ...@@ -215,27 +168,76 @@ int st_select_lex_unit::prepare(THD *thd, select_result *sel_result,
(ORDER*) sl->group_list.first, (ORDER*) sl->group_list.first,
sl->having, sl->having,
(ORDER*) NULL, (ORDER*) NULL,
sl, this, t_and_f); sl, this);
t_and_f= 0;
if (res || thd->is_fatal_error) if (res || thd->is_fatal_error)
goto err; goto err;
if (sl == first_select)
{
types.empty();
List_iterator_fast<Item> it(sl->item_list);
Item *item;
while((item= it++))
{
types.push_back(new Item_type_holder(thd, item));
}
if (thd->is_fatal_error)
goto err; // out of memory
}
else
{
if (types.elements != sl->item_list.elements)
{
my_message(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT,
ER(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT),MYF(0));
goto err;
}
List_iterator_fast<Item> it(sl->item_list);
List_iterator_fast<Item> tp(types);
Item *type, *item;
while((type= tp++, item= it++))
{
((Item_type_holder*)type)->join_types(thd, item);
}
}
} }
item_list.empty(); if (first_select->next_select())
thd->lex.current_select= lex_select_save;
{ {
List_iterator<Item> it(select_cursor->item_list); tmp_table_param.field_count= types.elements;
Field **field; if (!(table= create_tmp_table(thd, &tmp_table_param, types,
(ORDER*) 0, !union_option, 1,
(first_select_in_union()->options |
thd->options |
TMP_TABLE_ALL_COLUMNS),
HA_POS_ERROR, (char*) "")))
goto err;
table->file->extra(HA_EXTRA_WRITE_CACHE);
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
bzero((char*) &result_table_list, sizeof(result_table_list));
result_table_list.db= (char*) "";
result_table_list.real_name= result_table_list.alias= (char*) "union";
result_table_list.table= table;
union_result->set_table(table);
for (field= table->field; *field; field++) item_list.empty();
thd->lex.current_select= lex_select_save;
{ {
(void) it++; Field **field;
if (item_list.push_back(new Item_field(*field))) for (field= table->field; *field; field++)
DBUG_RETURN(-1); {
if (item_list.push_back(new Item_field(*field)))
DBUG_RETURN(-1);
}
} }
} }
else
first_select->braces= 0; // remove our changes
thd->lex.current_select= lex_select_save;
DBUG_RETURN(res || thd->is_fatal_error ? 1 : 0); DBUG_RETURN(res || thd->is_fatal_error ? 1 : 0);
err: err:
thd->lex.current_select= lex_select_save; thd->lex.current_select= lex_select_save;
DBUG_RETURN(-1); DBUG_RETURN(-1);
...@@ -419,7 +421,7 @@ int st_select_lex_unit::exec() ...@@ -419,7 +421,7 @@ int st_select_lex_unit::exec()
(ORDER*)global_parameters->order_list.first, (ORDER*)global_parameters->order_list.first,
(ORDER*) NULL, NULL, (ORDER*) NULL, (ORDER*) NULL, NULL, (ORDER*) NULL,
options | SELECT_NO_UNLOCK, options | SELECT_NO_UNLOCK,
result, this, fake_select_lex, 0); result, this, fake_select_lex);
if (!res) if (!res)
thd->limit_found_rows = (ulonglong)table->file->records + add_rows; thd->limit_found_rows = (ulonglong)table->file->records + add_rows;
/* /*
......
...@@ -461,7 +461,7 @@ int mysql_multi_update(THD *thd, ...@@ -461,7 +461,7 @@ int mysql_multi_update(THD *thd,
conds, 0, (ORDER *) NULL, (ORDER *)NULL, (Item *) NULL, conds, 0, (ORDER *) NULL, (ORDER *)NULL, (Item *) NULL,
(ORDER *)NULL, (ORDER *)NULL,
options | SELECT_NO_JOIN_CACHE | SELECT_NO_UNLOCK, options | SELECT_NO_JOIN_CACHE | SELECT_NO_UNLOCK,
result, unit, select_lex, 0); result, unit, select_lex);
delete result; delete result;
DBUG_RETURN(res); DBUG_RETURN(res);
} }
......
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