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

Merge

parents cff4a437 0c5b323d
...@@ -95,7 +95,17 @@ id select_type table type possible_keys key key_len ref rows Extra ...@@ -95,7 +95,17 @@ id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 8 1 PRIMARY <derived2> ALL NULL NULL NULL NULL 8
2 DERIVED t1 ALL NULL NULL NULL NULL 4 2 DERIVED t1 ALL NULL NULL NULL NULL 4
3 UNION t1 ALL NULL NULL NULL NULL 4 3 UNION t1 ALL NULL NULL NULL NULL 4
drop table if exists t1; CREATE TABLE t2 (a int not null);
insert into t2 values(1);
select * from (select * from t1 where t1.a=(select a from t2 where t2.a=t1.a)) a;
a b
1 a
select * from (select * from t1 where t1.a=(select t2.a from t2 where t2.a=t1.a) union select t1.a, t1.b from t1) a;
a b
1 a
2 b
3 c
drop table t1, t2;
create table t1(a int not null, t char(8), index(a)); create table t1(a int not null, t char(8), index(a));
SELECT * FROM (SELECT * FROM t1) as b ORDER BY a ASC LIMIT 0,20; SELECT * FROM (SELECT * FROM t1) as b ORDER BY a ASC LIMIT 0,20;
a t a t
......
...@@ -155,21 +155,18 @@ select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1); ...@@ -155,21 +155,18 @@ select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1);
a b a b
1 7 1 7
2 7 2 7
(select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)) (select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)) union (select * from t4 order by a limit 2) limit 3;
union (select * from t4 order by a limit 2) limit 3;
a b a b
1 7 1 7
2 7 2 7
3 8 3 8
(select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)) (select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)) union (select * from t4 where t4.b=(select max(t2.a)*4 from t2) order by a);
union (select * from t4 where t4.b=(select max(t2.a)*4 from t2) order by a);
a b a b
1 7 1 7
2 7 2 7
3 8 3 8
4 8 4 8
explain (select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)) explain (select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)) union (select * from t4 where t4.b=(select max(t2.a)*4 from t2) order by a);
union (select * from t4 where t4.b=(select max(t2.a)*4 from t2) order by a);
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Using where 1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Using where
2 SUBSELECT t3 ALL NULL NULL NULL NULL 3 Using filesort 2 SUBSELECT t3 ALL NULL NULL NULL NULL 3 Using filesort
...@@ -281,7 +278,7 @@ NULL 1 ...@@ -281,7 +278,7 @@ NULL 1
explain select (select a from t1 where t1.a=t2.a union select a from t5 where t5.a=t2.a), a from t2; explain select (select a from t1 where t1.a=t2.a union select a from t5 where t5.a=t2.a), a from t2;
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 2 1 PRIMARY t2 ALL NULL NULL NULL NULL 2
2 DEPENDENT SUBSELECT t1 system NULL NULL NULL NULL 1 Using where 2 DEPENDENT SUBSELECT t1 system NULL NULL NULL NULL 1
3 DEPENDENT UNION t5 ALL NULL NULL NULL NULL 2 Using where 3 DEPENDENT UNION t5 ALL NULL NULL NULL NULL 2 Using where
select (select a from t1 where t1.a=t2.a union all select a from t5 where t5.a=t2.a), a from t2; select (select a from t1 where t1.a=t2.a union all select a from t5 where t5.a=t2.a), a from t2;
Subselect returns more than 1 record Subselect returns more than 1 record
...@@ -324,9 +321,9 @@ INSERT INTO t8 (pseudo,email) VALUES ('2joce1','2test1'); ...@@ -324,9 +321,9 @@ INSERT INTO t8 (pseudo,email) VALUES ('2joce1','2test1');
EXPLAIN SELECT pseudo,(SELECT email FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo='joce')) FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo='joce'); EXPLAIN SELECT pseudo,(SELECT email FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo='joce')) FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo='joce');
id select_type table type possible_keys key key_len ref rows Extra id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t8 const PRIMARY PRIMARY 35 const 1 1 PRIMARY t8 const PRIMARY PRIMARY 35 const 1
4 SUBSELECT t8 const PRIMARY PRIMARY 35 const 1 4 SUBSELECT t8 const PRIMARY PRIMARY 35 1
2 SUBSELECT t8 const PRIMARY PRIMARY 35 const 1 2 SUBSELECT t8 const PRIMARY PRIMARY 35 const 1
3 SUBSELECT t8 const PRIMARY PRIMARY 35 const 1 3 SUBSELECT t8 const PRIMARY PRIMARY 35 1
SELECT pseudo FROM t8 WHERE pseudo=(SELECT pseudo,email FROM SELECT pseudo FROM t8 WHERE pseudo=(SELECT pseudo,email FROM
t8 WHERE pseudo='joce'); t8 WHERE pseudo='joce');
Cardinality error (more/less than 1 columns) Cardinality error (more/less than 1 columns)
...@@ -400,36 +397,51 @@ SELECT (SELECT 1) as a FROM (SELECT 1 FROM t1 HAVING a=1) b; ...@@ -400,36 +397,51 @@ SELECT (SELECT 1) as a FROM (SELECT 1 FROM t1 HAVING a=1) b;
Unknown column 'a' in 'having clause' Unknown column 'a' in 'having clause'
SELECT 1 IN (SELECT 1 FROM t2 HAVING a); SELECT 1 IN (SELECT 1 FROM t2 HAVING a);
Unknown column 'a' in 'having clause' Unknown column 'a' in 'having clause'
SELECT * from t2 where topic IN (SELECT topic FROM t2 GROUP BY date); SELECT * from t2 where topic IN (SELECT topic FROM t2 GROUP BY topic);
mot topic date pseudo mot topic date pseudo
joce 40143 2002-10-22 joce joce 40143 2002-10-22 joce
joce 43506 2002-10-22 joce joce 43506 2002-10-22 joce
SELECT * from t2 where topic IN (SELECT topic FROM t2 GROUP BY date HAVING topic < 4100); SELECT * from t2 where topic IN (SELECT topic FROM t2 GROUP BY topic HAVING topic < 4100);
mot topic date pseudo mot topic date pseudo
joce 43506 2002-10-22 joce
SELECT * from t2 where topic IN (SELECT SUM(topic) FROM t1); SELECT * from t2 where topic IN (SELECT SUM(topic) FROM t1);
mot topic date pseudo mot topic date pseudo
SELECT * from t2 where topic = any (SELECT topic FROM t2 GROUP BY date); SELECT * from t2 where topic = any (SELECT topic FROM t2 GROUP BY topic);
mot topic date pseudo mot topic date pseudo
joce 40143 2002-10-22 joce joce 40143 2002-10-22 joce
joce 43506 2002-10-22 joce joce 43506 2002-10-22 joce
SELECT * from t2 where topic = any (SELECT topic FROM t2 GROUP BY date HAVING topic < 4100); SELECT * from t2 where topic = any (SELECT topic FROM t2 GROUP BY topic HAVING topic < 4100);
mot topic date pseudo mot topic date pseudo
joce 43506 2002-10-22 joce
SELECT * from t2 where topic = any (SELECT SUM(topic) FROM t1); SELECT * from t2 where topic = any (SELECT SUM(topic) FROM t1);
mot topic date pseudo mot topic date pseudo
SELECT * from t2 where topic = all (SELECT topic FROM t2 GROUP BY date); SELECT * from t2 where topic = all (SELECT topic FROM t2 GROUP BY topic);
mot topic date pseudo mot topic date pseudo
joce 40143 2002-10-22 joce SELECT * from t2 where topic = all (SELECT topic FROM t2 GROUP BY topic HAVING topic < 4100);
SELECT * from t2 where topic = all (SELECT topic FROM t2 GROUP BY date HAVING topic < 4100);
mot topic date pseudo mot topic date pseudo
joce 40143 2002-10-22 joce joce 40143 2002-10-22 joce
joce 43506 2002-10-22 joce
SELECT *, topic = all (SELECT topic FROM t2 GROUP BY topic HAVING topic < 4100) from t2;
mot topic date pseudo topic = all (SELECT topic FROM t2 GROUP BY topic HAVING topic < 4100)
joce 40143 2002-10-22 joce 1
joce 43506 2002-10-22 joce 1
SELECT * from t2 where topic = all (SELECT SUM(topic) FROM t2); SELECT * from t2 where topic = all (SELECT SUM(topic) FROM t2);
mot topic date pseudo mot topic date pseudo
SELECT * from t2 where topic <> any (SELECT SUM(topic) FROM t2); SELECT * from t2 where topic <> any (SELECT SUM(topic) FROM t2);
mot topic date pseudo mot topic date pseudo
joce 40143 2002-10-22 joce joce 40143 2002-10-22 joce
joce 43506 2002-10-22 joce joce 43506 2002-10-22 joce
SELECT * from t2 where topic IN (SELECT topic FROM t2 GROUP BY topic HAVING topic < 41000);
mot topic date pseudo
joce 40143 2002-10-22 joce
SELECT * from t2 where topic = any (SELECT topic FROM t2 GROUP BY topic HAVING topic < 41000);
mot topic date pseudo
joce 40143 2002-10-22 joce
SELECT * from t2 where topic = all (SELECT topic FROM t2 GROUP BY topic HAVING topic < 41000);
mot topic date pseudo
joce 40143 2002-10-22 joce
SELECT *, topic = all (SELECT topic FROM t2 GROUP BY topic HAVING topic < 41000) from t2;
mot topic date pseudo topic = all (SELECT topic FROM t2 GROUP BY topic HAVING topic < 41000)
joce 40143 2002-10-22 joce 1
joce 43506 2002-10-22 joce 0
drop table t1,t2; drop table t1,t2;
CREATE TABLE `t1` ( CREATE TABLE `t1` (
`numeropost` mediumint(8) unsigned NOT NULL auto_increment, `numeropost` mediumint(8) unsigned NOT NULL auto_increment,
...@@ -856,3 +868,86 @@ do (SELECT a from t1); ...@@ -856,3 +868,86 @@ do (SELECT a from t1);
Table 'test.t1' doesn't exist Table 'test.t1' doesn't exist
set @a:=(SELECT a from t1); set @a:=(SELECT a from t1);
Table 'test.t1' doesn't exist Table 'test.t1' doesn't exist
CREATE TABLE t1 (a int, KEY(a));
HANDLER t1 OPEN;
HANDLER t1 READ a=((SELECT 1));
You have an error in your SQL syntax. Check the manual that corresponds to your MySQL server version for the right syntax to use
HANDLER t1 CLOSE;
drop table t1;
create table t1 (a int);
create table t2 (b int);
insert into t1 values (1),(2);
insert into t2 values (1);
select a from t1 where a in (select a from t1 where a in (select b from t2));
a
1
drop table t1, t2;
create table t1 (a int, b int);
create table t2 like t1;
insert into t1 values (1,2),(1,3),(1,4),(1,5);
insert into t2 values (1,2),(1,3);
select * from t1 where row(a,b) in (select a,b from t2);
a b
1 2
1 3
drop table t1, t2;
CREATE TABLE `t1` (`i` int(11) NOT NULL default '0',PRIMARY KEY (`i`)) TYPE=MyISAM CHARSET=latin1;
INSERT INTO t1 VALUES (1);
UPDATE t1 SET i=i+1 WHERE i=(SELECT MAX(i));
Invalid use of group function
drop table t1;
CREATE TABLE t (a int(1));
EXPLAIN SELECT (SELECT RAND() FROM t) FROM t;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t system NULL NULL NULL NULL 0 const row not found
2 UNCACHEABLE SUBSELECT t system NULL NULL NULL NULL 0 const row not found
EXPLAIN SELECT (SELECT ENCRYPT('test') FROM t) FROM t;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t system NULL NULL NULL NULL 0 const row not found
2 UNCACHEABLE SUBSELECT t system NULL NULL NULL NULL 0 const row not found
EXPLAIN SELECT (SELECT BENCHMARK(1,1) FROM t) FROM t;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t system NULL NULL NULL NULL 0 const row not found
2 UNCACHEABLE SUBSELECT t system NULL NULL NULL NULL 0 const row not found
drop table t;
CREATE TABLE `t1` (
`mot` varchar(30) character set latin1 NOT NULL default '',
`topic` mediumint(8) unsigned NOT NULL default '0',
`date` date NOT NULL default '0000-00-00',
`pseudo` varchar(35) character set latin1 NOT NULL default '',
PRIMARY KEY (`mot`,`pseudo`,`date`,`topic`),
KEY `pseudo` (`pseudo`,`date`,`topic`),
KEY `topic` (`topic`)
) TYPE=MyISAM CHARSET=latin1 ROW_FORMAT=DYNAMIC;
CREATE TABLE `t2` (
`mot` varchar(30) character set latin1 NOT NULL default '',
`topic` mediumint(8) unsigned NOT NULL default '0',
`date` date NOT NULL default '0000-00-00',
`pseudo` varchar(35) character set latin1 NOT NULL default '',
PRIMARY KEY (`mot`,`pseudo`,`date`,`topic`),
KEY `pseudo` (`pseudo`,`date`,`topic`),
KEY `topic` (`topic`)
) TYPE=MyISAM CHARSET=latin1 ROW_FORMAT=DYNAMIC;
CREATE TABLE `t3` (
`numeropost` mediumint(8) unsigned NOT NULL auto_increment,
`maxnumrep` int(10) unsigned NOT NULL default '0',
PRIMARY KEY (`numeropost`),
UNIQUE KEY `maxnumrep` (`maxnumrep`)
) TYPE=MyISAM CHARSET=latin1;
INSERT INTO t1 VALUES ('joce','1','','joce'),('test','2','','test');
INSERT INTO t2 VALUES ('joce','1','','joce'),('test','2','','test');
INSERT INTO t3 VALUES (1,1);
SELECT DISTINCT topic FROM t2 WHERE NOT EXISTS(SELECT * FROM t3 WHERE
numeropost=topic);
topic
2
select * from t1;
mot topic date pseudo
joce 1 0000-00-00 joce
test 2 0000-00-00 test
DELETE FROM t1 WHERE topic IN (SELECT DISTINCT topic FROM t2 WHERE NOT
EXISTS(SELECT * FROM t3 WHERE numeropost=topic));
select * from t1;
mot topic date pseudo
joce 1 0000-00-00 joce
drop table t1, t2, t3;
...@@ -37,7 +37,11 @@ select * from (select * from t1 union select * from t1) a; ...@@ -37,7 +37,11 @@ select * from (select * from t1 union select * from t1) a;
select * from (select * from t1 union all select * from t1) a; select * from (select * from t1 union all select * from t1) a;
explain select * from (select * from t1 union select * from t1) a; explain select * from (select * from t1 union select * from t1) a;
explain select * from (select * from t1 union all select * from t1) a; explain select * from (select * from t1 union all select * from t1) a;
drop table if exists t1; CREATE TABLE t2 (a int not null);
insert into t2 values(1);
select * from (select * from t1 where t1.a=(select a from t2 where t2.a=t1.a)) a;
select * from (select * from t1 where t1.a=(select t2.a from t2 where t2.a=t1.a) union select t1.a, t1.b from t1) a;
drop table t1, t2;
create table t1(a int not null, t char(8), index(a)); create table t1(a int not null, t char(8), index(a));
disable_query_log; disable_query_log;
let $1 = 10000; let $1 = 10000;
......
...@@ -70,12 +70,9 @@ select (select a from t3), a from t2; ...@@ -70,12 +70,9 @@ select (select a from t3), a from t2;
select * from t2 where t2.a=(select a from t1); select * from t2 where t2.a=(select a from t1);
insert into t3 values (6),(7),(3); insert into t3 values (6),(7),(3);
select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1); select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1);
(select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)) (select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)) union (select * from t4 order by a limit 2) limit 3;
union (select * from t4 order by a limit 2) limit 3; (select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)) union (select * from t4 where t4.b=(select max(t2.a)*4 from t2) order by a);
(select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)) explain (select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1)) union (select * from t4 where t4.b=(select max(t2.a)*4 from t2) order by a);
union (select * from t4 where t4.b=(select max(t2.a)*4 from t2) order by a);
explain (select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1))
union (select * from t4 where t4.b=(select max(t2.a)*4 from t2) order by a);
select (select a from t3 where a<t2.a*4 order by 1 desc limit 1), a from t2; select (select a from t3 where a<t2.a*4 order by 1 desc limit 1), a from t2;
select (select t3.a from t3 where a<8 order by 1 desc limit 1), a from select (select t3.a from t3 where a<8 order by 1 desc limit 1), a from
(select * from t2 where a>1) as tt; (select * from t2 where a>1) as tt;
...@@ -209,16 +206,22 @@ SELECT numeropost,maxnumrep FROM t1 WHERE exists (SELECT 1 FROM t2 WHERE (mot='j ...@@ -209,16 +206,22 @@ SELECT numeropost,maxnumrep FROM t1 WHERE exists (SELECT 1 FROM t2 WHERE (mot='j
SELECT (SELECT 1) as a FROM (SELECT 1 FROM t1 HAVING a=1) b; SELECT (SELECT 1) as a FROM (SELECT 1 FROM t1 HAVING a=1) b;
-- error 1054 -- error 1054
SELECT 1 IN (SELECT 1 FROM t2 HAVING a); SELECT 1 IN (SELECT 1 FROM t2 HAVING a);
SELECT * from t2 where topic IN (SELECT topic FROM t2 GROUP BY date);
SELECT * from t2 where topic IN (SELECT topic FROM t2 GROUP BY date HAVING topic < 4100); SELECT * from t2 where topic IN (SELECT topic FROM t2 GROUP BY topic);
SELECT * from t2 where topic IN (SELECT topic FROM t2 GROUP BY topic HAVING topic < 4100);
SELECT * from t2 where topic IN (SELECT SUM(topic) FROM t1); SELECT * from t2 where topic IN (SELECT SUM(topic) FROM t1);
SELECT * from t2 where topic = any (SELECT topic FROM t2 GROUP BY date); SELECT * from t2 where topic = any (SELECT topic FROM t2 GROUP BY topic);
SELECT * from t2 where topic = any (SELECT topic FROM t2 GROUP BY date HAVING topic < 4100); SELECT * from t2 where topic = any (SELECT topic FROM t2 GROUP BY topic HAVING topic < 4100);
SELECT * from t2 where topic = any (SELECT SUM(topic) FROM t1); SELECT * from t2 where topic = any (SELECT SUM(topic) FROM t1);
SELECT * from t2 where topic = all (SELECT topic FROM t2 GROUP BY date); SELECT * from t2 where topic = all (SELECT topic FROM t2 GROUP BY topic);
SELECT * from t2 where topic = all (SELECT topic FROM t2 GROUP BY date HAVING topic < 4100); SELECT * from t2 where topic = all (SELECT topic FROM t2 GROUP BY topic HAVING topic < 4100);
SELECT *, topic = all (SELECT topic FROM t2 GROUP BY topic HAVING topic < 4100) from t2;
SELECT * from t2 where topic = all (SELECT SUM(topic) FROM t2); SELECT * from t2 where topic = all (SELECT SUM(topic) FROM t2);
SELECT * from t2 where topic <> any (SELECT SUM(topic) FROM t2); SELECT * from t2 where topic <> any (SELECT SUM(topic) FROM t2);
SELECT * from t2 where topic IN (SELECT topic FROM t2 GROUP BY topic HAVING topic < 41000);
SELECT * from t2 where topic = any (SELECT topic FROM t2 GROUP BY topic HAVING topic < 41000);
SELECT * from t2 where topic = all (SELECT topic FROM t2 GROUP BY topic HAVING topic < 41000);
SELECT *, topic = all (SELECT topic FROM t2 GROUP BY topic HAVING topic < 41000) from t2;
drop table t1,t2; drop table t1,t2;
#forumconthardwarefr7 #forumconthardwarefr7
...@@ -480,3 +483,79 @@ drop table t1; ...@@ -480,3 +483,79 @@ drop table t1;
do (SELECT a from t1); do (SELECT a from t1);
-- error 1146 -- error 1146
set @a:=(SELECT a from t1); set @a:=(SELECT a from t1);
CREATE TABLE t1 (a int, KEY(a));
HANDLER t1 OPEN;
-- error 1149
HANDLER t1 READ a=((SELECT 1));
HANDLER t1 CLOSE;
drop table t1;
create table t1 (a int);
create table t2 (b int);
insert into t1 values (1),(2);
insert into t2 values (1);
select a from t1 where a in (select a from t1 where a in (select b from t2));
drop table t1, t2;
create table t1 (a int, b int);
create table t2 like t1;
insert into t1 values (1,2),(1,3),(1,4),(1,5);
insert into t2 values (1,2),(1,3);
select * from t1 where row(a,b) in (select a,b from t2);
drop table t1, t2;
CREATE TABLE `t1` (`i` int(11) NOT NULL default '0',PRIMARY KEY (`i`)) TYPE=MyISAM CHARSET=latin1;
INSERT INTO t1 VALUES (1);
-- error 1111
UPDATE t1 SET i=i+1 WHERE i=(SELECT MAX(i));
drop table t1;
#test of uncacheable subqueries
CREATE TABLE t (a int(1));
EXPLAIN SELECT (SELECT RAND() FROM t) FROM t;
EXPLAIN SELECT (SELECT ENCRYPT('test') FROM t) FROM t;
EXPLAIN SELECT (SELECT BENCHMARK(1,1) FROM t) FROM t;
drop table t;
CREATE TABLE `t1` (
`mot` varchar(30) character set latin1 NOT NULL default '',
`topic` mediumint(8) unsigned NOT NULL default '0',
`date` date NOT NULL default '0000-00-00',
`pseudo` varchar(35) character set latin1 NOT NULL default '',
PRIMARY KEY (`mot`,`pseudo`,`date`,`topic`),
KEY `pseudo` (`pseudo`,`date`,`topic`),
KEY `topic` (`topic`)
) TYPE=MyISAM CHARSET=latin1 ROW_FORMAT=DYNAMIC;
CREATE TABLE `t2` (
`mot` varchar(30) character set latin1 NOT NULL default '',
`topic` mediumint(8) unsigned NOT NULL default '0',
`date` date NOT NULL default '0000-00-00',
`pseudo` varchar(35) character set latin1 NOT NULL default '',
PRIMARY KEY (`mot`,`pseudo`,`date`,`topic`),
KEY `pseudo` (`pseudo`,`date`,`topic`),
KEY `topic` (`topic`)
) TYPE=MyISAM CHARSET=latin1 ROW_FORMAT=DYNAMIC;
CREATE TABLE `t3` (
`numeropost` mediumint(8) unsigned NOT NULL auto_increment,
`maxnumrep` int(10) unsigned NOT NULL default '0',
PRIMARY KEY (`numeropost`),
UNIQUE KEY `maxnumrep` (`maxnumrep`)
) TYPE=MyISAM CHARSET=latin1;
INSERT INTO t1 VALUES ('joce','1','','joce'),('test','2','','test');
INSERT INTO t2 VALUES ('joce','1','','joce'),('test','2','','test');
INSERT INTO t3 VALUES (1,1);
SELECT DISTINCT topic FROM t2 WHERE NOT EXISTS(SELECT * FROM t3 WHERE
numeropost=topic);
select * from t1;
DELETE FROM t1 WHERE topic IN (SELECT DISTINCT topic FROM t2 WHERE NOT
EXISTS(SELECT * FROM t3 WHERE numeropost=topic));
select * from t1;
drop table t1, t2, t3;
\ No newline at end of file
...@@ -46,6 +46,30 @@ Item::Item(): ...@@ -46,6 +46,30 @@ Item::Item():
loop_id= 0; loop_id= 0;
} }
Item::Item(Item &item):
loop_id(0),
str_value(item.str_value),
name(item.name),
max_length(item.max_length),
marker(item.marker),
decimals(item.decimals),
maybe_null(item.maybe_null),
null_value(item.null_value),
unsigned_flag(item.unsigned_flag),
with_sum_func(item.with_sum_func),
fixed(item.fixed)
{
next=current_thd->free_list; // Put in free list
current_thd->free_list= this;
}
Item_ident::Item_ident(Item_ident &item):
Item(item),
db_name(item.db_name),
table_name(item.table_name),
field_name(item.field_name),
depended_from(item.depended_from)
{}
bool Item::check_loop(uint id) bool Item::check_loop(uint id)
{ {
...@@ -154,6 +178,11 @@ Item_field::Item_field(Field *f) :Item_ident(NullS,f->table_name,f->field_name) ...@@ -154,6 +178,11 @@ Item_field::Item_field(Field *f) :Item_ident(NullS,f->table_name,f->field_name)
fixed= 1; // This item is not needed in fix_fields fixed= 1; // This item is not needed in fix_fields
} }
Item_field::Item_field(Item_field &item):
Item_ident(item),
field(item.field),
result_field(item.result_field)
{}
void Item_field::set_field(Field *field_par) void Item_field::set_field(Field *field_par)
{ {
...@@ -262,9 +291,16 @@ table_map Item_field::used_tables() const ...@@ -262,9 +291,16 @@ table_map Item_field::used_tables() const
{ {
if (field->table->const_table) if (field->table->const_table)
return 0; // const item return 0; // const item
return field->table->map; return (depended_from? RAND_TABLE_BIT : field->table->map);
} }
Item * Item_field::get_tmp_table_item()
{
Item_field *new_item= new Item_field(*this);
if (new_item)
new_item->field= new_item->result_field;
return new_item;
}
String *Item_int::val_str(String *str) String *Item_int::val_str(String *str)
{ {
...@@ -537,20 +573,14 @@ bool Item_ref_on_list_position::fix_fields(THD *thd, ...@@ -537,20 +573,14 @@ bool Item_ref_on_list_position::fix_fields(THD *thd,
struct st_table_list *tables, struct st_table_list *tables,
Item ** reference) Item ** reference)
{ {
List_iterator<Item> li(list); if (select_lex->item_list.elements <= pos)
Item *item;
for (uint i= 0; (item= li++) && i < pos; i++);
if (item)
{
ref= li.ref();
return Item_ref_null_helper::fix_fields(thd, tables, reference);
}
else
{ {
ref= 0; ref= 0;
my_error(ER_CARDINALITY_COL, MYF(0), pos); my_error(ER_CARDINALITY_COL, MYF(0), pos);
return 1; return 1;
} }
ref= select_lex->ref_pointer_array + pos;
return Item_ref_null_helper::fix_fields(thd, tables, reference);
} }
double Item_ref_null_helper::val() double Item_ref_null_helper::val()
...@@ -600,6 +630,7 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) ...@@ -600,6 +630,7 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
thd->net.last_errno= 0; thd->net.last_errno= 0;
#endif #endif
Item **refer= (Item **)not_found_item; Item **refer= (Item **)not_found_item;
uint counter= 0;
// Prevent using outer fields in subselects, that is not supported now // Prevent using outer fields in subselects, that is not supported now
SELECT_LEX *cursel=(SELECT_LEX *) thd->lex.current_select; SELECT_LEX *cursel=(SELECT_LEX *) thd->lex.current_select;
if (cursel->master_unit()->first_select()->linkage != DERIVED_TABLE_TYPE) if (cursel->master_unit()->first_select()->linkage != DERIVED_TABLE_TYPE)
...@@ -611,7 +642,7 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) ...@@ -611,7 +642,7 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
(last= sl)->get_table_list(), &where, (last= sl)->get_table_list(), &where,
0)) != not_found_field) 0)) != not_found_field)
break; break;
if ((refer= find_item_in_list(this, sl->item_list, if ((refer= find_item_in_list(this, sl->item_list, &counter,
REPORT_EXCEPT_NOT_FOUND)) != REPORT_EXCEPT_NOT_FOUND)) !=
(Item **)not_found_item) (Item **)not_found_item)
break; break;
...@@ -631,8 +662,16 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref) ...@@ -631,8 +662,16 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
} }
else if (refer != (Item **)not_found_item) else if (refer != (Item **)not_found_item)
{ {
if (!(*refer)->fixed)
{
my_error(ER_ILLEGAL_REFERENCE, MYF(0), name,
"forward reference in item list");
return -1;
}
Item_ref *r; Item_ref *r;
*ref= r= new Item_ref(refer, (char *)table_name, *ref= r= new Item_ref(last->ref_pointer_array + counter-1
, (char *)table_name,
(char *)field_name); (char *)field_name);
if (!r) if (!r)
return 1; return 1;
...@@ -1045,6 +1084,7 @@ bool Item_field::send(Protocol *protocol, String *buffer) ...@@ -1045,6 +1084,7 @@ bool Item_field::send(Protocol *protocol, String *buffer)
bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
{ {
uint counter= 0;
if (!ref) if (!ref)
{ {
TABLE_LIST *where= 0; TABLE_LIST *where= 0;
...@@ -1059,6 +1099,7 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) ...@@ -1059,6 +1099,7 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
if (outer_resolving || if (outer_resolving ||
(ref= find_item_in_list(this, (ref= find_item_in_list(this,
*(thd->lex.current_select->get_item_list()), *(thd->lex.current_select->get_item_list()),
&counter,
((sl && ((sl &&
thd->lex.current_select->master_unit()-> thd->lex.current_select->master_unit()->
first_select()->linkage != first_select()->linkage !=
...@@ -1081,7 +1122,8 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) ...@@ -1081,7 +1122,8 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
for ( ; sl ; sl= sl->outer_select()) for ( ; sl ; sl= sl->outer_select())
{ {
if ((ref= find_item_in_list(this, (last= sl)->item_list, if ((ref= find_item_in_list(this, (last= sl)->item_list,
REPORT_EXCEPT_NOT_FOUND)) != &counter,
REPORT_EXCEPT_NOT_FOUND)) !=
(Item **)not_found_item) (Item **)not_found_item)
break; break;
if ((tmp= find_field_in_tables(thd, this, if ((tmp= find_field_in_tables(thd, this,
...@@ -1102,6 +1144,7 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) ...@@ -1102,6 +1144,7 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
// Call to report error // Call to report error
find_item_in_list(this, find_item_in_list(this,
*(thd->lex.current_select->get_item_list()), *(thd->lex.current_select->get_item_list()),
&counter,
REPORT_ALL_ERRORS); REPORT_ALL_ERRORS);
ref= 0; ref= 0;
return 1; return 1;
...@@ -1118,17 +1161,35 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) ...@@ -1118,17 +1161,35 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
} }
else else
{ {
depended_from= last; if (!(*ref)->fixed)
{
my_error(ER_ILLEGAL_REFERENCE, MYF(0), name,
"forward reference in item list");
return -1;
}
ref= (depended_from= last)->ref_pointer_array + counter-1;
thd->lex.current_select->mark_as_dependent(last); thd->lex.current_select->mark_as_dependent(last);
thd->add_possible_loop(this); thd->add_possible_loop(this);
} }
} }
else if (!ref) else if (!ref)
return 1; return 1;
else
{
if (!(*ref)->fixed)
{
my_error(ER_ILLEGAL_REFERENCE, MYF(0), name,
"forward reference in item list");
return -1;
}
ref= thd->lex.current_select->ref_pointer_array + counter-1;
}
max_length= (*ref)->max_length; max_length= (*ref)->max_length;
maybe_null= (*ref)->maybe_null; maybe_null= (*ref)->maybe_null;
decimals= (*ref)->decimals; decimals= (*ref)->decimals;
} }
if (((*ref)->with_sum_func && if (((*ref)->with_sum_func &&
(depended_from || (depended_from ||
!(thd->lex.current_select->linkage != GLOBAL_OPTIONS_TYPE && !(thd->lex.current_select->linkage != GLOBAL_OPTIONS_TYPE &&
......
...@@ -53,6 +53,8 @@ public: ...@@ -53,6 +53,8 @@ public:
// alloc & destruct is done as start of select using sql_alloc // alloc & destruct is done as start of select using sql_alloc
Item(); Item();
// copy constructor used by Item_field, Item_ref & agregate (sum) functions
Item(Item &item);
virtual ~Item() { name=0; } /*lint -e1509 */ virtual ~Item() { name=0; } /*lint -e1509 */
void set_name(const char *str,uint length=0); void set_name(const char *str,uint length=0);
void init_make_field(Send_field *tmp_field,enum enum_field_types type); void init_make_field(Send_field *tmp_field,enum enum_field_types type);
...@@ -71,7 +73,8 @@ public: ...@@ -71,7 +73,8 @@ public:
virtual double val()=0; virtual double val()=0;
virtual longlong val_int()=0; virtual longlong val_int()=0;
virtual String *val_str(String*)=0; virtual String *val_str(String*)=0;
virtual Field *tmp_table_field(TABLE *t_arg=(TABLE *)0) { return 0; } virtual Field *tmp_table_field() { return 0; }
virtual Field *tmp_table_field(TABLE *t_arg) { return 0; }
virtual const char *full_name() const { return name ? name : "???"; } virtual const char *full_name() const { return name ? name : "???"; }
virtual double val_result() { return val(); } virtual double val_result() { return val(); }
virtual longlong val_int_result() { return val_int(); } virtual longlong val_int_result() { return val_int(); }
...@@ -85,12 +88,14 @@ public: ...@@ -85,12 +88,14 @@ public:
virtual bool const_item() const { return used_tables() == 0; } virtual bool const_item() const { return used_tables() == 0; }
virtual void print(String *str_arg) { str_arg->append(full_name()); } virtual void print(String *str_arg) { str_arg->append(full_name()); }
virtual void update_used_tables() {} virtual void update_used_tables() {}
virtual void split_sum_func(List<Item> &fields) {} virtual void split_sum_func(Item **ref_pointer_array, List<Item> &fields) {}
virtual bool get_date(TIME *ltime,bool fuzzydate); virtual bool get_date(TIME *ltime,bool fuzzydate);
virtual bool get_time(TIME *ltime); virtual bool get_time(TIME *ltime);
virtual bool is_null() { return 0; }; virtual bool is_null() { return 0; };
virtual bool check_loop(uint id); virtual bool check_loop(uint id);
virtual void top_level_item() {} virtual void top_level_item() {}
virtual Item * get_same() { return this; }
virtual Item * get_tmp_table_item() { return get_same(); }
virtual bool binary() const virtual bool binary() const
{ return str_value.charset()->state & MY_CS_BINSORT ? 1 : 0 ; } { return str_value.charset()->state & MY_CS_BINSORT ? 1 : 0 ; }
...@@ -125,6 +130,8 @@ public: ...@@ -125,6 +130,8 @@ public:
:db_name(db_name_par), table_name(table_name_par), :db_name(db_name_par), table_name(table_name_par),
field_name(field_name_par), depended_from(0), outer_resolving(0) field_name(field_name_par), depended_from(0), outer_resolving(0)
{ name = (char*) field_name_par; } { name = (char*) field_name_par; }
// copy constructor used by Item_field & Item_ref
Item_ident(Item_ident &item);
const char *full_name() const; const char *full_name() const;
void set_outer_resolving() { outer_resolving= 1; } void set_outer_resolving() { outer_resolving= 1; }
}; };
...@@ -141,6 +148,8 @@ public: ...@@ -141,6 +148,8 @@ public:
const char *field_name_par) const char *field_name_par)
:Item_ident(db_par,table_name_par,field_name_par),field(0),result_field(0) :Item_ident(db_par,table_name_par,field_name_par),field(0),result_field(0)
{} {}
// copy constructor need to process subselect with temporary tables
Item_field(Item_field &item);
Item_field(Field *field); Item_field(Field *field);
enum Type type() const { return FIELD_ITEM; } enum Type type() const { return FIELD_ITEM; }
bool eq(const Item *item, bool binary_cmp) const; bool eq(const Item *item, bool binary_cmp) const;
...@@ -164,10 +173,12 @@ public: ...@@ -164,10 +173,12 @@ public:
{ {
return field->type(); return field->type();
} }
Field *tmp_table_field(TABLE *t_arg=(TABLE *)0) { return result_field; } Field *tmp_table_field() { return result_field; }
Field *tmp_table_field(TABLE *t_arg) { return result_field; }
bool get_date(TIME *ltime,bool fuzzydate); bool get_date(TIME *ltime,bool fuzzydate);
bool get_time(TIME *ltime); bool get_time(TIME *ltime);
bool is_null() { return field->is_null(); } bool is_null() { return field->is_null(); }
Item * get_tmp_table_item();
friend class Item_default_value; friend class Item_default_value;
}; };
...@@ -427,8 +438,13 @@ class Item_result_field :public Item /* Item with result field */ ...@@ -427,8 +438,13 @@ class Item_result_field :public Item /* Item with result field */
public: public:
Field *result_field; /* Save result here */ Field *result_field; /* Save result here */
Item_result_field() :result_field(0) {} Item_result_field() :result_field(0) {}
Item_result_field(Item_result_field &item): Item(item)
{
result_field= item.result_field;
}
~Item_result_field() {} /* Required with gcc 2.95 */ ~Item_result_field() {} /* Required with gcc 2.95 */
Field *tmp_table_field(TABLE *t_arg=(TABLE *)0) { return result_field; } Field *tmp_table_field() { return result_field; }
Field *tmp_table_field(TABLE *t_arg) { return result_field; }
table_map used_tables() const { return 1; } table_map used_tables() const { return 1; }
virtual void fix_length_and_dec()=0; virtual void fix_length_and_dec()=0;
}; };
...@@ -442,6 +458,8 @@ public: ...@@ -442,6 +458,8 @@ public:
:Item_ident(db_par,table_name_par,field_name_par),ref(0) {} :Item_ident(db_par,table_name_par,field_name_par),ref(0) {}
Item_ref(Item **item, char *table_name_par,char *field_name_par) Item_ref(Item **item, char *table_name_par,char *field_name_par)
:Item_ident(NullS,table_name_par,field_name_par),ref(item) {} :Item_ident(NullS,table_name_par,field_name_par),ref(item) {}
// copy constructor need to process subselect with temporary tables
Item_ref(Item_ref &item): Item_ident(item), ref(item.ref) {}
enum Type type() const { return REF_ITEM; } enum Type type() const { return REF_ITEM; }
bool eq(const Item *item, bool binary_cmp) const bool eq(const Item *item, bool binary_cmp) const
{ return ref && (*ref)->eq(item, binary_cmp); } { return ref && (*ref)->eq(item, binary_cmp); }
...@@ -511,14 +529,14 @@ public: ...@@ -511,14 +529,14 @@ public:
class Item_ref_on_list_position: public Item_ref_null_helper class Item_ref_on_list_position: public Item_ref_null_helper
{ {
protected: protected:
List<Item> &list; st_select_lex *select_lex;
uint pos; uint pos;
public: public:
Item_ref_on_list_position(Item_in_subselect* master, Item_ref_on_list_position(Item_in_subselect* master,
List<Item> &li, uint num, st_select_lex *sl, uint num,
char *table_name, char *field_name): char *table_name, char *field_name):
Item_ref_null_helper(master, 0, table_name, field_name), Item_ref_null_helper(master, 0, table_name, field_name),
list(li), pos(num) {} select_lex(sl), pos(num) {}
bool fix_fields(THD *, struct st_table_list *, Item ** ref); bool fix_fields(THD *, struct st_table_list *, Item ** ref);
}; };
...@@ -692,7 +710,12 @@ public: ...@@ -692,7 +710,12 @@ public:
class Item_cache: public Item class Item_cache: public Item
{ {
table_map used_table_map;
public: public:
Item_cache(): used_table_map(0) {fixed= 1; null_value= 1;}
void set_used_tables(table_map map) { used_table_map= map; }
virtual bool allocate(uint i) { return 0; }; virtual bool allocate(uint i) { return 0; };
virtual bool setup(Item *) { return 0; }; virtual bool setup(Item *) { return 0; };
virtual void store(Item *)= 0; virtual void store(Item *)= 0;
...@@ -703,13 +726,14 @@ public: ...@@ -703,13 +726,14 @@ public:
} }
enum Type type() const { return CACHE_ITEM; } enum Type type() const { return CACHE_ITEM; }
static Item_cache* get_cache(Item_result type); static Item_cache* get_cache(Item_result type);
table_map used_tables() const { return used_table_map; }
}; };
class Item_cache_int: public Item_cache class Item_cache_int: public Item_cache
{ {
longlong value; longlong value;
public: public:
Item_cache_int() { fixed= 1; null_value= 1; } Item_cache_int(): Item_cache() {}
void store(Item *item) void store(Item *item)
{ {
...@@ -726,7 +750,7 @@ class Item_cache_real: public Item_cache ...@@ -726,7 +750,7 @@ class Item_cache_real: public Item_cache
{ {
double value; double value;
public: public:
Item_cache_real() { fixed= 1; null_value= 1; } Item_cache_real(): Item_cache() {}
void store(Item *item) void store(Item *item)
{ {
...@@ -748,7 +772,7 @@ class Item_cache_str: public Item_cache ...@@ -748,7 +772,7 @@ class Item_cache_str: public Item_cache
char buffer[80]; char buffer[80];
String *value; String *value;
public: public:
Item_cache_str() { fixed= 1; null_value= 1; } Item_cache_str(): Item_cache() { }
void store(Item *item); void store(Item *item);
double val(); double val();
...@@ -763,7 +787,7 @@ class Item_cache_row: public Item_cache ...@@ -763,7 +787,7 @@ class Item_cache_row: public Item_cache
Item_cache **values; Item_cache **values;
uint item_count; uint item_count;
public: public:
Item_cache_row(): values(0), item_count(2) { fixed= 1; null_value= 1; } Item_cache_row(): Item_cache(), values(0), item_count(2) {}
/* /*
'allocate' used only in row transformer, to preallocate space for row 'allocate' used only in row transformer, to preallocate space for row
......
...@@ -289,6 +289,14 @@ bool Item_in_optimizer::fix_fields(THD *thd, struct st_table_list *tables, ...@@ -289,6 +289,14 @@ bool Item_in_optimizer::fix_fields(THD *thd, struct st_table_list *tables,
if (!cache && !(cache= Item_cache::get_cache(args[0]->result_type()))) if (!cache && !(cache= Item_cache::get_cache(args[0]->result_type())))
return 1; return 1;
cache->setup(args[0]); cache->setup(args[0]);
if (cache->cols() == 1)
cache->set_used_tables(RAND_TABLE_BIT);
else
{
uint n= cache->cols();
for (uint i= 0; i < n; i++)
((Item_cache *)cache->el(i))->set_used_tables(RAND_TABLE_BIT);
}
if (args[1]->fix_fields(thd, tables, args)) if (args[1]->fix_fields(thd, tables, args))
return 1; return 1;
Item_in_subselect * sub= (Item_in_subselect *)args[1]; Item_in_subselect * sub= (Item_in_subselect *)args[1];
...@@ -1372,16 +1380,20 @@ void Item_func_in::update_used_tables() ...@@ -1372,16 +1380,20 @@ void Item_func_in::update_used_tables()
const_item_cache&=item->const_item(); const_item_cache&=item->const_item();
} }
void Item_func_in::split_sum_func(List<Item> &fields) void Item_func_in::split_sum_func(Item **ref_pointer_array, List<Item> &fields)
{ {
if (item->with_sum_func && item->type() != SUM_FUNC_ITEM) if (item->with_sum_func && item->type() != SUM_FUNC_ITEM)
item->split_sum_func(fields); item->split_sum_func(ref_pointer_array, fields);
else if (item->used_tables() || item->type() == SUM_FUNC_ITEM) else if (item->used_tables() || item->type() == SUM_FUNC_ITEM)
{ {
uint el= fields.elements;
fields.push_front(item); fields.push_front(item);
item=new Item_ref((Item**) fields.head_ref(),0,item->name); ref_pointer_array[el]= item;
item=new Item_ref(ref_pointer_array + el,
0, item->name);
} }
Item_func::split_sum_func(fields); Item_func::split_sum_func(ref_pointer_array, fields);
} }
...@@ -1487,7 +1499,7 @@ void Item_cond::set_outer_resolving() ...@@ -1487,7 +1499,7 @@ void Item_cond::set_outer_resolving()
item->set_outer_resolving(); item->set_outer_resolving();
} }
void Item_cond::split_sum_func(List<Item> &fields) void Item_cond::split_sum_func(Item **ref_pointer_array, List<Item> &fields)
{ {
List_iterator<Item> li(list); List_iterator<Item> li(list);
Item *item; Item *item;
...@@ -1496,11 +1508,13 @@ void Item_cond::split_sum_func(List<Item> &fields) ...@@ -1496,11 +1508,13 @@ void Item_cond::split_sum_func(List<Item> &fields)
while ((item=li++)) while ((item=li++))
{ {
if (item->with_sum_func && item->type() != SUM_FUNC_ITEM) if (item->with_sum_func && item->type() != SUM_FUNC_ITEM)
item->split_sum_func(fields); item->split_sum_func(ref_pointer_array, fields);
else if (item->used_tables() || item->type() == SUM_FUNC_ITEM) else if (item->used_tables() || item->type() == SUM_FUNC_ITEM)
{ {
uint el= fields.elements;
fields.push_front(item); fields.push_front(item);
li.replace(new Item_ref((Item**) fields.head_ref(),0,item->name)); ref_pointer_array[el]= item;
li.replace(new Item_ref(ref_pointer_array + el, 0, item->name));
} }
item->update_used_tables(); item->update_used_tables();
used_tables_cache|=item->used_tables(); used_tables_cache|=item->used_tables();
......
...@@ -17,8 +17,6 @@ ...@@ -17,8 +17,6 @@
/* compare and test functions */ /* compare and test functions */
#include "assert.h"
#ifdef __GNUC__ #ifdef __GNUC__
#pragma interface /* gcc class implementation */ #pragma interface /* gcc class implementation */
#endif #endif
...@@ -637,7 +635,7 @@ class Item_func_in :public Item_int_func ...@@ -637,7 +635,7 @@ class Item_func_in :public Item_int_func
enum Functype functype() const { return IN_FUNC; } enum Functype functype() const { return IN_FUNC; }
const char *func_name() const { return " IN "; } const char *func_name() const { return " IN "; }
void update_used_tables(); void update_used_tables();
void split_sum_func(List<Item> &fields); void split_sum_func(Item **ref_pointer_array, List<Item> &fields);
bool check_loop(uint id) bool check_loop(uint id)
{ {
DBUG_ENTER("Item_func_in::check_loop"); DBUG_ENTER("Item_func_in::check_loop");
...@@ -788,7 +786,7 @@ public: ...@@ -788,7 +786,7 @@ public:
table_map used_tables() const; table_map used_tables() const;
void update_used_tables(); void update_used_tables();
void print(String *str); void print(String *str);
void split_sum_func(List<Item> &fields); void split_sum_func(Item **ref_pointer_array, List<Item> &fields);
friend int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds); friend int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds);
bool check_loop(uint id); bool check_loop(uint id);
void top_level_item() { abort_on_null=1; } void top_level_item() { abort_on_null=1; }
......
...@@ -167,7 +167,7 @@ Item *create_func_from_days(Item* a) ...@@ -167,7 +167,7 @@ Item *create_func_from_days(Item* a)
Item *create_func_get_lock(Item* a, Item *b) Item *create_func_get_lock(Item* a, Item *b)
{ {
current_thd->lex.safe_to_cache_query=0; current_thd->lex.uncacheable();
return new Item_func_get_lock(a, b); return new Item_func_get_lock(a, b);
} }
...@@ -327,7 +327,7 @@ Item *create_func_radians(Item *a) ...@@ -327,7 +327,7 @@ Item *create_func_radians(Item *a)
Item *create_func_release_lock(Item* a) Item *create_func_release_lock(Item* a)
{ {
current_thd->lex.safe_to_cache_query=0; current_thd->lex.uncacheable();
return new Item_func_release_lock(a); return new Item_func_release_lock(a);
} }
...@@ -435,13 +435,13 @@ Item *create_func_year(Item* a) ...@@ -435,13 +435,13 @@ Item *create_func_year(Item* a)
Item *create_load_file(Item* a) Item *create_load_file(Item* a)
{ {
current_thd->lex.safe_to_cache_query=0; current_thd->lex.uncacheable();
return new Item_load_file(a); return new Item_load_file(a);
} }
Item *create_wait_for_master_pos(Item* a, Item* b) Item *create_wait_for_master_pos(Item* a, Item* b)
{ {
current_thd->lex.safe_to_cache_query=0; current_thd->lex.uncacheable();
return new Item_master_pos_wait(a, b); return new Item_master_pos_wait(a, b);
} }
...@@ -463,7 +463,7 @@ Item *create_func_cast(Item *a, Item_cast cast_type) ...@@ -463,7 +463,7 @@ Item *create_func_cast(Item *a, Item_cast cast_type)
Item *create_func_is_free_lock(Item* a) Item *create_func_is_free_lock(Item* a)
{ {
current_thd->lex.safe_to_cache_query=0; current_thd->lex.uncacheable();
return new Item_func_is_free_lock(a); return new Item_func_is_free_lock(a);
} }
......
...@@ -155,17 +155,19 @@ void Item_func::set_outer_resolving() ...@@ -155,17 +155,19 @@ void Item_func::set_outer_resolving()
} }
} }
void Item_func::split_sum_func(List<Item> &fields) void Item_func::split_sum_func(Item **ref_pointer_array, List<Item> &fields)
{ {
Item **arg,**arg_end; Item **arg,**arg_end;
for (arg=args, arg_end=args+arg_count; arg != arg_end ; arg++) for (arg=args, arg_end=args+arg_count; arg != arg_end ; arg++)
{ {
if ((*arg)->with_sum_func && (*arg)->type() != SUM_FUNC_ITEM) if ((*arg)->with_sum_func && (*arg)->type() != SUM_FUNC_ITEM)
(*arg)->split_sum_func(fields); (*arg)->split_sum_func(ref_pointer_array, fields);
else if ((*arg)->used_tables() || (*arg)->type() == SUM_FUNC_ITEM) else if ((*arg)->used_tables() || (*arg)->type() == SUM_FUNC_ITEM)
{ {
uint el= fields.elements;
fields.push_front(*arg); fields.push_front(*arg);
*arg=new Item_ref((Item**) fields.head_ref(),0,(*arg)->name); ref_pointer_array[el]= *arg;
*arg=new Item_ref(ref_pointer_array + el, 0, (*arg)->name);
} }
} }
} }
...@@ -234,14 +236,11 @@ bool Item_func::eq(const Item *item, bool binary_cmp) const ...@@ -234,14 +236,11 @@ bool Item_func::eq(const Item *item, bool binary_cmp) const
return 1; return 1;
} }
Field *Item_func::tmp_table_field(TABLE *t_arg) Field *Item_func::tmp_table_field(TABLE *t_arg)
{ {
Field *res; Field *res;
LINT_INIT(res); LINT_INIT(res);
if (!t_arg)
return result_field;
switch (result_type()) { switch (result_type()) {
case INT_RESULT: case INT_RESULT:
if (max_length > 11) if (max_length > 11)
...@@ -312,6 +311,16 @@ void Item_func::fix_num_length_and_dec() ...@@ -312,6 +311,16 @@ void Item_func::fix_num_length_and_dec()
max_length=float_length(decimals); max_length=float_length(decimals);
} }
Item * Item_func::get_tmp_table_item()
{
if (!with_sum_func && !const_item())
{
return new Item_field(result_field);
}
else
return get_same();
}
String *Item_int_func::val_str(String *str) String *Item_int_func::val_str(String *str)
{ {
longlong nr=val_int(); longlong nr=val_int();
...@@ -2535,7 +2544,7 @@ Item *get_system_var(enum_var_type var_type, LEX_STRING name) ...@@ -2535,7 +2544,7 @@ Item *get_system_var(enum_var_type var_type, LEX_STRING name)
} }
if (!(item=var->item(thd, var_type))) if (!(item=var->item(thd, var_type)))
return 0; // Impossible return 0; // Impossible
thd->lex.safe_to_cache_query=0; thd->lex.uncacheable();
buff[0]='@'; buff[0]='@';
buff[1]='@'; buff[1]='@';
pos=buff+2; pos=buff+2;
...@@ -2561,7 +2570,7 @@ Item *get_system_var(enum_var_type var_type, const char *var_name, uint length, ...@@ -2561,7 +2570,7 @@ Item *get_system_var(enum_var_type var_type, const char *var_name, uint length,
DBUG_ASSERT(var != 0); DBUG_ASSERT(var != 0);
if (!(item=var->item(thd, var_type))) if (!(item=var->item(thd, var_type)))
return 0; // Impossible return 0; // Impossible
thd->lex.safe_to_cache_query=0; thd->lex.uncacheable();
item->set_name(item_name); // Will use original name item->set_name(item_name); // Will use original name
return item; return item;
} }
......
...@@ -117,7 +117,7 @@ public: ...@@ -117,7 +117,7 @@ public:
inline Item **arguments() const { return args; } inline Item **arguments() const { return args; }
inline uint argument_count() const { return arg_count; } inline uint argument_count() const { return arg_count; }
inline void remove_arguments() { arg_count=0; } inline void remove_arguments() { arg_count=0; }
virtual void split_sum_func(List<Item> &fields); virtual void split_sum_func(Item **ref_pointer_array, List<Item> &fields);
void print(String *str); void print(String *str);
void print_op(String *str); void print_op(String *str);
void fix_num_length_and_dec(); void fix_num_length_and_dec();
...@@ -131,9 +131,11 @@ public: ...@@ -131,9 +131,11 @@ public:
} }
bool is_null() { (void) val_int(); return null_value; } bool is_null() { (void) val_int(); return null_value; }
friend class udf_handler; friend class udf_handler;
Field *tmp_table_field() { return result_field; }
Field *tmp_table_field(TABLE *t_arg); Field *tmp_table_field(TABLE *t_arg);
bool check_loop(uint id); bool check_loop(uint id);
void set_outer_resolving(); void set_outer_resolving();
Item * get_tmp_table_item();
}; };
......
...@@ -129,7 +129,8 @@ void Item_subselect::fix_length_and_dec() ...@@ -129,7 +129,8 @@ void Item_subselect::fix_length_and_dec()
inline table_map Item_subselect::used_tables() const inline table_map Item_subselect::used_tables() const
{ {
return (table_map) engine->depended() ? 1L : 0L; return (table_map) (engine->dependent() ? 1L :
(engine->uncacheable() ? RAND_TABLE_BIT : 0L));
} }
Item_singlerow_subselect::Item_singlerow_subselect(THD *thd, Item_singlerow_subselect::Item_singlerow_subselect(THD *thd,
...@@ -439,6 +440,7 @@ void Item_in_subselect::single_value_transformer(THD *thd, ...@@ -439,6 +440,7 @@ void Item_in_subselect::single_value_transformer(THD *thd,
compare_func_creator func) compare_func_creator func)
{ {
DBUG_ENTER("Item_in_subselect::single_value_transformer"); DBUG_ENTER("Item_in_subselect::single_value_transformer");
if (unit->global_parameters->select_limit != HA_POS_ERROR) if (unit->global_parameters->select_limit != HA_POS_ERROR)
{ {
my_error(ER_NOT_SUPPORTED_YET, MYF(0), my_error(ER_NOT_SUPPORTED_YET, MYF(0),
...@@ -482,11 +484,14 @@ void Item_in_subselect::single_value_transformer(THD *thd, ...@@ -482,11 +484,14 @@ void Item_in_subselect::single_value_transformer(THD *thd,
sl->order_list.empty(); // no sense in ORDER BY without LIMIT sl->order_list.empty(); // no sense in ORDER BY without LIMIT
if (sl->having || sl->with_sum_func || sl->group_list.first) if (sl->having || sl->with_sum_func || sl->group_list.elements)
{ {
sl->item_list.push_back(item); sl->item_list.push_back(item);
setup_ref_array(thd, &sl->ref_pointer_array,
1 + sl->with_sum_func +
sl->order_list.elements + sl->group_list.elements);
item= (*func)(expr, new Item_ref_null_helper(this, item= (*func)(expr, new Item_ref_null_helper(this,
sl->item_list.head_ref(), sl->ref_pointer_array,
(char *)"<no matter>", (char *)"<no matter>",
(char*)"<result>")); (char*)"<result>"));
sl->having= and_items(sl->having, item); sl->having= and_items(sl->having, item);
...@@ -591,9 +596,9 @@ void Item_in_subselect::row_value_transformer(THD *thd, ...@@ -591,9 +596,9 @@ void Item_in_subselect::row_value_transformer(THD *thd,
for (uint i= 0; i < n; i++) for (uint i= 0; i < n; i++)
{ {
Item *func= Item *func=
new Item_ref_on_list_position(this, sl->item_list, i, new Item_ref_on_list_position(this, sl, i,
(char *) "<no matter>", (char *) "<no matter>",
(char *) "<list ref>"); (char *) "<list ref>");
func= func=
Item_bool_func2::eq_creator(new Item_ref((*optimizer->get_cache())-> Item_bool_func2::eq_creator(new Item_ref((*optimizer->get_cache())->
addr(i), addr(i),
...@@ -678,8 +683,12 @@ int subselect_single_select_engine::prepare() ...@@ -678,8 +683,12 @@ int subselect_single_select_engine::prepare()
prepared= 1; prepared= 1;
SELECT_LEX_NODE *save_select= thd->lex.current_select; SELECT_LEX_NODE *save_select= thd->lex.current_select;
thd->lex.current_select= select_lex; thd->lex.current_select= select_lex;
if (join->prepare((TABLE_LIST*) select_lex->table_list.first, if (join->prepare(&select_lex->ref_pointer_array,
(TABLE_LIST*) select_lex->table_list.first,
select_lex->with_wild,
select_lex->where, select_lex->where,
select_lex->order_list.elements +
select_lex->group_list.elements,
(ORDER*) select_lex->order_list.first, (ORDER*) select_lex->order_list.first,
(ORDER*) select_lex->group_list.first, (ORDER*) select_lex->group_list.first,
select_lex->having, select_lex->having,
...@@ -787,7 +796,7 @@ int subselect_single_select_engine::exec() ...@@ -787,7 +796,7 @@ int subselect_single_select_engine::exec()
DBUG_RETURN(join->error?join->error:1); DBUG_RETURN(join->error?join->error:1);
} }
} }
if (select_lex->dependent && executed) if ((select_lex->dependent || select_lex->uncacheable) && executed)
{ {
if (join->reinit()) if (join->reinit())
{ {
...@@ -829,16 +838,26 @@ uint subselect_union_engine::cols() ...@@ -829,16 +838,26 @@ uint subselect_union_engine::cols()
return unit->first_select()->item_list.elements; return unit->first_select()->item_list.elements;
} }
bool subselect_single_select_engine::depended() bool subselect_single_select_engine::dependent()
{ {
return select_lex->dependent; return select_lex->dependent;
} }
bool subselect_union_engine::depended() bool subselect_union_engine::dependent()
{ {
return unit->dependent; return unit->dependent;
} }
bool subselect_single_select_engine::uncacheable()
{
return select_lex->uncacheable;
}
bool subselect_union_engine::uncacheable()
{
return unit->uncacheable;
}
bool subselect_single_select_engine::check_loop(uint id) bool subselect_single_select_engine::check_loop(uint id)
{ {
DBUG_ENTER("subselect_single_select_engine::check_loop"); DBUG_ENTER("subselect_single_select_engine::check_loop");
...@@ -857,13 +876,9 @@ bool subselect_union_engine::check_loop(uint id) ...@@ -857,13 +876,9 @@ bool subselect_union_engine::check_loop(uint id)
void subselect_single_select_engine::exclude() void subselect_single_select_engine::exclude()
{ {
select_lex->master_unit()->exclude_level(); select_lex->master_unit()->exclude_level();
//if (current_thd->lex->describe)
} }
void subselect_union_engine::exclude() void subselect_union_engine::exclude()
{ {
unit->exclude_level(); unit->exclude_level();
// for (SELECT_LEX *sl= unit->first_select(); sl; sl= sl->next_select())
// if (sl->join && sl->join->check_loop(id))
// DBUG_RETURN(1);
} }
...@@ -223,7 +223,8 @@ public: ...@@ -223,7 +223,8 @@ public:
virtual void fix_length_and_dec(Item_cache** row)= 0; virtual void fix_length_and_dec(Item_cache** row)= 0;
virtual int exec()= 0; virtual int exec()= 0;
virtual uint cols()= 0; /* return number of columnss in select */ virtual uint cols()= 0; /* return number of columnss in select */
virtual bool depended()= 0; /* depended from outer select */ virtual bool dependent()= 0; /* depended from outer select */
virtual bool uncacheable()= 0; /* query is uncacheable */
enum Item_result type() { return res_type; } enum Item_result type() { return res_type; }
virtual bool check_loop(uint id)= 0; virtual bool check_loop(uint id)= 0;
virtual void exclude()= 0; virtual void exclude()= 0;
...@@ -245,7 +246,8 @@ public: ...@@ -245,7 +246,8 @@ public:
void fix_length_and_dec(Item_cache** row); void fix_length_and_dec(Item_cache** row);
int exec(); int exec();
uint cols(); uint cols();
bool depended(); bool dependent();
bool uncacheable();
bool check_loop(uint id); bool check_loop(uint id);
void exclude(); void exclude();
}; };
...@@ -262,7 +264,8 @@ public: ...@@ -262,7 +264,8 @@ public:
void fix_length_and_dec(Item_cache** row); void fix_length_and_dec(Item_cache** row);
int exec(); int exec();
uint cols(); uint cols();
bool depended(); bool dependent();
bool uncacheable();
bool check_loop(uint id); bool check_loop(uint id);
void exclude(); void exclude();
}; };
...@@ -41,9 +41,22 @@ Item_sum::Item_sum(List<Item> &list) ...@@ -41,9 +41,22 @@ Item_sum::Item_sum(List<Item> &list)
list.empty(); // Fields are used list.empty(); // Fields are used
} }
Item_sum::Item_sum(Item_sum &item):
Item_result_field(item), quick_group(item.quick_group)
{
arg_count= item.arg_count;
if (arg_count <= 2)
args=tmp_args;
else
if (!(args=(Item**) sql_alloc(sizeof(Item*)*arg_count)))
return;
for(uint i= 0; i < arg_count; i++)
args[i]= item.args[i];
}
void Item_sum::mark_as_sum_func() void Item_sum::mark_as_sum_func()
{ {
current_thd->lex.current_select->with_sum_func=1; current_thd->lex.current_select->with_sum_func++;
with_sum_func= 1; with_sum_func= 1;
} }
...@@ -83,6 +96,26 @@ void Item_sum::fix_num_length_and_dec() ...@@ -83,6 +96,26 @@ void Item_sum::fix_num_length_and_dec()
max_length=float_length(decimals); max_length=float_length(decimals);
} }
Item * Item_sum::get_tmp_table_item()
{
Item_sum* sum_item= (Item_sum *) get_same();
if (sum_item && sum_item->result_field) // If not a const sum func
{
Field *result_field= sum_item->result_field;
for (uint i=0 ; i < sum_item->arg_count ; i++)
{
Item *arg= sum_item->args[i];
if (!arg->const_item())
{
if (arg->type() == Item::FIELD_ITEM)
((Item_field*) arg)->field= result_field++;
else
sum_item->args[i]= new Item_field(result_field++);
}
}
}
return sum_item;
}
String * String *
Item_sum_num::val_str(String *str) Item_sum_num::val_str(String *str)
...@@ -952,7 +985,7 @@ int dump_leaf(byte* key, uint32 count __attribute__((unused)), ...@@ -952,7 +985,7 @@ int dump_leaf(byte* key, uint32 count __attribute__((unused)),
The first item->rec_offset bytes are taken care of with The first item->rec_offset bytes are taken care of with
restore_record(table,2) in setup() restore_record(table,2) in setup()
*/ */
memcpy(buf + item->rec_offset, key, item->tree.size_of_element); memcpy(buf + item->rec_offset, key, item->tree->size_of_element);
if ((error = item->table->file->write_row(buf))) if ((error = item->table->file->write_row(buf)))
{ {
if (error != HA_ERR_FOUND_DUPP_KEY && if (error != HA_ERR_FOUND_DUPP_KEY &&
...@@ -965,11 +998,14 @@ int dump_leaf(byte* key, uint32 count __attribute__((unused)), ...@@ -965,11 +998,14 @@ int dump_leaf(byte* key, uint32 count __attribute__((unused)),
Item_sum_count_distinct::~Item_sum_count_distinct() Item_sum_count_distinct::~Item_sum_count_distinct()
{ {
if (table) if (!original)
free_tmp_table(current_thd, table); {
delete tmp_table_param; if (table)
if (use_tree) free_tmp_table(current_thd, table);
delete_tree(&tree); delete tmp_table_param;
if (use_tree)
delete_tree(tree);
}
} }
...@@ -1100,8 +1136,8 @@ bool Item_sum_count_distinct::setup(THD *thd) ...@@ -1100,8 +1136,8 @@ bool Item_sum_count_distinct::setup(THD *thd)
} }
} }
init_tree(&tree, min(thd->variables.max_heap_table_size, init_tree(tree, min(thd->variables.max_heap_table_size,
thd->variables.sortbuff_size/16), 0, thd->variables.sortbuff_size/16), 0,
key_length, compare_key, 0, NULL, cmp_arg); key_length, compare_key, 0, NULL, cmp_arg);
use_tree = 1; use_tree = 1;
...@@ -1113,6 +1149,12 @@ bool Item_sum_count_distinct::setup(THD *thd) ...@@ -1113,6 +1149,12 @@ bool Item_sum_count_distinct::setup(THD *thd)
*/ */
max_elements_in_tree = ((key_length) ? max_elements_in_tree = ((key_length) ?
thd->variables.max_heap_table_size/key_length : 1); thd->variables.max_heap_table_size/key_length : 1);
}
if (original)
{
original->table= table;
original->use_tree= use_tree;
} }
return 0; return 0;
} }
...@@ -1122,10 +1164,10 @@ int Item_sum_count_distinct::tree_to_myisam() ...@@ -1122,10 +1164,10 @@ int Item_sum_count_distinct::tree_to_myisam()
{ {
if (create_myisam_from_heap(current_thd, table, tmp_table_param, if (create_myisam_from_heap(current_thd, table, tmp_table_param,
HA_ERR_RECORD_FILE_FULL, 1) || HA_ERR_RECORD_FILE_FULL, 1) ||
tree_walk(&tree, (tree_walk_action)&dump_leaf, (void*)this, tree_walk(tree, (tree_walk_action)&dump_leaf, (void*)this,
left_root_right)) left_root_right))
return 1; return 1;
delete_tree(&tree); delete_tree(tree);
use_tree = 0; use_tree = 0;
return 0; return 0;
} }
...@@ -1133,7 +1175,7 @@ int Item_sum_count_distinct::tree_to_myisam() ...@@ -1133,7 +1175,7 @@ int Item_sum_count_distinct::tree_to_myisam()
void Item_sum_count_distinct::reset() void Item_sum_count_distinct::reset()
{ {
if (use_tree) if (use_tree)
reset_tree(&tree); reset_tree(tree);
else if (table) else if (table)
{ {
table->file->extra(HA_EXTRA_NO_CACHE); table->file->extra(HA_EXTRA_NO_CACHE);
...@@ -1161,13 +1203,13 @@ bool Item_sum_count_distinct::add() ...@@ -1161,13 +1203,13 @@ bool Item_sum_count_distinct::add()
If the tree got too big, convert to MyISAM, otherwise insert into the If the tree got too big, convert to MyISAM, otherwise insert into the
tree. tree.
*/ */
if (tree.elements_in_tree > max_elements_in_tree) if (tree->elements_in_tree > max_elements_in_tree)
{ {
if (tree_to_myisam()) if (tree_to_myisam())
return 1; return 1;
} }
else if (!tree_insert(&tree, table->record[0] + rec_offset, 0, else if (!tree_insert(tree, table->record[0] + rec_offset, 0,
tree.custom_arg)) tree->custom_arg))
return 1; return 1;
} }
else if ((error=table->file->write_row(table->record[0]))) else if ((error=table->file->write_row(table->record[0])))
...@@ -1189,7 +1231,7 @@ longlong Item_sum_count_distinct::val_int() ...@@ -1189,7 +1231,7 @@ longlong Item_sum_count_distinct::val_int()
if (!table) // Empty query if (!table) // Empty query
return LL(0); return LL(0);
if (use_tree) if (use_tree)
return tree.elements_in_tree; return tree->elements_in_tree;
table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK); table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
return table->file->records; return table->file->records;
} }
......
This diff is collapsed.
...@@ -327,9 +327,10 @@ public: ...@@ -327,9 +327,10 @@ public:
max_length=10*thd_charset()->mbmaxlen; max_length=10*thd_charset()->mbmaxlen;
} }
int save_in_field(Field *to, bool no_conversions); int save_in_field(Field *to, bool no_conversions);
Field *tmp_table_field() { return result_field; }
Field *tmp_table_field(TABLE *t_arg) Field *tmp_table_field(TABLE *t_arg)
{ {
return (!t_arg) ? result_field : new Field_date(maybe_null, name, t_arg, thd_charset()); return (new Field_date(maybe_null, name, t_arg, thd_charset()));
} }
}; };
...@@ -341,10 +342,10 @@ public: ...@@ -341,10 +342,10 @@ public:
Item_date_func(Item *a) :Item_str_func(a) {} Item_date_func(Item *a) :Item_str_func(a) {}
Item_date_func(Item *a,Item *b) :Item_str_func(a,b) {} Item_date_func(Item *a,Item *b) :Item_str_func(a,b) {}
enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; } enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; }
Field *tmp_table_field() { return result_field; }
Field *tmp_table_field(TABLE *t_arg) Field *tmp_table_field(TABLE *t_arg)
{ {
return (!t_arg) ? result_field : new Field_datetime(maybe_null, name, return (new Field_datetime(maybe_null, name, t_arg, thd_charset()));
t_arg, thd_charset());
} }
}; };
...@@ -364,10 +365,10 @@ public: ...@@ -364,10 +365,10 @@ public:
String *val_str(String *str); String *val_str(String *str);
const char *func_name() const { return "curtime"; } const char *func_name() const { return "curtime"; }
void fix_length_and_dec(); void fix_length_and_dec();
Field *tmp_table_field() { return result_field; }
Field *tmp_table_field(TABLE *t_arg) Field *tmp_table_field(TABLE *t_arg)
{ {
return (!t_arg) ? result_field : return (new Field_time(maybe_null, name, t_arg, thd_charset()));
new Field_time(maybe_null, name, t_arg, thd_charset());
} }
}; };
...@@ -462,10 +463,10 @@ public: ...@@ -462,10 +463,10 @@ public:
} }
enum_field_types field_type() const { return MYSQL_TYPE_TIME; } enum_field_types field_type() const { return MYSQL_TYPE_TIME; }
const char *func_name() const { return "sec_to_time"; } const char *func_name() const { return "sec_to_time"; }
Field *tmp_table_field() { return result_field; }
Field *tmp_table_field(TABLE *t_arg) Field *tmp_table_field(TABLE *t_arg)
{ {
return (!t_arg) ? result_field : return (new Field_time(maybe_null, name, t_arg, thd_charset()));
new Field_time(maybe_null, name, t_arg, thd_charset());
} }
}; };
...@@ -556,10 +557,10 @@ public: ...@@ -556,10 +557,10 @@ public:
Item_date_typecast(Item *a) :Item_typecast(a) {} Item_date_typecast(Item *a) :Item_typecast(a) {}
const char *func_name() const { return "date"; } const char *func_name() const { return "date"; }
enum_field_types field_type() const { return MYSQL_TYPE_DATE; } enum_field_types field_type() const { return MYSQL_TYPE_DATE; }
Field *tmp_table_field() { return result_field; }
Field *tmp_table_field(TABLE *t_arg) Field *tmp_table_field(TABLE *t_arg)
{ {
return (!t_arg) ? result_field : return (new Field_date(maybe_null, name, t_arg, thd_charset()));
new Field_date(maybe_null, name, t_arg, thd_charset());
} }
}; };
...@@ -570,10 +571,10 @@ public: ...@@ -570,10 +571,10 @@ public:
Item_time_typecast(Item *a) :Item_typecast(a) {} Item_time_typecast(Item *a) :Item_typecast(a) {}
const char *func_name() const { return "time"; } const char *func_name() const { return "time"; }
enum_field_types field_type() const { return MYSQL_TYPE_TIME; } enum_field_types field_type() const { return MYSQL_TYPE_TIME; }
Field *tmp_table_field() { return result_field; }
Field *tmp_table_field(TABLE *t_arg) Field *tmp_table_field(TABLE *t_arg)
{ {
return (!t_arg) ? result_field : return (new Field_time(maybe_null, name, t_arg, thd_charset()));
new Field_time(maybe_null, name, t_arg, thd_charset());
} }
}; };
...@@ -584,9 +585,9 @@ public: ...@@ -584,9 +585,9 @@ public:
Item_datetime_typecast(Item *a) :Item_typecast(a) {} Item_datetime_typecast(Item *a) :Item_typecast(a) {}
const char *func_name() const { return "datetime"; } const char *func_name() const { return "datetime"; }
enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; } enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; }
Field *tmp_table_field() { return result_field; }
Field *tmp_table_field(TABLE *t_arg) Field *tmp_table_field(TABLE *t_arg)
{ {
return (!t_arg) ? result_field : new Field_datetime(maybe_null, name, return (new Field_datetime(maybe_null, name, t_arg, thd_charset()));
t_arg, thd_charset());
} }
}; };
...@@ -37,6 +37,7 @@ class Item_sum_unique_users :public Item_sum_num ...@@ -37,6 +37,7 @@ class Item_sum_unique_users :public Item_sum_num
public: public:
Item_sum_unique_users(Item *name_arg,int start,int end,Item *item_arg) Item_sum_unique_users(Item *name_arg,int start,int end,Item *item_arg)
:Item_sum_num(item_arg) {} :Item_sum_num(item_arg) {}
Item_sum_unique_users(Item_sum_unique_users &item): Item_sum_num(item) {}
double val() { return 0.0; } double val() { return 0.0; }
enum Sumfunctype sum_func () const {return UNIQUE_USERS_FUNC;} enum Sumfunctype sum_func () const {return UNIQUE_USERS_FUNC;}
void reset() {} void reset() {}
...@@ -48,4 +49,5 @@ public: ...@@ -48,4 +49,5 @@ public:
fixed= 1; fixed= 1;
return 0; return 0;
} }
Item_sum * get_same() { return new Item_sum_unique_users(*this); }
}; };
...@@ -390,19 +390,23 @@ int mysql_optimize_table(THD* thd, TABLE_LIST* table_list, ...@@ -390,19 +390,23 @@ int mysql_optimize_table(THD* thd, TABLE_LIST* table_list,
bool check_simple_select(); bool check_simple_select();
SORT_FIELD * make_unireg_sortorder(ORDER *order, uint *length); SORT_FIELD * make_unireg_sortorder(ORDER *order, uint *length);
int setup_order(THD *thd,TABLE_LIST *tables, List<Item> &fields, int setup_ref_array(THD *thd, Item ***rref_pointer_array, uint elements);
List <Item> &all_fields, ORDER *order); int setup_order(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
int setup_group(THD *thd,TABLE_LIST *tables,List<Item> &fields, List<Item> &fields, List <Item> &all_fields, ORDER *order);
List<Item> &all_fields, ORDER *order, int setup_group(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
List<Item> &fields, List<Item> &all_fields, ORDER *order,
bool *hidden_group_fields); bool *hidden_group_fields);
int handle_select(THD *thd, LEX *lex, select_result *result); int handle_select(THD *thd, LEX *lex, select_result *result);
int mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &list,COND *conds, int mysql_select(THD *thd, Item ***rref_pointer_array,
ORDER *order, ORDER *group,Item *having,ORDER *proc_param, TABLE_LIST *tables, uint wild_num, List<Item> &list,
ulong select_type,select_result *result, COND *conds, uint og_num, ORDER *order, ORDER *group,
SELECT_LEX_UNIT *unit, SELECT_LEX *select_lex, Item *having, ORDER *proc_param, ulong select_type,
bool fake_select_lex); select_result *result, SELECT_LEX_UNIT *unit,
SELECT_LEX *select_lex, bool fake_select_lex);
void free_ulderlayed_joins(THD *thd, SELECT_LEX *select);
void fix_tables_pointers(SELECT_LEX *select_lex); void fix_tables_pointers(SELECT_LEX *select_lex);
void fix_tables_pointers(SELECT_LEX_UNIT *select_lex);
int mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, int mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit,
select_result *result); select_result *result);
int mysql_explain_select(THD *thd, SELECT_LEX *sl, char const *type, int mysql_explain_select(THD *thd, SELECT_LEX *sl, char const *type,
...@@ -428,7 +432,7 @@ int mysql_alter_table(THD *thd, char *new_db, char *new_name, ...@@ -428,7 +432,7 @@ int mysql_alter_table(THD *thd, char *new_db, char *new_name,
List<create_field> &fields, List<create_field> &fields,
List<Key> &keys,List<Alter_drop> &drop_list, List<Key> &keys,List<Alter_drop> &drop_list,
List<Alter_column> &alter_list, List<Alter_column> &alter_list,
ORDER *order, uint order_num, ORDER *order,
bool drop_primary, bool drop_primary,
enum enum_duplicates handle_duplicates, enum enum_duplicates handle_duplicates,
enum enum_enable_or_disable keys_onoff=LEAVE_AS_IS, enum enum_enable_or_disable keys_onoff=LEAVE_AS_IS,
...@@ -447,7 +451,7 @@ int mysql_drop_index(THD *thd, TABLE_LIST *table_list, ...@@ -447,7 +451,7 @@ int mysql_drop_index(THD *thd, TABLE_LIST *table_list,
List<Alter_drop> &drop_list); List<Alter_drop> &drop_list);
int mysql_update(THD *thd,TABLE_LIST *tables,List<Item> &fields, int mysql_update(THD *thd,TABLE_LIST *tables,List<Item> &fields,
List<Item> &values,COND *conds, List<Item> &values,COND *conds,
ORDER *order, ha_rows limit, uint order_num, ORDER *order, ha_rows limit,
enum enum_duplicates handle_duplicates); enum enum_duplicates handle_duplicates);
int mysql_multi_update(THD *thd, TABLE_LIST *table_list, int mysql_multi_update(THD *thd, TABLE_LIST *table_list,
List<Item> *fields, List<Item> *values, List<Item> *fields, List<Item> *values,
...@@ -567,15 +571,17 @@ SQL_SELECT *make_select(TABLE *head, table_map const_tables, ...@@ -567,15 +571,17 @@ SQL_SELECT *make_select(TABLE *head, table_map const_tables,
enum find_item_error_report_type {REPORT_ALL_ERRORS, REPORT_EXCEPT_NOT_FOUND, enum find_item_error_report_type {REPORT_ALL_ERRORS, REPORT_EXCEPT_NOT_FOUND,
IGNORE_ERRORS}; IGNORE_ERRORS};
extern const Item **not_found_item; extern const Item **not_found_item;
Item ** find_item_in_list(Item *item, List<Item> &items, Item ** find_item_in_list(Item *item, List<Item> &items, uint *counter,
find_item_error_report_type report_error); find_item_error_report_type report_error);
bool insert_fields(THD *thd,TABLE_LIST *tables, bool insert_fields(THD *thd,TABLE_LIST *tables,
const char *db_name, const char *table_name, const char *db_name, const char *table_name,
List_iterator<Item> *it); List_iterator<Item> *it);
bool setup_tables(TABLE_LIST *tables); bool setup_tables(TABLE_LIST *tables);
int setup_fields(THD *thd,TABLE_LIST *tables,List<Item> &item, int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
bool set_query_id,List<Item> *sum_func_list, List<Item> *sum_func_list, uint wild_num);
bool allow_sum_func); int setup_fields(THD *thd, Item** ref_pointer_array, TABLE_LIST *tables,
List<Item> &item, bool set_query_id,
List<Item> *sum_func_list, bool allow_sum_func);
int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds); int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds);
int setup_ftfuncs(SELECT_LEX* select); int setup_ftfuncs(SELECT_LEX* select);
int init_ftfuncs(THD *thd, SELECT_LEX* select, bool no_order); int init_ftfuncs(THD *thd, SELECT_LEX* select, bool no_order);
......
...@@ -1807,11 +1807,15 @@ const Item **not_found_item= (const Item**) 0x1; ...@@ -1807,11 +1807,15 @@ const Item **not_found_item= (const Item**) 0x1;
/* /*
Find Item in list of items (find_field_in_tables analog) Find Item in list of items (find_field_in_tables analog)
TODO
is it better return only counter?
SYNOPSIS SYNOPSIS
find_item_in_list() find_item_in_list()
find - item to find find - item to find
items - list of items items - list of items
counter - to return number of found item
report_error report_error
REPORT_ALL_ERRORS - report errors, return 0 if error REPORT_ALL_ERRORS - report errors, return 0 if error
REPORT_EXCEPT_NOT_FOUND - do not report 'not found' error and return not_ found_item, report other errors, return 0 REPORT_EXCEPT_NOT_FOUND - do not report 'not found' error and return not_ found_item, report other errors, return 0
...@@ -1828,7 +1832,7 @@ const Item **not_found_item= (const Item**) 0x1; ...@@ -1828,7 +1832,7 @@ const Item **not_found_item= (const Item**) 0x1;
*/ */
Item ** Item **
find_item_in_list(Item *find, List<Item> &items, find_item_in_list(Item *find, List<Item> &items, uint *counter,
find_item_error_report_type report_error) find_item_error_report_type report_error)
{ {
List_iterator<Item> li(items); List_iterator<Item> li(items);
...@@ -1841,8 +1845,10 @@ find_item_in_list(Item *find, List<Item> &items, ...@@ -1841,8 +1845,10 @@ find_item_in_list(Item *find, List<Item> &items,
table_name= ((Item_ident*) find)->table_name; table_name= ((Item_ident*) find)->table_name;
} }
uint i= 0;
while ((item=li++)) while ((item=li++))
{ {
i++;
if (field_name && item->type() == Item::FIELD_ITEM) if (field_name && item->type() == Item::FIELD_ITEM)
{ {
if (!my_strcasecmp(system_charset_info, if (!my_strcasecmp(system_charset_info,
...@@ -1859,11 +1865,13 @@ find_item_in_list(Item *find, List<Item> &items, ...@@ -1859,11 +1865,13 @@ find_item_in_list(Item *find, List<Item> &items,
find->full_name(), current_thd->where); find->full_name(), current_thd->where);
return (Item**) 0; return (Item**) 0;
} }
found=li.ref(); found= li.ref();
*counter= i;
} }
else if (!strcmp(((Item_field*) item)->table_name,table_name)) else if (!strcmp(((Item_field*) item)->table_name,table_name))
{ {
found=li.ref(); found= li.ref();
*counter= i;
break; break;
} }
} }
...@@ -1873,7 +1881,8 @@ find_item_in_list(Item *find, List<Item> &items, ...@@ -1873,7 +1881,8 @@ find_item_in_list(Item *find, List<Item> &items,
!my_strcasecmp(system_charset_info, !my_strcasecmp(system_charset_info,
item->name,find->name))) item->name,find->name)))
{ {
found=li.ref(); found= li.ref();
*counter= i;
break; break;
} }
} }
...@@ -1891,30 +1900,26 @@ find_item_in_list(Item *find, List<Item> &items, ...@@ -1891,30 +1900,26 @@ find_item_in_list(Item *find, List<Item> &items,
} }
/**************************************************************************** /****************************************************************************
** Check that all given fields exists and fill struct with current data ** Expand all '*' in given fields
****************************************************************************/ ****************************************************************************/
int setup_fields(THD *thd, TABLE_LIST *tables, List<Item> &fields, int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
bool set_query_id, List<Item> *sum_func_list, List<Item> *sum_func_list,
bool allow_sum_func) uint wild_num)
{ {
if (!wild_num)
return 0;
reg2 Item *item; reg2 Item *item;
List_iterator<Item> it(fields); List_iterator<Item> it(fields);
DBUG_ENTER("setup_fields"); while ( wild_num && (item= it++))
{
thd->set_query_id=set_query_id;
thd->allow_sum_func= allow_sum_func;
thd->where="field list";
while ((item=it++))
{
if (item->type() == Item::FIELD_ITEM && ((Item_field*) item)->field_name && if (item->type() == Item::FIELD_ITEM && ((Item_field*) item)->field_name &&
((Item_field*) item)->field_name[0] == '*') ((Item_field*) item)->field_name[0] == '*')
{ {
uint elem= fields.elements; uint elem= fields.elements;
if (insert_fields(thd,tables,((Item_field*) item)->db_name, if (insert_fields(thd,tables,((Item_field*) item)->db_name,
((Item_field*) item)->table_name, &it)) ((Item_field*) item)->table_name, &it))
DBUG_RETURN(-1); /* purecov: inspected */ return (-1);
if (sum_func_list) if (sum_func_list)
{ {
/* /*
...@@ -1924,21 +1929,43 @@ int setup_fields(THD *thd, TABLE_LIST *tables, List<Item> &fields, ...@@ -1924,21 +1929,43 @@ int setup_fields(THD *thd, TABLE_LIST *tables, List<Item> &fields,
*/ */
sum_func_list->elements+= fields.elements - elem; sum_func_list->elements+= fields.elements - elem;
} }
} wild_num--;
else
{
if (item->fix_fields(thd, tables, it.ref()) || item->check_cols(1))
DBUG_RETURN(-1); /* purecov: inspected */
item= *(it.ref()); //Item can be chenged in fix fields
if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM &&
sum_func_list)
item->split_sum_func(*sum_func_list);
thd->used_tables|=item->used_tables();
} }
} }
DBUG_RETURN(test(thd->fatal_error || thd->net.report_error)); return 0;
} }
/****************************************************************************
** Check that all given fields exists and fill struct with current data
****************************************************************************/
int setup_fields(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
List<Item> &fields, bool set_query_id,
List<Item> *sum_func_list, bool allow_sum_func)
{
reg2 Item *item;
List_iterator<Item> it(fields);
DBUG_ENTER("setup_fields");
thd->set_query_id=set_query_id;
thd->allow_sum_func= allow_sum_func;
thd->where="field list";
for (uint i= 0; (item= it++); i++)
{
if (item->fix_fields(thd, tables, it.ref()) ||
item->check_cols(1))
DBUG_RETURN(-1); /* purecov: inspected */
item= *(it.ref()); //Item can be chenged in fix fields
if (ref_pointer_array)
ref_pointer_array[i]= item;
if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM &&
sum_func_list)
item->split_sum_func(ref_pointer_array, *sum_func_list);
thd->used_tables|=item->used_tables();
}
DBUG_RETURN(test(thd->fatal_error || thd->net.report_error));
}
/* /*
Remap table numbers if INSERT ... SELECT Remap table numbers if INSERT ... SELECT
...@@ -2254,7 +2281,7 @@ int mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys) ...@@ -2254,7 +2281,7 @@ int mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys)
create_info.table_charset=default_charset_info; create_info.table_charset=default_charset_info;
DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->real_name, DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->real_name,
&create_info, table_list, &create_info, table_list,
fields, keys, drop, alter, (ORDER*)0, FALSE, fields, keys, drop, alter, 0, (ORDER*)0, FALSE,
DUP_ERROR)); DUP_ERROR));
} }
...@@ -2271,7 +2298,7 @@ int mysql_drop_index(THD *thd, TABLE_LIST *table_list, List<Alter_drop> &drop) ...@@ -2271,7 +2298,7 @@ int mysql_drop_index(THD *thd, TABLE_LIST *table_list, List<Alter_drop> &drop)
create_info.table_charset=default_charset_info; create_info.table_charset=default_charset_info;
DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->real_name, DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->real_name,
&create_info, table_list, &create_info, table_list,
fields, keys, drop, alter, (ORDER*)0, FALSE, fields, keys, drop, alter, 0, (ORDER*)0, FALSE,
DUP_ERROR)); DUP_ERROR));
} }
......
...@@ -394,7 +394,7 @@ struct system_variables ...@@ -394,7 +394,7 @@ struct system_variables
CHARSET_INFO *thd_charset; CHARSET_INFO *thd_charset;
}; };
void free_tmp_table(THD *thd, TABLE *entry);
/* /*
For each client connection we create a separate thread with THD serving as For each client connection we create a separate thread with THD serving as
a thread/connection descriptor a thread/connection descriptor
...@@ -507,6 +507,7 @@ public: ...@@ -507,6 +507,7 @@ public:
USER_CONN *user_connect; USER_CONN *user_connect;
CHARSET_INFO *db_charset; CHARSET_INFO *db_charset;
List<Item> *possible_loops; // Items that may cause loops in subselects List<Item> *possible_loops; // Items that may cause loops in subselects
List<TABLE> temporary_tables_should_be_free; // list of temporary tables
List <MYSQL_ERROR> warn_list; List <MYSQL_ERROR> warn_list;
uint warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_END]; uint warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_END];
uint total_warn_count, old_total_warn_count; uint total_warn_count, old_total_warn_count;
......
...@@ -92,6 +92,7 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order, ...@@ -92,6 +92,7 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order,
if ((select && select->check_quick(safe_update, limit)) || !limit) if ((select && select->check_quick(safe_update, limit)) || !limit)
{ {
delete select; delete select;
free_ulderlayed_joins(thd, &thd->lex.select_lex);
send_ok(thd,0L); send_ok(thd,0L);
DBUG_RETURN(0); // Nothing to delete DBUG_RETURN(0); // Nothing to delete
} }
...@@ -103,6 +104,7 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order, ...@@ -103,6 +104,7 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order,
if (safe_update && !using_limit) if (safe_update && !using_limit)
{ {
delete select; delete select;
free_ulderlayed_joins(thd, &thd->lex.select_lex);
send_error(thd,ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE); send_error(thd,ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE);
DBUG_RETURN(1); DBUG_RETURN(1);
} }
...@@ -124,7 +126,7 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order, ...@@ -124,7 +126,7 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order,
table->io_cache = (IO_CACHE *) my_malloc(sizeof(IO_CACHE), table->io_cache = (IO_CACHE *) my_malloc(sizeof(IO_CACHE),
MYF(MY_FAE | MY_ZEROFILL)); MYF(MY_FAE | MY_ZEROFILL));
if (setup_order(thd, &tables, fields, all_fields, order) || if (setup_order(thd, 0, &tables, fields, all_fields, order) ||
!(sortorder=make_unireg_sortorder(order, &length)) || !(sortorder=make_unireg_sortorder(order, &length)) ||
(table->found_records = filesort(thd, table, sortorder, length, (table->found_records = filesort(thd, table, sortorder, length,
(SQL_SELECT *) 0, HA_POS_ERROR, (SQL_SELECT *) 0, HA_POS_ERROR,
...@@ -132,6 +134,7 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order, ...@@ -132,6 +134,7 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order,
== HA_POS_ERROR) == HA_POS_ERROR)
{ {
delete select; delete select;
free_ulderlayed_joins(thd, &thd->lex.select_lex);
DBUG_RETURN(-1); // This will force out message DBUG_RETURN(-1); // This will force out message
} }
} }
...@@ -207,6 +210,7 @@ cleanup: ...@@ -207,6 +210,7 @@ cleanup:
thd->lock=0; thd->lock=0;
} }
delete select; delete select;
free_ulderlayed_joins(thd, &thd->lex.select_lex);
if (error >= 0 || thd->net.report_error) if (error >= 0 || thd->net.report_error)
send_error(thd,thd->killed ? ER_SERVER_SHUTDOWN: 0); send_error(thd,thd->killed ? ER_SERVER_SHUTDOWN: 0);
else else
......
...@@ -70,7 +70,8 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t) ...@@ -70,7 +70,8 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
select_union *derived_result; select_union *derived_result;
TABLE_LIST *tables= (TABLE_LIST *)sl->table_list.first; TABLE_LIST *tables= (TABLE_LIST *)sl->table_list.first;
TMP_TABLE_PARAM tmp_table_param; TMP_TABLE_PARAM tmp_table_param;
bool is_union=sl->next_select() && sl->next_select()->linkage == UNION_TYPE; bool is_union= sl->next_select() && sl->next_select()->linkage == UNION_TYPE;
bool is_subsel= sl->first_inner_unit();
SELECT_LEX_NODE *save_current_select= lex->current_select; SELECT_LEX_NODE *save_current_select= lex->current_select;
DBUG_ENTER("mysql_derived"); DBUG_ENTER("mysql_derived");
...@@ -81,7 +82,7 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t) ...@@ -81,7 +82,7 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
recognize better when this function is called from derived tables recognize better when this function is called from derived tables
and when from other functions. and when from other functions.
*/ */
if (is_union && unit->create_total_list(thd, lex, &tables)) if ((is_union || is_subsel) && unit->create_total_list(thd, lex, &tables, 1))
DBUG_RETURN(-1); DBUG_RETURN(-1);
if (tables) if (tables)
...@@ -90,16 +91,10 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t) ...@@ -90,16 +91,10 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
res= check_access(thd, SELECT_ACL, any_db); res= check_access(thd, SELECT_ACL, any_db);
if (res) if (res)
DBUG_RETURN(-1); DBUG_RETURN(-1);
Item *item;
List_iterator<Item> it(sl->item_list);
while ((item= it++))
item_list.push_back(item);
if (!(res=open_and_lock_tables(thd,tables))) if (!(res=open_and_lock_tables(thd,tables)))
{ {
if (is_union) if (is_union || is_subsel)
{ {
/* /*
The following code is a re-do of fix_tables_pointers() found The following code is a re-do of fix_tables_pointers() found
...@@ -108,24 +103,32 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t) ...@@ -108,24 +103,32 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
this level only. this level only.
*/ */
for (SELECT_LEX *sel= sl; sel; sel= sel->next_select()) fix_tables_pointers(unit);
relink_tables(sel);
} }
Item *item;
List_iterator<Item> it(sl->item_list);
while ((item= it++))
item_list.push_back(item);
lex->current_select= sl; lex->current_select= sl;
if (setup_fields(thd,tables,item_list,0,0,1)) TABLE_LIST *first_table= (TABLE_LIST*) sl->table_list.first;
if (setup_wild(thd, first_table, item_list, 0, sl->with_wild) ||
setup_fields(thd, 0, first_table, item_list, 0, 0, 1))
{ {
res= -1; res= -1;
goto exit; goto exit;
} }
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= item_list.elements;
if (!(table=create_tmp_table(thd, &tmp_table_param, item_list, if (!(table= create_tmp_table(thd, &tmp_table_param, item_list,
(ORDER*) 0, (ORDER*) 0,
is_union && !unit->union_option, 1, is_union && !unit->union_option, 1,
(sl->options | thd->options | (sl->options | thd->options |
TMP_TABLE_ALL_COLUMNS), TMP_TABLE_ALL_COLUMNS),
HA_POS_ERROR))) HA_POS_ERROR)))
{ {
res= -1; res= -1;
goto exit; goto exit;
...@@ -142,14 +145,18 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t) ...@@ -142,14 +145,18 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
sl->options&= ~OPTION_FOUND_ROWS; sl->options&= ~OPTION_FOUND_ROWS;
if (is_union) if (is_union)
res= mysql_union(thd,lex,derived_result,unit); res= mysql_union(thd, lex, derived_result, unit);
else else
res= mysql_select(thd, tables, sl->item_list, res= mysql_select(thd, &sl->ref_pointer_array,
sl->where, (ORDER *) sl->order_list.first, (TABLE_LIST*) sl->table_list.first,
(ORDER*) sl->group_list.first, sl->with_wild,
sl->having, (ORDER*) NULL, sl->item_list, sl->where,
sl->options | thd->options | SELECT_NO_UNLOCK, sl->order_list.elements+sl->group_list.elements,
derived_result, unit, sl, 0); (ORDER *) sl->order_list.first,
(ORDER *) sl->group_list.first,
sl->having, (ORDER*) NULL,
sl->options | thd->options | SELECT_NO_UNLOCK,
derived_result, unit, sl, 0);
if (!res) if (!res)
{ {
...@@ -187,6 +194,7 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t) ...@@ -187,6 +194,7 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
table->next= thd->derived_tables; table->next= thd->derived_tables;
thd->derived_tables= table; thd->derived_tables= table;
} }
exit: exit:
lex->current_select= save_current_select; lex->current_select= save_current_select;
close_thread_tables(thd, 0, 1); close_thread_tables(thd, 0, 1);
......
...@@ -25,7 +25,7 @@ int mysql_do(THD *thd, List<Item> &values) ...@@ -25,7 +25,7 @@ int mysql_do(THD *thd, List<Item> &values)
List_iterator<Item> li(values); List_iterator<Item> li(values);
Item *value; Item *value;
DBUG_ENTER("mysql_do"); DBUG_ENTER("mysql_do");
if (setup_fields(thd,0, values, 0, 0, 0)) if (setup_fields(thd, 0, 0, values, 0, 0, 0))
DBUG_RETURN(-1); DBUG_RETURN(-1);
while ((value = li++)) while ((value = li++))
value->val_int(); value->val_int();
......
...@@ -81,7 +81,7 @@ check_insert_fields(THD *thd,TABLE *table,List<Item> &fields, ...@@ -81,7 +81,7 @@ check_insert_fields(THD *thd,TABLE *table,List<Item> &fields,
thd->dupp_field=0; thd->dupp_field=0;
if (setup_tables(&table_list) || if (setup_tables(&table_list) ||
setup_fields(thd,&table_list,fields,1,0,0)) setup_fields(thd, 0, &table_list,fields,1,0,0))
return -1; return -1;
if (thd->dupp_field) if (thd->dupp_field)
{ {
...@@ -171,10 +171,10 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, ...@@ -171,10 +171,10 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
values= its++; values= its++;
if (check_insert_fields(thd,table,fields,*values,1) || if (check_insert_fields(thd,table,fields,*values,1) ||
setup_tables(insert_table_list) || setup_tables(insert_table_list) ||
setup_fields(thd, insert_table_list, *values, 0, 0, 0) || setup_fields(thd, 0, insert_table_list, *values, 0, 0, 0) ||
(duplic == DUP_UPDATE && (duplic == DUP_UPDATE &&
(setup_fields(thd, insert_table_list, update_fields, 0, 0, 0) || (setup_fields(thd, 0, insert_table_list, update_fields, 0, 0, 0) ||
setup_fields(thd, insert_table_list, update_values, 0, 0, 0)))) setup_fields(thd, 0, insert_table_list, update_values, 0, 0, 0))))
goto abort; goto abort;
if (find_real_table_in_list(table_list->next, if (find_real_table_in_list(table_list->next,
table_list->db, table_list->real_name)) table_list->db, table_list->real_name))
...@@ -194,7 +194,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, ...@@ -194,7 +194,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
MYF(0),counter); MYF(0),counter);
goto abort; goto abort;
} }
if (setup_fields(thd,insert_table_list,*values,0,0,0)) if (setup_fields(thd, 0, insert_table_list, *values, 0, 0, 0))
goto abort; goto abort;
} }
its.rewind (); its.rewind ();
...@@ -376,11 +376,13 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list, ...@@ -376,11 +376,13 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
thd->cuted_fields); thd->cuted_fields);
::send_ok(thd,info.copied+info.deleted,(ulonglong)id,buff); ::send_ok(thd,info.copied+info.deleted,(ulonglong)id,buff);
} }
free_ulderlayed_joins(thd, &thd->lex.select_lex);
DBUG_RETURN(0); DBUG_RETURN(0);
abort: abort:
if (lock_type == TL_WRITE_DELAYED) if (lock_type == TL_WRITE_DELAYED)
end_delayed_insert(thd); end_delayed_insert(thd);
free_ulderlayed_joins(thd, &thd->lex.select_lex);
DBUG_RETURN(-1); DBUG_RETURN(-1);
} }
......
...@@ -995,7 +995,8 @@ int yylex(void *arg, void *yythd) ...@@ -995,7 +995,8 @@ int yylex(void *arg, void *yythd)
void st_select_lex_node::init_query() void st_select_lex_node::init_query()
{ {
no_table_names_allowed= dependent= 0; no_table_names_allowed= uncacheable= dependent= 0;
ref_pointer_array= 0;
} }
void st_select_lex_node::init_select() void st_select_lex_node::init_select()
...@@ -1019,6 +1020,8 @@ void st_select_lex_unit::init_query() ...@@ -1019,6 +1020,8 @@ void st_select_lex_unit::init_query()
union_option= 0; union_option= 0;
prepared= optimized= executed= 0; prepared= optimized= executed= 0;
item= 0; item= 0;
union_result= 0;
table= 0;
} }
void st_select_lex::init_query() void st_select_lex::init_query()
...@@ -1031,6 +1034,7 @@ void st_select_lex::init_query() ...@@ -1031,6 +1034,7 @@ void st_select_lex::init_query()
join= 0; join= 0;
olap= UNSPECIFIED_OLAP_TYPE; olap= UNSPECIFIED_OLAP_TYPE;
having_fix_field= 0; having_fix_field= 0;
with_wild= 0;
} }
void st_select_lex::init_select() void st_select_lex::init_select()
...@@ -1160,12 +1164,12 @@ bool st_select_lex_node::add_item_to_list(THD *thd, Item *item) ...@@ -1160,12 +1164,12 @@ bool st_select_lex_node::add_item_to_list(THD *thd, Item *item)
bool st_select_lex_node::add_group_to_list(THD *thd, Item *item, bool asc) bool st_select_lex_node::add_group_to_list(THD *thd, Item *item, bool asc)
{ {
return 1; return 1;
} }
bool st_select_lex_node::add_order_to_list(THD *thd, Item *item, bool asc) bool st_select_lex_node::add_order_to_list(THD *thd, Item *item, bool asc)
{ {
return add_to_list(thd, order_list,item,asc); return add_to_list(thd, order_list, item, asc);
} }
bool st_select_lex_node::add_ftfunc_to_list(Item_func_match *func) bool st_select_lex_node::add_ftfunc_to_list(Item_func_match *func)
...@@ -1241,15 +1245,17 @@ ulong st_select_lex_node::get_table_join_options() { return 0; } ...@@ -1241,15 +1245,17 @@ ulong st_select_lex_node::get_table_join_options() { return 0; }
// interface // interface
bool st_select_lex_unit::create_total_list(THD *thd, st_lex *lex, bool st_select_lex_unit::create_total_list(THD *thd, st_lex *lex,
TABLE_LIST **result) TABLE_LIST **result,
bool check_derived)
{ {
*result= 0; *result= 0;
return create_total_list_n_last_return(thd, lex, &result); return create_total_list_n_last_return(thd, lex, &result, check_derived);
} }
// list creator // list creator
bool st_select_lex_unit::create_total_list_n_last_return(THD *thd, st_lex *lex, bool st_select_lex_unit::create_total_list_n_last_return(THD *thd, st_lex *lex,
TABLE_LIST ***result) TABLE_LIST ***result,
bool check_derived)
{ {
TABLE_LIST *slave_list_first=0, **slave_list_last= &slave_list_first; TABLE_LIST *slave_list_first=0, **slave_list_last= &slave_list_first;
TABLE_LIST **new_table_list= *result, *aux; TABLE_LIST **new_table_list= *result, *aux;
...@@ -1262,13 +1268,13 @@ bool st_select_lex_unit::create_total_list_n_last_return(THD *thd, st_lex *lex, ...@@ -1262,13 +1268,13 @@ bool st_select_lex_unit::create_total_list_n_last_return(THD *thd, st_lex *lex,
net_printf(thd,ER_WRONG_USAGE,"UNION","ORDER BY"); net_printf(thd,ER_WRONG_USAGE,"UNION","ORDER BY");
return 1; return 1;
} }
if (sl->linkage == DERIVED_TABLE_TYPE && !sl->next_select()) if (sl->linkage == DERIVED_TABLE_TYPE && !check_derived)
continue; continue;
for (SELECT_LEX_UNIT *inner= sl->first_inner_unit(); for (SELECT_LEX_UNIT *inner= sl->first_inner_unit();
inner; inner;
inner= inner->next_unit()) inner= inner->next_unit())
if (inner->create_total_list_n_last_return(thd, lex, if (inner->create_total_list_n_last_return(thd, lex,
&slave_list_last)) &slave_list_last, 0))
return 1; return 1;
if ((aux= (TABLE_LIST*) sl->table_list.first)) if ((aux= (TABLE_LIST*) sl->table_list.first))
{ {
......
...@@ -210,9 +210,13 @@ public: ...@@ -210,9 +210,13 @@ public:
List<List_item> expr_list; List<List_item> expr_list;
List<List_item> when_list; /* WHEN clause (expression) */ List<List_item> when_list; /* WHEN clause (expression) */
ha_rows select_limit, offset_limit; /* LIMIT clause parameters */ ha_rows select_limit, offset_limit; /* LIMIT clause parameters */
bool with_sum_func; // Arrays of pointers to top elements of all_fields list
bool create_refs; Item **ref_pointer_array;
uint with_sum_func; /* sum function indicator and number of it */
bool create_refs;
bool dependent; /* dependent from outer select subselect */ bool dependent; /* dependent from outer select subselect */
bool uncacheable; /* result of this query can't be cached */
bool no_table_names_allowed; /* used for global order by */ bool no_table_names_allowed; /* used for global order by */
static void *operator new(size_t size) static void *operator new(size_t size)
...@@ -274,11 +278,10 @@ class select_union; ...@@ -274,11 +278,10 @@ class select_union;
class st_select_lex_unit: public st_select_lex_node { class st_select_lex_unit: public st_select_lex_node {
protected: protected:
List<Item> item_list; List<Item> item_list;
List<JOIN*> joins; /* list of *JOINs, to delete it in cleanup() */
TABLE_LIST result_table_list; TABLE_LIST result_table_list;
select_union *union_result; select_union *union_result;
TABLE *table; /* temporary table using for appending UNION results */ TABLE *table; /* temporary table using for appending UNION results */
THD *thd;
select_result *result; select_result *result;
int res; int res;
bool describe, found_rows_for_union, bool describe, found_rows_for_union,
...@@ -295,10 +298,13 @@ public: ...@@ -295,10 +298,13 @@ public:
ha_rows select_limit_cnt, offset_limit_cnt; ha_rows select_limit_cnt, offset_limit_cnt;
/* not NULL if union used in subselect, point to subselect item */ /* not NULL if union used in subselect, point to subselect item */
Item_subselect *item; Item_subselect *item;
THD *thd;
uint union_option; uint union_option;
void init_query(); void init_query();
bool create_total_list(THD *thd, st_lex *lex, TABLE_LIST **result); bool create_total_list(THD *thd, st_lex *lex, TABLE_LIST **result,
bool check_current_derived);
st_select_lex_unit* master_unit(); st_select_lex_unit* master_unit();
st_select_lex* outer_select(); st_select_lex* outer_select();
st_select_lex* first_select() { return (st_select_lex*) slave; } st_select_lex* first_select() { return (st_select_lex*) slave; }
...@@ -314,7 +320,8 @@ public: ...@@ -314,7 +320,8 @@ public:
friend int subselect_union_engine::exec(); friend int subselect_union_engine::exec();
private: private:
bool create_total_list_n_last_return(THD *thd, st_lex *lex, bool create_total_list_n_last_return(THD *thd, st_lex *lex,
TABLE_LIST ***result); TABLE_LIST ***result,
bool check_current_derived);
}; };
typedef class st_select_lex_unit SELECT_LEX_UNIT; typedef class st_select_lex_unit SELECT_LEX_UNIT;
...@@ -342,6 +349,7 @@ public: ...@@ -342,6 +349,7 @@ public:
ulong table_join_options; ulong table_join_options;
uint in_sum_expr; uint in_sum_expr;
uint select_number; /* number of select (used for EXPLAIN) */ uint select_number; /* number of select (used for EXPLAIN) */
uint with_wild; /* item list contain '*' */
bool braces; /* SELECT ... UNION (SELECT ... ) <- this braces */ bool braces; /* SELECT ... UNION (SELECT ... ) <- this braces */
/* TRUE when having fix field called in processing of this SELECT */ /* TRUE when having fix field called in processing of this SELECT */
bool having_fix_field; bool having_fix_field;
...@@ -468,6 +476,13 @@ typedef struct st_lex ...@@ -468,6 +476,13 @@ typedef struct st_lex
CHARSET_INFO *charset; CHARSET_INFO *charset;
char *help_arg; char *help_arg;
bool tmp_table_used; bool tmp_table_used;
inline void uncacheable()
{
safe_to_cache_query= 0;
current_select->uncacheable =
current_select->master_unit()->uncacheable= 1;
}
} LEX; } LEX;
......
...@@ -155,12 +155,20 @@ protected: ...@@ -155,12 +155,20 @@ protected:
class base_list_iterator class base_list_iterator
{ {
protected:
base_list *list; base_list *list;
list_node **el,**prev,*current; list_node **el,**prev,*current;
void sublist(base_list &ls, uint elm)
{
ls.first= *el;
ls.last= list->last;
ls.elements= elm;
}
public: public:
base_list_iterator(base_list &list_par) :list(&list_par),el(&list_par.first), base_list_iterator(base_list &list_par)
prev(0),current(0) :list(&list_par), el(&list_par.first), prev(0), current(0)
{} {}
inline void *next(void) inline void *next(void)
{ {
prev=el; prev=el;
...@@ -220,7 +228,6 @@ public: ...@@ -220,7 +228,6 @@ public:
friend class error_list_iterator; friend class error_list_iterator;
}; };
template <class T> class List :public base_list template <class T> class List :public base_list
{ {
public: public:
...@@ -268,6 +275,10 @@ public: ...@@ -268,6 +275,10 @@ public:
List_iterator_fast(List<T> &a) : base_list_iterator(a) {} List_iterator_fast(List<T> &a) : base_list_iterator(a) {}
inline T* operator++(int) { return (T*) base_list_iterator::next_fast(); } inline T* operator++(int) { return (T*) base_list_iterator::next_fast(); }
inline void rewind(void) { base_list_iterator::rewind(); } inline void rewind(void) { base_list_iterator::rewind(); }
void sublist(List<T> &list, uint el)
{
base_list_iterator::sublist(list, el);
}
}; };
......
...@@ -119,7 +119,8 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, ...@@ -119,7 +119,8 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
else else
{ // Part field list { // Part field list
thd->dupp_field=0; thd->dupp_field=0;
if (setup_tables(table_list) || setup_fields(thd,table_list,fields,1,0,0)) if (setup_tables(table_list) ||
setup_fields(thd, 0, table_list, fields, 1, 0, 0))
DBUG_RETURN(-1); DBUG_RETURN(-1);
if (thd->dupp_field) if (thd->dupp_field)
{ {
......
...@@ -164,8 +164,10 @@ int handle_olaps(LEX *lex, SELECT_LEX *select_lex) ...@@ -164,8 +164,10 @@ int handle_olaps(LEX *lex, SELECT_LEX *select_lex)
if (setup_tables((TABLE_LIST *)select_lex->table_list.first) || if (setup_tables((TABLE_LIST *)select_lex->table_list.first) ||
setup_fields(lex->thd,(TABLE_LIST *)select_lex->table_list.first,select_lex->item_list,1,&all_fields,1) || setup_fields(lex->thd, 0, (TABLE_LIST *)select_lex->table_list.first,
setup_fields(lex->thd,(TABLE_LIST *)select_lex->table_list.first,item_list_copy,1,&all_fields,1)) select_lex->item_list, 1, &all_fields,1) ||
setup_fields(lex->thd, 0, (TABLE_LIST *)select_lex->table_list.first,
item_list_copy, 1, &all_fields, 1))
return -1; return -1;
if (select_lex->olap == CUBE_TYPE) if (select_lex->olap == CUBE_TYPE)
......
...@@ -1599,7 +1599,7 @@ mysql_execute_command(THD *thd) ...@@ -1599,7 +1599,7 @@ mysql_execute_command(THD *thd)
} }
} }
if ((&lex->select_lex != lex->all_selects_list && if ((&lex->select_lex != lex->all_selects_list &&
lex->unit.create_total_list(thd, lex, &tables)) lex->unit.create_total_list(thd, lex, &tables, 0))
#ifndef EMBEDDED_LIBRARY #ifndef EMBEDDED_LIBRARY
|| ||
(table_rules_on && tables && thd->slave_thread && (table_rules_on && tables && thd->slave_thread &&
...@@ -2041,6 +2041,7 @@ mysql_execute_command(THD *thd) ...@@ -2041,6 +2041,7 @@ mysql_execute_command(THD *thd)
&lex->create_info, &lex->create_info,
tables, lex->create_list, tables, lex->create_list,
lex->key_list, lex->drop_list, lex->alter_list, lex->key_list, lex->drop_list, lex->alter_list,
select_lex->order_list.elements,
(ORDER *) select_lex->order_list.first, (ORDER *) select_lex->order_list.first,
lex->drop_primary, lex->duplicates, lex->drop_primary, lex->duplicates,
lex->alter_keys_onoff, lex->simple_alter); lex->alter_keys_onoff, lex->simple_alter);
...@@ -2154,8 +2155,8 @@ mysql_execute_command(THD *thd) ...@@ -2154,8 +2155,8 @@ mysql_execute_command(THD *thd)
res= mysql_alter_table(thd, NullS, NullS, &create_info, res= mysql_alter_table(thd, NullS, NullS, &create_info,
tables, lex->create_list, tables, lex->create_list,
lex->key_list, lex->drop_list, lex->alter_list, lex->key_list, lex->drop_list, lex->alter_list,
(ORDER *) 0, 0, (ORDER *) 0,
0,DUP_ERROR); 0, DUP_ERROR);
} }
else else
res = mysql_optimize_table(thd, tables, &lex->check_opt); res = mysql_optimize_table(thd, tables, &lex->check_opt);
...@@ -2175,6 +2176,7 @@ mysql_execute_command(THD *thd) ...@@ -2175,6 +2176,7 @@ mysql_execute_command(THD *thd)
select_lex->item_list, select_lex->item_list,
lex->value_list, lex->value_list,
select_lex->where, select_lex->where,
select_lex->order_list.elements,
(ORDER *) select_lex->order_list.first, (ORDER *) select_lex->order_list.first,
select_lex->select_limit, select_lex->select_limit,
lex->duplicates); lex->duplicates);
...@@ -2376,10 +2378,12 @@ mysql_execute_command(THD *thd) ...@@ -2376,10 +2378,12 @@ mysql_execute_command(THD *thd)
if (!thd->fatal_error && (result= new multi_delete(thd,aux_tables, if (!thd->fatal_error && (result= new multi_delete(thd,aux_tables,
table_count))) table_count)))
{ {
res= mysql_select(thd,select_lex->get_table_list(), res= mysql_select(thd, &select_lex->ref_pointer_array,
select_lex->get_table_list(),
select_lex->with_wild,
select_lex->item_list, select_lex->item_list,
select_lex->where, select_lex->where,
(ORDER *)NULL,(ORDER *)NULL,(Item *)NULL, 0, (ORDER *)NULL, (ORDER *)NULL, (Item *)NULL,
(ORDER *)NULL, (ORDER *)NULL,
select_lex->options | thd->options | select_lex->options | thd->options |
SELECT_NO_JOIN_CACHE, SELECT_NO_JOIN_CACHE,
...@@ -3130,6 +3134,7 @@ mysql_init_query(THD *thd) ...@@ -3130,6 +3134,7 @@ mysql_init_query(THD *thd)
LEX *lex=&thd->lex; LEX *lex=&thd->lex;
lex->unit.init_query(); lex->unit.init_query();
lex->unit.init_select(); lex->unit.init_select();
lex->unit.thd= thd;
lex->select_lex.init_query(); lex->select_lex.init_query();
lex->value_list.empty(); lex->value_list.empty();
lex->param_list.empty(); lex->param_list.empty();
...@@ -3191,6 +3196,7 @@ mysql_new_select(LEX *lex, bool move_down) ...@@ -3191,6 +3196,7 @@ mysql_new_select(LEX *lex, bool move_down)
return 1; return 1;
unit->init_query(); unit->init_query();
unit->init_select(); unit->init_select();
unit->thd= lex->thd;
unit->include_down(lex->current_select); unit->include_down(lex->current_select);
unit->link_next= 0; unit->link_next= 0;
unit->link_prev= 0; unit->link_prev= 0;
......
...@@ -437,6 +437,7 @@ static bool setup_params_data(PREP_STMT *stmt) ...@@ -437,6 +437,7 @@ static bool setup_params_data(PREP_STMT *stmt)
} }
/* /*
Validate the following information for INSERT statement: Validate the following information for INSERT statement:
- field existance - field existance
- fields count - fields count
...@@ -504,8 +505,9 @@ static bool mysql_test_upd_fields(PREP_STMT *stmt, TABLE_LIST *table_list, ...@@ -504,8 +505,9 @@ static bool mysql_test_upd_fields(PREP_STMT *stmt, TABLE_LIST *table_list,
if (open_and_lock_tables(thd, table_list)) if (open_and_lock_tables(thd, table_list))
DBUG_RETURN(1); DBUG_RETURN(1);
if (setup_tables(table_list) || setup_fields(thd,table_list,fields,1,0,0) || if (setup_tables(table_list) ||
setup_conds(thd,table_list,&conds) || thd->net.report_error) setup_fields(thd, 0, table_list, fields, 1, 0, 0) ||
setup_conds(thd, table_list, &conds) || thd->net.report_error)
DBUG_RETURN(1); DBUG_RETURN(1);
/* /*
...@@ -530,8 +532,9 @@ static bool mysql_test_upd_fields(PREP_STMT *stmt, TABLE_LIST *table_list, ...@@ -530,8 +532,9 @@ static bool mysql_test_upd_fields(PREP_STMT *stmt, TABLE_LIST *table_list,
And send column list fields info back to client. And send column list fields info back to client.
*/ */
static bool mysql_test_select_fields(PREP_STMT *stmt, TABLE_LIST *tables, static bool mysql_test_select_fields(PREP_STMT *stmt, TABLE_LIST *tables,
uint wild_num,
List<Item> &fields, COND *conds, List<Item> &fields, COND *conds,
ORDER *order, ORDER *group, uint og_num, ORDER *order, ORDER *group,
Item *having, ORDER *proc, Item *having, ORDER *proc,
ulong select_options, ulong select_options,
SELECT_LEX_UNIT *unit, SELECT_LEX_UNIT *unit,
...@@ -543,7 +546,7 @@ static bool mysql_test_select_fields(PREP_STMT *stmt, TABLE_LIST *tables, ...@@ -543,7 +546,7 @@ static bool mysql_test_select_fields(PREP_STMT *stmt, TABLE_LIST *tables,
DBUG_ENTER("mysql_test_select_fields"); DBUG_ENTER("mysql_test_select_fields");
if ((&lex->select_lex != lex->all_selects_list && if ((&lex->select_lex != lex->all_selects_list &&
lex->unit.create_total_list(thd, lex, &tables))) lex->unit.create_total_list(thd, lex, &tables, 0)))
DBUG_RETURN(1); DBUG_RETURN(1);
if (open_and_lock_tables(thd, tables)) if (open_and_lock_tables(thd, tables))
...@@ -562,7 +565,8 @@ static bool mysql_test_select_fields(PREP_STMT *stmt, TABLE_LIST *tables, ...@@ -562,7 +565,8 @@ static bool mysql_test_select_fields(PREP_STMT *stmt, TABLE_LIST *tables,
JOIN *join= new JOIN(thd, fields, select_options, result); JOIN *join= new JOIN(thd, fields, select_options, result);
thd->used_tables= 0; // Updated by setup_fields thd->used_tables= 0; // Updated by setup_fields
if (join->prepare(tables, conds, order, group, having, proc, 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, 0))
DBUG_RETURN(1); DBUG_RETURN(1);
...@@ -621,9 +625,11 @@ static bool send_prepare_results(PREP_STMT *stmt) ...@@ -621,9 +625,11 @@ static bool send_prepare_results(PREP_STMT *stmt)
break; break;
case SQLCOM_SELECT: case SQLCOM_SELECT:
if (mysql_test_select_fields(stmt, tables, if (mysql_test_select_fields(stmt, tables, select_lex->with_wild,
select_lex->item_list, select_lex->item_list,
select_lex->where, select_lex->where,
select_lex->order_list.elements +
select_lex->group_list.elements,
(ORDER*) select_lex->order_list.first, (ORDER*) select_lex->order_list.first,
(ORDER*) select_lex->group_list.first, (ORDER*) select_lex->group_list.first,
select_lex->having, select_lex->having,
......
This diff is collapsed.
...@@ -119,8 +119,10 @@ class TMP_TABLE_PARAM :public Sql_alloc ...@@ -119,8 +119,10 @@ class TMP_TABLE_PARAM :public Sql_alloc
{ {
public: public:
List<Item> copy_funcs; List<Item> copy_funcs;
List<Item> save_copy_funcs;
List_iterator_fast<Item> copy_funcs_it; List_iterator_fast<Item> copy_funcs_it;
Copy_field *copy_field, *copy_field_end; Copy_field *copy_field, *copy_field_end;
Copy_field *save_copy_field, *save_copy_field_end;
byte *group_buff; byte *group_buff;
Item_result_field **funcs; Item_result_field **funcs;
MI_COLUMNDEF *recinfo,*start_recinfo; MI_COLUMNDEF *recinfo,*start_recinfo;
...@@ -166,10 +168,13 @@ class JOIN :public Sql_alloc ...@@ -166,10 +168,13 @@ class JOIN :public Sql_alloc
List<Item> *fields; List<Item> *fields;
List<Item_buff> group_fields; List<Item_buff> group_fields;
TABLE *tmp_table; TABLE *tmp_table;
// used to store 2 possible tmp table of SELECT
TABLE *exec_tmp_table1, *exec_tmp_table2;
THD *thd; THD *thd;
Item_sum **sum_funcs; Item_sum **sum_funcs;
Procedure *procedure; Procedure *procedure;
Item *having; Item *having;
Item *tmp_having; // To store Having when processed tenporary table
uint select_options; uint select_options;
select_result *result; select_result *result;
TMP_TABLE_PARAM tmp_table_param; TMP_TABLE_PARAM tmp_table_param;
...@@ -178,6 +183,8 @@ class JOIN :public Sql_alloc ...@@ -178,6 +183,8 @@ class JOIN :public Sql_alloc
SELECT_LEX_UNIT *unit; SELECT_LEX_UNIT *unit;
// select that processed // select that processed
SELECT_LEX *select_lex; SELECT_LEX *select_lex;
JOIN *tmp_join; // copy of this JOIN to be used with temporary tables
bool select_distinct, //Is select distinct? bool select_distinct, //Is select distinct?
no_order, simple_order, simple_group, no_order, simple_order, simple_group,
...@@ -186,7 +193,11 @@ class JOIN :public Sql_alloc ...@@ -186,7 +193,11 @@ class JOIN :public Sql_alloc
buffer_result; buffer_result;
DYNAMIC_ARRAY keyuse; DYNAMIC_ARRAY keyuse;
Item::cond_result cond_value; Item::cond_result cond_value;
List<Item> all_fields; List<Item> all_fields; // to store all fields that used in query
//Above list changed to use temporary table
List<Item> tmp_all_fields1, tmp_all_fields2, tmp_all_fields3;
//Part, shared with list above, emulate following list
List<Item> tmp_fields_list1, tmp_fields_list2, tmp_fields_list3;
List<Item> & fields_list; // hold field list passed to mysql_select List<Item> & fields_list; // hold field list passed to mysql_select
int error; int error;
...@@ -194,11 +205,14 @@ class JOIN :public Sql_alloc ...@@ -194,11 +205,14 @@ class JOIN :public Sql_alloc
COND *conds; // ---"--- COND *conds; // ---"---
TABLE_LIST *tables_list; //hold 'tables' parameter of mysql_selec TABLE_LIST *tables_list; //hold 'tables' parameter of mysql_selec
SQL_SELECT *select; //created in optimisation phase SQL_SELECT *select; //created in optimisation phase
TABLE *exec_tmp_table; //used in 'exec' to hold temporary Item **ref_pointer_array; //used pointer reference for this select
// Copy of above to be used with different lists
Item **items0, **items1, **items2, **items3;
uint ref_pointer_array_size; // size of above in bytes
const char *zero_result_cause; // not 0 if exec must return zero result const char *zero_result_cause; // not 0 if exec must return zero result
my_bool union_part; // this subselect is part of union bool union_part; // this subselect is part of union
bool optimized; // flag to avoid double optimization in EXPLAIN
JOIN(THD *thd, List<Item> &fields, JOIN(THD *thd, List<Item> &fields,
ulong select_options, select_result *result): ulong select_options, select_result *result):
...@@ -208,14 +222,16 @@ class JOIN :public Sql_alloc ...@@ -208,14 +222,16 @@ class JOIN :public Sql_alloc
sort_and_group(0), first_record(0), sort_and_group(0), first_record(0),
do_send_rows(1), do_send_rows(1),
send_records(0), found_records(0), examined_rows(0), send_records(0), found_records(0), examined_rows(0),
exec_tmp_table1(0), exec_tmp_table2(0),
thd(thd), thd(thd),
sum_funcs(0), sum_funcs(0),
procedure(0), procedure(0),
having(0), having(0), tmp_having(0),
select_options(select_options), select_options(select_options),
result(result), result(result),
lock(thd->lock), lock(thd->lock),
select_lex(0), //for safety select_lex(0), //for safety
tmp_join(0),
select_distinct(test(select_options & SELECT_DISTINCT)), select_distinct(test(select_options & SELECT_DISTINCT)),
no_order(0), simple_order(0), simple_group(0), skip_sort_order(0), no_order(0), simple_order(0), simple_group(0), skip_sort_order(0),
need_tmp(0), need_tmp(0),
...@@ -226,8 +242,10 @@ class JOIN :public Sql_alloc ...@@ -226,8 +242,10 @@ class JOIN :public Sql_alloc
fields_list(fields), fields_list(fields),
error(0), error(0),
select(0), select(0),
exec_tmp_table(0), ref_pointer_array(0), items0(0), items1(0), items2(0), items3(0),
zero_result_cause(0) ref_pointer_array_size(0),
zero_result_cause(0),
optimized(0)
{ {
fields_list = fields; fields_list = fields;
bzero((char*) &keyuse,sizeof(keyuse)); bzero((char*) &keyuse,sizeof(keyuse));
...@@ -235,16 +253,23 @@ class JOIN :public Sql_alloc ...@@ -235,16 +253,23 @@ class JOIN :public Sql_alloc
tmp_table_param.end_write_records= HA_POS_ERROR; tmp_table_param.end_write_records= HA_POS_ERROR;
} }
int prepare(TABLE_LIST *tables, int prepare(Item ***rref_pointer_array, TABLE_LIST *tables, uint wind_num,
COND *conds, ORDER *order, ORDER *group, Item *having, COND *conds, uint og_num, ORDER *order, ORDER *group,
ORDER *proc_param, SELECT_LEX *select, SELECT_LEX_UNIT *unit, Item *having, ORDER *proc_param, SELECT_LEX *select,
bool fake_select_lex); SELECT_LEX_UNIT *unit, bool fake_select_lex);
int optimize(); int optimize();
int global_optimize();
int reinit(); int reinit();
void exec(); void exec();
int cleanup(THD *thd); int cleanup(THD *thd);
bool check_loop(uint id); bool check_loop(uint id);
void restore_tmp();
inline void init_items_ref_array()
{
items0= ref_pointer_array + all_fields.elements;
ref_pointer_array_size= all_fields.elements*sizeof(Item*);
memcpy(items0, ref_pointer_array, ref_pointer_array_size);
}
}; };
...@@ -263,7 +288,10 @@ TABLE *create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, ...@@ -263,7 +288,10 @@ TABLE *create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
void free_tmp_table(THD *thd, TABLE *entry); void free_tmp_table(THD *thd, TABLE *entry);
void count_field_types(TMP_TABLE_PARAM *param, List<Item> &fields, void count_field_types(TMP_TABLE_PARAM *param, List<Item> &fields,
bool reset_with_sum_func); bool reset_with_sum_func);
bool setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param,List<Item> &fields); bool setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param,
Item **ref_pointer_array,
List<Item> &new_list1, List<Item> &new_list2,
uint elements, List<Item> &fields);
void copy_fields(TMP_TABLE_PARAM *param); void copy_fields(TMP_TABLE_PARAM *param);
void copy_funcs(Item_result_field **func_ptr); void copy_funcs(Item_result_field **func_ptr);
bool create_myisam_from_heap(THD *thd, TABLE *table, TMP_TABLE_PARAM *param, bool create_myisam_from_heap(THD *thd, TABLE *table, TMP_TABLE_PARAM *param,
......
...@@ -36,7 +36,7 @@ static char *make_unique_key_name(const char *field_name,KEY *start,KEY *end); ...@@ -36,7 +36,7 @@ static char *make_unique_key_name(const char *field_name,KEY *start,KEY *end);
static int copy_data_between_tables(TABLE *from,TABLE *to, static int copy_data_between_tables(TABLE *from,TABLE *to,
List<create_field> &create, List<create_field> &create,
enum enum_duplicates handle_duplicates, enum enum_duplicates handle_duplicates,
ORDER *order, uint order_num, ORDER *order,
ha_rows *copied,ha_rows *deleted); ha_rows *copied,ha_rows *deleted);
/***************************************************************************** /*****************************************************************************
...@@ -1572,7 +1572,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -1572,7 +1572,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
List<create_field> &fields, List<create_field> &fields,
List<Key> &keys,List<Alter_drop> &drop_list, List<Key> &keys,List<Alter_drop> &drop_list,
List<Alter_column> &alter_list, List<Alter_column> &alter_list,
ORDER *order, uint order_num, ORDER *order,
bool drop_primary, bool drop_primary,
enum enum_duplicates handle_duplicates, enum enum_duplicates handle_duplicates,
enum enum_enable_or_disable keys_onoff, enum enum_enable_or_disable keys_onoff,
...@@ -2034,7 +2034,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -2034,7 +2034,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
if (!new_table->is_view) if (!new_table->is_view)
error=copy_data_between_tables(table,new_table,create_list, error=copy_data_between_tables(table,new_table,create_list,
handle_duplicates, handle_duplicates,
order, &copied, &deleted); order_num, order, &copied, &deleted);
thd->last_insert_id=next_insert_id; // Needed for correct log thd->last_insert_id=next_insert_id; // Needed for correct log
thd->count_cuted_fields=0; // Don`t calc cuted fields thd->count_cuted_fields=0; // Don`t calc cuted fields
new_table->time_stamp=save_time_stamp; new_table->time_stamp=save_time_stamp;
...@@ -2244,7 +2244,7 @@ static int ...@@ -2244,7 +2244,7 @@ static int
copy_data_between_tables(TABLE *from,TABLE *to, copy_data_between_tables(TABLE *from,TABLE *to,
List<create_field> &create, List<create_field> &create,
enum enum_duplicates handle_duplicates, enum enum_duplicates handle_duplicates,
ORDER *order, uint order_num, ORDER *order,
ha_rows *copied, ha_rows *copied,
ha_rows *deleted) ha_rows *deleted)
{ {
...@@ -2292,7 +2292,10 @@ copy_data_between_tables(TABLE *from,TABLE *to, ...@@ -2292,7 +2292,10 @@ copy_data_between_tables(TABLE *from,TABLE *to,
tables.db = from->table_cache_key; tables.db = from->table_cache_key;
error=1; error=1;
if (setup_order(thd, &tables, fields, all_fields, order) || if (setup_ref_array(thd, &thd->lex.select_lex.ref_pointer_array,
order_num)||
setup_order(thd, thd->lex.select_lex.ref_pointer_array,
&tables, fields, all_fields, order) ||
!(sortorder=make_unireg_sortorder(order, &length)) || !(sortorder=make_unireg_sortorder(order, &length)) ||
(from->found_records = filesort(thd, from, sortorder, length, (from->found_records = filesort(thd, from, sortorder, length,
(SQL_SELECT *) 0, HA_POS_ERROR, (SQL_SELECT *) 0, HA_POS_ERROR,
......
...@@ -107,7 +107,6 @@ bool select_union::flush() ...@@ -107,7 +107,6 @@ bool select_union::flush()
return 0; return 0;
} }
typedef JOIN * JOIN_P;
int st_select_lex_unit::prepare(THD *thd, select_result *result) int st_select_lex_unit::prepare(THD *thd, select_result *result)
{ {
DBUG_ENTER("st_select_lex_unit::prepare"); DBUG_ENTER("st_select_lex_unit::prepare");
...@@ -115,11 +114,9 @@ int st_select_lex_unit::prepare(THD *thd, select_result *result) ...@@ -115,11 +114,9 @@ int st_select_lex_unit::prepare(THD *thd, select_result *result)
if (prepared) if (prepared)
DBUG_RETURN(0); DBUG_RETURN(0);
prepared= 1; prepared= 1;
union_result=0;
res= 0; res= 0;
found_rows_for_union= 0; found_rows_for_union= 0;
TMP_TABLE_PARAM tmp_table_param; TMP_TABLE_PARAM tmp_table_param;
this->thd= thd;
this->result= result; this->result= result;
SELECT_LEX_NODE *lex_select_save= thd->lex.current_select; SELECT_LEX_NODE *lex_select_save= thd->lex.current_select;
SELECT_LEX *sl; SELECT_LEX *sl;
...@@ -143,7 +140,9 @@ int st_select_lex_unit::prepare(THD *thd, select_result *result) ...@@ -143,7 +140,9 @@ int st_select_lex_unit::prepare(THD *thd, select_result *result)
while ((item= it++)) while ((item= it++))
if (item_list.push_back(item)) if (item_list.push_back(item))
goto err; goto err;
if (setup_fields(thd,first_table,item_list,0,0,1)) if (setup_wild(thd, first_table, item_list, 0,
first_select()->with_wild) ||
setup_fields(thd, 0, first_table, item_list, 0, 0, 1))
goto err; goto err;
} }
...@@ -169,13 +168,11 @@ int st_select_lex_unit::prepare(THD *thd, select_result *result) ...@@ -169,13 +168,11 @@ int st_select_lex_unit::prepare(THD *thd, select_result *result)
union_result->tmp_table_param=&tmp_table_param; union_result->tmp_table_param=&tmp_table_param;
// prepare selects // prepare selects
joins.empty();
for (sl= first_select(); sl; sl= sl->next_select()) for (sl= first_select(); sl; sl= sl->next_select())
{ {
JOIN *join= new JOIN(thd, sl->item_list, JOIN *join= new JOIN(thd, sl->item_list,
sl->options | thd->options | SELECT_NO_UNLOCK, sl->options | thd->options | SELECT_NO_UNLOCK,
union_result); union_result);
joins.push_back(new JOIN_P(join));
thd->lex.current_select= sl; thd->lex.current_select= sl;
offset_limit_cnt= sl->offset_limit; offset_limit_cnt= sl->offset_limit;
select_limit_cnt= sl->select_limit+sl->offset_limit; select_limit_cnt= sl->select_limit+sl->offset_limit;
...@@ -184,8 +181,11 @@ int st_select_lex_unit::prepare(THD *thd, select_result *result) ...@@ -184,8 +181,11 @@ int st_select_lex_unit::prepare(THD *thd, select_result *result)
if (select_limit_cnt == HA_POS_ERROR) if (select_limit_cnt == HA_POS_ERROR)
sl->options&= ~OPTION_FOUND_ROWS; sl->options&= ~OPTION_FOUND_ROWS;
res= join->prepare((TABLE_LIST*) sl->table_list.first, res= join->prepare(&sl->ref_pointer_array,
(TABLE_LIST*) sl->table_list.first, sl->with_wild,
sl->where, sl->where,
((sl->braces) ? sl->order_list.elements : 0) +
sl->group_list.elements,
(sl->braces) ? (sl->braces) ?
(ORDER *)sl->order_list.first : (ORDER *) 0, (ORDER *)sl->order_list.first : (ORDER *) 0,
(ORDER*) sl->group_list.first, (ORDER*) sl->group_list.first,
...@@ -207,11 +207,11 @@ int st_select_lex_unit::exec() ...@@ -207,11 +207,11 @@ int st_select_lex_unit::exec()
DBUG_ENTER("st_select_lex_unit::exec"); DBUG_ENTER("st_select_lex_unit::exec");
SELECT_LEX_NODE *lex_select_save= thd->lex.current_select; SELECT_LEX_NODE *lex_select_save= thd->lex.current_select;
if (executed && !dependent) if (executed && !(dependent||uncacheable))
DBUG_RETURN(0); DBUG_RETURN(0);
executed= 1; executed= 1;
if (dependent || !item || !item->assigned()) if ((dependent||uncacheable) || !item || !item->assigned())
{ {
if (optimized && item && item->assigned()) if (optimized && item && item->assigned())
{ {
...@@ -287,8 +287,9 @@ int st_select_lex_unit::exec() ...@@ -287,8 +287,9 @@ int st_select_lex_unit::exec()
select_limit_cnt= HA_POS_ERROR; // no limit select_limit_cnt= HA_POS_ERROR; // no limit
if (select_limit_cnt == HA_POS_ERROR) if (select_limit_cnt == HA_POS_ERROR)
thd->options&= ~OPTION_FOUND_ROWS; thd->options&= ~OPTION_FOUND_ROWS;
res= mysql_select(thd,&result_table_list, res= mysql_select(thd, &ref_pointer_array, &result_table_list,
item_list, NULL, 0, item_list, NULL,
global_parameters->order_list.elements,
(ORDER*)global_parameters->order_list.first, (ORDER*)global_parameters->order_list.first,
(ORDER*) NULL, NULL, (ORDER*) NULL, (ORDER*) NULL, NULL, (ORDER*) NULL,
thd->options, result, this, first_select(), 1); thd->options, result, this, first_select(), 1);
...@@ -304,20 +305,24 @@ int st_select_lex_unit::exec() ...@@ -304,20 +305,24 @@ int st_select_lex_unit::exec()
int st_select_lex_unit::cleanup() int st_select_lex_unit::cleanup()
{ {
DBUG_ENTER("st_select_lex_unit::cleanup"); DBUG_ENTER("st_select_lex_unit::cleanup");
int error= 0;
if (union_result) if (union_result)
{ {
delete union_result; delete union_result;
free_tmp_table(thd,table); if (table)
free_tmp_table(thd, table);
table= 0; // Safety table= 0; // Safety
} }
List_iterator<JOIN*> j(joins); for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select())
JOIN** join;
while ((join= j++))
{ {
(*join)->cleanup(thd); JOIN *join;
delete *join; if ((join= sl->join))
delete join; {
error|= sl->join->cleanup(thd);
delete join;
}
} }
joins.empty(); DBUG_RETURN(error);
DBUG_RETURN(0);
} }
...@@ -50,7 +50,7 @@ int mysql_update(THD *thd, ...@@ -50,7 +50,7 @@ int mysql_update(THD *thd,
List<Item> &fields, List<Item> &fields,
List<Item> &values, List<Item> &values,
COND *conds, COND *conds,
ORDER *order, uint order_num, ORDER *order,
ha_rows limit, ha_rows limit,
enum enum_duplicates handle_duplicates) enum enum_duplicates handle_duplicates)
{ {
...@@ -109,7 +109,7 @@ int mysql_update(THD *thd, ...@@ -109,7 +109,7 @@ int mysql_update(THD *thd,
/* Check the fields we are going to modify */ /* Check the fields we are going to modify */
table->grant.want_privilege=want_privilege; table->grant.want_privilege=want_privilege;
if (setup_fields(thd,update_table_list,fields,1,0,0)) if (setup_fields(thd, 0, update_table_list, fields, 1, 0, 0))
DBUG_RETURN(-1); /* purecov: inspected */ DBUG_RETURN(-1); /* purecov: inspected */
if (table->timestamp_field) if (table->timestamp_field)
{ {
...@@ -122,8 +122,9 @@ int mysql_update(THD *thd, ...@@ -122,8 +122,9 @@ int mysql_update(THD *thd,
/* Check values */ /* Check values */
table->grant.want_privilege=(SELECT_ACL & ~table->grant.privilege); table->grant.want_privilege=(SELECT_ACL & ~table->grant.privilege);
if (setup_fields(thd,update_table_list,values,0,0,0)) if (setup_fields(thd, 0, update_table_list, values, 0, 0, 0))
{ {
free_ulderlayed_joins(thd, &thd->lex.select_lex);
DBUG_RETURN(-1); /* purecov: inspected */ DBUG_RETURN(-1); /* purecov: inspected */
} }
...@@ -134,6 +135,7 @@ int mysql_update(THD *thd, ...@@ -134,6 +135,7 @@ int mysql_update(THD *thd,
(select && select->check_quick(safe_update, limit)) || !limit) (select && select->check_quick(safe_update, limit)) || !limit)
{ {
delete select; delete select;
free_ulderlayed_joins(thd, &thd->lex.select_lex);
if (error) if (error)
{ {
DBUG_RETURN(-1); // Error in where DBUG_RETURN(-1); // Error in where
...@@ -148,6 +150,7 @@ int mysql_update(THD *thd, ...@@ -148,6 +150,7 @@ int mysql_update(THD *thd,
if (safe_update && !using_limit) if (safe_update && !using_limit)
{ {
delete select; delete select;
free_ulderlayed_joins(thd, &thd->lex.select_lex);
send_error(thd,ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE); send_error(thd,ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE);
DBUG_RETURN(1); DBUG_RETURN(1);
} }
...@@ -175,6 +178,7 @@ int mysql_update(THD *thd, ...@@ -175,6 +178,7 @@ int mysql_update(THD *thd,
DISK_BUFFER_SIZE, MYF(MY_WME))) DISK_BUFFER_SIZE, MYF(MY_WME)))
{ {
delete select; /* purecov: inspected */ delete select; /* purecov: inspected */
free_ulderlayed_joins(thd, &thd->lex.select_lex);
DBUG_RETURN(-1); DBUG_RETURN(-1);
} }
if (old_used_keys & ((key_map) 1 << used_index)) if (old_used_keys & ((key_map) 1 << used_index))
...@@ -197,7 +201,10 @@ int mysql_update(THD *thd, ...@@ -197,7 +201,10 @@ int mysql_update(THD *thd,
table->io_cache = (IO_CACHE *) my_malloc(sizeof(IO_CACHE), table->io_cache = (IO_CACHE *) my_malloc(sizeof(IO_CACHE),
MYF(MY_FAE | MY_ZEROFILL)); MYF(MY_FAE | MY_ZEROFILL));
if (setup_order(thd, &tables, fields, all_fields, order) || if (setup_ref_array(thd, &thd->lex.select_lex.ref_pointer_array,
order_num)||
setup_order(thd, thd->lex.select_lex.ref_pointer_array,
&tables, fields, all_fields, order) ||
!(sortorder=make_unireg_sortorder(order, &length)) || !(sortorder=make_unireg_sortorder(order, &length)) ||
(table->found_records = filesort(thd, table, sortorder, length, (table->found_records = filesort(thd, table, sortorder, length,
(SQL_SELECT *) 0, (SQL_SELECT *) 0,
...@@ -205,6 +212,7 @@ int mysql_update(THD *thd, ...@@ -205,6 +212,7 @@ int mysql_update(THD *thd,
== HA_POS_ERROR) == HA_POS_ERROR)
{ {
delete select; delete select;
free_ulderlayed_joins(thd, &thd->lex.select_lex);
DBUG_RETURN(-1); DBUG_RETURN(-1);
} }
} }
...@@ -259,6 +267,7 @@ int mysql_update(THD *thd, ...@@ -259,6 +267,7 @@ int mysql_update(THD *thd,
if (error >= 0) if (error >= 0)
{ {
delete select; delete select;
free_ulderlayed_joins(thd, &thd->lex.select_lex);
DBUG_RETURN(-1); DBUG_RETURN(-1);
} }
} }
...@@ -344,6 +353,7 @@ int mysql_update(THD *thd, ...@@ -344,6 +353,7 @@ int mysql_update(THD *thd,
} }
delete select; delete select;
free_ulderlayed_joins(thd, &thd->lex.select_lex);
if (error >= 0) if (error >= 0)
send_error(thd,thd->killed ? ER_SERVER_SHUTDOWN : 0); /* purecov: inspected */ send_error(thd,thd->killed ? ER_SERVER_SHUTDOWN : 0); /* purecov: inspected */
else else
...@@ -358,6 +368,7 @@ int mysql_update(THD *thd, ...@@ -358,6 +368,7 @@ int mysql_update(THD *thd,
} }
thd->count_cuted_fields=0; /* calc cuted fields */ thd->count_cuted_fields=0; /* calc cuted fields */
free_io_cache(table); free_io_cache(table);
DBUG_RETURN(0); DBUG_RETURN(0);
} }
...@@ -389,7 +400,7 @@ int mysql_multi_update(THD *thd, ...@@ -389,7 +400,7 @@ int mysql_multi_update(THD *thd,
DBUG_RETURN(res); DBUG_RETURN(res);
thd->select_limit=HA_POS_ERROR; thd->select_limit=HA_POS_ERROR;
if (setup_fields(thd, table_list, *fields, 1, 0, 0)) if (setup_fields(thd, 0, table_list, *fields, 1, 0, 0))
DBUG_RETURN(-1); DBUG_RETURN(-1);
/* /*
...@@ -412,8 +423,9 @@ int mysql_multi_update(THD *thd, ...@@ -412,8 +423,9 @@ int mysql_multi_update(THD *thd,
DBUG_RETURN(-1); DBUG_RETURN(-1);
List<Item> total_list; List<Item> total_list;
res= mysql_select(thd,table_list,total_list, res= mysql_select(thd, &select_lex->ref_pointer_array,
conds, (ORDER *) NULL, (ORDER *)NULL, (Item *) NULL, table_list, select_lex->with_wild, total_list,
conds, 0, (ORDER *) NULL, (ORDER *)NULL, (Item *) NULL,
(ORDER *)NULL, (ORDER *)NULL,
options | SELECT_NO_JOIN_CACHE, options | SELECT_NO_JOIN_CACHE,
result, unit, select_lex, 0); result, unit, select_lex, 0);
...@@ -466,7 +478,7 @@ int multi_update::prepare(List<Item> &not_used_values, SELECT_LEX_UNIT *unit) ...@@ -466,7 +478,7 @@ int multi_update::prepare(List<Item> &not_used_values, SELECT_LEX_UNIT *unit)
reference tables reference tables
*/ */
if (setup_fields(thd, all_tables, *values, 1,0,0)) if (setup_fields(thd, 0, all_tables, *values, 1, 0, 0))
DBUG_RETURN(1); DBUG_RETURN(1);
/* /*
......
...@@ -1798,7 +1798,7 @@ select_option: ...@@ -1798,7 +1798,7 @@ select_option:
YYABORT; YYABORT;
Select->options|= OPTION_FOUND_ROWS; Select->options|= OPTION_FOUND_ROWS;
} }
| SQL_NO_CACHE_SYM { Lex->safe_to_cache_query=0; } | SQL_NO_CACHE_SYM { Lex->uncacheable();; }
| SQL_CACHE_SYM { Select->options|= OPTION_TO_QUERY_CACHE; } | SQL_CACHE_SYM { Select->options|= OPTION_TO_QUERY_CACHE; }
| ALL {} | ALL {}
; ;
...@@ -1825,8 +1825,10 @@ select_item_list: ...@@ -1825,8 +1825,10 @@ select_item_list:
| select_item | select_item
| '*' | '*'
{ {
if (add_item_to_list(YYTHD, new Item_field(NULL,NULL,"*"))) THD *thd= YYTHD;
if (add_item_to_list(thd, new Item_field(NULL, NULL, "*")))
YYABORT; YYABORT;
(thd->lex.current_select->select_lex()->with_wild)++;
}; };
...@@ -2049,12 +2051,12 @@ simple_expr: ...@@ -2049,12 +2051,12 @@ simple_expr:
| '@' ident_or_text SET_VAR expr | '@' ident_or_text SET_VAR expr
{ {
$$= new Item_func_set_user_var($2,$4); $$= new Item_func_set_user_var($2,$4);
Lex->safe_to_cache_query=0; Lex->uncacheable();;
} }
| '@' ident_or_text | '@' ident_or_text
{ {
$$= new Item_func_get_user_var($2); $$= new Item_func_get_user_var($2);
Lex->safe_to_cache_query=0; Lex->uncacheable();;
} }
| '@' '@' opt_var_ident_type ident_or_text | '@' '@' opt_var_ident_type ident_or_text
{ {
...@@ -2145,7 +2147,7 @@ simple_expr: ...@@ -2145,7 +2147,7 @@ simple_expr:
| ENCRYPT '(' expr ')' | ENCRYPT '(' expr ')'
{ {
$$= new Item_func_encrypt($3); $$= new Item_func_encrypt($3);
Lex->safe_to_cache_query=0; Lex->uncacheable();;
} }
| ENCRYPT '(' expr ',' expr ')' { $$= new Item_func_encrypt($3,$5); } | ENCRYPT '(' expr ',' expr ')' { $$= new Item_func_encrypt($3,$5); }
| DECODE_SYM '(' expr ',' TEXT_STRING ')' | DECODE_SYM '(' expr ',' TEXT_STRING ')'
...@@ -2208,11 +2210,12 @@ simple_expr: ...@@ -2208,11 +2210,12 @@ simple_expr:
{ {
$$= get_system_var(OPT_SESSION, "last_insert_id", 14, $$= get_system_var(OPT_SESSION, "last_insert_id", 14,
"last_insert_id()"); "last_insert_id()");
Lex->safe_to_cache_query= 0;
} }
| LAST_INSERT_ID '(' expr ')' | LAST_INSERT_ID '(' expr ')'
{ {
$$= new Item_func_set_last_insert_id($3); $$= new Item_func_set_last_insert_id($3);
Lex->safe_to_cache_query=0; Lex->safe_to_cache_query= 0;
} }
| LEFT '(' expr ',' expr ')' | LEFT '(' expr ',' expr ')'
{ $$= new Item_func_left($3,$5); } { $$= new Item_func_left($3,$5); }
...@@ -2288,9 +2291,9 @@ simple_expr: ...@@ -2288,9 +2291,9 @@ simple_expr:
| POSITION_SYM '(' no_in_expr IN_SYM expr ')' | POSITION_SYM '(' no_in_expr IN_SYM expr ')'
{ $$ = new Item_func_locate($5,$3); } { $$ = new Item_func_locate($5,$3); }
| RAND '(' expr ')' | RAND '(' expr ')'
{ $$= new Item_func_rand($3); Lex->safe_to_cache_query=0;} { $$= new Item_func_rand($3); Lex->uncacheable();}
| RAND '(' ')' | RAND '(' ')'
{ $$= new Item_func_rand(); Lex->safe_to_cache_query=0;} { $$= new Item_func_rand(); Lex->uncacheable();}
| REPLACE '(' expr ',' expr ',' expr ')' | REPLACE '(' expr ',' expr ',' expr ')'
{ $$= new Item_func_replace($3,$5,$7); } { $$= new Item_func_replace($3,$5,$7); }
| RIGHT '(' expr ',' expr ')' | RIGHT '(' expr ',' expr ')'
...@@ -2392,7 +2395,7 @@ simple_expr: ...@@ -2392,7 +2395,7 @@ simple_expr:
| BENCHMARK_SYM '(' ULONG_NUM ',' expr ')' | BENCHMARK_SYM '(' ULONG_NUM ',' expr ')'
{ {
$$=new Item_func_benchmark($3,$5); $$=new Item_func_benchmark($3,$5);
Lex->safe_to_cache_query=0; Lex->uncacheable();
} }
| EXTRACT_SYM '(' interval FROM expr ')' | EXTRACT_SYM '(' interval FROM expr ')'
{ $$=new Item_extract( $3, $5); }; { $$=new Item_extract( $3, $5); };
...@@ -2890,7 +2893,7 @@ procedure_clause: ...@@ -2890,7 +2893,7 @@ procedure_clause:
lex->proc_list.next= (byte**) &lex->proc_list.first; lex->proc_list.next= (byte**) &lex->proc_list.first;
if (add_proc_to_list(lex->thd, new Item_field(NULL,NULL,$2.str))) if (add_proc_to_list(lex->thd, new Item_field(NULL,NULL,$2.str)))
YYABORT; YYABORT;
Lex->safe_to_cache_query=0; Lex->uncacheable();
} }
'(' procedure_list ')'; '(' procedure_list ')';
...@@ -2964,7 +2967,7 @@ into: ...@@ -2964,7 +2967,7 @@ into:
} }
| INTO select_var_list_init | INTO select_var_list_init
{ {
Lex->safe_to_cache_query=0; Lex->uncacheable();
} }
; ;
...@@ -3750,10 +3753,19 @@ insert_ident: ...@@ -3750,10 +3753,19 @@ insert_ident:
| table_wild { $$=$1; }; | table_wild { $$=$1; };
table_wild: table_wild:
ident '.' '*' { $$ = new Item_field(NullS,$1.str,"*"); } ident '.' '*'
{
$$ = new Item_field(NullS,$1.str,"*");
Lex->current_select->select_lex()->with_wild++;
}
| ident '.' ident '.' '*' | ident '.' ident '.' '*'
{ $$ = new Item_field((YYTHD->client_capabilities & {
CLIENT_NO_SCHEMA ? NullS : $1.str),$3.str,"*"); }; $$ = new Item_field((YYTHD->client_capabilities &
CLIENT_NO_SCHEMA ? NullS : $1.str),
$3.str,"*");
Lex->current_select->select_lex()->with_wild++;
}
;
order_ident: order_ident:
expr { $$=$1; }; expr { $$=$1; };
......
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