Fixed UNION fields type/length detecting
This commit is contained in:
parent
4883d21b29
commit
7191ea0ae3
@ -53,7 +53,7 @@ select 0,'#' union select a,b from t1 union all select a,b from t2 union select
|
||||
4 d
|
||||
5 f
|
||||
6 e
|
||||
7 g
|
||||
7 gg
|
||||
select a,b from t1 union select a,b from t1;
|
||||
a b
|
||||
1 a
|
||||
@ -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;
|
||||
id_master id text1 text2
|
||||
1 1 NULL ABCDE
|
||||
1 1 bar1
|
||||
1 2 bar2
|
||||
1 1 foo1 bar1
|
||||
1 2 foo2 bar2
|
||||
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;
|
||||
id_master id text1 text2
|
||||
1 1 ABCDE ABCDE
|
||||
@ -523,3 +523,204 @@ pla_id matintnum
|
||||
105 c
|
||||
0 0
|
||||
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'
|
||||
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;
|
||||
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;
|
||||
|
48
sql/field.h
48
sql/field.h
@ -230,6 +230,24 @@ public:
|
||||
virtual bool has_charset(void) const { return FALSE; }
|
||||
virtual void set_charset(CHARSET_INFO *charset) { }
|
||||
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 int cre_myisam(my_string name, register TABLE *form, uint options,
|
||||
ulonglong auto_increment_value);
|
||||
@ -334,6 +352,7 @@ public:
|
||||
void overflow(bool negative);
|
||||
bool zero_pack() const { return 0; }
|
||||
void sql_type(String &str) const;
|
||||
uint convert_order() { return 130; }
|
||||
};
|
||||
|
||||
|
||||
@ -369,6 +388,7 @@ public:
|
||||
void sort_string(char *buff,uint length);
|
||||
uint32 pack_length() const { return 1; }
|
||||
void sql_type(String &str) const;
|
||||
uint convert_order() { return 100; }
|
||||
};
|
||||
|
||||
|
||||
@ -404,6 +424,7 @@ public:
|
||||
void sort_string(char *buff,uint length);
|
||||
uint32 pack_length() const { return 2; }
|
||||
void sql_type(String &str) const;
|
||||
uint convert_order() { return 101; }
|
||||
};
|
||||
|
||||
|
||||
@ -434,6 +455,7 @@ public:
|
||||
void sort_string(char *buff,uint length);
|
||||
uint32 pack_length() const { return 3; }
|
||||
void sql_type(String &str) const;
|
||||
uint convert_order() { return 102; }
|
||||
};
|
||||
|
||||
|
||||
@ -469,6 +491,7 @@ public:
|
||||
void sort_string(char *buff,uint length);
|
||||
uint32 pack_length() const { return 4; }
|
||||
void sql_type(String &str) const;
|
||||
uint convert_order() { return 103; }
|
||||
};
|
||||
|
||||
|
||||
@ -507,6 +530,7 @@ public:
|
||||
uint32 pack_length() const { return 8; }
|
||||
void sql_type(String &str) const;
|
||||
bool store_for_compare() { return 1; }
|
||||
uint convert_order() { return 104; }
|
||||
};
|
||||
#endif
|
||||
|
||||
@ -540,6 +564,7 @@ public:
|
||||
void sort_string(char *buff,uint length);
|
||||
uint32 pack_length() const { return sizeof(float); }
|
||||
void sql_type(String &str) const;
|
||||
uint convert_order() { return 300; }
|
||||
};
|
||||
|
||||
|
||||
@ -573,6 +598,7 @@ public:
|
||||
void sort_string(char *buff,uint length);
|
||||
uint32 pack_length() const { return sizeof(double); }
|
||||
void sql_type(String &str) const;
|
||||
uint convert_order() { return 301; }
|
||||
};
|
||||
|
||||
|
||||
@ -606,6 +632,7 @@ public:
|
||||
uint32 pack_length() const { return 0; }
|
||||
void sql_type(String &str) const;
|
||||
uint size_of() const { return sizeof(*this); }
|
||||
uint convert_order() { return 0; }
|
||||
};
|
||||
|
||||
|
||||
@ -649,6 +676,8 @@ public:
|
||||
}
|
||||
bool get_date(TIME *ltime,uint fuzzydate);
|
||||
bool get_time(TIME *ltime);
|
||||
uint convert_order() { return 520; }
|
||||
bool convert_order_compatible(uint ord) { return ord<520; }
|
||||
};
|
||||
|
||||
|
||||
@ -674,6 +703,8 @@ public:
|
||||
String *val_str(String*,String *);
|
||||
bool send_binary(Protocol *protocol);
|
||||
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:
|
||||
void sql_type(String &str) const;
|
||||
bool store_for_compare() { 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 {
|
||||
@ -737,6 +770,8 @@ public:
|
||||
bool zero_pack() const { return 1; }
|
||||
bool get_date(TIME *ltime,uint fuzzydate);
|
||||
bool get_time(TIME *ltime);
|
||||
uint convert_order() { return 503; }
|
||||
bool convert_order_compatible(uint ord) { return ord<520; }
|
||||
};
|
||||
|
||||
|
||||
@ -770,6 +805,8 @@ public:
|
||||
void sql_type(String &str) const;
|
||||
bool store_for_compare() { 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:
|
||||
bool zero_pack() const { return 1; }
|
||||
bool get_date(TIME *ltime,uint fuzzydate);
|
||||
bool get_time(TIME *ltime);
|
||||
uint convert_order() { return 530; }
|
||||
bool convert_order_compatible(uint ord) { return ord<=501; }
|
||||
};
|
||||
|
||||
|
||||
@ -851,6 +890,7 @@ public:
|
||||
uint size_of() const { return sizeof(*this); }
|
||||
enum_field_types real_type() const { return FIELD_TYPE_STRING; }
|
||||
bool has_charset(void) const { return TRUE; }
|
||||
uint convert_order() { return 700; }
|
||||
};
|
||||
|
||||
|
||||
@ -894,6 +934,7 @@ public:
|
||||
uint size_of() const { return sizeof(*this); }
|
||||
enum_field_types real_type() const { return FIELD_TYPE_VAR_STRING; }
|
||||
bool has_charset(void) const { return TRUE; }
|
||||
uint convert_order() { return 701; }
|
||||
};
|
||||
|
||||
|
||||
@ -983,6 +1024,7 @@ public:
|
||||
uint size_of() const { return sizeof(*this); }
|
||||
bool has_charset(void) const
|
||||
{ return charset() == &my_charset_bin ? FALSE : TRUE; }
|
||||
uint convert_order() { return 701; }
|
||||
};
|
||||
|
||||
|
||||
@ -1011,6 +1053,8 @@ public:
|
||||
|
||||
void get_key_image(char *buff,uint length, CHARSET_INFO *cs,imagetype type);
|
||||
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:
|
||||
bool optimize_range(uint idx) { return 0; }
|
||||
bool eq_def(Field *field);
|
||||
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:
|
||||
void sql_type(String &str) const;
|
||||
enum_field_types real_type() const { return FIELD_TYPE_SET; }
|
||||
bool has_charset(void) const { return TRUE; }
|
||||
uint convert_order() { return 40; }
|
||||
bool convert_order_compatible(uint ord) { return ord < 40; };
|
||||
};
|
||||
|
||||
|
||||
|
121
sql/item.cc
121
sql/item.cc
@ -312,7 +312,7 @@ void Item_field::set_field(Field *field_par)
|
||||
const char *Item_ident::full_name() const
|
||||
{
|
||||
char *tmp;
|
||||
if (!table_name)
|
||||
if (!table_name || !field_name)
|
||||
return field_name ? field_name : name ? name : "tmp_field";
|
||||
if (db_name && db_name[0])
|
||||
{
|
||||
@ -1876,6 +1876,8 @@ void Item_cache_str::store(Item *item)
|
||||
}
|
||||
collation.set(item->collation);
|
||||
}
|
||||
|
||||
|
||||
double Item_cache_str::val()
|
||||
{
|
||||
int err;
|
||||
@ -1885,6 +1887,8 @@ double Item_cache_str::val()
|
||||
else
|
||||
return (double)0;
|
||||
}
|
||||
|
||||
|
||||
longlong Item_cache_str::val_int()
|
||||
{
|
||||
int err;
|
||||
@ -1895,6 +1899,7 @@ longlong Item_cache_str::val_int()
|
||||
return (longlong)0;
|
||||
}
|
||||
|
||||
|
||||
bool Item_cache_row::allocate(uint num)
|
||||
{
|
||||
item_count= num;
|
||||
@ -1903,6 +1908,7 @@ bool Item_cache_row::allocate(uint num)
|
||||
(Item_cache **) thd->calloc(sizeof(Item_cache *)*item_count)));
|
||||
}
|
||||
|
||||
|
||||
bool Item_cache_row::setup(Item * item)
|
||||
{
|
||||
example= item;
|
||||
@ -1919,6 +1925,7 @@ bool Item_cache_row::setup(Item * item)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void Item_cache_row::store(Item * item)
|
||||
{
|
||||
null_value= 0;
|
||||
@ -1930,6 +1937,7 @@ void Item_cache_row::store(Item * item)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Item_cache_row::illegal_method_call(const char *method)
|
||||
{
|
||||
DBUG_ENTER("Item_cache_row::illegal_method_call");
|
||||
@ -1939,6 +1947,7 @@ void Item_cache_row::illegal_method_call(const char *method)
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
||||
bool Item_cache_row::check_cols(uint c)
|
||||
{
|
||||
if (c != item_count)
|
||||
@ -1949,6 +1958,7 @@ bool Item_cache_row::check_cols(uint c)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
bool Item_cache_row::null_inside()
|
||||
{
|
||||
for (uint i= 0; i < item_count; i++)
|
||||
@ -1968,6 +1978,7 @@ bool Item_cache_row::null_inside()
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void Item_cache_row::bring_value()
|
||||
{
|
||||
for (uint i= 0; i < item_count; i++)
|
||||
@ -1975,6 +1986,114 @@ void Item_cache_row::bring_value()
|
||||
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
|
||||
*****************************************************************************/
|
||||
|
32
sql/item.h
32
sql/item.h
@ -98,7 +98,7 @@ public:
|
||||
COPY_STR_ITEM, FIELD_AVG_ITEM, DEFAULT_VALUE_ITEM,
|
||||
PROC_ITEM,COND_ITEM, REF_ITEM, FIELD_STD_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 };
|
||||
|
||||
@ -371,17 +371,17 @@ class Item_int :public Item
|
||||
public:
|
||||
const longlong value;
|
||||
Item_int(int32 i,uint length=11) :value((longlong) i)
|
||||
{ max_length=length;}
|
||||
{ max_length=length; fixed= 1; }
|
||||
#ifdef HAVE_LONG_LONG
|
||||
Item_int(longlong i,uint length=21) :value(i)
|
||||
{ max_length=length;}
|
||||
{ max_length=length; fixed= 1;}
|
||||
#endif
|
||||
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) :
|
||||
value(str_arg[0] == '-' ? strtoll(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 Item_result result_type () const { return INT_RESULT; }
|
||||
enum_field_types field_type() const { return MYSQL_TYPE_LONGLONG; }
|
||||
@ -969,6 +969,28 @@ public:
|
||||
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_result item_cmp_type(Item_result a,Item_result b);
|
||||
extern Item *resolve_const_item(Item *item,Item *cmp_item);
|
||||
|
@ -924,7 +924,7 @@ int subselect_single_select_engine::prepare()
|
||||
(ORDER*) select_lex->group_list.first,
|
||||
select_lex->having,
|
||||
(ORDER*) 0, select_lex,
|
||||
select_lex->master_unit(), 0))
|
||||
select_lex->master_unit()))
|
||||
return 1;
|
||||
thd->lex.current_select= save_select;
|
||||
return 0;
|
||||
@ -932,7 +932,7 @@ int subselect_single_select_engine::prepare()
|
||||
|
||||
int subselect_union_engine::prepare()
|
||||
{
|
||||
return unit->prepare(thd, result, 0);
|
||||
return unit->prepare(thd, result);
|
||||
}
|
||||
|
||||
int subselect_uniquesubquery_engine::prepare()
|
||||
@ -942,12 +942,12 @@ int subselect_uniquesubquery_engine::prepare()
|
||||
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_result res_type= STRING_RESULT;
|
||||
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++)
|
||||
{
|
||||
item->max_length= sel_item->max_length;
|
||||
@ -962,7 +962,7 @@ static Item_result set_row(SELECT_LEX *select_lex, Item * item,
|
||||
row[i]->collation.set(sel_item->collation);
|
||||
}
|
||||
}
|
||||
if (select_lex->item_list.elements > 1)
|
||||
if (item_list.elements > 1)
|
||||
res_type= ROW_RESULT;
|
||||
return res_type;
|
||||
}
|
||||
@ -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)
|
||||
{
|
||||
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);
|
||||
if (cols() != 1)
|
||||
maybe_null= 0;
|
||||
@ -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);
|
||||
|
||||
if (unit->first_select()->item_list.elements == 1)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
res_type= set_row(unit->types, item, row, &maybe_null);
|
||||
else
|
||||
{
|
||||
SELECT_LEX *sl= unit->first_select();
|
||||
bool fake= 0;
|
||||
res_type= set_row(sl, 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;
|
||||
}
|
||||
}
|
||||
res_type= set_row(unit->types, item, row, &fake);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -482,7 +482,7 @@ int mysql_select(THD *thd, Item ***rref_pointer_array,
|
||||
COND *conds, uint og_num, ORDER *order, ORDER *group,
|
||||
Item *having, ORDER *proc_param, ulong select_type,
|
||||
select_result *result, SELECT_LEX_UNIT *unit,
|
||||
SELECT_LEX *select_lex, bool tables_and_fields_initied);
|
||||
SELECT_LEX *select_lex);
|
||||
void free_underlaid_joins(THD *thd, SELECT_LEX *select);
|
||||
void fix_tables_pointers(SELECT_LEX *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,
|
||||
int mysql_explain_select(THD *thd, SELECT_LEX *sl, char const *type,
|
||||
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);
|
||||
Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
|
||||
Item ***copy_func, Field **from_field,
|
||||
@ -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,
|
||||
List<Item> &item, bool set_query_id,
|
||||
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_ftfuncs(SELECT_LEX* select);
|
||||
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,
|
||||
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
|
||||
|
@ -946,6 +946,7 @@ class select_union :public select_result {
|
||||
bool send_data(List<Item> &items);
|
||||
bool send_eof();
|
||||
bool flush();
|
||||
void set_table(TABLE *tbl) { table= tbl; }
|
||||
};
|
||||
|
||||
/* Base subselect interface class */
|
||||
|
@ -62,16 +62,15 @@
|
||||
int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit,
|
||||
TABLE_LIST *org_table_list)
|
||||
{
|
||||
SELECT_LEX *select_cursor= unit->first_select();
|
||||
List<Item> item_list;
|
||||
SELECT_LEX *first_select= unit->first_select();
|
||||
TABLE *table;
|
||||
int res;
|
||||
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;
|
||||
bool is_union= select_cursor->next_select() &&
|
||||
select_cursor->next_select()->linkage == UNION_TYPE;
|
||||
bool is_subsel= select_cursor->first_inner_unit() ? 1: 0;
|
||||
bool is_union= first_select->next_select() &&
|
||||
first_select->next_select()->linkage == UNION_TYPE;
|
||||
bool is_subsel= first_select->first_inner_unit() ? 1: 0;
|
||||
SELECT_LEX *save_current_select= lex->current_select;
|
||||
DBUG_ENTER("mysql_derived");
|
||||
|
||||
@ -112,16 +111,12 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit,
|
||||
fix_tables_pointers(unit);
|
||||
}
|
||||
|
||||
lex->current_select= select_cursor;
|
||||
TABLE_LIST *first_table= (TABLE_LIST*) select_cursor->table_list.first;
|
||||
/* Setting up. A must if a join or IGNORE, USE or similar are utilised */
|
||||
if (setup_tables(first_table) ||
|
||||
setup_wild(thd, first_table, select_cursor->item_list, 0,
|
||||
select_cursor->with_wild))
|
||||
{
|
||||
res= -1;
|
||||
if(!(derived_result= new select_union(0)))
|
||||
DBUG_RETURN(1); // out of memory
|
||||
|
||||
// st_select_lex_unit::prepare coppectly work for single select
|
||||
if ((res= unit->prepare(thd, derived_result)))
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/*
|
||||
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,
|
||||
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));
|
||||
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
|
||||
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,
|
||||
is_union && !unit->union_option, 1,
|
||||
(select_cursor->options | thd->options |
|
||||
(first_select->options | thd->options |
|
||||
TMP_TABLE_ALL_COLUMNS),
|
||||
HA_POS_ERROR,
|
||||
org_table_list->alias)))
|
||||
@ -164,70 +145,69 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit,
|
||||
res= -1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if ((derived_result=new select_union(table)))
|
||||
derived_result->set_table(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;
|
||||
unit->select_limit_cnt= select_cursor->select_limit+
|
||||
select_cursor->offset_limit;
|
||||
if (unit->select_limit_cnt < select_cursor->select_limit)
|
||||
unit->select_limit_cnt= HA_POS_ERROR;
|
||||
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);
|
||||
/*
|
||||
Here we entirely fix both TABLE_LIST and list of SELECT's as
|
||||
there were no derived tables
|
||||
*/
|
||||
if (derived_result->flush())
|
||||
res= 1;
|
||||
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)
|
||||
{
|
||||
/*
|
||||
Here we entirely fix both TABLE_LIST and list of SELECT's as
|
||||
there were no derived tables
|
||||
*/
|
||||
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;
|
||||
org_table_list->real_name=table->real_name;
|
||||
org_table_list->table=table;
|
||||
table->derived_select_number= first_select->select_number;
|
||||
table->tmp_table= TMP_TABLE;
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
org_table_list->grant.privilege= SELECT_ACL;
|
||||
org_table_list->grant.privilege= SELECT_ACL;
|
||||
#endif
|
||||
if (lex->describe)
|
||||
if (lex->describe)
|
||||
{
|
||||
// to fix a problem in EXPLAIN
|
||||
if (tables)
|
||||
{
|
||||
// to fix a problem in EXPLAIN
|
||||
if (tables)
|
||||
{
|
||||
for (TABLE_LIST *cursor= tables; cursor; cursor= cursor->next)
|
||||
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)
|
||||
free_tmp_table(thd, table);
|
||||
else
|
||||
|
@ -295,7 +295,6 @@ class JOIN;
|
||||
class select_union;
|
||||
class st_select_lex_unit: public st_select_lex_node {
|
||||
protected:
|
||||
List<Item> item_list;
|
||||
TABLE_LIST result_table_list;
|
||||
select_union *union_result;
|
||||
TABLE *table; /* temporary table using for appending UNION results */
|
||||
@ -305,9 +304,13 @@ protected:
|
||||
ulong found_rows_for_union;
|
||||
bool prepared, // prepare phase already performed for UNION (unit)
|
||||
optimized, // optimize phase already performed for UNION (unit)
|
||||
executed, // already executed
|
||||
t_and_f; // used for transferring tables_and_fields_initied UNIT:: methods
|
||||
executed; // already executed
|
||||
|
||||
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
|
||||
global parameters for union
|
||||
@ -342,7 +345,7 @@ public:
|
||||
void exclude_tree();
|
||||
|
||||
/* UNION methods */
|
||||
int prepare(THD *thd, select_result *result, bool tables_and_fields_initied);
|
||||
int prepare(THD *thd, select_result *result);
|
||||
int exec();
|
||||
int cleanup();
|
||||
|
||||
|
@ -2716,7 +2716,7 @@ mysql_execute_command(THD *thd)
|
||||
(ORDER *)NULL,
|
||||
select_lex->options | thd->options |
|
||||
SELECT_NO_JOIN_CACHE | SELECT_NO_UNLOCK,
|
||||
result, unit, select_lex, 0);
|
||||
result, unit, select_lex);
|
||||
if (thd->net.report_error)
|
||||
res= -1;
|
||||
delete result;
|
||||
|
@ -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,
|
||||
wild_num, conds, og_num, order, group, having, proc,
|
||||
select_lex, unit, 0))
|
||||
select_lex, unit))
|
||||
DBUG_RETURN(1);
|
||||
if (send_prep_stmt(stmt, fields.elements) ||
|
||||
thd->protocol_simple.send_fields(&fields, 0) ||
|
||||
|
@ -177,7 +177,7 @@ int handle_select(THD *thd, LEX *lex, select_result *result)
|
||||
|
||||
fix_tables_pointers(lex->all_selects_list);
|
||||
if (select_lex->next_select())
|
||||
res=mysql_union(thd, lex, result, &lex->unit, 0);
|
||||
res=mysql_union(thd, lex, result, &lex->unit);
|
||||
else
|
||||
res= mysql_select(thd, &select_lex->ref_pointer_array,
|
||||
(TABLE_LIST*) select_lex->table_list.first,
|
||||
@ -190,7 +190,7 @@ int handle_select(THD *thd, LEX *lex, select_result *result)
|
||||
select_lex->having,
|
||||
(ORDER*) lex->proc_list.first,
|
||||
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 */
|
||||
DBUG_PRINT("info",("res: %d report_error: %d", res,
|
||||
@ -285,8 +285,7 @@ JOIN::prepare(Item ***rref_pointer_array,
|
||||
ORDER *order_init, ORDER *group_init,
|
||||
Item *having_init,
|
||||
ORDER *proc_param_init, SELECT_LEX *select,
|
||||
SELECT_LEX_UNIT *unit,
|
||||
bool tables_and_fields_initied)
|
||||
SELECT_LEX_UNIT *unit)
|
||||
{
|
||||
DBUG_ENTER("JOIN::prepare");
|
||||
|
||||
@ -302,10 +301,8 @@ JOIN::prepare(Item ***rref_pointer_array,
|
||||
|
||||
/* Check that all tables, fields, conds and order are ok */
|
||||
|
||||
if ((tables_and_fields_initied ? 0 : (setup_tables(tables_list) ||
|
||||
setup_wild(thd, tables_list,
|
||||
fields_list,
|
||||
&all_fields, wild_num))) ||
|
||||
if (setup_tables(tables_list) ||
|
||||
setup_wild(thd, tables_list, fields_list, &all_fields, wild_num) ||
|
||||
select_lex->setup_ref_array(thd, og_num) ||
|
||||
setup_fields(thd, (*rref_pointer_array), tables_list, fields_list, 1,
|
||||
&all_fields, 1) ||
|
||||
@ -1536,7 +1533,7 @@ mysql_select(THD *thd, Item ***rref_pointer_array,
|
||||
COND *conds, uint og_num, ORDER *order, ORDER *group,
|
||||
Item *having, ORDER *proc_param, ulong select_options,
|
||||
select_result *result, SELECT_LEX_UNIT *unit,
|
||||
SELECT_LEX *select_lex, bool tables_and_fields_initied)
|
||||
SELECT_LEX *select_lex)
|
||||
{
|
||||
int err;
|
||||
bool free_join= 1;
|
||||
@ -1546,26 +1543,31 @@ mysql_select(THD *thd, Item ***rref_pointer_array,
|
||||
if (select_lex->join != 0)
|
||||
{
|
||||
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
|
||||
join->result= result;
|
||||
if (!join->procedure && result->prepare(join->fields_list, unit))
|
||||
if (select_lex->linkage != GLOBAL_OPTIONS_TYPE)
|
||||
{
|
||||
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
|
||||
{
|
||||
if (join->prepare(rref_pointer_array, tables, wild_num,
|
||||
conds, og_num, order, group, having, proc_param,
|
||||
select_lex, unit, tables_and_fields_initied))
|
||||
else
|
||||
{
|
||||
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;
|
||||
free_join= 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1574,7 +1576,7 @@ mysql_select(THD *thd, Item ***rref_pointer_array,
|
||||
thd->used_tables=0; // Updated by setup_fields
|
||||
if (join->prepare(rref_pointer_array, tables, wild_num,
|
||||
conds, og_num, order, group, having, proc_param,
|
||||
select_lex, unit, tables_and_fields_initied))
|
||||
select_lex, unit))
|
||||
{
|
||||
goto err;
|
||||
}
|
||||
@ -4545,6 +4547,115 @@ const_expression_in_where(COND *cond, Item *comp_item, Item **const_item)
|
||||
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
|
||||
|
||||
@ -4556,6 +4667,8 @@ const_expression_in_where(COND *cond, Item *comp_item, Item **const_item)
|
||||
type Type of item (normally item->type)
|
||||
copy_func If set and item is a function, store copy of item
|
||||
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
|
||||
modify_item 1 if item->result_field should point to new item.
|
||||
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,
|
||||
return 0; // Error
|
||||
}
|
||||
case Item::FIELD_ITEM:
|
||||
{
|
||||
Field *org_field=((Item_field*) item)->field,*new_field;
|
||||
|
||||
*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;
|
||||
}
|
||||
return create_tmp_field_from_field(thd, (*from_field=
|
||||
((Item_field*) item)->field),
|
||||
item, table, modify_item);
|
||||
case Item::FUNC_ITEM:
|
||||
case Item::COND_ITEM:
|
||||
case Item::FIELD_AVG_ITEM:
|
||||
@ -4653,40 +4751,14 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
|
||||
case Item::REF_ITEM:
|
||||
case Item::NULL_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 *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;
|
||||
Field *example= ((Item_type_holder *)item)->example();
|
||||
if (example)
|
||||
return create_tmp_field_from_field(thd, example, item, table, 0);
|
||||
return create_tmp_field_from_item(thd, item, table, copy_func, 0);
|
||||
}
|
||||
default: // Dosen't have to be stored
|
||||
return 0;
|
||||
@ -9077,7 +9149,7 @@ int mysql_explain_select(THD *thd, SELECT_LEX *select_lex, char const *type,
|
||||
select_lex->having,
|
||||
(ORDER*) thd->lex.proc_list.first,
|
||||
select_lex->options | thd->options | SELECT_DESCRIBE,
|
||||
result, unit, select_lex, 0);
|
||||
result, unit, select_lex);
|
||||
DBUG_RETURN(res);
|
||||
}
|
||||
|
||||
|
@ -266,7 +266,7 @@ class JOIN :public Sql_alloc
|
||||
int prepare(Item ***rref_pointer_array, TABLE_LIST *tables, uint wind_num,
|
||||
COND *conds, uint og_num, ORDER *order, ORDER *group,
|
||||
Item *having, ORDER *proc_param, SELECT_LEX *select,
|
||||
SELECT_LEX_UNIT *unit, bool tables_and_fields_initied);
|
||||
SELECT_LEX_UNIT *unit);
|
||||
int optimize();
|
||||
int reinit();
|
||||
void exec();
|
||||
|
162
sql/sql_union.cc
162
sql/sql_union.cc
@ -25,11 +25,11 @@
|
||||
#include "sql_select.h"
|
||||
|
||||
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");
|
||||
int res= 0;
|
||||
if (!(res= unit->prepare(thd, result, tables_and_fields_initied)))
|
||||
if (!(res= unit->prepare(thd, result)))
|
||||
res= unit->exec();
|
||||
res|= unit->cleanup();
|
||||
DBUG_RETURN(res);
|
||||
@ -59,12 +59,6 @@ select_union::~select_union()
|
||||
int select_union::prepare(List<Item> &list, SELECT_LEX_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;
|
||||
}
|
||||
|
||||
@ -112,11 +106,11 @@ bool select_union::flush()
|
||||
}
|
||||
|
||||
|
||||
int st_select_lex_unit::prepare(THD *thd, select_result *sel_result,
|
||||
bool tables_and_fields_initied)
|
||||
int st_select_lex_unit::prepare(THD *thd, select_result *sel_result)
|
||||
{
|
||||
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");
|
||||
|
||||
/*
|
||||
@ -129,74 +123,33 @@ int st_select_lex_unit::prepare(THD *thd, select_result *sel_result,
|
||||
DBUG_RETURN(0);
|
||||
prepared= 1;
|
||||
res= 0;
|
||||
found_rows_for_union= first_select_in_union()->options & OPTION_FOUND_ROWS;
|
||||
TMP_TABLE_PARAM tmp_table_param;
|
||||
t_and_f= tables_and_fields_initied;
|
||||
|
||||
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 */
|
||||
if (t_and_f)
|
||||
|
||||
if (first_select->next_select())
|
||||
{
|
||||
// Item list and tables will be initialized by mysql_derived
|
||||
item_list= select_cursor->item_list;
|
||||
if (!(tmp_result= union_result= new select_union(0)))
|
||||
goto err;
|
||||
union_result->not_describe= 1;
|
||||
union_result->tmp_table_param= tmp_table_param;
|
||||
}
|
||||
else
|
||||
{
|
||||
item_list.empty();
|
||||
TABLE_LIST *first_table= (TABLE_LIST*) select_cursor->table_list.first;
|
||||
|
||||
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_result= sel_result;
|
||||
// single select should be processed like select in p[arantses
|
||||
first_select->braces= 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())
|
||||
{
|
||||
JOIN *join= new JOIN(thd, sl->item_list,
|
||||
sl->options | thd->options | SELECT_NO_UNLOCK,
|
||||
union_result);
|
||||
tmp_result);
|
||||
thd->lex.current_select= sl;
|
||||
offset_limit_cnt= 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,
|
||||
(ORDER*) sl->group_list.first,
|
||||
sl->having,
|
||||
(ORDER*) NULL,
|
||||
sl, this, t_and_f);
|
||||
t_and_f= 0;
|
||||
sl, this);
|
||||
if (res || thd->is_fatal_error)
|
||||
goto err;
|
||||
}
|
||||
|
||||
item_list.empty();
|
||||
thd->lex.current_select= lex_select_save;
|
||||
{
|
||||
List_iterator<Item> it(select_cursor->item_list);
|
||||
Field **field;
|
||||
|
||||
for (field= table->field; *field; field++)
|
||||
if (sl == first_select)
|
||||
{
|
||||
(void) it++;
|
||||
if (item_list.push_back(new Item_field(*field)))
|
||||
DBUG_RETURN(-1);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (first_select->next_select())
|
||||
{
|
||||
tmp_table_param.field_count= types.elements;
|
||||
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);
|
||||
|
||||
item_list.empty();
|
||||
thd->lex.current_select= lex_select_save;
|
||||
{
|
||||
Field **field;
|
||||
for (field= table->field; *field; field++)
|
||||
{
|
||||
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);
|
||||
|
||||
err:
|
||||
thd->lex.current_select= lex_select_save;
|
||||
DBUG_RETURN(-1);
|
||||
@ -419,7 +421,7 @@ int st_select_lex_unit::exec()
|
||||
(ORDER*)global_parameters->order_list.first,
|
||||
(ORDER*) NULL, NULL, (ORDER*) NULL,
|
||||
options | SELECT_NO_UNLOCK,
|
||||
result, this, fake_select_lex, 0);
|
||||
result, this, fake_select_lex);
|
||||
if (!res)
|
||||
thd->limit_found_rows = (ulonglong)table->file->records + add_rows;
|
||||
/*
|
||||
|
@ -461,7 +461,7 @@ int mysql_multi_update(THD *thd,
|
||||
conds, 0, (ORDER *) NULL, (ORDER *)NULL, (Item *) NULL,
|
||||
(ORDER *)NULL,
|
||||
options | SELECT_NO_JOIN_CACHE | SELECT_NO_UNLOCK,
|
||||
result, unit, select_lex, 0);
|
||||
result, unit, select_lex);
|
||||
delete result;
|
||||
DBUG_RETURN(res);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user