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
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 8
2 DERIVED 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));
SELECT * FROM (SELECT * FROM t1) as b ORDER BY a ASC LIMIT 0,20;
a t
......
......@@ -155,21 +155,18 @@ select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1);
a b
1 7
2 7
(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;
(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;
a b
1 7
2 7
3 8
(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)) union (select * from t4 where t4.b=(select max(t2.a)*4 from t2) order by a);
a b
1 7
2 7
3 8
4 8
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);
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);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t2 ALL NULL NULL NULL NULL 2 Using where
2 SUBSELECT t3 ALL NULL NULL NULL NULL 3 Using filesort
......@@ -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;
id select_type table type possible_keys key key_len ref rows Extra
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
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
......@@ -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');
id select_type table type possible_keys key key_len ref rows Extra
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
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
t8 WHERE pseudo='joce');
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;
Unknown column 'a' in 'having clause'
SELECT 1 IN (SELECT 1 FROM t2 HAVING a);
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
joce 40143 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
joce 43506 2002-10-22 joce
SELECT * from t2 where topic IN (SELECT SUM(topic) FROM t1);
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
joce 40143 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
joce 43506 2002-10-22 joce
SELECT * from t2 where topic = any (SELECT SUM(topic) FROM t1);
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
joce 40143 2002-10-22 joce
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);
mot topic date pseudo
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);
mot topic date pseudo
SELECT * from t2 where topic <> any (SELECT SUM(topic) FROM t2);
mot topic date pseudo
joce 40143 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;
CREATE TABLE `t1` (
`numeropost` mediumint(8) unsigned NOT NULL auto_increment,
......@@ -856,3 +868,86 @@ do (SELECT a from t1);
Table 'test.t1' doesn't exist
set @a:=(SELECT a from t1);
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;
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 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));
disable_query_log;
let $1 = 10000;
......
......@@ -70,12 +70,9 @@ select (select a from t3), a from t2;
select * from t2 where t2.a=(select a from t1);
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))
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);
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 * 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;
(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);
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 t3.a from t3 where a<8 order by 1 desc limit 1), a from
(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
SELECT (SELECT 1) as a FROM (SELECT 1 FROM t1 HAVING a=1) b;
-- error 1054
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 = any (SELECT topic FROM t2 GROUP BY date);
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);
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 = all (SELECT topic FROM t2 GROUP BY date);
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);
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 <> 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;
#forumconthardwarefr7
......@@ -480,3 +483,79 @@ drop table t1;
do (SELECT a from t1);
-- error 1146
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():
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)
{
......@@ -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
}
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)
{
......@@ -262,9 +291,16 @@ table_map Item_field::used_tables() const
{
if (field->table->const_table)
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)
{
......@@ -537,20 +573,14 @@ bool Item_ref_on_list_position::fix_fields(THD *thd,
struct st_table_list *tables,
Item ** reference)
{
List_iterator<Item> li(list);
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
if (select_lex->item_list.elements <= pos)
{
ref= 0;
my_error(ER_CARDINALITY_COL, MYF(0), pos);
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()
......@@ -600,6 +630,7 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
thd->net.last_errno= 0;
#endif
Item **refer= (Item **)not_found_item;
uint counter= 0;
// Prevent using outer fields in subselects, that is not supported now
SELECT_LEX *cursel=(SELECT_LEX *) thd->lex.current_select;
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)
(last= sl)->get_table_list(), &where,
0)) != not_found_field)
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)) !=
(Item **)not_found_item)
break;
......@@ -631,8 +662,16 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
}
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;
*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);
if (!r)
return 1;
......@@ -1045,6 +1084,7 @@ bool Item_field::send(Protocol *protocol, String *buffer)
bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
{
uint counter= 0;
if (!ref)
{
TABLE_LIST *where= 0;
......@@ -1059,6 +1099,7 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
if (outer_resolving ||
(ref= find_item_in_list(this,
*(thd->lex.current_select->get_item_list()),
&counter,
((sl &&
thd->lex.current_select->master_unit()->
first_select()->linkage !=
......@@ -1081,7 +1122,8 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
for ( ; sl ; sl= sl->outer_select())
{
if ((ref= find_item_in_list(this, (last= sl)->item_list,
REPORT_EXCEPT_NOT_FOUND)) !=
&counter,
REPORT_EXCEPT_NOT_FOUND)) !=
(Item **)not_found_item)
break;
if ((tmp= find_field_in_tables(thd, this,
......@@ -1102,6 +1144,7 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
// Call to report error
find_item_in_list(this,
*(thd->lex.current_select->get_item_list()),
&counter,
REPORT_ALL_ERRORS);
ref= 0;
return 1;
......@@ -1118,17 +1161,35 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
}
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->add_possible_loop(this);
}
}
else if (!ref)
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;
maybe_null= (*ref)->maybe_null;
decimals= (*ref)->decimals;
}
if (((*ref)->with_sum_func &&
(depended_from ||
!(thd->lex.current_select->linkage != GLOBAL_OPTIONS_TYPE &&
......
......@@ -53,6 +53,8 @@ public:
// alloc & destruct is done as start of select using sql_alloc
Item();
// copy constructor used by Item_field, Item_ref & agregate (sum) functions
Item(Item &item);
virtual ~Item() { name=0; } /*lint -e1509 */
void set_name(const char *str,uint length=0);
void init_make_field(Send_field *tmp_field,enum enum_field_types type);
......@@ -71,7 +73,8 @@ public:
virtual double val()=0;
virtual longlong val_int()=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 double val_result() { return val(); }
virtual longlong val_int_result() { return val_int(); }
......@@ -85,12 +88,14 @@ public:
virtual bool const_item() const { return used_tables() == 0; }
virtual void print(String *str_arg) { str_arg->append(full_name()); }
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_time(TIME *ltime);
virtual bool is_null() { return 0; };
virtual bool check_loop(uint id);
virtual void top_level_item() {}
virtual Item * get_same() { return this; }
virtual Item * get_tmp_table_item() { return get_same(); }
virtual bool binary() const
{ return str_value.charset()->state & MY_CS_BINSORT ? 1 : 0 ; }
......@@ -125,6 +130,8 @@ public:
:db_name(db_name_par), table_name(table_name_par),
field_name(field_name_par), depended_from(0), outer_resolving(0)
{ name = (char*) field_name_par; }
// copy constructor used by Item_field & Item_ref
Item_ident(Item_ident &item);
const char *full_name() const;
void set_outer_resolving() { outer_resolving= 1; }
};
......@@ -141,6 +148,8 @@ public:
const char *field_name_par)
: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);
enum Type type() const { return FIELD_ITEM; }
bool eq(const Item *item, bool binary_cmp) const;
......@@ -164,10 +173,12 @@ public:
{
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_time(TIME *ltime);
bool is_null() { return field->is_null(); }
Item * get_tmp_table_item();
friend class Item_default_value;
};
......@@ -427,8 +438,13 @@ class Item_result_field :public Item /* Item with result field */
public:
Field *result_field; /* Save result here */
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 */
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; }
virtual void fix_length_and_dec()=0;
};
......@@ -442,6 +458,8 @@ public:
: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_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; }
bool eq(const Item *item, bool binary_cmp) const
{ return ref && (*ref)->eq(item, binary_cmp); }
......@@ -511,14 +529,14 @@ public:
class Item_ref_on_list_position: public Item_ref_null_helper
{
protected:
List<Item> &list;
st_select_lex *select_lex;
uint pos;
public:
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):
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);
};
......@@ -692,7 +710,12 @@ public:
class Item_cache: public Item
{
table_map used_table_map;
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 setup(Item *) { return 0; };
virtual void store(Item *)= 0;
......@@ -703,13 +726,14 @@ public:
}
enum Type type() const { return CACHE_ITEM; }
static Item_cache* get_cache(Item_result type);
table_map used_tables() const { return used_table_map; }
};
class Item_cache_int: public Item_cache
{
longlong value;
public:
Item_cache_int() { fixed= 1; null_value= 1; }
Item_cache_int(): Item_cache() {}
void store(Item *item)
{
......@@ -726,7 +750,7 @@ class Item_cache_real: public Item_cache
{
double value;
public:
Item_cache_real() { fixed= 1; null_value= 1; }
Item_cache_real(): Item_cache() {}
void store(Item *item)
{
......@@ -748,7 +772,7 @@ class Item_cache_str: public Item_cache
char buffer[80];
String *value;
public:
Item_cache_str() { fixed= 1; null_value= 1; }
Item_cache_str(): Item_cache() { }
void store(Item *item);
double val();
......@@ -763,7 +787,7 @@ class Item_cache_row: public Item_cache
Item_cache **values;
uint item_count;
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
......
......@@ -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())))
return 1;
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))
return 1;
Item_in_subselect * sub= (Item_in_subselect *)args[1];
......@@ -1372,16 +1380,20 @@ void Item_func_in::update_used_tables()
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)
item->split_sum_func(fields);
item->split_sum_func(ref_pointer_array, fields);
else if (item->used_tables() || item->type() == SUM_FUNC_ITEM)
{
uint el= fields.elements;
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()
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);
Item *item;
......@@ -1496,11 +1508,13 @@ void Item_cond::split_sum_func(List<Item> &fields)
while ((item=li++))
{
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)
{
uint el= fields.elements;
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();
used_tables_cache|=item->used_tables();
......
......@@ -17,8 +17,6 @@
/* compare and test functions */
#include "assert.h"
#ifdef __GNUC__
#pragma interface /* gcc class implementation */
#endif
......@@ -637,7 +635,7 @@ class Item_func_in :public Item_int_func
enum Functype functype() const { return IN_FUNC; }
const char *func_name() const { return " IN "; }
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)
{
DBUG_ENTER("Item_func_in::check_loop");
......@@ -788,7 +786,7 @@ public:
table_map used_tables() const;
void update_used_tables();
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);
bool check_loop(uint id);
void top_level_item() { abort_on_null=1; }
......
......@@ -167,7 +167,7 @@ Item *create_func_from_days(Item* a)
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);
}
......@@ -327,7 +327,7 @@ Item *create_func_radians(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);
}
......@@ -435,13 +435,13 @@ Item *create_func_year(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);
}
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);
}
......@@ -463,7 +463,7 @@ Item *create_func_cast(Item *a, Item_cast cast_type)
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);
}
......
......@@ -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;
for (arg=args, arg_end=args+arg_count; arg != arg_end ; arg++)
{
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)
{
uint el= fields.elements;
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
return 1;
}
Field *Item_func::tmp_table_field(TABLE *t_arg)
{
Field *res;
LINT_INIT(res);
if (!t_arg)
return result_field;
switch (result_type()) {
case INT_RESULT:
if (max_length > 11)
......@@ -312,6 +311,16 @@ void Item_func::fix_num_length_and_dec()
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)
{
longlong nr=val_int();
......@@ -2535,7 +2544,7 @@ Item *get_system_var(enum_var_type var_type, LEX_STRING name)
}
if (!(item=var->item(thd, var_type)))
return 0; // Impossible
thd->lex.safe_to_cache_query=0;
thd->lex.uncacheable();
buff[0]='@';
buff[1]='@';
pos=buff+2;
......@@ -2561,7 +2570,7 @@ Item *get_system_var(enum_var_type var_type, const char *var_name, uint length,
DBUG_ASSERT(var != 0);
if (!(item=var->item(thd, var_type)))
return 0; // Impossible
thd->lex.safe_to_cache_query=0;
thd->lex.uncacheable();
item->set_name(item_name); // Will use original name
return item;
}
......
......@@ -117,7 +117,7 @@ public:
inline Item **arguments() const { return args; }
inline uint argument_count() const { return arg_count; }
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_op(String *str);
void fix_num_length_and_dec();
......@@ -131,9 +131,11 @@ public:
}
bool is_null() { (void) val_int(); return null_value; }
friend class udf_handler;
Field *tmp_table_field() { return result_field; }
Field *tmp_table_field(TABLE *t_arg);
bool check_loop(uint id);
void set_outer_resolving();
Item * get_tmp_table_item();
};
......
......@@ -129,7 +129,8 @@ void Item_subselect::fix_length_and_dec()
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,
......@@ -439,6 +440,7 @@ void Item_in_subselect::single_value_transformer(THD *thd,
compare_func_creator func)
{
DBUG_ENTER("Item_in_subselect::single_value_transformer");
if (unit->global_parameters->select_limit != HA_POS_ERROR)
{
my_error(ER_NOT_SUPPORTED_YET, MYF(0),
......@@ -482,11 +484,14 @@ void Item_in_subselect::single_value_transformer(THD *thd,
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);
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,
sl->item_list.head_ref(),
sl->ref_pointer_array,
(char *)"<no matter>",
(char*)"<result>"));
sl->having= and_items(sl->having, item);
......@@ -591,9 +596,9 @@ void Item_in_subselect::row_value_transformer(THD *thd,
for (uint i= 0; i < n; i++)
{
Item *func=
new Item_ref_on_list_position(this, sl->item_list, i,
(char *) "<no matter>",
(char *) "<list ref>");
new Item_ref_on_list_position(this, sl, i,
(char *) "<no matter>",
(char *) "<list ref>");
func=
Item_bool_func2::eq_creator(new Item_ref((*optimizer->get_cache())->
addr(i),
......@@ -678,8 +683,12 @@ int subselect_single_select_engine::prepare()
prepared= 1;
SELECT_LEX_NODE *save_select= thd->lex.current_select;
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->order_list.elements +
select_lex->group_list.elements,
(ORDER*) select_lex->order_list.first,
(ORDER*) select_lex->group_list.first,
select_lex->having,
......@@ -787,7 +796,7 @@ int subselect_single_select_engine::exec()
DBUG_RETURN(join->error?join->error:1);
}
}
if (select_lex->dependent && executed)
if ((select_lex->dependent || select_lex->uncacheable) && executed)
{
if (join->reinit())
{
......@@ -829,16 +838,26 @@ uint subselect_union_engine::cols()
return unit->first_select()->item_list.elements;
}
bool subselect_single_select_engine::depended()
bool subselect_single_select_engine::dependent()
{
return select_lex->dependent;
}
bool subselect_union_engine::depended()
bool subselect_union_engine::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)
{
DBUG_ENTER("subselect_single_select_engine::check_loop");
......@@ -857,13 +876,9 @@ bool subselect_union_engine::check_loop(uint id)
void subselect_single_select_engine::exclude()
{
select_lex->master_unit()->exclude_level();
//if (current_thd->lex->describe)
}
void subselect_union_engine::exclude()
{
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:
virtual void fix_length_and_dec(Item_cache** row)= 0;
virtual int exec()= 0;
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; }
virtual bool check_loop(uint id)= 0;
virtual void exclude()= 0;
......@@ -245,7 +246,8 @@ public:
void fix_length_and_dec(Item_cache** row);
int exec();
uint cols();
bool depended();
bool dependent();
bool uncacheable();
bool check_loop(uint id);
void exclude();
};
......@@ -262,7 +264,8 @@ public:
void fix_length_and_dec(Item_cache** row);
int exec();
uint cols();
bool depended();
bool dependent();
bool uncacheable();
bool check_loop(uint id);
void exclude();
};
......@@ -41,9 +41,22 @@ Item_sum::Item_sum(List<Item> &list)
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()
{
current_thd->lex.current_select->with_sum_func=1;
current_thd->lex.current_select->with_sum_func++;
with_sum_func= 1;
}
......@@ -83,6 +96,26 @@ void Item_sum::fix_num_length_and_dec()
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 *
Item_sum_num::val_str(String *str)
......@@ -952,7 +985,7 @@ int dump_leaf(byte* key, uint32 count __attribute__((unused)),
The first item->rec_offset bytes are taken care of with
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 != HA_ERR_FOUND_DUPP_KEY &&
......@@ -965,11 +998,14 @@ int dump_leaf(byte* key, uint32 count __attribute__((unused)),
Item_sum_count_distinct::~Item_sum_count_distinct()
{
if (table)
free_tmp_table(current_thd, table);
delete tmp_table_param;
if (use_tree)
delete_tree(&tree);
if (!original)
{
if (table)
free_tmp_table(current_thd, table);
delete tmp_table_param;
if (use_tree)
delete_tree(tree);
}
}
......@@ -1100,8 +1136,8 @@ bool Item_sum_count_distinct::setup(THD *thd)
}
}
init_tree(&tree, min(thd->variables.max_heap_table_size,
thd->variables.sortbuff_size/16), 0,
init_tree(tree, min(thd->variables.max_heap_table_size,
thd->variables.sortbuff_size/16), 0,
key_length, compare_key, 0, NULL, cmp_arg);
use_tree = 1;
......@@ -1113,6 +1149,12 @@ bool Item_sum_count_distinct::setup(THD *thd)
*/
max_elements_in_tree = ((key_length) ?
thd->variables.max_heap_table_size/key_length : 1);
}
if (original)
{
original->table= table;
original->use_tree= use_tree;
}
return 0;
}
......@@ -1122,10 +1164,10 @@ int Item_sum_count_distinct::tree_to_myisam()
{
if (create_myisam_from_heap(current_thd, table, tmp_table_param,
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))
return 1;
delete_tree(&tree);
delete_tree(tree);
use_tree = 0;
return 0;
}
......@@ -1133,7 +1175,7 @@ int Item_sum_count_distinct::tree_to_myisam()
void Item_sum_count_distinct::reset()
{
if (use_tree)
reset_tree(&tree);
reset_tree(tree);
else if (table)
{
table->file->extra(HA_EXTRA_NO_CACHE);
......@@ -1161,13 +1203,13 @@ bool Item_sum_count_distinct::add()
If the tree got too big, convert to MyISAM, otherwise insert into the
tree.
*/
if (tree.elements_in_tree > max_elements_in_tree)
if (tree->elements_in_tree > max_elements_in_tree)
{
if (tree_to_myisam())
return 1;
}
else if (!tree_insert(&tree, table->record[0] + rec_offset, 0,
tree.custom_arg))
else if (!tree_insert(tree, table->record[0] + rec_offset, 0,
tree->custom_arg))
return 1;
}
else if ((error=table->file->write_row(table->record[0])))
......@@ -1189,7 +1231,7 @@ longlong Item_sum_count_distinct::val_int()
if (!table) // Empty query
return LL(0);
if (use_tree)
return tree.elements_in_tree;
return tree->elements_in_tree;
table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
return table->file->records;
}
......
This diff is collapsed.
......@@ -327,9 +327,10 @@ public:
max_length=10*thd_charset()->mbmaxlen;
}
int save_in_field(Field *to, bool no_conversions);
Field *tmp_table_field() { return result_field; }
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:
Item_date_func(Item *a) :Item_str_func(a) {}
Item_date_func(Item *a,Item *b) :Item_str_func(a,b) {}
enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; }
Field *tmp_table_field() { return result_field; }
Field *tmp_table_field(TABLE *t_arg)
{
return (!t_arg) ? result_field : new Field_datetime(maybe_null, name,
t_arg, thd_charset());
return (new Field_datetime(maybe_null, name, t_arg, thd_charset()));
}
};
......@@ -364,10 +365,10 @@ public:
String *val_str(String *str);
const char *func_name() const { return "curtime"; }
void fix_length_and_dec();
Field *tmp_table_field() { return result_field; }
Field *tmp_table_field(TABLE *t_arg)
{
return (!t_arg) ? result_field :
new Field_time(maybe_null, name, t_arg, thd_charset());
return (new Field_time(maybe_null, name, t_arg, thd_charset()));
}
};
......@@ -462,10 +463,10 @@ public:
}
enum_field_types field_type() const { return MYSQL_TYPE_TIME; }
const char *func_name() const { return "sec_to_time"; }
Field *tmp_table_field() { return result_field; }
Field *tmp_table_field(TABLE *t_arg)
{
return (!t_arg) ? result_field :
new Field_time(maybe_null, name, t_arg, thd_charset());
return (new Field_time(maybe_null, name, t_arg, thd_charset()));
}
};
......@@ -556,10 +557,10 @@ public:
Item_date_typecast(Item *a) :Item_typecast(a) {}
const char *func_name() const { return "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)
{
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()));
}
};
......@@ -570,10 +571,10 @@ public:
Item_time_typecast(Item *a) :Item_typecast(a) {}
const char *func_name() const { return "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)
{
return (!t_arg) ? result_field :
new Field_time(maybe_null, name, t_arg, thd_charset());
return (new Field_time(maybe_null, name, t_arg, thd_charset()));
}
};
......@@ -584,9 +585,9 @@ public:
Item_datetime_typecast(Item *a) :Item_typecast(a) {}
const char *func_name() const { return "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)
{
return (!t_arg) ? result_field : new Field_datetime(maybe_null, name,
t_arg, thd_charset());
return (new Field_datetime(maybe_null, name, t_arg, thd_charset()));
}
};
......@@ -37,6 +37,7 @@ class Item_sum_unique_users :public Item_sum_num
public:
Item_sum_unique_users(Item *name_arg,int start,int end,Item *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; }
enum Sumfunctype sum_func () const {return UNIQUE_USERS_FUNC;}
void reset() {}
......@@ -48,4 +49,5 @@ public:
fixed= 1;
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,
bool check_simple_select();
SORT_FIELD * make_unireg_sortorder(ORDER *order, uint *length);
int setup_order(THD *thd,TABLE_LIST *tables, List<Item> &fields,
List <Item> &all_fields, ORDER *order);
int setup_group(THD *thd,TABLE_LIST *tables,List<Item> &fields,
List<Item> &all_fields, ORDER *order,
int setup_ref_array(THD *thd, Item ***rref_pointer_array, uint elements);
int setup_order(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
List<Item> &fields, 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);
int handle_select(THD *thd, LEX *lex, select_result *result);
int mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &list,COND *conds,
ORDER *order, ORDER *group,Item *having,ORDER *proc_param,
ulong select_type,select_result *result,
SELECT_LEX_UNIT *unit, SELECT_LEX *select_lex,
bool fake_select_lex);
int mysql_select(THD *thd, Item ***rref_pointer_array,
TABLE_LIST *tables, uint wild_num, List<Item> &list,
COND *conds, uint og_num, ORDER *order, ORDER *group,
Item *having, ORDER *proc_param, ulong select_type,
select_result *result, SELECT_LEX_UNIT *unit,
SELECT_LEX *select_lex, bool 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_UNIT *select_lex);
int mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit,
select_result *result);
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,
List<create_field> &fields,
List<Key> &keys,List<Alter_drop> &drop_list,
List<Alter_column> &alter_list,
ORDER *order,
uint order_num, ORDER *order,
bool drop_primary,
enum enum_duplicates handle_duplicates,
enum enum_enable_or_disable keys_onoff=LEAVE_AS_IS,
......@@ -447,7 +451,7 @@ int mysql_drop_index(THD *thd, TABLE_LIST *table_list,
List<Alter_drop> &drop_list);
int mysql_update(THD *thd,TABLE_LIST *tables,List<Item> &fields,
List<Item> &values,COND *conds,
ORDER *order, ha_rows limit,
uint order_num, ORDER *order, ha_rows limit,
enum enum_duplicates handle_duplicates);
int mysql_multi_update(THD *thd, TABLE_LIST *table_list,
List<Item> *fields, List<Item> *values,
......@@ -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,
IGNORE_ERRORS};
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);
bool insert_fields(THD *thd,TABLE_LIST *tables,
const char *db_name, const char *table_name,
List_iterator<Item> *it);
bool setup_tables(TABLE_LIST *tables);
int setup_fields(THD *thd,TABLE_LIST *tables,List<Item> &item,
bool set_query_id,List<Item> *sum_func_list,
bool allow_sum_func);
int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
List<Item> *sum_func_list, uint wild_num);
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_ftfuncs(SELECT_LEX* select);
int init_ftfuncs(THD *thd, SELECT_LEX* select, bool no_order);
......
......@@ -1807,11 +1807,15 @@ const Item **not_found_item= (const Item**) 0x1;
/*
Find Item in list of items (find_field_in_tables analog)
TODO
is it better return only counter?
SYNOPSIS
find_item_in_list()
find - item to find
items - list of items
counter - to return number of found item
report_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
......@@ -1828,7 +1832,7 @@ const Item **not_found_item= (const Item**) 0x1;
*/
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)
{
List_iterator<Item> li(items);
......@@ -1841,8 +1845,10 @@ find_item_in_list(Item *find, List<Item> &items,
table_name= ((Item_ident*) find)->table_name;
}
uint i= 0;
while ((item=li++))
{
i++;
if (field_name && item->type() == Item::FIELD_ITEM)
{
if (!my_strcasecmp(system_charset_info,
......@@ -1859,11 +1865,13 @@ find_item_in_list(Item *find, List<Item> &items,
find->full_name(), current_thd->where);
return (Item**) 0;
}
found=li.ref();
found= li.ref();
*counter= i;
}
else if (!strcmp(((Item_field*) item)->table_name,table_name))
{
found=li.ref();
found= li.ref();
*counter= i;
break;
}
}
......@@ -1873,7 +1881,8 @@ find_item_in_list(Item *find, List<Item> &items,
!my_strcasecmp(system_charset_info,
item->name,find->name)))
{
found=li.ref();
found= li.ref();
*counter= i;
break;
}
}
......@@ -1891,30 +1900,26 @@ find_item_in_list(Item *find, List<Item> &items,
}
/****************************************************************************
** Check that all given fields exists and fill struct with current data
** Expand all '*' in given fields
****************************************************************************/
int setup_fields(THD *thd, TABLE_LIST *tables, List<Item> &fields,
bool set_query_id, List<Item> *sum_func_list,
bool allow_sum_func)
int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
List<Item> *sum_func_list,
uint wild_num)
{
if (!wild_num)
return 0;
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";
while ((item=it++))
{
while ( wild_num && (item= it++))
{
if (item->type() == Item::FIELD_ITEM && ((Item_field*) item)->field_name &&
((Item_field*) item)->field_name[0] == '*')
{
uint elem= fields.elements;
if (insert_fields(thd,tables,((Item_field*) item)->db_name,
((Item_field*) item)->table_name, &it))
DBUG_RETURN(-1); /* purecov: inspected */
return (-1);
if (sum_func_list)
{
/*
......@@ -1924,21 +1929,43 @@ int setup_fields(THD *thd, TABLE_LIST *tables, List<Item> &fields,
*/
sum_func_list->elements+= fields.elements - elem;
}
}
else
{
if (item->fix_fields(thd, tables, it.ref()) || item->check_cols(1))
DBUG_RETURN(-1); /* purecov: inspected */
item= *(it.ref()); //Item can be chenged in fix fields
if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM &&
sum_func_list)
item->split_sum_func(*sum_func_list);
thd->used_tables|=item->used_tables();
wild_num--;
}
}
DBUG_RETURN(test(thd->fatal_error || thd->net.report_error));
return 0;
}
/****************************************************************************
** Check that all given fields exists and fill struct with current data
****************************************************************************/
int setup_fields(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
List<Item> &fields, bool set_query_id,
List<Item> *sum_func_list, bool allow_sum_func)
{
reg2 Item *item;
List_iterator<Item> it(fields);
DBUG_ENTER("setup_fields");
thd->set_query_id=set_query_id;
thd->allow_sum_func= allow_sum_func;
thd->where="field list";
for (uint i= 0; (item= it++); i++)
{
if (item->fix_fields(thd, tables, it.ref()) ||
item->check_cols(1))
DBUG_RETURN(-1); /* purecov: inspected */
item= *(it.ref()); //Item can be chenged in fix fields
if (ref_pointer_array)
ref_pointer_array[i]= item;
if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM &&
sum_func_list)
item->split_sum_func(ref_pointer_array, *sum_func_list);
thd->used_tables|=item->used_tables();
}
DBUG_RETURN(test(thd->fatal_error || thd->net.report_error));
}
/*
Remap table numbers if INSERT ... SELECT
......@@ -2254,7 +2281,7 @@ int mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys)
create_info.table_charset=default_charset_info;
DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->real_name,
&create_info, table_list,
fields, keys, drop, alter, (ORDER*)0, FALSE,
fields, keys, drop, alter, 0, (ORDER*)0, FALSE,
DUP_ERROR));
}
......@@ -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;
DBUG_RETURN(mysql_alter_table(thd,table_list->db,table_list->real_name,
&create_info, table_list,
fields, keys, drop, alter, (ORDER*)0, FALSE,
fields, keys, drop, alter, 0, (ORDER*)0, FALSE,
DUP_ERROR));
}
......
......@@ -394,7 +394,7 @@ struct system_variables
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
a thread/connection descriptor
......@@ -507,6 +507,7 @@ public:
USER_CONN *user_connect;
CHARSET_INFO *db_charset;
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;
uint warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_END];
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,
if ((select && select->check_quick(safe_update, limit)) || !limit)
{
delete select;
free_ulderlayed_joins(thd, &thd->lex.select_lex);
send_ok(thd,0L);
DBUG_RETURN(0); // Nothing to delete
}
......@@ -103,6 +104,7 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order,
if (safe_update && !using_limit)
{
delete select;
free_ulderlayed_joins(thd, &thd->lex.select_lex);
send_error(thd,ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE);
DBUG_RETURN(1);
}
......@@ -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),
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)) ||
(table->found_records = filesort(thd, table, sortorder, length,
(SQL_SELECT *) 0, HA_POS_ERROR,
......@@ -132,6 +134,7 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ORDER *order,
== HA_POS_ERROR)
{
delete select;
free_ulderlayed_joins(thd, &thd->lex.select_lex);
DBUG_RETURN(-1); // This will force out message
}
}
......@@ -207,6 +210,7 @@ cleanup:
thd->lock=0;
}
delete select;
free_ulderlayed_joins(thd, &thd->lex.select_lex);
if (error >= 0 || thd->net.report_error)
send_error(thd,thd->killed ? ER_SERVER_SHUTDOWN: 0);
else
......
......@@ -70,7 +70,8 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
select_union *derived_result;
TABLE_LIST *tables= (TABLE_LIST *)sl->table_list.first;
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;
DBUG_ENTER("mysql_derived");
......@@ -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
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);
if (tables)
......@@ -90,16 +91,10 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
res= check_access(thd, SELECT_ACL, any_db);
if (res)
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 (is_union)
if (is_union || is_subsel)
{
/*
The following code is a re-do of fix_tables_pointers() found
......@@ -108,24 +103,32 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
this level only.
*/
for (SELECT_LEX *sel= sl; sel; sel= sel->next_select())
relink_tables(sel);
fix_tables_pointers(unit);
}
Item *item;
List_iterator<Item> it(sl->item_list);
while ((item= it++))
item_list.push_back(item);
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;
goto exit;
}
bzero((char*) &tmp_table_param,sizeof(tmp_table_param));
tmp_table_param.field_count=item_list.elements;
if (!(table=create_tmp_table(thd, &tmp_table_param, item_list,
(ORDER*) 0,
is_union && !unit->union_option, 1,
(sl->options | thd->options |
TMP_TABLE_ALL_COLUMNS),
HA_POS_ERROR)))
tmp_table_param.field_count= item_list.elements;
if (!(table= create_tmp_table(thd, &tmp_table_param, item_list,
(ORDER*) 0,
is_union && !unit->union_option, 1,
(sl->options | thd->options |
TMP_TABLE_ALL_COLUMNS),
HA_POS_ERROR)))
{
res= -1;
goto exit;
......@@ -142,14 +145,18 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
sl->options&= ~OPTION_FOUND_ROWS;
if (is_union)
res= mysql_union(thd,lex,derived_result,unit);
res= mysql_union(thd, lex, derived_result, unit);
else
res= mysql_select(thd, tables, sl->item_list,
sl->where, (ORDER *) sl->order_list.first,
(ORDER*) sl->group_list.first,
sl->having, (ORDER*) NULL,
sl->options | thd->options | SELECT_NO_UNLOCK,
derived_result, unit, sl, 0);
res= mysql_select(thd, &sl->ref_pointer_array,
(TABLE_LIST*) sl->table_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->options | thd->options | SELECT_NO_UNLOCK,
derived_result, unit, sl, 0);
if (!res)
{
......@@ -187,6 +194,7 @@ int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
table->next= thd->derived_tables;
thd->derived_tables= table;
}
exit:
lex->current_select= save_current_select;
close_thread_tables(thd, 0, 1);
......
......@@ -25,7 +25,7 @@ int mysql_do(THD *thd, List<Item> &values)
List_iterator<Item> li(values);
Item *value;
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);
while ((value = li++))
value->val_int();
......
......@@ -81,7 +81,7 @@ check_insert_fields(THD *thd,TABLE *table,List<Item> &fields,
thd->dupp_field=0;
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;
if (thd->dupp_field)
{
......@@ -171,10 +171,10 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
values= its++;
if (check_insert_fields(thd,table,fields,*values,1) ||
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 &&
(setup_fields(thd, 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_fields, 0, 0, 0) ||
setup_fields(thd, 0, insert_table_list, update_values, 0, 0, 0))))
goto abort;
if (find_real_table_in_list(table_list->next,
table_list->db, table_list->real_name))
......@@ -194,7 +194,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
MYF(0),counter);
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;
}
its.rewind ();
......@@ -376,11 +376,13 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
thd->cuted_fields);
::send_ok(thd,info.copied+info.deleted,(ulonglong)id,buff);
}
free_ulderlayed_joins(thd, &thd->lex.select_lex);
DBUG_RETURN(0);
abort:
if (lock_type == TL_WRITE_DELAYED)
end_delayed_insert(thd);
free_ulderlayed_joins(thd, &thd->lex.select_lex);
DBUG_RETURN(-1);
}
......
......@@ -995,7 +995,8 @@ int yylex(void *arg, void *yythd)
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()
......@@ -1019,6 +1020,8 @@ void st_select_lex_unit::init_query()
union_option= 0;
prepared= optimized= executed= 0;
item= 0;
union_result= 0;
table= 0;
}
void st_select_lex::init_query()
......@@ -1031,6 +1034,7 @@ void st_select_lex::init_query()
join= 0;
olap= UNSPECIFIED_OLAP_TYPE;
having_fix_field= 0;
with_wild= 0;
}
void st_select_lex::init_select()
......@@ -1160,12 +1164,12 @@ bool st_select_lex_node::add_item_to_list(THD *thd, Item *item)
bool st_select_lex_node::add_group_to_list(THD *thd, Item *item, bool asc)
{
return 1;
return 1;
}
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)
......@@ -1241,15 +1245,17 @@ ulong st_select_lex_node::get_table_join_options() { return 0; }
// interface
bool st_select_lex_unit::create_total_list(THD *thd, st_lex *lex,
TABLE_LIST **result)
TABLE_LIST **result,
bool check_derived)
{
*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
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 **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,
net_printf(thd,ER_WRONG_USAGE,"UNION","ORDER BY");
return 1;
}
if (sl->linkage == DERIVED_TABLE_TYPE && !sl->next_select())
if (sl->linkage == DERIVED_TABLE_TYPE && !check_derived)
continue;
for (SELECT_LEX_UNIT *inner= sl->first_inner_unit();
inner;
inner= inner->next_unit())
if (inner->create_total_list_n_last_return(thd, lex,
&slave_list_last))
&slave_list_last, 0))
return 1;
if ((aux= (TABLE_LIST*) sl->table_list.first))
{
......
......@@ -210,9 +210,13 @@ public:
List<List_item> expr_list;
List<List_item> when_list; /* WHEN clause (expression) */
ha_rows select_limit, offset_limit; /* LIMIT clause parameters */
bool with_sum_func;
bool create_refs;
// 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 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 */
static void *operator new(size_t size)
......@@ -274,11 +278,10 @@ class select_union;
class st_select_lex_unit: public st_select_lex_node {
protected:
List<Item> item_list;
List<JOIN*> joins; /* list of *JOINs, to delete it in cleanup() */
TABLE_LIST result_table_list;
select_union *union_result;
TABLE *table; /* temporary table using for appending UNION results */
THD *thd;
select_result *result;
int res;
bool describe, found_rows_for_union,
......@@ -295,10 +298,13 @@ public:
ha_rows select_limit_cnt, offset_limit_cnt;
/* not NULL if union used in subselect, point to subselect item */
Item_subselect *item;
THD *thd;
uint union_option;
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* outer_select();
st_select_lex* first_select() { return (st_select_lex*) slave; }
......@@ -314,7 +320,8 @@ public:
friend int subselect_union_engine::exec();
private:
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;
......@@ -342,6 +349,7 @@ public:
ulong table_join_options;
uint in_sum_expr;
uint select_number; /* number of select (used for EXPLAIN) */
uint with_wild; /* item list contain '*' */
bool braces; /* SELECT ... UNION (SELECT ... ) <- this braces */
/* TRUE when having fix field called in processing of this SELECT */
bool having_fix_field;
......@@ -468,6 +476,13 @@ typedef struct st_lex
CHARSET_INFO *charset;
char *help_arg;
bool tmp_table_used;
inline void uncacheable()
{
safe_to_cache_query= 0;
current_select->uncacheable =
current_select->master_unit()->uncacheable= 1;
}
} LEX;
......
......@@ -155,12 +155,20 @@ protected:
class base_list_iterator
{
protected:
base_list *list;
list_node **el,**prev,*current;
void sublist(base_list &ls, uint elm)
{
ls.first= *el;
ls.last= list->last;
ls.elements= elm;
}
public:
base_list_iterator(base_list &list_par) :list(&list_par),el(&list_par.first),
prev(0),current(0)
base_list_iterator(base_list &list_par)
:list(&list_par), el(&list_par.first), prev(0), current(0)
{}
inline void *next(void)
{
prev=el;
......@@ -220,7 +228,6 @@ public:
friend class error_list_iterator;
};
template <class T> class List :public base_list
{
public:
......@@ -268,6 +275,10 @@ public:
List_iterator_fast(List<T> &a) : base_list_iterator(a) {}
inline T* operator++(int) { return (T*) base_list_iterator::next_fast(); }
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,
else
{ // Part field list
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);
if (thd->dupp_field)
{
......
......@@ -164,8 +164,10 @@ int handle_olaps(LEX *lex, SELECT_LEX *select_lex)
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,(TABLE_LIST *)select_lex->table_list.first,item_list_copy,1,&all_fields,1))
setup_fields(lex->thd, 0, (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,
item_list_copy, 1, &all_fields, 1))
return -1;
if (select_lex->olap == CUBE_TYPE)
......
......@@ -1599,7 +1599,7 @@ mysql_execute_command(THD *thd)
}
}
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
||
(table_rules_on && tables && thd->slave_thread &&
......@@ -2041,6 +2041,7 @@ mysql_execute_command(THD *thd)
&lex->create_info,
tables, lex->create_list,
lex->key_list, lex->drop_list, lex->alter_list,
select_lex->order_list.elements,
(ORDER *) select_lex->order_list.first,
lex->drop_primary, lex->duplicates,
lex->alter_keys_onoff, lex->simple_alter);
......@@ -2154,8 +2155,8 @@ mysql_execute_command(THD *thd)
res= mysql_alter_table(thd, NullS, NullS, &create_info,
tables, lex->create_list,
lex->key_list, lex->drop_list, lex->alter_list,
(ORDER *) 0,
0,DUP_ERROR);
0, (ORDER *) 0,
0, DUP_ERROR);
}
else
res = mysql_optimize_table(thd, tables, &lex->check_opt);
......@@ -2175,6 +2176,7 @@ mysql_execute_command(THD *thd)
select_lex->item_list,
lex->value_list,
select_lex->where,
select_lex->order_list.elements,
(ORDER *) select_lex->order_list.first,
select_lex->select_limit,
lex->duplicates);
......@@ -2376,10 +2378,12 @@ mysql_execute_command(THD *thd)
if (!thd->fatal_error && (result= new multi_delete(thd,aux_tables,
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->where,
(ORDER *)NULL,(ORDER *)NULL,(Item *)NULL,
0, (ORDER *)NULL, (ORDER *)NULL, (Item *)NULL,
(ORDER *)NULL,
select_lex->options | thd->options |
SELECT_NO_JOIN_CACHE,
......@@ -3130,6 +3134,7 @@ mysql_init_query(THD *thd)
LEX *lex=&thd->lex;
lex->unit.init_query();
lex->unit.init_select();
lex->unit.thd= thd;
lex->select_lex.init_query();
lex->value_list.empty();
lex->param_list.empty();
......@@ -3191,6 +3196,7 @@ mysql_new_select(LEX *lex, bool move_down)
return 1;
unit->init_query();
unit->init_select();
unit->thd= lex->thd;
unit->include_down(lex->current_select);
unit->link_next= 0;
unit->link_prev= 0;
......
......@@ -437,6 +437,7 @@ static bool setup_params_data(PREP_STMT *stmt)
}
/*
Validate the following information for INSERT statement:
- field existance
- fields count
......@@ -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))
DBUG_RETURN(1);
if (setup_tables(table_list) || setup_fields(thd,table_list,fields,1,0,0) ||
setup_conds(thd,table_list,&conds) || thd->net.report_error)
if (setup_tables(table_list) ||
setup_fields(thd, 0, table_list, fields, 1, 0, 0) ||
setup_conds(thd, table_list, &conds) || thd->net.report_error)
DBUG_RETURN(1);
/*
......@@ -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.
*/
static bool mysql_test_select_fields(PREP_STMT *stmt, TABLE_LIST *tables,
uint wild_num,
List<Item> &fields, COND *conds,
ORDER *order, ORDER *group,
uint og_num, ORDER *order, ORDER *group,
Item *having, ORDER *proc,
ulong select_options,
SELECT_LEX_UNIT *unit,
......@@ -543,7 +546,7 @@ static bool mysql_test_select_fields(PREP_STMT *stmt, TABLE_LIST *tables,
DBUG_ENTER("mysql_test_select_fields");
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);
if (open_and_lock_tables(thd, 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);
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))
DBUG_RETURN(1);
......@@ -621,9 +625,11 @@ static bool send_prepare_results(PREP_STMT *stmt)
break;
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->where,
select_lex->order_list.elements +
select_lex->group_list.elements,
(ORDER*) select_lex->order_list.first,
(ORDER*) select_lex->group_list.first,
select_lex->having,
......
This diff is collapsed.
......@@ -119,8 +119,10 @@ class TMP_TABLE_PARAM :public Sql_alloc
{
public:
List<Item> copy_funcs;
List<Item> save_copy_funcs;
List_iterator_fast<Item> copy_funcs_it;
Copy_field *copy_field, *copy_field_end;
Copy_field *save_copy_field, *save_copy_field_end;
byte *group_buff;
Item_result_field **funcs;
MI_COLUMNDEF *recinfo,*start_recinfo;
......@@ -166,10 +168,13 @@ class JOIN :public Sql_alloc
List<Item> *fields;
List<Item_buff> group_fields;
TABLE *tmp_table;
// used to store 2 possible tmp table of SELECT
TABLE *exec_tmp_table1, *exec_tmp_table2;
THD *thd;
Item_sum **sum_funcs;
Procedure *procedure;
Item *having;
Item *tmp_having; // To store Having when processed tenporary table
uint select_options;
select_result *result;
TMP_TABLE_PARAM tmp_table_param;
......@@ -178,6 +183,8 @@ class JOIN :public Sql_alloc
SELECT_LEX_UNIT *unit;
// select that processed
SELECT_LEX *select_lex;
JOIN *tmp_join; // copy of this JOIN to be used with temporary tables
bool select_distinct, //Is select distinct?
no_order, simple_order, simple_group,
......@@ -186,7 +193,11 @@ class JOIN :public Sql_alloc
buffer_result;
DYNAMIC_ARRAY keyuse;
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
int error;
......@@ -194,11 +205,14 @@ class JOIN :public Sql_alloc
COND *conds; // ---"---
TABLE_LIST *tables_list; //hold 'tables' parameter of mysql_selec
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
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,
ulong select_options, select_result *result):
......@@ -208,14 +222,16 @@ class JOIN :public Sql_alloc
sort_and_group(0), first_record(0),
do_send_rows(1),
send_records(0), found_records(0), examined_rows(0),
exec_tmp_table1(0), exec_tmp_table2(0),
thd(thd),
sum_funcs(0),
procedure(0),
having(0),
having(0), tmp_having(0),
select_options(select_options),
result(result),
lock(thd->lock),
select_lex(0), //for safety
tmp_join(0),
select_distinct(test(select_options & SELECT_DISTINCT)),
no_order(0), simple_order(0), simple_group(0), skip_sort_order(0),
need_tmp(0),
......@@ -226,8 +242,10 @@ class JOIN :public Sql_alloc
fields_list(fields),
error(0),
select(0),
exec_tmp_table(0),
zero_result_cause(0)
ref_pointer_array(0), items0(0), items1(0), items2(0), items3(0),
ref_pointer_array_size(0),
zero_result_cause(0),
optimized(0)
{
fields_list = fields;
bzero((char*) &keyuse,sizeof(keyuse));
......@@ -235,16 +253,23 @@ class JOIN :public Sql_alloc
tmp_table_param.end_write_records= HA_POS_ERROR;
}
int prepare(TABLE_LIST *tables,
COND *conds, ORDER *order, ORDER *group, Item *having,
ORDER *proc_param, SELECT_LEX *select, SELECT_LEX_UNIT *unit,
bool fake_select_lex);
int prepare(Item ***rref_pointer_array, TABLE_LIST *tables, uint wind_num,
COND *conds, uint og_num, ORDER *order, ORDER *group,
Item *having, ORDER *proc_param, SELECT_LEX *select,
SELECT_LEX_UNIT *unit, bool fake_select_lex);
int optimize();
int global_optimize();
int reinit();
void exec();
int cleanup(THD *thd);
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,
void free_tmp_table(THD *thd, TABLE *entry);
void count_field_types(TMP_TABLE_PARAM *param, List<Item> &fields,
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_funcs(Item_result_field **func_ptr);
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);
static int copy_data_between_tables(TABLE *from,TABLE *to,
List<create_field> &create,
enum enum_duplicates handle_duplicates,
ORDER *order,
uint order_num, ORDER *order,
ha_rows *copied,ha_rows *deleted);
/*****************************************************************************
......@@ -1572,7 +1572,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
List<create_field> &fields,
List<Key> &keys,List<Alter_drop> &drop_list,
List<Alter_column> &alter_list,
ORDER *order,
uint order_num, ORDER *order,
bool drop_primary,
enum enum_duplicates handle_duplicates,
enum enum_enable_or_disable keys_onoff,
......@@ -2034,7 +2034,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
if (!new_table->is_view)
error=copy_data_between_tables(table,new_table,create_list,
handle_duplicates,
order, &copied, &deleted);
order_num, order, &copied, &deleted);
thd->last_insert_id=next_insert_id; // Needed for correct log
thd->count_cuted_fields=0; // Don`t calc cuted fields
new_table->time_stamp=save_time_stamp;
......@@ -2244,7 +2244,7 @@ static int
copy_data_between_tables(TABLE *from,TABLE *to,
List<create_field> &create,
enum enum_duplicates handle_duplicates,
ORDER *order,
uint order_num, ORDER *order,
ha_rows *copied,
ha_rows *deleted)
{
......@@ -2292,7 +2292,10 @@ copy_data_between_tables(TABLE *from,TABLE *to,
tables.db = from->table_cache_key;
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)) ||
(from->found_records = filesort(thd, from, sortorder, length,
(SQL_SELECT *) 0, HA_POS_ERROR,
......
......@@ -107,7 +107,6 @@ bool select_union::flush()
return 0;
}
typedef JOIN * JOIN_P;
int st_select_lex_unit::prepare(THD *thd, select_result *result)
{
DBUG_ENTER("st_select_lex_unit::prepare");
......@@ -115,11 +114,9 @@ int st_select_lex_unit::prepare(THD *thd, select_result *result)
if (prepared)
DBUG_RETURN(0);
prepared= 1;
union_result=0;
res= 0;
found_rows_for_union= 0;
TMP_TABLE_PARAM tmp_table_param;
this->thd= thd;
this->result= result;
SELECT_LEX_NODE *lex_select_save= thd->lex.current_select;
SELECT_LEX *sl;
......@@ -143,7 +140,9 @@ int st_select_lex_unit::prepare(THD *thd, select_result *result)
while ((item= it++))
if (item_list.push_back(item))
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;
}
......@@ -169,13 +168,11 @@ int st_select_lex_unit::prepare(THD *thd, select_result *result)
union_result->tmp_table_param=&tmp_table_param;
// prepare selects
joins.empty();
for (sl= first_select(); sl; sl= sl->next_select())
{
JOIN *join= new JOIN(thd, sl->item_list,
sl->options | thd->options | SELECT_NO_UNLOCK,
union_result);
joins.push_back(new JOIN_P(join));
thd->lex.current_select= sl;
offset_limit_cnt= 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)
if (select_limit_cnt == HA_POS_ERROR)
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->braces) ? sl->order_list.elements : 0) +
sl->group_list.elements,
(sl->braces) ?
(ORDER *)sl->order_list.first : (ORDER *) 0,
(ORDER*) sl->group_list.first,
......@@ -207,11 +207,11 @@ int st_select_lex_unit::exec()
DBUG_ENTER("st_select_lex_unit::exec");
SELECT_LEX_NODE *lex_select_save= thd->lex.current_select;
if (executed && !dependent)
if (executed && !(dependent||uncacheable))
DBUG_RETURN(0);
executed= 1;
if (dependent || !item || !item->assigned())
if ((dependent||uncacheable) || !item || !item->assigned())
{
if (optimized && item && item->assigned())
{
......@@ -287,8 +287,9 @@ int st_select_lex_unit::exec()
select_limit_cnt= HA_POS_ERROR; // no limit
if (select_limit_cnt == HA_POS_ERROR)
thd->options&= ~OPTION_FOUND_ROWS;
res= mysql_select(thd,&result_table_list,
item_list, NULL,
res= mysql_select(thd, &ref_pointer_array, &result_table_list,
0, item_list, NULL,
global_parameters->order_list.elements,
(ORDER*)global_parameters->order_list.first,
(ORDER*) NULL, NULL, (ORDER*) NULL,
thd->options, result, this, first_select(), 1);
......@@ -304,20 +305,24 @@ int st_select_lex_unit::exec()
int st_select_lex_unit::cleanup()
{
DBUG_ENTER("st_select_lex_unit::cleanup");
int error= 0;
if (union_result)
{
delete union_result;
free_tmp_table(thd,table);
if (table)
free_tmp_table(thd, table);
table= 0; // Safety
}
List_iterator<JOIN*> j(joins);
JOIN** join;
while ((join= j++))
for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select())
{
(*join)->cleanup(thd);
delete *join;
delete join;
JOIN *join;
if ((join= sl->join))
{
error|= sl->join->cleanup(thd);
delete join;
}
}
joins.empty();
DBUG_RETURN(0);
DBUG_RETURN(error);
}
......@@ -50,7 +50,7 @@ int mysql_update(THD *thd,
List<Item> &fields,
List<Item> &values,
COND *conds,
ORDER *order,
uint order_num, ORDER *order,
ha_rows limit,
enum enum_duplicates handle_duplicates)
{
......@@ -109,7 +109,7 @@ int mysql_update(THD *thd,
/* Check the fields we are going to modify */
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 */
if (table->timestamp_field)
{
......@@ -122,8 +122,9 @@ int mysql_update(THD *thd,
/* Check values */
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 */
}
......@@ -134,6 +135,7 @@ int mysql_update(THD *thd,
(select && select->check_quick(safe_update, limit)) || !limit)
{
delete select;
free_ulderlayed_joins(thd, &thd->lex.select_lex);
if (error)
{
DBUG_RETURN(-1); // Error in where
......@@ -148,6 +150,7 @@ int mysql_update(THD *thd,
if (safe_update && !using_limit)
{
delete select;
free_ulderlayed_joins(thd, &thd->lex.select_lex);
send_error(thd,ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE);
DBUG_RETURN(1);
}
......@@ -175,6 +178,7 @@ int mysql_update(THD *thd,
DISK_BUFFER_SIZE, MYF(MY_WME)))
{
delete select; /* purecov: inspected */
free_ulderlayed_joins(thd, &thd->lex.select_lex);
DBUG_RETURN(-1);
}
if (old_used_keys & ((key_map) 1 << used_index))
......@@ -197,7 +201,10 @@ int mysql_update(THD *thd,
table->io_cache = (IO_CACHE *) my_malloc(sizeof(IO_CACHE),
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)) ||
(table->found_records = filesort(thd, table, sortorder, length,
(SQL_SELECT *) 0,
......@@ -205,6 +212,7 @@ int mysql_update(THD *thd,
== HA_POS_ERROR)
{
delete select;
free_ulderlayed_joins(thd, &thd->lex.select_lex);
DBUG_RETURN(-1);
}
}
......@@ -259,6 +267,7 @@ int mysql_update(THD *thd,
if (error >= 0)
{
delete select;
free_ulderlayed_joins(thd, &thd->lex.select_lex);
DBUG_RETURN(-1);
}
}
......@@ -344,6 +353,7 @@ int mysql_update(THD *thd,
}
delete select;
free_ulderlayed_joins(thd, &thd->lex.select_lex);
if (error >= 0)
send_error(thd,thd->killed ? ER_SERVER_SHUTDOWN : 0); /* purecov: inspected */
else
......@@ -358,6 +368,7 @@ int mysql_update(THD *thd,
}
thd->count_cuted_fields=0; /* calc cuted fields */
free_io_cache(table);
DBUG_RETURN(0);
}
......@@ -389,7 +400,7 @@ int mysql_multi_update(THD *thd,
DBUG_RETURN(res);
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);
/*
......@@ -412,8 +423,9 @@ int mysql_multi_update(THD *thd,
DBUG_RETURN(-1);
List<Item> total_list;
res= mysql_select(thd,table_list,total_list,
conds, (ORDER *) NULL, (ORDER *)NULL, (Item *) NULL,
res= mysql_select(thd, &select_lex->ref_pointer_array,
table_list, select_lex->with_wild, total_list,
conds, 0, (ORDER *) NULL, (ORDER *)NULL, (Item *) NULL,
(ORDER *)NULL,
options | SELECT_NO_JOIN_CACHE,
result, unit, select_lex, 0);
......@@ -466,7 +478,7 @@ int multi_update::prepare(List<Item> &not_used_values, SELECT_LEX_UNIT *unit)
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);
/*
......
......@@ -1798,7 +1798,7 @@ select_option:
YYABORT;
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; }
| ALL {}
;
......@@ -1825,8 +1825,10 @@ select_item_list:
| 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;
(thd->lex.current_select->select_lex()->with_wild)++;
};
......@@ -2049,12 +2051,12 @@ simple_expr:
| '@' ident_or_text SET_VAR expr
{
$$= new Item_func_set_user_var($2,$4);
Lex->safe_to_cache_query=0;
Lex->uncacheable();;
}
| '@' ident_or_text
{
$$= new Item_func_get_user_var($2);
Lex->safe_to_cache_query=0;
Lex->uncacheable();;
}
| '@' '@' opt_var_ident_type ident_or_text
{
......@@ -2145,7 +2147,7 @@ simple_expr:
| ENCRYPT '(' expr ')'
{
$$= new Item_func_encrypt($3);
Lex->safe_to_cache_query=0;
Lex->uncacheable();;
}
| ENCRYPT '(' expr ',' expr ')' { $$= new Item_func_encrypt($3,$5); }
| DECODE_SYM '(' expr ',' TEXT_STRING ')'
......@@ -2208,11 +2210,12 @@ simple_expr:
{
$$= get_system_var(OPT_SESSION, "last_insert_id", 14,
"last_insert_id()");
Lex->safe_to_cache_query= 0;
}
| LAST_INSERT_ID '(' expr ')'
{
$$= new Item_func_set_last_insert_id($3);
Lex->safe_to_cache_query=0;
Lex->safe_to_cache_query= 0;
}
| LEFT '(' expr ',' expr ')'
{ $$= new Item_func_left($3,$5); }
......@@ -2288,9 +2291,9 @@ simple_expr:
| POSITION_SYM '(' no_in_expr IN_SYM expr ')'
{ $$ = new Item_func_locate($5,$3); }
| RAND '(' expr ')'
{ $$= new Item_func_rand($3); Lex->safe_to_cache_query=0;}
{ $$= new Item_func_rand($3); Lex->uncacheable();}
| RAND '(' ')'
{ $$= new Item_func_rand(); Lex->safe_to_cache_query=0;}
{ $$= new Item_func_rand(); Lex->uncacheable();}
| REPLACE '(' expr ',' expr ',' expr ')'
{ $$= new Item_func_replace($3,$5,$7); }
| RIGHT '(' expr ',' expr ')'
......@@ -2392,7 +2395,7 @@ simple_expr:
| BENCHMARK_SYM '(' ULONG_NUM ',' expr ')'
{
$$=new Item_func_benchmark($3,$5);
Lex->safe_to_cache_query=0;
Lex->uncacheable();
}
| EXTRACT_SYM '(' interval FROM expr ')'
{ $$=new Item_extract( $3, $5); };
......@@ -2890,7 +2893,7 @@ procedure_clause:
lex->proc_list.next= (byte**) &lex->proc_list.first;
if (add_proc_to_list(lex->thd, new Item_field(NULL,NULL,$2.str)))
YYABORT;
Lex->safe_to_cache_query=0;
Lex->uncacheable();
}
'(' procedure_list ')';
......@@ -2964,7 +2967,7 @@ into:
}
| INTO select_var_list_init
{
Lex->safe_to_cache_query=0;
Lex->uncacheable();
}
;
......@@ -3750,10 +3753,19 @@ insert_ident:
| table_wild { $$=$1; };
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 '.' '*'
{ $$ = 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:
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