Commit 0c1af74d authored by unknown's avatar unknown

processing of subselect in global ORDER BY (fifed crash of server)

  this implementation have limitation: prohibited subselect in ORDER BY dependence of most outer query (will be solved after removing passing first select_lex as fake select for global mysql_select())


mysql-test/r/subselect.result:
  test of subselect in global ORDER BY
mysql-test/t/subselect.test:
  test of subselect in global ORDER BY
sql/sql_lex.cc:
  fixed comments
  processing of subselect in global ORDER BY
sql/sql_lex.h:
  processing of subselect in global ORDER BY
sql/sql_parse.cc:
  processing of subselect in global ORDER BY
sql/sql_yacc.yy:
  processing of subselect in global ORDER BY
parent bbc8f836
...@@ -458,6 +458,14 @@ Subselect returns more than 1 record ...@@ -458,6 +458,14 @@ Subselect returns more than 1 record
select numeropost as a FROM t1 ORDER BY (SELECT 1 FROM t1 HAVING a=1); select numeropost as a FROM t1 ORDER BY (SELECT 1 FROM t1 HAVING a=1);
Subselect returns more than 1 record Subselect returns more than 1 record
drop table t1; drop table t1;
create table t1 (a int);
insert into t1 values (1),(2),(3);
(select * from t1) union (select * from t1) order by (select a from t1 limit 1);
a
1
2
3
drop table t1;
CREATE TABLE t1 (field char(1) NOT NULL DEFAULT 'b'); CREATE TABLE t1 (field char(1) NOT NULL DEFAULT 'b');
INSERT INTO t1 VALUES (); INSERT INTO t1 VALUES ();
SELECT field FROM t1 WHERE 1=(SELECT 1 UNION ALL SELECT 1 FROM (SELECT 1) a HAVING field='b'); SELECT field FROM t1 WHERE 1=(SELECT 1 UNION ALL SELECT 1 FROM (SELECT 1) a HAVING field='b');
......
...@@ -244,6 +244,11 @@ select numeropost as a FROM t1 GROUP BY (SELECT 1 FROM t1 HAVING a=1); ...@@ -244,6 +244,11 @@ select numeropost as a FROM t1 GROUP BY (SELECT 1 FROM t1 HAVING a=1);
select numeropost as a FROM t1 ORDER BY (SELECT 1 FROM t1 HAVING a=1); select numeropost as a FROM t1 ORDER BY (SELECT 1 FROM t1 HAVING a=1);
drop table t1; drop table t1;
create table t1 (a int);
insert into t1 values (1),(2),(3);
(select * from t1) union (select * from t1) order by (select a from t1 limit 1);
drop table t1;
#iftest #iftest
CREATE TABLE t1 (field char(1) NOT NULL DEFAULT 'b'); CREATE TABLE t1 (field char(1) NOT NULL DEFAULT 'b');
INSERT INTO t1 VALUES (); INSERT INTO t1 VALUES ();
......
...@@ -1240,23 +1240,60 @@ TABLE_LIST *st_select_lex_node::add_table_to_list(THD *thd, Table_ident *table, ...@@ -1240,23 +1240,60 @@ TABLE_LIST *st_select_lex_node::add_table_to_list(THD *thd, Table_ident *table,
} }
ulong st_select_lex_node::get_table_join_options() { return 0; } ulong st_select_lex_node::get_table_join_options() { return 0; }
/* /*
Interface method of table list creation for query
SYNOPSIS
st_select_lex_unit::create_total_list()
thd THD pointer
result pointer on result list of tables pointer
check_derived force derived table chacking (used for creating
table list for derived query)
DESCRIPTION
This is used for UNION & subselect to create a new table list of all used This is used for UNION & subselect to create a new table list of all used
tables. tables.
The table_list->table entry in all used tables are set to point The table_list->table entry in all used tables are set to point
to the entries in this list. to the entries in this list.
*/
// interface RETURN
0 - OK
!0 - error
*/
bool st_select_lex_unit::create_total_list(THD *thd, st_lex *lex, bool st_select_lex_unit::create_total_list(THD *thd, st_lex *lex,
TABLE_LIST **result, TABLE_LIST **result,
bool check_derived) bool check_derived)
{ {
*result= 0; *result= 0;
return create_total_list_n_last_return(thd, lex, &result, check_derived); for (SELECT_LEX_UNIT *unit= this; unit; unit= unit->next_unit())
{
if ((res= unit->create_total_list_n_last_return(thd, lex, &result,
check_derived)))
return res;
}
return 0;
} }
// list creator /*
Table list creation for query
SYNOPSIS
st_select_lex_unit::create_total_list()
thd THD pointer
lex pointer on LEX stricture
result pointer on pointer on result list of tables pointer
check_derived force derived table chacking (used for creating
table list for derived query)
DESCRIPTION
This is used for UNION & subselect to create a new table list of all used
tables.
The table_list->table entry in all used tables are set to point
to the entries in this list.
RETURN
0 - OK
!0 - error
*/
bool st_select_lex_unit::create_total_list_n_last_return(THD *thd, st_lex *lex, bool st_select_lex_unit::create_total_list_n_last_return(THD *thd, st_lex *lex,
TABLE_LIST ***result, TABLE_LIST ***result,
bool check_derived) bool check_derived)
......
...@@ -243,6 +243,7 @@ public: ...@@ -243,6 +243,7 @@ public:
virtual st_select_lex_unit* master_unit()= 0; virtual st_select_lex_unit* master_unit()= 0;
virtual st_select_lex* outer_select()= 0; virtual st_select_lex* outer_select()= 0;
virtual st_select_lex_node* return_after_parsing()= 0;
virtual bool set_braces(bool value); virtual bool set_braces(bool value);
virtual bool inc_in_sum_expr(); virtual bool inc_in_sum_expr();
...@@ -297,6 +298,8 @@ public: ...@@ -297,6 +298,8 @@ public:
global parameters for union global parameters for union
*/ */
st_select_lex_node *global_parameters; st_select_lex_node *global_parameters;
//node on wich we should return current_select pointer after parsing subquery
st_select_lex_node *return_to;
/* LIMIT clause runtime counters */ /* LIMIT clause runtime counters */
ha_rows select_limit_cnt, offset_limit_cnt; ha_rows select_limit_cnt, offset_limit_cnt;
/* not NULL if union used in subselect, point to subselect item */ /* not NULL if union used in subselect, point to subselect item */
...@@ -317,6 +320,7 @@ public: ...@@ -317,6 +320,7 @@ public:
(st_select_lex*) slave->next : (st_select_lex*) slave; (st_select_lex*) slave->next : (st_select_lex*) slave;
} }
st_select_lex_unit* next_unit() { return (st_select_lex_unit*) next; } st_select_lex_unit* next_unit() { return (st_select_lex_unit*) next; }
st_select_lex_node* return_after_parsing() { return return_to; }
void exclude_level(); void exclude_level();
/* UNION methods */ /* UNION methods */
...@@ -379,6 +383,10 @@ public: ...@@ -379,6 +383,10 @@ public:
{ {
return &link_next; return &link_next;
} }
st_select_lex_node* return_after_parsing()
{
return master_unit()->return_after_parsing();
}
bool set_braces(bool value); bool set_braces(bool value);
bool inc_in_sum_expr(); bool inc_in_sum_expr();
......
...@@ -3204,7 +3204,8 @@ mysql_init_query(THD *thd) ...@@ -3204,7 +3204,8 @@ mysql_init_query(THD *thd)
lex->select_lex.init_query(); lex->select_lex.init_query();
lex->value_list.empty(); lex->value_list.empty();
lex->param_list.empty(); lex->param_list.empty();
lex->unit.next= lex->unit.master= lex->unit.link_next= 0; lex->unit.next= lex->unit.master= lex->unit.return_to=
lex->unit.link_next= 0;
lex->unit.prev= lex->unit.link_prev= 0; lex->unit.prev= lex->unit.link_prev= 0;
lex->unit.global_parameters= lex->unit.slave= lex->current_select= lex->unit.global_parameters= lex->unit.slave= lex->current_select=
lex->all_selects_list= &lex->select_lex; lex->all_selects_list= &lex->select_lex;
...@@ -3252,9 +3253,9 @@ bool ...@@ -3252,9 +3253,9 @@ bool
mysql_new_select(LEX *lex, bool move_down) mysql_new_select(LEX *lex, bool move_down)
{ {
SELECT_LEX *select_lex = new SELECT_LEX(); SELECT_LEX *select_lex = new SELECT_LEX();
select_lex->select_number= ++lex->thd->select_number;
if (!select_lex) if (!select_lex)
return 1; return 1;
select_lex->select_number= ++lex->thd->select_number;
select_lex->init_query(); select_lex->init_query();
select_lex->init_select(); select_lex->init_select();
if (move_down) if (move_down)
...@@ -3266,9 +3267,13 @@ mysql_new_select(LEX *lex, bool move_down) ...@@ -3266,9 +3267,13 @@ mysql_new_select(LEX *lex, bool move_down)
unit->init_query(); unit->init_query();
unit->init_select(); unit->init_select();
unit->thd= lex->thd; unit->thd= lex->thd;
if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE)
unit->include_neighbour(lex->current_select);
else
unit->include_down(lex->current_select); unit->include_down(lex->current_select);
unit->link_next= 0; unit->link_next= 0;
unit->link_prev= 0; unit->link_prev= 0;
unit->return_to= lex->current_select;
select_lex->include_down(unit); select_lex->include_down(unit);
} }
else else
......
...@@ -4855,5 +4855,5 @@ subselect_end: ...@@ -4855,5 +4855,5 @@ subselect_end:
')' ')'
{ {
LEX *lex=Lex; LEX *lex=Lex;
lex->current_select = lex->current_select->outer_select(); lex->current_select = lex->current_select->return_after_parsing();
}; };
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