diff options
author | unknown <bell@sanja.is.com.ua> | 2003-03-11 01:06:28 +0200 |
---|---|---|
committer | unknown <bell@sanja.is.com.ua> | 2003-03-11 01:06:28 +0200 |
commit | 0c1af74d8aeafa09e2f216b0758204828ab47f9e (patch) | |
tree | 219aba0cea1c6f1fed0b6235ebf1893bfef27954 | |
parent | bbc8f836c0400f361458bffd42d71ea2177a9e18 (diff) | |
download | mariadb-git-0c1af74d8aeafa09e2f216b0758204828ab47f9e.tar.gz |
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
-rw-r--r-- | mysql-test/r/subselect.result | 8 | ||||
-rw-r--r-- | mysql-test/t/subselect.test | 5 | ||||
-rw-r--r-- | sql/sql_lex.cc | 55 | ||||
-rw-r--r-- | sql/sql_lex.h | 8 | ||||
-rw-r--r-- | sql/sql_parse.cc | 11 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 2 |
6 files changed, 76 insertions, 13 deletions
diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index 47f24a340cd..3a93d942b38 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -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); Subselect returns more than 1 record 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'); INSERT INTO t1 VALUES (); SELECT field FROM t1 WHERE 1=(SELECT 1 UNION ALL SELECT 1 FROM (SELECT 1) a HAVING field='b'); diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index 1841e9f109a..8229ab84acf 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -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); 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 CREATE TABLE t1 (field char(1) NOT NULL DEFAULT 'b'); INSERT INTO t1 VALUES (); diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 94c06d41634..61114247fed 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -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; } -/* - 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. -*/ -// interface +/* + 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 + 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(THD *thd, st_lex *lex, TABLE_LIST **result, bool check_derived) { *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, TABLE_LIST ***result, bool check_derived) diff --git a/sql/sql_lex.h b/sql/sql_lex.h index c0f24d6940e..23152c88c3b 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -243,6 +243,7 @@ public: virtual st_select_lex_unit* master_unit()= 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 inc_in_sum_expr(); @@ -297,6 +298,8 @@ public: global parameters for union */ 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 */ ha_rows select_limit_cnt, offset_limit_cnt; /* not NULL if union used in subselect, point to subselect item */ @@ -317,6 +320,7 @@ public: (st_select_lex*) slave->next : (st_select_lex*) slave; } 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(); /* UNION methods */ @@ -379,6 +383,10 @@ public: { return &link_next; } + st_select_lex_node* return_after_parsing() + { + return master_unit()->return_after_parsing(); + } bool set_braces(bool value); bool inc_in_sum_expr(); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index f0c04688a6b..85c962e7948 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -3204,7 +3204,8 @@ mysql_init_query(THD *thd) lex->select_lex.init_query(); lex->value_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.global_parameters= lex->unit.slave= lex->current_select= lex->all_selects_list= &lex->select_lex; @@ -3252,9 +3253,9 @@ bool mysql_new_select(LEX *lex, bool move_down) { SELECT_LEX *select_lex = new SELECT_LEX(); - select_lex->select_number= ++lex->thd->select_number; if (!select_lex) return 1; + select_lex->select_number= ++lex->thd->select_number; select_lex->init_query(); select_lex->init_select(); if (move_down) @@ -3266,9 +3267,13 @@ mysql_new_select(LEX *lex, bool move_down) unit->init_query(); unit->init_select(); unit->thd= lex->thd; - unit->include_down(lex->current_select); + if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE) + unit->include_neighbour(lex->current_select); + else + unit->include_down(lex->current_select); unit->link_next= 0; unit->link_prev= 0; + unit->return_to= lex->current_select; select_lex->include_down(unit); } else diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 99cf0986e30..bc3a853a2e2 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -4855,5 +4855,5 @@ subselect_end: ')' { LEX *lex=Lex; - lex->current_select = lex->current_select->outer_select(); + lex->current_select = lex->current_select->return_after_parsing(); }; |