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,6 +1122,7 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference) ...@@ -1081,6 +1122,7 @@ 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,
&counter,
REPORT_EXCEPT_NOT_FOUND)) != REPORT_EXCEPT_NOT_FOUND)) !=
(Item **)not_found_item) (Item **)not_found_item)
break; break;
...@@ -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,7 +596,7 @@ void Item_in_subselect::row_value_transformer(THD *thd, ...@@ -591,7 +596,7 @@ 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=
...@@ -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 (!original)
{
if (table) if (table)
free_tmp_table(current_thd, table); free_tmp_table(current_thd, table);
delete tmp_table_param; delete tmp_table_param;
if (use_tree) if (use_tree)
delete_tree(&tree); delete_tree(tree);
}
} }
...@@ -1100,7 +1136,7 @@ bool Item_sum_count_distinct::setup(THD *thd) ...@@ -1100,7 +1136,7 @@ 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);
......
...@@ -1808,10 +1808,14 @@ const Item **not_found_item= (const Item**) 0x1; ...@@ -1808,10 +1808,14 @@ 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,22 +1900,18 @@ find_item_in_list(Item *find, List<Item> &items, ...@@ -1891,22 +1900,18 @@ 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] == '*')
...@@ -1914,7 +1919,7 @@ int setup_fields(THD *thd, TABLE_LIST *tables, List<Item> &fields, ...@@ -1914,7 +1919,7 @@ int setup_fields(THD *thd, TABLE_LIST *tables, List<Item> &fields,
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,22 +1929,44 @@ int setup_fields(THD *thd, TABLE_LIST *tables, List<Item> &fields, ...@@ -1924,22 +1929,44 @@ 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 }
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)) if (item->fix_fields(thd, tables, it.ref()) ||
item->check_cols(1))
DBUG_RETURN(-1); /* purecov: inspected */ DBUG_RETURN(-1); /* purecov: inspected */
item= *(it.ref()); //Item can be chenged in fix fields 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 && if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM &&
sum_func_list) sum_func_list)
item->split_sum_func(*sum_func_list); item->split_sum_func(ref_pointer_array, *sum_func_list);
thd->used_tables|=item->used_tables(); thd->used_tables|=item->used_tables();
} }
}
DBUG_RETURN(test(thd->fatal_error || thd->net.report_error)); DBUG_RETURN(test(thd->fatal_error || thd->net.report_error));
} }
/* /*
Remap table numbers if INSERT ... SELECT Remap table numbers if INSERT ... SELECT
Check also that the 'used keys' and 'ignored keys' exists and set up the Check also that the 'used keys' and 'ignored keys' exists and set up the
...@@ -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)
...@@ -91,15 +92,9 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t) ...@@ -91,15 +92,9 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
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,19 +103,27 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t) ...@@ -108,19 +103,27 @@ 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 |
...@@ -142,11 +145,15 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t) ...@@ -142,11 +145,15 @@ 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->item_list, sl->where,
sl->order_list.elements+sl->group_list.elements,
(ORDER *) sl->order_list.first,
(ORDER *) sl->group_list.first,
sl->having, (ORDER*) NULL, sl->having, (ORDER*) NULL,
sl->options | thd->options | SELECT_NO_UNLOCK, sl->options | thd->options | SELECT_NO_UNLOCK,
derived_result, unit, sl, 0); derived_result, unit, sl, 0);
...@@ -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()
...@@ -1165,7 +1169,7 @@ bool st_select_lex_node::add_group_to_list(THD *thd, Item *item, bool asc) ...@@ -1165,7 +1169,7 @@ bool st_select_lex_node::add_group_to_list(THD *thd, Item *item, bool asc)
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
Item **ref_pointer_array;
uint with_sum_func; /* sum function indicator and number of it */
bool create_refs; 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;
...@@ -179,6 +184,8 @@ class JOIN :public Sql_alloc ...@@ -179,6 +184,8 @@ class JOIN :public Sql_alloc
// 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,
skip_sort_order, need_tmp, skip_sort_order, need_tmp,
...@@ -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))
{
error|= sl->join->cleanup(thd);
delete join; delete join;
} }
joins.empty(); }
DBUG_RETURN(0); DBUG_RETURN(error);
} }
...@@ -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