Below is the list of changes that have just been committed into a local
5.0 repository of martin. When martin does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html
ChangeSet@stripped, 2007-12-10 09:04:31+01:00, mhansson@stripped +4 -0
Bug #32858: Erro: "Incorrect usage of UNION and INTO" does not take
subselects into account
It is forbidden to use the SELECT INTO construction inside UNION statements
unless on the last SELECT of the union. The parser records whether it
has seen INTO or not when parsing a UNION statement. But if the INTO was
legally used in an outer query, an error is thrown if UNION is seen in a
subquery. Fixed in 5.0 by remembering the nesting level of INTO tokens and
mitigate the error unless it collides with the UNION.
mysql-test/r/union.result@stripped, 2007-12-10 09:04:29+01:00, mhansson@stripped +18 -0
Bug#32858: Test result
mysql-test/t/union.test@stripped, 2007-12-10 09:04:29+01:00, mhansson@stripped +30 -0
Bug#32858: Test case
sql/sql_class.h@stripped, 2007-12-10 09:04:29+01:00, mhansson@stripped +18 -1
Bug#32858: Added virtual property nest_level to select_result class, implemented
in subclass select_dumpvar.
sql/sql_yacc.yy@stripped, 2007-12-10 09:04:30+01:00, mhansson@stripped +14 -7
Bug#32858: The fix.
diff -Nrup a/mysql-test/r/union.result b/mysql-test/r/union.result
--- a/mysql-test/r/union.result 2007-03-22 14:58:37 +01:00
+++ b/mysql-test/r/union.result 2007-12-10 09:04:29 +01:00
@@ -1389,4 +1389,22 @@ select @var;
1
(select 2) union (select 1 into @var);
ERROR 42000: Result consisted of more than one row
+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 FROM (
+SELECT a FROM t1
+UNION
+SELECT a INTO @v FROM t1
+) alias;
+SELECT a FROM t1 UNION SELECT a INTO @v FROM t1;
+SELECT a INTO @v FROM t1 UNION SELECT a FROM t1;
+ERROR HY000: Incorrect usage of UNION and INTO
+DROP TABLE t1;
End of 5.0 tests
diff -Nrup a/mysql-test/t/union.test b/mysql-test/t/union.test
--- a/mysql-test/t/union.test 2007-03-21 19:53:51 +01:00
+++ b/mysql-test/t/union.test 2007-12-10 09:04:29 +01:00
@@ -877,4 +877,34 @@ DROP TABLE t1;
select @var;
--error 1172
(select 2) union (select 1 into @var);
+
+#
+# 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;
+
+# 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 t1 UNION SELECT a INTO @v FROM t1;
+--error ER_WRONG_USAGE
+SELECT a INTO @v FROM t1 UNION SELECT a FROM t1;
+
+DROP TABLE t1;
+
--echo End of 5.0 tests
+
diff -Nrup a/sql/sql_class.h b/sql/sql_class.h
--- a/sql/sql_class.h 2007-09-21 10:06:30 +02:00
+++ b/sql/sql_class.h 2007-12-10 09:04:29 +01:00
@@ -1927,6 +1927,12 @@ public:
*/
virtual void cleanup();
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.
+ */
+ virtual int get_nest_level() { return -1; }
#ifdef EMBEDDED_LIBRARY
virtual void begin_dataset() {}
#else
@@ -2420,9 +2426,20 @@ public:
class select_dumpvar :public select_result_interceptor {
ha_rows row_count;
+ uint nest_level;
public:
List<my_var> var_list;
- select_dumpvar() { var_list.empty(); row_count= 0;}
+ select_dumpvar() : nest_level(0) { 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) : nest_level(nest_level_arg)
+ {
+ var_list.empty();
+ row_count= 0;
+ }
+ int get_nest_level() { return (int)nest_level; }
~select_dumpvar() {}
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
bool send_data(List<Item> &items);
diff -Nrup a/sql/sql_yacc.yy b/sql/sql_yacc.yy
--- a/sql/sql_yacc.yy 2007-10-15 15:40:57 +02:00
+++ b/sql/sql_yacc.yy 2007-12-10 09:04:30 +01:00
@@ -6356,7 +6356,8 @@ procedure_item:
select_var_list_init:
{
LEX *lex=Lex;
- if (!lex->describe && (!(lex->result= new select_dumpvar())))
+ if (!lex->describe &&
+ (!(lex->result= new select_dumpvar(lex->nest_level))))
MYSQL_YYABORT;
}
select_var_list
@@ -9421,12 +9422,18 @@ union_list:
UNION_SYM union_option
{
LEX *lex=Lex;
- if (lex->result)
- {
- /* Only the last SELECT can have INTO...... */
- my_error(ER_WRONG_USAGE, MYF(0), "UNION", "INTO");
- MYSQL_YYABORT;
- }
+ if (lex->result &&
+ (lex->result->get_nest_level() == -1 ||
+ lex->result->get_nest_level() == lex->nest_level))
+ {
+ /*
+ 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)
{
my_parse_error(ER(ER_SYNTAX_ERROR));
| Thread |
|---|
| • bk commit into 5.0 tree (mhansson:1.2546) BUG#32858 | mhansson | 10 Dec |