Merge mhansson@bk-internal:/home/bk/mysql-5.0-opt
into linux-st28.site:/home/martin/mysql/src/bug32858/my50-bug32858-push sql/sql_class.cc: Auto merged sql/sql_class.h: Auto merged sql/sql_yacc.yy: Auto merged mysql-test/r/union.result: Bug#32858: Manual merge mysql-test/t/union.test: Bug#32858: Manual merge
This commit is contained in:
commit
30b17b997f
@ -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;
|
|||||||
|
|
||||||
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()
|
|||||||
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 {
|
|||||||
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:
|
|||||||
*/
|
*/
|
||||||
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 {
|
|||||||
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:
|
|||||||
|
|
||||||
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 {
|
|||||||
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:
|
|||||||
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:
|
|||||||
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:
|
|||||||
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,12 +9428,18 @@ 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 ||
|
||||||
/* Only the last SELECT can have INTO...... */
|
lex->result->get_nest_level() == lex->nest_level))
|
||||||
my_error(ER_WRONG_USAGE, MYF(0), "UNION", "INTO");
|
{
|
||||||
MYSQL_YYABORT;
|
/*
|
||||||
}
|
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");
|
||||||
|
MYSQL_YYABORT;
|
||||||
|
}
|
||||||
if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE)
|
if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE)
|
||||||
{
|
{
|
||||||
my_parse_error(ER(ER_SYNTAX_ERROR));
|
my_parse_error(ER(ER_SYNTAX_ERROR));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user