Commit 59314ee3 authored by mhansson/martin@linux-st28.site's avatar mhansson/martin@linux-st28.site

Merge mhansson@bk-internal:/home/bk/mysql-5.0-opt

into  linux-st28.site:/home/martin/mysql/src/bug32858/my50-bug32858-push
parents 43582593 33c4431d
...@@ -1440,4 +1440,46 @@ UNION ...@@ -1440,4 +1440,46 @@ UNION
SELECT 1,1; SELECT 1,1;
ERROR HY000: Incorrect usage of UNION and ORDER BY ERROR HY000: Incorrect usage of UNION and ORDER BY
DROP TABLE t1,t2; DROP TABLE t1,t2;
CREATE TABLE t1 (a INT);
INSERT INTO t1 VALUES (1);
SELECT a INTO @v FROM (
SELECT a FROM t1
UNION
SELECT a FROM t1
) alias;
SELECT a INTO OUTFILE 'union.out.file' FROM (
SELECT a FROM t1
UNION
SELECT a FROM t1 WHERE 0
) alias;
SELECT a INTO DUMPFILE 'union.out.file2' FROM (
SELECT a FROM t1
UNION
SELECT a FROM t1 WHERE 0
) alias;
SELECT a FROM (
SELECT a FROM t1
UNION
SELECT a INTO @v FROM t1
) alias;
SELECT a FROM (
SELECT a FROM t1
UNION
SELECT a INTO OUTFILE 'union.out.file3' FROM t1
) alias;
SELECT a FROM (
SELECT a FROM t1
UNION
SELECT a INTO DUMPFILE 'union.out.file4' FROM t1
) alias;
SELECT a FROM t1 UNION SELECT a INTO @v FROM t1;
SELECT a FROM t1 UNION SELECT a INTO OUTFILE 'union.out.file5' FROM t1;
SELECT a FROM t1 UNION SELECT a INTO OUTFILE 'union.out.file6' FROM t1;
SELECT a INTO @v FROM t1 UNION SELECT a FROM t1;
ERROR HY000: Incorrect usage of UNION and INTO
SELECT a INTO OUTFILE 'union.out.file7' FROM t1 UNION SELECT a FROM t1;
ERROR HY000: Incorrect usage of UNION and INTO
SELECT a INTO DUMPFILE 'union.out.file8' FROM t1 UNION SELECT a FROM t1;
ERROR HY000: Incorrect usage of UNION and INTO
DROP TABLE t1;
End of 5.0 tests End of 5.0 tests
...@@ -921,4 +921,61 @@ SELECT 1,1; ...@@ -921,4 +921,61 @@ SELECT 1,1;
DROP TABLE t1,t2; DROP TABLE t1,t2;
# Bug#32858: Erro: "Incorrect usage of UNION and INTO" does not take subselects
# into account
#
CREATE TABLE t1 (a INT);
INSERT INTO t1 VALUES (1);
SELECT a INTO @v FROM (
SELECT a FROM t1
UNION
SELECT a FROM t1
) alias;
SELECT a INTO OUTFILE 'union.out.file' FROM (
SELECT a FROM t1
UNION
SELECT a FROM t1 WHERE 0
) alias;
SELECT a INTO DUMPFILE 'union.out.file2' FROM (
SELECT a FROM t1
UNION
SELECT a FROM t1 WHERE 0
) alias;
#
# INTO will not be allowed in subqueries in version 5.1 and above.
#
SELECT a FROM (
SELECT a FROM t1
UNION
SELECT a INTO @v FROM t1
) alias;
SELECT a FROM (
SELECT a FROM t1
UNION
SELECT a INTO OUTFILE 'union.out.file3' FROM t1
) alias;
SELECT a FROM (
SELECT a FROM t1
UNION
SELECT a INTO DUMPFILE 'union.out.file4' FROM t1
) alias;
SELECT a FROM t1 UNION SELECT a INTO @v FROM t1;
SELECT a FROM t1 UNION SELECT a INTO OUTFILE 'union.out.file5' FROM t1;
SELECT a FROM t1 UNION SELECT a INTO OUTFILE 'union.out.file6' FROM t1;
--error ER_WRONG_USAGE
SELECT a INTO @v FROM t1 UNION SELECT a FROM t1;
--error ER_WRONG_USAGE
SELECT a INTO OUTFILE 'union.out.file7' FROM t1 UNION SELECT a FROM t1;
--error ER_WRONG_USAGE
SELECT a INTO DUMPFILE 'union.out.file8' FROM t1 UNION SELECT a FROM t1;
DROP TABLE t1;
--echo End of 5.0 tests --echo End of 5.0 tests
...@@ -931,6 +931,7 @@ void THD::rollback_item_tree_changes() ...@@ -931,6 +931,7 @@ void THD::rollback_item_tree_changes()
select_result::select_result() select_result::select_result()
{ {
thd=current_thd; thd=current_thd;
nest_level= -1;
} }
void select_result::send_error(uint errcode,const char *err) void select_result::send_error(uint errcode,const char *err)
......
...@@ -1912,6 +1912,7 @@ class select_result :public Sql_alloc { ...@@ -1912,6 +1912,7 @@ class select_result :public Sql_alloc {
protected: protected:
THD *thd; THD *thd;
SELECT_LEX_UNIT *unit; SELECT_LEX_UNIT *unit;
uint nest_level;
public: public:
select_result(); select_result();
virtual ~select_result() {}; virtual ~select_result() {};
...@@ -1948,6 +1949,12 @@ public: ...@@ -1948,6 +1949,12 @@ public:
*/ */
virtual void cleanup(); virtual void cleanup();
void set_thd(THD *thd_arg) { thd= thd_arg; } void set_thd(THD *thd_arg) { thd= thd_arg; }
/**
The nest level, if supported.
@return
-1 if nest level is undefined, otherwise a positive integer.
*/
int get_nest_level() { return nest_level; }
#ifdef EMBEDDED_LIBRARY #ifdef EMBEDDED_LIBRARY
virtual void begin_dataset() {} virtual void begin_dataset() {}
#else #else
...@@ -2034,7 +2041,14 @@ class select_export :public select_to_file { ...@@ -2034,7 +2041,14 @@ class select_export :public select_to_file {
bool is_unsafe_field_sep; bool is_unsafe_field_sep;
bool fixed_row_size; bool fixed_row_size;
public: public:
select_export(sql_exchange *ex) :select_to_file(ex) {} /**
Creates a select_export to represent INTO OUTFILE <filename> with a
defined level of subquery nesting.
*/
select_export(sql_exchange *ex, uint nest_level_arg) :select_to_file(ex)
{
nest_level= nest_level_arg;
}
~select_export(); ~select_export();
int prepare(List<Item> &list, SELECT_LEX_UNIT *u); int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
bool send_data(List<Item> &items); bool send_data(List<Item> &items);
...@@ -2043,7 +2057,15 @@ public: ...@@ -2043,7 +2057,15 @@ public:
class select_dump :public select_to_file { class select_dump :public select_to_file {
public: public:
select_dump(sql_exchange *ex) :select_to_file(ex) {} /**
Creates a select_export to represent INTO DUMPFILE <filename> with a
defined level of subquery nesting.
*/
select_dump(sql_exchange *ex, uint nest_level_arg) :
select_to_file(ex)
{
nest_level= nest_level_arg;
}
int prepare(List<Item> &list, SELECT_LEX_UNIT *u); int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
bool send_data(List<Item> &items); bool send_data(List<Item> &items);
}; };
...@@ -2461,7 +2483,16 @@ class select_dumpvar :public select_result_interceptor { ...@@ -2461,7 +2483,16 @@ class select_dumpvar :public select_result_interceptor {
ha_rows row_count; ha_rows row_count;
public: public:
List<my_var> var_list; List<my_var> var_list;
select_dumpvar() { var_list.empty(); row_count= 0;} /**
Creates a select_dumpvar to represent INTO <variable> with a defined
level of subquery nesting.
*/
select_dumpvar(uint nest_level_arg)
{
var_list.empty();
row_count= 0;
nest_level= nest_level_arg;
}
~select_dumpvar() {} ~select_dumpvar() {}
int prepare(List<Item> &list, SELECT_LEX_UNIT *u); int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
bool send_data(List<Item> &items); bool send_data(List<Item> &items);
......
...@@ -6350,7 +6350,8 @@ procedure_item: ...@@ -6350,7 +6350,8 @@ procedure_item:
select_var_list_init: select_var_list_init:
{ {
LEX *lex=Lex; LEX *lex=Lex;
if (!lex->describe && (!(lex->result= new select_dumpvar()))) if (!lex->describe &&
(!(lex->result= new select_dumpvar(lex->nest_level))))
MYSQL_YYABORT; MYSQL_YYABORT;
} }
select_var_list select_var_list
...@@ -6424,7 +6425,7 @@ into_destination: ...@@ -6424,7 +6425,7 @@ into_destination:
LEX *lex= Lex; LEX *lex= Lex;
lex->uncacheable(UNCACHEABLE_SIDEEFFECT); lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
if (!(lex->exchange= new sql_exchange($2.str, 0)) || if (!(lex->exchange= new sql_exchange($2.str, 0)) ||
!(lex->result= new select_export(lex->exchange))) !(lex->result= new select_export(lex->exchange, lex->nest_level)))
MYSQL_YYABORT; MYSQL_YYABORT;
} }
opt_field_term opt_line_term opt_field_term opt_line_term
...@@ -6436,7 +6437,7 @@ into_destination: ...@@ -6436,7 +6437,7 @@ into_destination:
lex->uncacheable(UNCACHEABLE_SIDEEFFECT); lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
if (!(lex->exchange= new sql_exchange($2.str,1))) if (!(lex->exchange= new sql_exchange($2.str,1)))
MYSQL_YYABORT; MYSQL_YYABORT;
if (!(lex->result= new select_dump(lex->exchange))) if (!(lex->result= new select_dump(lex->exchange, lex->nest_level)))
MYSQL_YYABORT; MYSQL_YYABORT;
} }
} }
...@@ -9427,9 +9428,15 @@ union_list: ...@@ -9427,9 +9428,15 @@ union_list:
UNION_SYM union_option UNION_SYM union_option
{ {
LEX *lex=Lex; LEX *lex=Lex;
if (lex->result) if (lex->result &&
(lex->result->get_nest_level() == -1 ||
lex->result->get_nest_level() == lex->nest_level))
{ {
/* Only the last SELECT can have INTO...... */ /*
Only the last SELECT can have INTO unless the INTO and UNION
are at different nest levels. In version 5.1 and above, INTO
will onle be allowed at top level.
*/
my_error(ER_WRONG_USAGE, MYF(0), "UNION", "INTO"); my_error(ER_WRONG_USAGE, MYF(0), "UNION", "INTO");
MYSQL_YYABORT; MYSQL_YYABORT;
} }
......
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