Below is the list of changes that have just been committed into a local
4.1 repository of igor. When igor 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
1.2462 06/04/20 22:15:38 igor@stripped +7 -0
Fixed bug #18767.
The bug caused wrong result sets for union constructs of the form
(SELECT ... ORDER BY order_list1 [LIMIT n]) ORDER BY order_list2.
For such queries order lists were concatenated and limit clause was
completely neglected.
sql/sql_yacc.yy
1.398 06/04/20 22:15:34 igor@stripped +21 -3
Fixed bug #18767.
Changed the condition at which a SELECT is treated as part of a UNION.
The SELECT in
(SELECT ... ORDER BY order_list1 [LIMIT n]) ORDER BY order_list2
now is handled in the same way as the first SELECT in a UNION
sequence. In the same way is handled the SELECT in
(SELECT ... LIMIT n) ORDER BY order list.
Yet if there is neither ORDER BY nor LIMIT in the single-select
union construct
(SELECT ...) ORDER BY order_list
then it is still handled as simple select with an order clause.
sql/sql_union.cc
1.145 06/04/20 22:15:34 igor@stripped +1 -1
Fixed bug #18767.
Changed the condition at which a SELECT is treated as part of a UNION.
The SELECT in
(SELECT ... ORDER BY order_list1 [LIMIT n]) ORDER BY order_list2
now is handled in the same way as the first SELECT in a UNION
sequence.
sql/sql_select.cc
1.452 06/04/20 22:15:34 igor@stripped +1 -1
Fixed bug #18767.
Changed the condition on which a SELECT is treated as part of a UNION.
The SELECT in
(SELECT ... ORDER BY order_list1 [LIMIT n]) ORDER BY order_list2
now is handled in the same way as the first SELECT in a UNION
sequence.
sql/sql_parse.cc
1.477 06/04/20 22:15:34 igor@stripped +57 -17
Fixed bug #18767.
Placed the code the created a fake SELECT_LEX into a separate function.
sql/sql_lex.h
1.188 06/04/20 22:15:34 igor@stripped +1 -0
Fixed bug #18767.
Placed the code the created a fake SELECT_LEX into a separate function.
mysql-test/t/order_by.test
1.34 06/04/20 22:15:34 igor@stripped +14 -0
Added a test case for bug #18767.
mysql-test/r/order_by.result
1.47 06/04/20 22:15:34 igor@stripped +32 -0
Added a test case for bug #18767.
# This is a BitKeeper patch. What follows are the unified diffs for the
# set of deltas contained in the patch. The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User: igor
# Host: rurik.mysql.com
# Root: /home/igor/dev/mysql-4.1-0
--- 1.187/sql/sql_lex.h 2005-10-11 16:32:13 -07:00
+++ 1.188/sql/sql_lex.h 2006-04-20 22:15:34 -07:00
@@ -400,6 +400,7 @@
bool check_updateable(char *db, char *table);
void print(String *str);
+ bool add_fake_select_lex(THD *thd);
ulong init_prepare_fake_select_lex(THD *thd);
int change_result(select_subselect *result, select_subselect *old_result);
inline bool is_prepared() { return prepared; }
--- 1.476/sql/sql_parse.cc 2006-02-21 08:52:15 -08:00
+++ 1.477/sql/sql_parse.cc 2006-04-20 22:15:34 -07:00
@@ -4189,23 +4189,9 @@
else
{
select_lex->include_neighbour(lex->current_select);
- SELECT_LEX_UNIT *unit= select_lex->master_unit();
- SELECT_LEX *fake= unit->fake_select_lex;
- if (!fake)
- {
- /*
- as far as we included SELECT_LEX for UNION unit should have
- fake SELECT_LEX for UNION processing
- */
- if (!(fake= unit->fake_select_lex= new(lex->thd->mem_root) SELECT_LEX()))
- return 1;
- fake->include_standalone(unit,
- (SELECT_LEX_NODE**)&unit->fake_select_lex);
- fake->select_number= INT_MAX;
- fake->make_empty_select();
- fake->linkage= GLOBAL_OPTIONS_TYPE;
- fake->select_limit= HA_POS_ERROR;
- }
+ if (!select_lex->master_unit()->fake_select_lex &&
+ select_lex->master_unit()->add_fake_select_lex(lex->thd))
+ return 1;
}
select_lex->master_unit()->global_parameters= select_lex;
@@ -4974,6 +4960,60 @@
DBUG_VOID_RETURN;
}
+
+/*
+ Create a fake SELECT_LEX for a unit
+
+ SYNOPSIS:
+ add_fake_select_lex()
+ thd thread handle
+
+ DESCRIPTION
+ The method create a fake SELECT_LEX object for a unit.
+ This object is created for any union construct containing a union
+ operation and also for any single select union construct of the form
+ (SELECT ... ORDER BY order_list [LIMIT n]) ORDER BY ...
+ or of the form
+ (SELECT ... ORDER BY LIMIT n) ORDER BY ...
+
+ NOTES
+ The object is used to retrieve rows from the temporary table
+ where the result on the union is obtained.
+
+ RETURN VALUES
+ 1 on failure to create the object
+ 0 on success
+*/
+
+bool st_select_lex_unit::add_fake_select_lex(THD *thd)
+{
+ SELECT_LEX *first_sl= first_select();
+ DBUG_ENTER("add_fake_select_lex");
+ DBUG_ASSERT(!fake_select_lex);
+
+ if (!(fake_select_lex= new (thd->mem_root) SELECT_LEX()))
+ DBUG_RETURN(1);
+ fake_select_lex->include_standalone(this,
+ (SELECT_LEX_NODE**)&fake_select_lex);
+ fake_select_lex->select_number= INT_MAX;
+ fake_select_lex->make_empty_select();
+ fake_select_lex->linkage= GLOBAL_OPTIONS_TYPE;
+ fake_select_lex->select_limit= HA_POS_ERROR;
+
+ if (!first_sl->next_select())
+ {
+ /*
+ This works only for
+ (SELECT ... ORDER BY list [LIMIT n]) ORDER BY order_list [LIMIT m],
+ (SELECT ... LIMIT n) ORDER BY order_list [LIMIT m]
+ just before the parser starts processing order_list
+ */
+ global_parameters= fake_select_lex;
+ fake_select_lex->no_table_names_allowed= 1;
+ thd->lex->current_select= fake_select_lex;
+ }
+ DBUG_RETURN(0);
+}
void add_join_on(TABLE_LIST *b,Item *expr)
{
--- 1.451/sql/sql_select.cc 2006-04-12 11:54:11 -07:00
+++ 1.452/sql/sql_select.cc 2006-04-20 22:15:34 -07:00
@@ -171,7 +171,7 @@
register SELECT_LEX *select_lex = &lex->select_lex;
DBUG_ENTER("handle_select");
- if (select_lex->next_select())
+ if (select_lex->next_select() || select_lex->master_unit()->fake_select_lex)
res=mysql_union(thd, lex, result, &lex->unit);
else
res= mysql_select(thd, &select_lex->ref_pointer_array,
--- 1.397/sql/sql_yacc.yy 2006-03-06 09:26:23 -08:00
+++ 1.398/sql/sql_yacc.yy 2006-04-20 22:15:34 -07:00
@@ -3790,15 +3790,33 @@
ORDER_SYM BY
{
LEX *lex=Lex;
- if (lex->current_select->linkage != GLOBAL_OPTIONS_TYPE &&
- lex->current_select->olap !=
- UNSPECIFIED_OLAP_TYPE)
+ SELECT_LEX *sel= lex->current_select;
+ SELECT_LEX_UNIT *unit= sel-> master_unit();
+ if (sel->linkage != GLOBAL_OPTIONS_TYPE &&
+ sel->olap != UNSPECIFIED_OLAP_TYPE)
{
net_printf(lex->thd, ER_WRONG_USAGE,
"CUBE/ROLLUP",
"ORDER BY");
YYABORT;
}
+ if (lex->sql_command != SQLCOM_ALTER_TABLE && !unit->fake_select_lex)
+ {
+ /*
+ A query of the of the form (SELECT ...) ORDER BY order_list is
+ executed in the same way as the query
+ SELECT ... ORDER BY order_list
+ unless the SELECT construct contains ORDER BY or LIMIT clauses.
+ Otherwise we create a fake SELECT_LEX if it has not been created
+ yet.
+ */
+ SELECT_LEX *first_sl= unit->first_select();
+ if (!first_sl->next_select() &&
+ (first_sl->order_list.elements ||
+ first_sl->select_limit != HA_POS_ERROR) &&
+ unit->add_fake_select_lex(lex->thd))
+ YYABORT;
+ }
} order_list;
order_list:
--- 1.144/sql/sql_union.cc 2005-08-08 14:13:46 -07:00
+++ 1.145/sql/sql_union.cc 2006-04-20 22:15:34 -07:00
@@ -184,7 +184,7 @@
thd_arg->lex->current_select= sl= first_select= first_select_in_union();
found_rows_for_union= first_select->options & OPTION_FOUND_ROWS;
- is_union= test(first_select->next_select());
+ is_union= test(first_select->next_select() || fake_select_lex);
/* Global option */
--- 1.46/mysql-test/r/order_by.result 2005-01-28 19:49:45 -08:00
+++ 1.47/mysql-test/r/order_by.result 2006-04-20 22:15:34 -07:00
@@ -788,3 +788,35 @@
2
2
DROP TABLE t1;
+CREATE TABLE t1 (a int, b int);
+INSERT INTO t1 VALUES (1,30), (2,20), (1,10), (2,30), (1,20), (2,10);
+(SELECT b,a FROM t1 ORDER BY a,b) ORDER BY b,a;
+b a
+10 1
+10 2
+20 1
+20 2
+30 1
+30 2
+(SELECT b FROM t1 ORDER BY b DESC) ORDER BY b ASC;
+b
+10
+10
+20
+20
+30
+30
+(SELECT b,a FROM t1 ORDER BY b,a) ORDER BY a,b;
+b a
+10 1
+20 1
+30 1
+10 2
+20 2
+30 2
+(SELECT b,a FROM t1 ORDER by b,a LIMIT 3) ORDER by a,b;
+b a
+10 1
+20 1
+10 2
+DROP TABLE t1;
--- 1.33/mysql-test/t/order_by.test 2005-07-27 17:21:46 -07:00
+++ 1.34/mysql-test/t/order_by.test 2006-04-20 22:15:34 -07:00
@@ -545,4 +545,18 @@
(SELECT a FROM t1) ORDER BY a;
DROP TABLE t1;
+#
+# Bug #18767: global ORDER BY applied to a SELECT with ORDER BY either was
+# ignored or 'concatened' to the latter.
+
+CREATE TABLE t1 (a int, b int);
+INSERT INTO t1 VALUES (1,30), (2,20), (1,10), (2,30), (1,20), (2,10);
+
+(SELECT b,a FROM t1 ORDER BY a,b) ORDER BY b,a;
+(SELECT b FROM t1 ORDER BY b DESC) ORDER BY b ASC;
+(SELECT b,a FROM t1 ORDER BY b,a) ORDER BY a,b;
+(SELECT b,a FROM t1 ORDER by b,a LIMIT 3) ORDER by a,b;
+
+DROP TABLE t1;
+
# End of 4.1 tests
| Thread |
|---|
| • bk commit into 4.1 tree (igor:1.2462) BUG#18767 | igor | 21 Apr |