Commit e0444ba4 authored by unknown's avatar unknown

Bug #27786:

When merging views into the enclosing statement
the ORDER BY clause of the view is merged to the
parent's ORDER BY clause.
However when the VIEW is merged into an UNION
branch the ORDER BY should be ignored. 
Use of ORDER BY for individual SELECT statements
implies nothing about the order in which the rows
appear in the final result because UNION by default
produces unordered set of rows.
Fixed by ignoring the ORDER BY clause from the merge
view when expanded in an UNION branch.


mysql-test/r/view.result:
  Bug #27786: test case
mysql-test/t/view.test:
  Bug #27786: test case
sql/sql_lex.h:
  Bug #27786: add a is_union() inlined function
  Returns true if the unit represents an UNION.
sql/sql_view.cc:
  Bug #27786: ignore ORDER BY in mergeable views when in UNION context
parent 579c2bff
...@@ -3319,4 +3319,39 @@ lgid clid ...@@ -3319,4 +3319,39 @@ lgid clid
2 YES 2 YES
DROP VIEW v1; DROP VIEW v1;
DROP table t1,t2; DROP table t1,t2;
CREATE TABLE t1 (a INT);
INSERT INTO t1 VALUES (1),(2),(3);
CREATE VIEW v1 AS SELECT a FROM t1 ORDER BY a;
SELECT * FROM t1 UNION SELECT * FROM v1;
a
1
2
3
EXPLAIN SELECT * FROM t1 UNION SELECT * FROM v1;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3
2 UNION t1 ALL NULL NULL NULL NULL 3
NULL UNION RESULT <union1,2> ALL NULL NULL NULL NULL NULL
SELECT * FROM v1 UNION SELECT * FROM t1;
a
1
2
3
EXPLAIN SELECT * FROM v1 UNION SELECT * FROM t1;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3
2 UNION t1 ALL NULL NULL NULL NULL 3
NULL UNION RESULT <union1,2> ALL NULL NULL NULL NULL NULL
SELECT * FROM t1 UNION SELECT * FROM v1 ORDER BY a;
a
1
2
3
EXPLAIN SELECT * FROM t1 UNION SELECT * FROM v1 ORDER BY a;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 3
2 UNION t1 ALL NULL NULL NULL NULL 3
NULL UNION RESULT <union1,2> ALL NULL NULL NULL NULL NULL Using filesort
DROP VIEW v1;
DROP TABLE t1;
End of 5.0 tests. End of 5.0 tests.
...@@ -3205,4 +3205,20 @@ SELECT * FROM v1; ...@@ -3205,4 +3205,20 @@ SELECT * FROM v1;
DROP VIEW v1; DROP VIEW v1;
DROP table t1,t2; DROP table t1,t2;
#
# Bug#27786: Inconsistent Operation Performing UNION On View With ORDER BY
#
CREATE TABLE t1 (a INT); INSERT INTO t1 VALUES (1),(2),(3);
CREATE VIEW v1 AS SELECT a FROM t1 ORDER BY a;
SELECT * FROM t1 UNION SELECT * FROM v1;
EXPLAIN SELECT * FROM t1 UNION SELECT * FROM v1;
SELECT * FROM v1 UNION SELECT * FROM t1;
EXPLAIN SELECT * FROM v1 UNION SELECT * FROM t1;
SELECT * FROM t1 UNION SELECT * FROM v1 ORDER BY a;
EXPLAIN SELECT * FROM t1 UNION SELECT * FROM v1 ORDER BY a;
DROP VIEW v1;
DROP TABLE t1;
--echo End of 5.0 tests. --echo End of 5.0 tests.
...@@ -468,6 +468,7 @@ public: ...@@ -468,6 +468,7 @@ public:
bool change_result(select_subselect *result, select_subselect *old_result); bool change_result(select_subselect *result, select_subselect *old_result);
void set_limit(st_select_lex *values); void set_limit(st_select_lex *values);
void set_thd(THD *thd_arg) { thd= thd_arg; } void set_thd(THD *thd_arg) { thd= thd_arg; }
inline bool is_union ();
friend void lex_start(THD *thd, uchar *buf, uint length); friend void lex_start(THD *thd, uchar *buf, uint length);
friend int subselect_union_engine::exec(); friend int subselect_union_engine::exec();
...@@ -700,6 +701,13 @@ public: ...@@ -700,6 +701,13 @@ public:
}; };
typedef class st_select_lex SELECT_LEX; typedef class st_select_lex SELECT_LEX;
inline bool st_select_lex_unit::is_union ()
{
return first_select()->next_select() &&
first_select()->next_select()->linkage == UNION_TYPE;
}
#define ALTER_ADD_COLUMN 1 #define ALTER_ADD_COLUMN 1
#define ALTER_DROP_COLUMN 2 #define ALTER_DROP_COLUMN 2
#define ALTER_CHANGE_COLUMN 4 #define ALTER_CHANGE_COLUMN 4
......
...@@ -1263,13 +1263,18 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table, ...@@ -1263,13 +1263,18 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table,
unit->slave= save_slave; // fix include_down initialisation unit->slave= save_slave; // fix include_down initialisation
} }
/*
We can safely ignore the VIEW's ORDER BY if we merge into union
branch, as order is not important there.
*/
if (!table->select_lex->master_unit()->is_union())
table->select_lex->order_list.push_back(&lex->select_lex.order_list);
/* /*
This SELECT_LEX will be linked in global SELECT_LEX list This SELECT_LEX will be linked in global SELECT_LEX list
to make it processed by mysql_handle_derived(), to make it processed by mysql_handle_derived(),
but it will not be included to SELECT_LEX tree, because it but it will not be included to SELECT_LEX tree, because it
will not be executed will not be executed
*/ */
table->select_lex->order_list.push_back(&lex->select_lex.order_list);
goto ok; goto ok;
} }
......
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