Commit e3763981 authored by monty@hundin.mysql.fi's avatar monty@hundin.mysql.fi

merge

parents 9ecc5783 0a242026
...@@ -73,8 +73,8 @@ type=heap; ...@@ -73,8 +73,8 @@ type=heap;
insert into t1 values (1,1),(2,2),(1,3),(2,4),(2,5),(2,6); insert into t1 values (1,1),(2,2),(1,3),(2,4),(2,5),(2,6);
select * from t1 where x=1; select * from t1 where x=1;
x y x y
1 1
1 3 1 3
1 1
select * from t1,t1 as t2 where t1.x=t2.y; select * from t1,t1 as t2 where t1.x=t2.y;
x y x y x y x y
1 1 1 1 1 1 1 1
......
...@@ -3266,6 +3266,16 @@ select wss_type from t1 where wss_type =102935229216544093; ...@@ -3266,6 +3266,16 @@ select wss_type from t1 where wss_type =102935229216544093;
wss_type wss_type
102935229216544093 102935229216544093
drop table t1; drop table t1;
select 1+2,"aaaa",3.13*2.0 into @a,@b,@c;
select @a;
@a
3
select @b;
@b
aaaa
select @c;
@c
6.26
create table t1 (a int not null auto_increment primary key); create table t1 (a int not null auto_increment primary key);
insert into t1 values (); insert into t1 values ();
insert into t1 values (); insert into t1 values ();
......
...@@ -54,9 +54,9 @@ explain select * from t2 where t2.b=(select a from t3 order by 1 desc limit 1) ...@@ -54,9 +54,9 @@ 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 where used 1 PRIMARY t2 ALL NULL NULL NULL NULL 2 where used
2 SUBSELECT t3 ALL NULL NULL NULL NULL 3 Using filesort
3 UNION t4 ALL NULL NULL NULL NULL 3 where used; Using filesort 3 UNION t4 ALL NULL NULL NULL NULL 3 where used; Using filesort
4 SUBSELECT t2 ALL NULL NULL NULL NULL 2 4 SUBSELECT t2 ALL NULL NULL NULL NULL 2
2 SUBSELECT t3 ALL NULL NULL NULL NULL 3 Using filesort
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 a from t3 where a<t2.a*4 order by 1 desc limit 1) a (select a from t3 where a<t2.a*4 order by 1 desc limit 1) a
3 1 3 1
...@@ -163,9 +163,7 @@ UNIQUE KEY `email` (`email`) ...@@ -163,9 +163,7 @@ UNIQUE KEY `email` (`email`)
INSERT INTO inscrit (pseudo,email) VALUES ('joce','test'); INSERT INTO inscrit (pseudo,email) VALUES ('joce','test');
INSERT INTO inscrit (pseudo,email) VALUES ('joce1','test1'); INSERT INTO inscrit (pseudo,email) VALUES ('joce1','test1');
INSERT INTO inscrit (pseudo,email) VALUES ('2joce1','2test1'); INSERT INTO inscrit (pseudo,email) VALUES ('2joce1','2test1');
EXPLAIN SELECT pseudo,(SELECT email FROM inscrit WHERE pseudo=(SELECT EXPLAIN SELECT pseudo,(SELECT email FROM inscrit WHERE pseudo=(SELECT pseudo FROM inscrit WHERE pseudo='joce')) FROM inscrit WHERE pseudo=(SELECT pseudo FROM inscrit WHERE pseudo='joce');
pseudo FROM inscrit WHERE pseudo='joce')) FROM inscrit WHERE pseudo=(SELECT
pseudo FROM inscrit 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 inscrit const PRIMARY PRIMARY 35 const 1 1 PRIMARY inscrit const PRIMARY PRIMARY 35 const 1
4 SUBSELECT inscrit const PRIMARY PRIMARY 35 const 1 4 SUBSELECT inscrit const PRIMARY PRIMARY 35 const 1
...@@ -183,3 +181,21 @@ joce ...@@ -183,3 +181,21 @@ joce
SELECT pseudo FROM inscrit WHERE pseudo=(SELECT pseudo FROM inscrit WHERE pseudo LIKE '%joce%'); SELECT pseudo FROM inscrit WHERE pseudo=(SELECT pseudo FROM inscrit WHERE pseudo LIKE '%joce%');
Subselect returns more than 1 record Subselect returns more than 1 record
drop table if exists t1,t2,t3,t4,t5,attend,clinic,inscrit; drop table if exists t1,t2,t3,t4,t5,attend,clinic,inscrit;
drop table if exists searchconthardwarefr3;
CREATE TABLE `searchconthardwarefr3` (
`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 (`pseudo`,`date`,`topic`),
KEY `topic` (`topic`)
) TYPE=MyISAM ROW_FORMAT=DYNAMIC;
INSERT INTO searchconthardwarefr3 (topic,date,pseudo) VALUES
('43506','2002-10-02','joce'),('40143','2002-08-03','joce');
EXPLAIN SELECT DISTINCT date FROM searchconthardwarefr3 WHERE date='2002-08-03';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE searchconthardwarefr3 index NULL PRIMARY 41 NULL 2 where used; Using index
EXPLAIN SELECT (SELECT DISTINCT date FROM searchconthardwarefr3 WHERE date='2002-08-03');
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY No tables used
2 SUBSELECT searchconthardwarefr3 index NULL PRIMARY 41 NULL 2 where used; Using index
drop table searchconthardwarefr3;
...@@ -1751,6 +1751,10 @@ select wss_type from t1 where wss_type ='102935229216544104'; ...@@ -1751,6 +1751,10 @@ select wss_type from t1 where wss_type ='102935229216544104';
select wss_type from t1 where wss_type ='102935229216544093'; select wss_type from t1 where wss_type ='102935229216544093';
select wss_type from t1 where wss_type =102935229216544093; select wss_type from t1 where wss_type =102935229216544093;
drop table t1; drop table t1;
select 1+2,"aaaa",3.13*2.0 into @a,@b,@c;
select @a;
select @b;
select @c;
# #
# Test of removing redundant braces in the FROM part # Test of removing redundant braces in the FROM part
......
...@@ -83,9 +83,7 @@ CREATE TABLE `inscrit` ( ...@@ -83,9 +83,7 @@ CREATE TABLE `inscrit` (
INSERT INTO inscrit (pseudo,email) VALUES ('joce','test'); INSERT INTO inscrit (pseudo,email) VALUES ('joce','test');
INSERT INTO inscrit (pseudo,email) VALUES ('joce1','test1'); INSERT INTO inscrit (pseudo,email) VALUES ('joce1','test1');
INSERT INTO inscrit (pseudo,email) VALUES ('2joce1','2test1'); INSERT INTO inscrit (pseudo,email) VALUES ('2joce1','2test1');
EXPLAIN SELECT pseudo,(SELECT email FROM inscrit WHERE pseudo=(SELECT EXPLAIN SELECT pseudo,(SELECT email FROM inscrit WHERE pseudo=(SELECT pseudo FROM inscrit WHERE pseudo='joce')) FROM inscrit WHERE pseudo=(SELECT pseudo FROM inscrit WHERE pseudo='joce');
pseudo FROM inscrit WHERE pseudo='joce')) FROM inscrit WHERE pseudo=(SELECT
pseudo FROM inscrit WHERE pseudo='joce');
-- error 1239 -- error 1239
SELECT pseudo FROM inscrit WHERE pseudo=(SELECT pseudo,email FROM SELECT pseudo FROM inscrit WHERE pseudo=(SELECT pseudo,email FROM
inscrit WHERE pseudo='joce'); inscrit WHERE pseudo='joce');
...@@ -96,4 +94,18 @@ SELECT pseudo FROM inscrit WHERE pseudo=(SELECT pseudo FROM inscrit WHERE pseudo ...@@ -96,4 +94,18 @@ SELECT pseudo FROM inscrit WHERE pseudo=(SELECT pseudo FROM inscrit WHERE pseudo
-- error 1240 -- error 1240
SELECT pseudo FROM inscrit WHERE pseudo=(SELECT pseudo FROM inscrit WHERE pseudo LIKE '%joce%'); SELECT pseudo FROM inscrit WHERE pseudo=(SELECT pseudo FROM inscrit WHERE pseudo LIKE '%joce%');
drop table if exists t1,t2,t3,t4,t5,attend,clinic,inscrit; drop table if exists t1,t2,t3,t4,t5,attend,clinic,inscrit;
\ No newline at end of file
drop table if exists searchconthardwarefr3;
CREATE TABLE `searchconthardwarefr3` (
`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 (`pseudo`,`date`,`topic`),
KEY `topic` (`topic`)
) TYPE=MyISAM ROW_FORMAT=DYNAMIC;
INSERT INTO searchconthardwarefr3 (topic,date,pseudo) VALUES
('43506','2002-10-02','joce'),('40143','2002-08-03','joce');
EXPLAIN SELECT DISTINCT date FROM searchconthardwarefr3 WHERE date='2002-08-03';
EXPLAIN SELECT (SELECT DISTINCT date FROM searchconthardwarefr3 WHERE date='2002-08-03');
drop table searchconthardwarefr3;
\ No newline at end of file
...@@ -392,6 +392,8 @@ int mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &list,COND *conds, ...@@ -392,6 +392,8 @@ int mysql_select(THD *thd,TABLE_LIST *tables,List<Item> &list,COND *conds,
SELECT_LEX_UNIT *unit, SELECT_LEX *select_lex, SELECT_LEX_UNIT *unit, SELECT_LEX *select_lex,
bool fake_select_lex); bool fake_select_lex);
void fix_tables_pointers(SELECT_LEX *select_lex); void fix_tables_pointers(SELECT_LEX *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, int mysql_explain_select(THD *thd, SELECT_LEX *sl, char const *type,
select_result *result); select_result *result);
int mysql_union(THD *thd, LEX *lex,select_result *result); int mysql_union(THD *thd, LEX *lex,select_result *result);
......
...@@ -912,3 +912,57 @@ bool select_exists_subselect::send_data(List<Item> &items) ...@@ -912,3 +912,57 @@ bool select_exists_subselect::send_data(List<Item> &items)
DBUG_RETURN(0); DBUG_RETURN(0);
} }
/***************************************************************************
** Dump of select to variables
***************************************************************************/
int select_dumpvar::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
{
List_iterator_fast<Item> li(list);
List_iterator_fast<LEX_STRING> gl(var_list);
Item *item;
LEX_STRING *ls;
if (var_list.elements != list.elements)
{
my_error(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT, MYF(0));
return 1;
}
while ((item=li++))
{
ls= gl++;
Item_func_set_user_var *xx = new Item_func_set_user_var(*ls,item);
xx->fix_fields(current_thd,(TABLE_LIST*) current_thd->lex.select_lex.table_list.first,&item);
xx->fix_length_and_dec();
vars.push_back(xx);
}
return 0;
}
bool select_dumpvar::send_data(List<Item> &items)
{
List_iterator_fast<Item_func_set_user_var> li(vars);
Item_func_set_user_var *xx;
DBUG_ENTER("send_data");
if (row_count++)
{
my_error(ER_TOO_MANY_ROWS, MYF(0));
DBUG_RETURN(1);
}
while ((xx=li++))
xx->update();
DBUG_RETURN(0);
}
bool select_dumpvar::send_eof()
{
if (row_count)
{
::send_ok(thd,row_count);
return 0;
}
else
{
my_error(ER_EMPTY_QUERY,MYF(0));
return 1;
}
}
...@@ -966,3 +966,15 @@ public: ...@@ -966,3 +966,15 @@ public:
bool send_eof(); bool send_eof();
}; };
class select_dumpvar :public select_result {
ha_rows row_count;
public:
List<LEX_STRING> var_list;
List<Item_func_set_user_var> vars;
select_dumpvar(void) { var_list.empty(); vars.empty(); row_count=0;}
~select_dumpvar() {}
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
bool send_fields(List<Item> &list, uint flag) {return 0;}
bool send_data(List<Item> &items);
bool send_eof();
};
...@@ -955,6 +955,7 @@ void st_select_lex::init_query() ...@@ -955,6 +955,7 @@ void st_select_lex::init_query()
table_list.first= 0; table_list.first= 0;
table_list.next= (byte**) &table_list.first; table_list.next= (byte**) &table_list.first;
item_list.empty(); item_list.empty();
join= 0;
} }
void st_select_lex::init_select() void st_select_lex::init_select()
...@@ -973,7 +974,6 @@ void st_select_lex::init_select() ...@@ -973,7 +974,6 @@ void st_select_lex::init_select()
ftfunc_list= &ftfunc_list_alloc; ftfunc_list= &ftfunc_list_alloc;
linkage= UNSPECIFIED_TYPE; linkage= UNSPECIFIED_TYPE;
depended= having_fix_field= 0; depended= having_fix_field= 0;
} }
/* /*
......
...@@ -334,6 +334,7 @@ typedef struct st_lex ...@@ -334,6 +334,7 @@ typedef struct st_lex
enum SSL_type ssl_type; /* defined in violite.h */ enum SSL_type ssl_type; /* defined in violite.h */
String *wild; String *wild;
sql_exchange *exchange; sql_exchange *exchange;
select_result *result;
List<key_part_spec> col_list; List<key_part_spec> col_list;
List<key_part_spec> ref_list; List<key_part_spec> ref_list;
...@@ -377,7 +378,7 @@ typedef struct st_lex ...@@ -377,7 +378,7 @@ typedef struct st_lex
uint param_count; uint param_count;
bool drop_primary, drop_if_exists, local_file, olap; bool drop_primary, drop_if_exists, local_file, olap;
bool in_comment, ignore_space, verbose, simple_alter; bool in_comment, ignore_space, verbose, simple_alter;
bool derived_tables; bool derived_tables, describe;
uint slave_thd_opt; uint slave_thd_opt;
CHARSET_INFO *charset; CHARSET_INFO *charset;
} LEX; } LEX;
......
...@@ -1335,8 +1335,7 @@ mysql_execute_command(THD *thd) ...@@ -1335,8 +1335,7 @@ mysql_execute_command(THD *thd)
TODO: solve problem with depended derived tables in subselects TODO: solve problem with depended derived tables in subselects
*/ */
if (lex->sql_command == SQLCOM_SELECT && if (lex->sql_command == SQLCOM_SELECT &&
(select_lex->options & SELECT_DESCRIBE) && lex->describe && lex->derived_tables)
lex->derived_tables)
{ {
if (!(explain_result= new select_send())) if (!(explain_result= new select_send()))
{ {
...@@ -1404,9 +1403,7 @@ mysql_execute_command(THD *thd) ...@@ -1404,9 +1403,7 @@ mysql_execute_command(THD *thd)
switch (lex->sql_command) { switch (lex->sql_command) {
case SQLCOM_SELECT: case SQLCOM_SELECT:
{ {
select_result *result; select_result *result=lex->result;
if (select_lex->options & SELECT_DESCRIBE)
lex->exchange=0;
if (tables) if (tables)
{ {
res=check_table_access(thd, res=check_table_access(thd,
...@@ -1431,51 +1428,10 @@ mysql_execute_command(THD *thd) ...@@ -1431,51 +1428,10 @@ mysql_execute_command(THD *thd)
if (unit->select_limit_cnt == HA_POS_ERROR) if (unit->select_limit_cnt == HA_POS_ERROR)
select_lex->options&= ~OPTION_FOUND_ROWS; select_lex->options&= ~OPTION_FOUND_ROWS;
if (lex->exchange)
{
if (lex->exchange->dumpfile)
{
if (!(result=new select_dump(lex->exchange)))
{
res= -1;
break;
}
}
else
{
if (!(result=new select_export(lex->exchange)))
{
res= -1;
break;
}
}
}
else if (!(result=new select_send()))
{
res= -1;
#ifdef DELETE_ITEMS
delete select_lex->having;
delete select_lex->where;
#endif
break;
}
else
{
/*
Normal select:
Change lock if we are using SELECT HIGH PRIORITY,
FOR UPDATE or IN SHARE MODE
*/
TABLE_LIST *table;
for (table = tables ; table ; table=table->next)
table->lock_type= lex->lock_option;
}
if (!(res=open_and_lock_tables(thd,tables))) if (!(res=open_and_lock_tables(thd,tables)))
{ {
if (select_lex->options & SELECT_DESCRIBE) if (lex->describe)
{ {
delete result; // we do not need it for explain
if (!explain_result) if (!explain_result)
if (!(explain_result= new select_send())) if (!(explain_result= new select_send()))
{ {
...@@ -1485,24 +1441,7 @@ mysql_execute_command(THD *thd) ...@@ -1485,24 +1441,7 @@ mysql_execute_command(THD *thd)
else else
thd->send_explain_fields(explain_result); thd->send_explain_fields(explain_result);
fix_tables_pointers(select_lex); fix_tables_pointers(select_lex);
for ( SELECT_LEX *sl= select_lex; res= mysql_explain_union(thd, &thd->lex.unit, explain_result);
sl && res == 0;
sl= sl->next_select_in_list())
{
SELECT_LEX *first= sl->master_unit()->first_select();
res= mysql_explain_select(thd, sl,
((select_lex==sl)?
((sl->next_select_in_list())?"PRIMARY":
"SIMPLE"):
((sl == first)?
((sl->depended)?"DEPENDENT SUBSELECT":
"SUBSELECT"):
((sl->depended)?"DEPENDENT UNION":
"UNION"))),
explain_result);
}
if (res > 0)
res= -res; // mysql_explain_select do not report error
MYSQL_LOCK *save_lock= thd->lock; MYSQL_LOCK *save_lock= thd->lock;
thd->lock= (MYSQL_LOCK *)0; thd->lock= (MYSQL_LOCK *)0;
explain_result->send_eof(); explain_result->send_eof();
...@@ -1510,12 +1449,33 @@ mysql_execute_command(THD *thd) ...@@ -1510,12 +1449,33 @@ mysql_execute_command(THD *thd)
} }
else else
{ {
if (!result)
{
if ((result=new select_send()))
{
/*
Normal select:
Change lock if we are using SELECT HIGH PRIORITY,
FOR UPDATE or IN SHARE MODE
*/
TABLE_LIST *table;
for (table = tables ; table ; table=table->next)
table->lock_type= lex->lock_option;
}
else
{
res= -1;
#ifdef DELETE_ITEMS
delete select_lex->having;
delete select_lex->where;
#endif
break;
}
}
query_cache_store_query(thd, tables); query_cache_store_query(thd, tables);
res=handle_select(thd, lex, result); res=handle_select(thd, lex, result);
} }
} }
else
delete result;
break; break;
} }
case SQLCOM_DO: case SQLCOM_DO:
...@@ -2946,7 +2906,7 @@ mysql_init_query(THD *thd) ...@@ -2946,7 +2906,7 @@ mysql_init_query(THD *thd)
thd->free_list= 0; thd->free_list= 0;
thd->lex.union_option= 0; thd->lex.union_option= 0;
thd->lex.select= &thd->lex.select_lex; thd->lex.select= &thd->lex.select_lex;
thd->lex.olap=0; thd->lex.olap=thd->lex.describe=0;
thd->lex.select->olap= UNSPECIFIED_OLAP_TYPE; thd->lex.select->olap= UNSPECIFIED_OLAP_TYPE;
thd->fatal_error= 0; // Safety thd->fatal_error= 0; // Safety
thd->total_warn_count=0; // Warnings for this query thd->total_warn_count=0; // Warnings for this query
...@@ -2966,6 +2926,7 @@ mysql_init_select(LEX *lex) ...@@ -2966,6 +2926,7 @@ mysql_init_select(LEX *lex)
lex->thd->variables.select_limit; lex->thd->variables.select_limit;
select_lex->olap= UNSPECIFIED_OLAP_TYPE; select_lex->olap= UNSPECIFIED_OLAP_TYPE;
lex->exchange= 0; lex->exchange= 0;
lex->result= 0;
lex->proc_list.first= 0; lex->proc_list.first= 0;
} }
......
...@@ -216,7 +216,7 @@ JOIN::prepare(TABLE_LIST *tables_init, ...@@ -216,7 +216,7 @@ JOIN::prepare(TABLE_LIST *tables_init,
SELECT_LEX_UNIT *unit, bool fake_select_lex) SELECT_LEX_UNIT *unit, bool fake_select_lex)
{ {
DBUG_ENTER("JOIN::prepare"); DBUG_ENTER("JOIN::prepare");
conds= conds_init; conds= conds_init;
order= order_init; order= order_init;
group_list= group_init; group_list= group_init;
...@@ -351,7 +351,7 @@ int ...@@ -351,7 +351,7 @@ int
JOIN::optimize() JOIN::optimize()
{ {
DBUG_ENTER("JOIN::optimize"); DBUG_ENTER("JOIN::optimize");
#ifdef HAVE_REF_TO_FIELDS // Not done yet #ifdef HAVE_REF_TO_FIELDS // Not done yet
/* Add HAVING to WHERE if possible */ /* Add HAVING to WHERE if possible */
if (having && !group_list && ! sum_func_count) if (having && !group_list && ! sum_func_count)
...@@ -1043,36 +1043,60 @@ mysql_select(THD *thd, TABLE_LIST *tables, List<Item> &fields, COND *conds, ...@@ -1043,36 +1043,60 @@ mysql_select(THD *thd, TABLE_LIST *tables, List<Item> &fields, COND *conds,
SELECT_LEX_UNIT *unit, SELECT_LEX *select_lex, SELECT_LEX_UNIT *unit, SELECT_LEX *select_lex,
bool fake_select_lex) bool fake_select_lex)
{ {
JOIN *join = new JOIN(thd, fields, select_options, result);
DBUG_ENTER("mysql_select"); DBUG_ENTER("mysql_select");
thd->proc_info="init";
thd->used_tables=0; // Updated by setup_fields
if (join->prepare(tables, conds, order, group, having, proc_param, bool free_join= 1;
select_lex, unit, fake_select_lex)) JOIN *join;
if (!fake_select_lex && select_lex->join != 0)
{ {
DBUG_RETURN(-1); //here is EXPLAIN of subselect or derived table
join= select_lex->join;
join->result= result;
if (!join->procedure && result->prepare(join->fields_list, unit))
{
DBUG_RETURN(-1);
}
join->select_options= select_options;
free_join= 0;
} }
switch (join->optimize()) { else
{
join= new JOIN(thd, fields, select_options, result);
thd->proc_info="init";
thd->used_tables=0; // Updated by setup_fields
if (join->prepare(tables, conds, order, group, having, proc_param,
select_lex, unit, fake_select_lex))
{
DBUG_RETURN(-1);
}
}
switch (join->optimize())
{
case 1: case 1:
DBUG_RETURN(join->error); DBUG_RETURN(join->error);
case -1: case -1:
goto err; goto err;
} }
if (join->global_optimize()) if (free_join && join->global_optimize())
goto err; goto err;
join->exec(); join->exec();
err: err:
thd->limit_found_rows = join->send_records; if (free_join)
thd->examined_row_count = join->examined_rows; {
thd->proc_info="end"; thd->limit_found_rows = join->send_records;
int error= (fake_select_lex?0:join->cleanup(thd)) || thd->net.report_error; thd->examined_row_count = join->examined_rows;
delete join; thd->proc_info="end";
DBUG_RETURN(error); int error= (fake_select_lex?0:join->cleanup(thd)) || thd->net.report_error;
delete join;
DBUG_RETURN(error);
}
else
DBUG_RETURN(0);
} }
/***************************************************************************** /*****************************************************************************
...@@ -7411,9 +7435,43 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order, ...@@ -7411,9 +7435,43 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
result->send_error(0,NullS); result->send_error(0,NullS);
} }
} }
for (SELECT_LEX_UNIT *unit= join->select_lex->first_inner_unit();
unit;
unit= unit->next_unit())
{
if (mysql_explain_union(thd, unit, result))
DBUG_VOID_RETURN;
}
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
int mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result)
{
int res= 0;
SELECT_LEX *first= unit->first_select();
for (SELECT_LEX *sl= first;
sl;
sl= sl->next_select())
{
res= mysql_explain_select(thd, sl,
(((&thd->lex.select_lex)==sl)?
((sl->next_select_in_list())?"PRIMARY":
"SIMPLE"):
((sl == first)?
((sl->depended)?"DEPENDENT SUBSELECT":
"SUBSELECT"):
((sl->depended)?"DEPENDENT UNION":
"UNION"))),
result);
if (res)
break;
}
if (res > 0)
res= -res; // mysql_explain_select do not report error
return res;
}
int mysql_explain_select(THD *thd, SELECT_LEX *select_lex, char const *type, int mysql_explain_select(THD *thd, SELECT_LEX *select_lex, char const *type,
select_result *result) select_result *result)
{ {
......
...@@ -109,7 +109,7 @@ int st_select_lex_unit::prepare(THD *thd, select_result *result) ...@@ -109,7 +109,7 @@ 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;
describe=(first_select()->options & SELECT_DESCRIBE) ? 1 : 0; describe=(first_select()->options & SELECT_DESCRIBE) ? 1 : 0;
res= 0; res= 0;
found_rows_for_union= false; found_rows_for_union= false;
...@@ -309,10 +309,12 @@ int st_select_lex_unit::exec() ...@@ -309,10 +309,12 @@ 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");
delete union_result; if (union_result)
free_tmp_table(thd,table); {
table= 0; // Safety delete union_result;
free_tmp_table(thd,table);
table= 0; // Safety
}
List_iterator<JOIN*> j(joins); List_iterator<JOIN*> j(joins);
JOIN** join; JOIN** join;
while ((join= j++)) while ((join= j++))
......
...@@ -528,7 +528,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); ...@@ -528,7 +528,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%type <lex_str> %type <lex_str>
IDENT TEXT_STRING REAL_NUM FLOAT_NUM NUM LONG_NUM HEX_NUM LEX_HOSTNAME IDENT TEXT_STRING REAL_NUM FLOAT_NUM NUM LONG_NUM HEX_NUM LEX_HOSTNAME
ULONGLONG_NUM field_ident select_alias ident ident_or_text UNDERSCORE_CHARSET ULONGLONG_NUM field_ident select_alias ident ident_or_text UNDERSCORE_CHARSET
%type <lex_str_ptr> %type <lex_str_ptr>
opt_table_alias opt_table_alias
...@@ -637,7 +637,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); ...@@ -637,7 +637,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
handler_rkey_function handler_read_or_scan handler_rkey_function handler_read_or_scan
single_multi table_wild_list table_wild_one opt_wild union union_list single_multi table_wild_list table_wild_one opt_wild union union_list
precision union_option opt_on_delete_item subselect_start opt_and precision union_option opt_on_delete_item subselect_start opt_and
subselect_end subselect_end select_var_list select_var_list_init
END_OF_INPUT END_OF_INPUT
%type <NONE> %type <NONE>
...@@ -759,7 +759,8 @@ master_def: ...@@ -759,7 +759,8 @@ master_def:
RELAY_LOG_POS_SYM EQ ULONG_NUM RELAY_LOG_POS_SYM EQ ULONG_NUM
{ {
Lex->mi.relay_log_pos = $3; Lex->mi.relay_log_pos = $3;
}; }
;
/* create a table */ /* create a table */
...@@ -824,11 +825,13 @@ create: ...@@ -824,11 +825,13 @@ create:
LEX *lex=Lex; LEX *lex=Lex;
lex->udf.returns=(Item_result) $7; lex->udf.returns=(Item_result) $7;
lex->udf.dl=$9.str; lex->udf.dl=$9.str;
}; }
;
create2: create2:
'(' field_list ')' opt_create_table_options create3 {} '(' field_list ')' opt_create_table_options create3 {}
| opt_create_table_options create3 {}; | opt_create_table_options create3 {}
;
create3: create3:
/* empty */ {} /* empty */ {}
...@@ -838,7 +841,8 @@ create3: ...@@ -838,7 +841,8 @@ create3:
lex->lock_option= (using_update_log) ? TL_READ_NO_INSERT : TL_READ; lex->lock_option= (using_update_log) ? TL_READ_NO_INSERT : TL_READ;
mysql_init_select(lex); mysql_init_select(lex);
} }
select_options select_item_list opt_select_from union {}; select_options select_item_list opt_select_from union {}
;
opt_as: opt_as:
/* empty */ {} /* empty */ {}
...@@ -1549,6 +1553,7 @@ select_part2: ...@@ -1549,6 +1553,7 @@ select_part2:
select_into: select_into:
limit_clause {} limit_clause {}
| select_from | select_from
| opt_into
| opt_into select_from | opt_into select_from
| select_from opt_into; | select_from opt_into;
...@@ -2293,11 +2298,11 @@ select_part3: ...@@ -2293,11 +2298,11 @@ select_part3:
mysql_init_select(lex); mysql_init_select(lex);
lex->select->linkage= DERIVED_TABLE_TYPE; lex->select->linkage= DERIVED_TABLE_TYPE;
} }
select_options select_item_list select_intoto select_options select_item_list select_intoto;
select_intoto: select_intoto:
limit_clause {} limit_clause {}
| select_from | select_from;
opt_outer: opt_outer:
/* empty */ {} /* empty */ {}
...@@ -2548,20 +2553,61 @@ procedure_item: ...@@ -2548,20 +2553,61 @@ procedure_item:
YYABORT; YYABORT;
if (!$2->name) if (!$2->name)
$2->set_name($1,(uint) ((char*) Lex->tok_end - $1)); $2->set_name($1,(uint) ((char*) Lex->tok_end - $1));
}; }
;
select_var_list_init:
{
LEX *lex=Lex;
if (!lex->describe && (!(lex->result= new select_dumpvar())))
YYABORT;
}
select_var_list
;
select_var_list:
select_var_list ',' select_var_ident
| select_var_ident {}
;
select_var_ident: '@' ident_or_text
{
LEX *lex=Lex;
if (lex->result && ((select_dumpvar *)lex->result)->var_list.push_back((LEX_STRING*) sql_memdup(&$2,sizeof(LEX_STRING))))
YYABORT;
}
;
opt_into: opt_into:
INTO OUTFILE TEXT_STRING INTO OUTFILE TEXT_STRING
{ {
if (!(Lex->exchange= new sql_exchange($3.str,0))) LEX *lex=Lex;
YYABORT; if (!lex->describe)
{
if (!(lex->exchange= new sql_exchange($3.str,0)))
YYABORT;
if (!(lex->result= new select_export(lex->exchange)))
YYABORT;
}
} }
opt_field_term opt_line_term opt_field_term opt_line_term
| INTO DUMPFILE TEXT_STRING | INTO DUMPFILE TEXT_STRING
{ {
if (!(Lex->exchange= new sql_exchange($3.str,1))) LEX *lex=Lex;
YYABORT; if (!lex->describe)
}; {
if (!(lex->exchange= new sql_exchange($3.str,1)))
YYABORT;
if (!(lex->result= new select_dump(lex->exchange)))
YYABORT;
}
}
| INTO select_var_list_init
{
current_thd->safe_to_cache_query=0;
}
;
/* /*
DO statement DO statement
...@@ -3025,7 +3071,11 @@ describe: ...@@ -3025,7 +3071,11 @@ describe:
} }
opt_describe_column opt_describe_column
| describe_command select | describe_command select
{ Lex->select_lex.options|= SELECT_DESCRIBE; }; {
LEX *lex=Lex;
lex->select_lex.options|= SELECT_DESCRIBE;
lex->describe=1;
};
describe_command: describe_command:
...@@ -3231,7 +3281,7 @@ param_marker: ...@@ -3231,7 +3281,7 @@ param_marker:
yyerror("You have an error in your SQL syntax"); yyerror("You have an error in your SQL syntax");
YYABORT; YYABORT;
} }
} };
literal: literal:
text_literal { $$ = $1; } text_literal { $$ = $1; }
| NUM { $$ = new Item_int($1.str, (longlong) atol($1.str),$1.length); } | NUM { $$ = new Item_int($1.str, (longlong) atol($1.str),$1.length); }
...@@ -3582,7 +3632,7 @@ internal_variable_name: ...@@ -3582,7 +3632,7 @@ internal_variable_name:
YYABORT; YYABORT;
$$=tmp; $$=tmp;
} }
; ;
isolation_types: isolation_types:
READ_SYM UNCOMMITTED_SYM { $$= ISO_READ_UNCOMMITTED; } READ_SYM UNCOMMITTED_SYM { $$= ISO_READ_UNCOMMITTED; }
...@@ -3603,7 +3653,8 @@ text_or_password: ...@@ -3603,7 +3653,8 @@ text_or_password:
make_scrambled_password(buff,$3.str); make_scrambled_password(buff,$3.str);
$$=buff; $$=buff;
} }
}; }
;
set_expr_or_default: set_expr_or_default:
...@@ -3633,16 +3684,19 @@ table_lock_list: ...@@ -3633,16 +3684,19 @@ table_lock_list:
table_lock: table_lock:
table_ident opt_table_alias lock_option table_ident opt_table_alias lock_option
{ if (!add_table_to_list($1,$2,0,(thr_lock_type) $3)) YYABORT; }; { if (!add_table_to_list($1,$2,0,(thr_lock_type) $3)) YYABORT; }
;
lock_option: lock_option:
READ_SYM { $$=TL_READ_NO_INSERT; } READ_SYM { $$=TL_READ_NO_INSERT; }
| WRITE_SYM { $$=current_thd->update_lock_default; } | WRITE_SYM { $$=current_thd->update_lock_default; }
| LOW_PRIORITY WRITE_SYM { $$=TL_WRITE_LOW_PRIORITY; } | LOW_PRIORITY WRITE_SYM { $$=TL_WRITE_LOW_PRIORITY; }
| READ_SYM LOCAL_SYM { $$= TL_READ; }; | READ_SYM LOCAL_SYM { $$= TL_READ; }
;
unlock: unlock:
UNLOCK_SYM table_or_tables { Lex->sql_command=SQLCOM_UNLOCK_TABLES; }; UNLOCK_SYM table_or_tables { Lex->sql_command=SQLCOM_UNLOCK_TABLES; }
;
/* /*
...@@ -3672,15 +3726,18 @@ handler: ...@@ -3672,15 +3726,18 @@ handler:
if (!add_table_to_list($2,0,0)) if (!add_table_to_list($2,0,0))
YYABORT; YYABORT;
} }
handler_read_or_scan where_clause limit_clause { }; handler_read_or_scan where_clause limit_clause { }
;
handler_read_or_scan: handler_read_or_scan:
handler_scan_function { Lex->backup_dir= 0; } handler_scan_function { Lex->backup_dir= 0; }
| ident handler_rkey_function { Lex->backup_dir= $1.str; }; | ident handler_rkey_function { Lex->backup_dir= $1.str; }
;
handler_scan_function: handler_scan_function:
FIRST_SYM { Lex->ha_read_mode = RFIRST; } FIRST_SYM { Lex->ha_read_mode = RFIRST; }
| NEXT_SYM { Lex->ha_read_mode = RNEXT; }; | NEXT_SYM { Lex->ha_read_mode = RNEXT; }
;
handler_rkey_function: handler_rkey_function:
FIRST_SYM { Lex->ha_read_mode = RFIRST; } FIRST_SYM { Lex->ha_read_mode = RFIRST; }
...@@ -3694,14 +3751,16 @@ handler_rkey_function: ...@@ -3694,14 +3751,16 @@ handler_rkey_function:
lex->ha_rkey_mode=$1; lex->ha_rkey_mode=$1;
if (!(lex->insert_list = new List_item)) if (!(lex->insert_list = new List_item))
YYABORT; YYABORT;
} '(' values ')' { }; } '(' values ')' { }
;
handler_rkey_mode: handler_rkey_mode:
EQ { $$=HA_READ_KEY_EXACT; } EQ { $$=HA_READ_KEY_EXACT; }
| GE { $$=HA_READ_KEY_OR_NEXT; } | GE { $$=HA_READ_KEY_OR_NEXT; }
| LE { $$=HA_READ_KEY_OR_PREV; } | LE { $$=HA_READ_KEY_OR_PREV; }
| GT_SYM { $$=HA_READ_AFTER_KEY; } | GT_SYM { $$=HA_READ_AFTER_KEY; }
| LT { $$=HA_READ_BEFORE_KEY; }; | LT { $$=HA_READ_BEFORE_KEY; }
;
/* GRANT / REVOKE */ /* GRANT / REVOKE */
...@@ -3739,7 +3798,8 @@ grant: ...@@ -3739,7 +3798,8 @@ grant:
grant_privileges: grant_privileges:
grant_privilege_list {} grant_privilege_list {}
| ALL PRIVILEGES { Lex->grant = GLOBAL_ACLS;} | ALL PRIVILEGES { Lex->grant = GLOBAL_ACLS;}
| ALL { Lex->grant = GLOBAL_ACLS;}; | ALL { Lex->grant = GLOBAL_ACLS;}
;
grant_privilege_list: grant_privilege_list:
grant_privilege grant_privilege
...@@ -3858,7 +3918,8 @@ opt_table: ...@@ -3858,7 +3918,8 @@ opt_table:
YYABORT; YYABORT;
if (lex->grant == GLOBAL_ACLS) if (lex->grant == GLOBAL_ACLS)
lex->grant = TABLE_ACLS & ~GRANT_ACL; lex->grant = TABLE_ACLS & ~GRANT_ACL;
}; }
;
user_list: user_list:
...@@ -3889,7 +3950,8 @@ grant_user: ...@@ -3889,7 +3950,8 @@ grant_user:
| user IDENTIFIED_SYM BY PASSWORD TEXT_STRING | user IDENTIFIED_SYM BY PASSWORD TEXT_STRING
{ $$=$1; $1->password=$5 ; } { $$=$1; $1->password=$5 ; }
| user | user
{ $$=$1; $1->password.str=NullS; }; { $$=$1; $1->password.str=NullS; }
;
opt_column_list: opt_column_list:
...@@ -3922,7 +3984,8 @@ column_list_id: ...@@ -3922,7 +3984,8 @@ column_list_id:
point->rights |= lex->which_columns; point->rights |= lex->which_columns;
else else
lex->columns.push_back(new LEX_COLUMN (*new_str,lex->which_columns)); lex->columns.push_back(new LEX_COLUMN (*new_str,lex->which_columns));
}; }
;
require_clause: /* empty */ require_clause: /* empty */
...@@ -3942,7 +4005,7 @@ require_clause: /* empty */ ...@@ -3942,7 +4005,7 @@ require_clause: /* empty */
{ {
Lex->ssl_type=SSL_TYPE_NONE; Lex->ssl_type=SSL_TYPE_NONE;
} }
; ;
grant_options: grant_options:
/* empty */ {} /* empty */ {}
...@@ -3950,7 +4013,8 @@ grant_options: ...@@ -3950,7 +4013,8 @@ grant_options:
grant_option_list: grant_option_list:
grant_option_list grant_option {} grant_option_list grant_option {}
| grant_option {}; | grant_option {}
;
grant_option: grant_option:
GRANT OPTION { Lex->grant |= GRANT_ACL;} GRANT OPTION { Lex->grant |= GRANT_ACL;}
...@@ -3968,14 +4032,16 @@ grant_option: ...@@ -3968,14 +4032,16 @@ grant_option:
{ {
Lex->mqh.connections=$2; Lex->mqh.connections=$2;
Lex->mqh.bits |= 4; Lex->mqh.bits |= 4;
}; }
;
begin: begin:
BEGIN_SYM { Lex->sql_command = SQLCOM_BEGIN;} opt_work; BEGIN_SYM { Lex->sql_command = SQLCOM_BEGIN;} opt_work;
opt_work: opt_work:
/* empty */ {} /* empty */ {}
| WORK_SYM {;}; | WORK_SYM {;}
;
commit: commit:
COMMIT_SYM { Lex->sql_command = SQLCOM_COMMIT;}; COMMIT_SYM { Lex->sql_command = SQLCOM_COMMIT;};
...@@ -4085,4 +4151,4 @@ subselect_end: ...@@ -4085,4 +4151,4 @@ subselect_end:
{ {
LEX *lex=Lex; LEX *lex=Lex;
lex->select = lex->select->outer_select(); lex->select = lex->select->outer_select();
} };
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