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 @@ public: ...@@ -230,6 +230,24 @@ public:
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 @@ public: ...@@ -334,6 +352,7 @@ public:
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 @@ public: ...@@ -369,6 +388,7 @@ public:
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 @@ public: ...@@ -404,6 +424,7 @@ public:
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 @@ public: ...@@ -434,6 +455,7 @@ public:
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 @@ public: ...@@ -469,6 +491,7 @@ public:
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 @@ public: ...@@ -507,6 +530,7 @@ public:
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 @@ public: ...@@ -540,6 +564,7 @@ public:
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 @@ public: ...@@ -573,6 +598,7 @@ public:
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 @@ public: ...@@ -606,6 +632,7 @@ public:
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 @@ public: ...@@ -649,6 +676,8 @@ public:
} }
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 @@ public: ...@@ -674,6 +703,8 @@ public:
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 @@ public: ...@@ -706,6 +737,8 @@ public:
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 @@ public: ...@@ -737,6 +770,8 @@ public:
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 @@ public: ...@@ -770,6 +805,8 @@ public:
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 @@ public: ...@@ -807,6 +844,8 @@ public:
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 @@ public: ...@@ -851,6 +890,7 @@ public:
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 @@ public: ...@@ -894,6 +934,7 @@ public:
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 @@ public: ...@@ -983,6 +1024,7 @@ public:
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 @@ public: ...@@ -1011,6 +1053,8 @@ public:
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 @@ public: ...@@ -1052,6 +1096,8 @@ public:
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 @@ public: ...@@ -1077,6 +1123,8 @@ public:
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 @@ public: ...@@ -98,7 +98,7 @@ public:
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 @@ public: ...@@ -988,6 +988,28 @@ public:
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 @@ protected: ...@@ -305,9 +304,13 @@ protected:
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 @@ public: ...@@ -342,7 +345,7 @@ public:
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) ||
......
...@@ -177,7 +177,7 @@ int handle_select(THD *thd, LEX *lex, select_result *result) ...@@ -177,7 +177,7 @@ int handle_select(THD *thd, LEX *lex, select_result *result)
fix_tables_pointers(lex->all_selects_list); fix_tables_pointers(lex->all_selects_list);
if (select_lex->next_select()) if (select_lex->next_select())
res=mysql_union(thd, lex, result, &lex->unit, 0); res=mysql_union(thd, lex, result, &lex->unit);
else else
res= mysql_select(thd, &select_lex->ref_pointer_array, res= mysql_select(thd, &select_lex->ref_pointer_array,
(TABLE_LIST*) select_lex->table_list.first, (TABLE_LIST*) select_lex->table_list.first,
...@@ -190,7 +190,7 @@ int handle_select(THD *thd, LEX *lex, select_result *result) ...@@ -190,7 +190,7 @@ int handle_select(THD *thd, LEX *lex, select_result *result)
select_lex->having, select_lex->having,
(ORDER*) lex->proc_list.first, (ORDER*) lex->proc_list.first,
select_lex->options | thd->options, select_lex->options | thd->options,
result, &(lex->unit), &(lex->select_lex), 0); result, &(lex->unit), &(lex->select_lex));
/* Don't set res if it's -1 as we may want this later */ /* Don't set res if it's -1 as we may want this later */
DBUG_PRINT("info",("res: %d report_error: %d", res, DBUG_PRINT("info",("res: %d report_error: %d", res,
...@@ -285,8 +285,7 @@ JOIN::prepare(Item ***rref_pointer_array, ...@@ -285,8 +285,7 @@ JOIN::prepare(Item ***rref_pointer_array,
ORDER *order_init, ORDER *group_init, ORDER *order_init, ORDER *group_init,
Item *having_init, Item *having_init,
ORDER *proc_param_init, SELECT_LEX *select, ORDER *proc_param_init, SELECT_LEX *select,
SELECT_LEX_UNIT *unit, SELECT_LEX_UNIT *unit)
bool tables_and_fields_initied)
{ {
DBUG_ENTER("JOIN::prepare"); DBUG_ENTER("JOIN::prepare");
...@@ -302,10 +301,8 @@ JOIN::prepare(Item ***rref_pointer_array, ...@@ -302,10 +301,8 @@ JOIN::prepare(Item ***rref_pointer_array,
/* Check that all tables, fields, conds and order are ok */ /* Check that all tables, fields, conds and order are ok */
if ((tables_and_fields_initied ? 0 : (setup_tables(tables_list) || if (setup_tables(tables_list) ||
setup_wild(thd, tables_list, setup_wild(thd, tables_list, fields_list, &all_fields, wild_num) ||
fields_list,
&all_fields, wild_num))) ||
select_lex->setup_ref_array(thd, og_num) || select_lex->setup_ref_array(thd, og_num) ||
setup_fields(thd, (*rref_pointer_array), tables_list, fields_list, 1, setup_fields(thd, (*rref_pointer_array), tables_list, fields_list, 1,
&all_fields, 1) || &all_fields, 1) ||
...@@ -1536,7 +1533,7 @@ mysql_select(THD *thd, Item ***rref_pointer_array, ...@@ -1536,7 +1533,7 @@ 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_options, Item *having, ORDER *proc_param, ulong select_options,
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)
{ {
int err; int err;
bool free_join= 1; bool free_join= 1;
...@@ -1546,26 +1543,31 @@ mysql_select(THD *thd, Item ***rref_pointer_array, ...@@ -1546,26 +1543,31 @@ mysql_select(THD *thd, Item ***rref_pointer_array,
if (select_lex->join != 0) if (select_lex->join != 0)
{ {
join= select_lex->join; join= select_lex->join;
if (select_lex->linkage != GLOBAL_OPTIONS_TYPE) // is it single SELECT in derived table, called in derived table creation
if (select_lex->linkage != DERIVED_TABLE_TYPE ||
(select_options & SELECT_DESCRIBE))
{ {
//here is EXPLAIN of subselect or derived table if (select_lex->linkage != GLOBAL_OPTIONS_TYPE)
join->result= result;
if (!join->procedure && result->prepare(join->fields_list, unit))
{ {
DBUG_RETURN(-1); //here is EXPLAIN of subselect or derived table
join->result= result;
if (!join->procedure && result->prepare(join->fields_list, unit))
{
DBUG_RETURN(-1);
}
} }
} else
else
{
if (join->prepare(rref_pointer_array, tables, wild_num,
conds, og_num, order, group, having, proc_param,
select_lex, unit, tables_and_fields_initied))
{ {
goto err; if (join->prepare(rref_pointer_array, tables, wild_num,
conds, og_num, order, group, having, proc_param,
select_lex, unit))
{
goto err;
}
} }
free_join= 0;
} }
join->select_options= select_options; join->select_options= select_options;
free_join= 0;
} }
else else
{ {
...@@ -1574,7 +1576,7 @@ mysql_select(THD *thd, Item ***rref_pointer_array, ...@@ -1574,7 +1576,7 @@ mysql_select(THD *thd, Item ***rref_pointer_array,
thd->used_tables=0; // Updated by setup_fields thd->used_tables=0; // Updated by setup_fields
if (join->prepare(rref_pointer_array, tables, wild_num, if (join->prepare(rref_pointer_array, tables, wild_num,
conds, og_num, order, group, having, proc_param, conds, og_num, order, group, having, proc_param,
select_lex, unit, tables_and_fields_initied)) select_lex, unit))
{ {
goto err; goto err;
} }
...@@ -4545,6 +4547,115 @@ const_expression_in_where(COND *cond, Item *comp_item, Item **const_item) ...@@ -4545,6 +4547,115 @@ const_expression_in_where(COND *cond, Item *comp_item, Item **const_item)
Create internal temporary table Create internal temporary table
****************************************************************************/ ****************************************************************************/
/*
Create field for temporary table from given field
SYNOPSIS
create_tmp_field_from_field()
thd Thread handler
org_field field from which new field will be created
item Item to create a field for
table Temporary table
modify_item 1 if item->result_field should point to new item.
This is relevent for how fill_record() is going to
work:
If modify_item is 1 then fill_record() will update
the record in the original table.
If modify_item is 0 then fill_record() will update
the temporary table
RETURN
0 on error
new_created field
*/
static Field* create_tmp_field_from_field(THD *thd,
Field* org_field,
Item *item,
TABLE *table,
bool modify_item)
{
Field *new_field;
// The following should always be true
if ((new_field= org_field->new_field(&thd->mem_root,table)))
{
if (modify_item)
((Item_field *)item)->result_field= new_field;
else
new_field->field_name= item->name;
if (org_field->maybe_null())
new_field->flags&= ~NOT_NULL_FLAG; // Because of outer join
if (org_field->type() == FIELD_TYPE_VAR_STRING)
table->db_create_options|= HA_OPTION_PACK_RECORD;
}
return new_field;
}
/*
Create field for temporary table using type of given item
SYNOPSIS
create_tmp_field_from_item()
thd Thread handler
item Item to create a field for
table Temporary table
copy_func If set and item is a function, store copy of item
in this array
modify_item 1 if item->result_field should point to new item.
This is relevent for how fill_record() is going to
work:
If modify_item is 1 then fill_record() will update
the record in the original table.
If modify_item is 0 then fill_record() will update
the temporary table
RETURN
0 on error
new_created field
*/
static Field* create_tmp_field_from_item(THD *thd,
Item *item,
TABLE *table,
Item ***copy_func,
bool modify_item)
{
bool maybe_null=item->maybe_null;
Field *new_field;
LINT_INIT(new_field);
switch (item->result_type()) {
case REAL_RESULT:
new_field=new Field_double(item->max_length, maybe_null,
item->name, table, item->decimals);
break;
case INT_RESULT:
new_field=new Field_longlong(item->max_length, maybe_null,
item->name, table, item->unsigned_flag);
break;
case STRING_RESULT:
if (item->max_length > 255)
new_field= new Field_blob(item->max_length, maybe_null,
item->name, table,
item->collation.collation);
else
new_field= new Field_string(item->max_length, maybe_null,
item->name, table,
item->collation.collation);
break;
case ROW_RESULT:
default:
// This case should never be choosen
DBUG_ASSERT(0);
new_field= 0; // to satisfy compiler (uninitialized variable)
break;
}
if (copy_func && item->is_result_field())
*((*copy_func)++) = item; // Save for copy_funcs
if (modify_item)
item->set_result_field(new_field);
return new_field;
}
/* /*
Create field for temporary table Create field for temporary table
...@@ -4556,6 +4667,8 @@ const_expression_in_where(COND *cond, Item *comp_item, Item **const_item) ...@@ -4556,6 +4667,8 @@ const_expression_in_where(COND *cond, Item *comp_item, Item **const_item)
type Type of item (normally item->type) type Type of item (normally item->type)
copy_func If set and item is a function, store copy of item copy_func If set and item is a function, store copy of item
in this array in this array
from_field if field will be created using other field as example,
pointer example field will be written here
group 1 if we are going to do a relative group by on result group 1 if we are going to do a relative group by on result
modify_item 1 if item->result_field should point to new item. modify_item 1 if item->result_field should point to new item.
This is relevent for how fill_record() is going to This is relevent for how fill_record() is going to
...@@ -4622,24 +4735,9 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, ...@@ -4622,24 +4735,9 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
return 0; // Error return 0; // Error
} }
case Item::FIELD_ITEM: case Item::FIELD_ITEM:
{ return create_tmp_field_from_field(thd, (*from_field=
Field *org_field=((Item_field*) item)->field,*new_field; ((Item_field*) item)->field),
item, table, modify_item);
*from_field=org_field;
// The following should always be true
if ((new_field= org_field->new_field(&thd->mem_root,table)))
{
if (modify_item)
((Item_field*) item)->result_field= new_field;
else
new_field->field_name=item->name;
if (org_field->maybe_null())
new_field->flags&= ~NOT_NULL_FLAG; // Because of outer join
if (org_field->type()==FIELD_TYPE_VAR_STRING)
table->db_create_options|= HA_OPTION_PACK_RECORD;
}
return new_field;
}
case Item::FUNC_ITEM: case Item::FUNC_ITEM:
case Item::COND_ITEM: case Item::COND_ITEM:
case Item::FIELD_AVG_ITEM: case Item::FIELD_AVG_ITEM:
...@@ -4653,40 +4751,14 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type, ...@@ -4653,40 +4751,14 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
case Item::REF_ITEM: case Item::REF_ITEM:
case Item::NULL_ITEM: case Item::NULL_ITEM:
case Item::VARBIN_ITEM: case Item::VARBIN_ITEM:
return create_tmp_field_from_item(thd, item, table,
copy_func, modify_item);
case Item::TYPE_HOLDER:
{ {
bool maybe_null=item->maybe_null; Field *example= ((Item_type_holder *)item)->example();
Field *new_field; if (example)
LINT_INIT(new_field); return create_tmp_field_from_field(thd, example, item, table, 0);
return create_tmp_field_from_item(thd, item, table, copy_func, 0);
switch (item->result_type()) {
case REAL_RESULT:
new_field=new Field_double(item->max_length,maybe_null,
item->name,table,item->decimals);
break;
case INT_RESULT:
new_field=new Field_longlong(item->max_length,maybe_null,
item->name,table, item->unsigned_flag);
break;
case STRING_RESULT:
if (item->max_length > 255)
new_field= new Field_blob(item->max_length,maybe_null,
item->name,table,item->collation.collation);
else
new_field= new Field_string(item->max_length,maybe_null,
item->name,table,item->collation.collation);
break;
case ROW_RESULT:
default:
// This case should never be choosen
DBUG_ASSERT(0);
new_field= 0; // to satisfy compiler (uninitialized variable)
break;
}
if (copy_func && item->is_result_field())
*((*copy_func)++) = item; // Save for copy_funcs
if (modify_item)
item->set_result_field(new_field);
return new_field;
} }
default: // Dosen't have to be stored default: // Dosen't have to be stored
return 0; return 0;
...@@ -9077,7 +9149,7 @@ int mysql_explain_select(THD *thd, SELECT_LEX *select_lex, char const *type, ...@@ -9077,7 +9149,7 @@ int mysql_explain_select(THD *thd, SELECT_LEX *select_lex, char const *type,
select_lex->having, select_lex->having,
(ORDER*) thd->lex.proc_list.first, (ORDER*) thd->lex.proc_list.first,
select_lex->options | thd->options | SELECT_DESCRIBE, select_lex->options | thd->options | SELECT_DESCRIBE,
result, unit, select_lex, 0); result, unit, select_lex);
DBUG_RETURN(res); DBUG_RETURN(res);
} }
......
...@@ -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