Merge rurik.mysql.com:/home/igor/dev/mysql-4.1-0
into rurik.mysql.com:/home/igor/dev/mysql-5.0-0 mysql-test/r/order_by.result: Auto merged sql/sql_select.cc: Auto merged sql/sql_yacc.yy: Auto merged mysql-test/t/func_gconcat.test: Manual merge mysql-test/t/order_by.test: Manual merge sql/sql_lex.h: Manual merge sql/sql_parse.cc: Manual merge sql/sql_union.cc: Manual merge
This commit is contained in:
commit
103fbcee45
@ -820,3 +820,35 @@ a
|
|||||||
2
|
2
|
||||||
2
|
2
|
||||||
DROP TABLE t1;
|
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;
|
||||||
|
@ -398,6 +398,16 @@ select f1, group_concat(f1+1) from t1 group by f1 with rollup;
|
|||||||
select count(distinct (f1+1)) from t1 group by f1 with rollup;
|
select count(distinct (f1+1)) from t1 group by f1 with rollup;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Bug#14169 type of group_concat() result changed to blob if tmp_table was used
|
||||||
|
#
|
||||||
|
create table t1 (f1 int unsigned, f2 varchar(255));
|
||||||
|
insert into t1 values (1,repeat('a',255)),(2,repeat('b',255));
|
||||||
|
--enable_metadata
|
||||||
|
select f2,group_concat(f1) from t1 group by f2;
|
||||||
|
--disable_metadata
|
||||||
|
drop table t1;
|
||||||
|
|
||||||
# End of 4.1 tests
|
# End of 4.1 tests
|
||||||
|
|
||||||
#
|
#
|
||||||
|
@ -563,4 +563,18 @@ SELECT a FROM t1 ORDER BY a;
|
|||||||
(SELECT a FROM t1) ORDER BY a;
|
(SELECT a FROM t1) ORDER BY a;
|
||||||
DROP TABLE t1;
|
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
|
# End of 4.1 tests
|
||||||
|
@ -454,6 +454,7 @@ public:
|
|||||||
|
|
||||||
void print(String *str);
|
void print(String *str);
|
||||||
|
|
||||||
|
bool add_fake_select_lex(THD *thd);
|
||||||
void init_prepare_fake_select_lex(THD *thd);
|
void init_prepare_fake_select_lex(THD *thd);
|
||||||
inline bool is_prepared() { return prepared; }
|
inline bool is_prepared() { return prepared; }
|
||||||
bool change_result(select_subselect *result, select_subselect *old_result);
|
bool change_result(select_subselect *result, select_subselect *old_result);
|
||||||
|
@ -5544,48 +5544,17 @@ mysql_new_select(LEX *lex, bool move_down)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Name_resolution_context *outer_context;
|
|
||||||
if (lex->current_select->order_list.first && !lex->current_select->braces)
|
if (lex->current_select->order_list.first && !lex->current_select->braces)
|
||||||
{
|
{
|
||||||
my_error(ER_WRONG_USAGE, MYF(0), "UNION", "ORDER BY");
|
my_error(ER_WRONG_USAGE, MYF(0), "UNION", "ORDER BY");
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
}
|
}
|
||||||
select_lex->include_neighbour(lex->current_select);
|
select_lex->include_neighbour(lex->current_select);
|
||||||
/*
|
|
||||||
we are not sure that we have one level of SELECTs above, so we take
|
|
||||||
outer_context address from first select of unit
|
|
||||||
*/
|
|
||||||
outer_context=
|
|
||||||
select_lex->master_unit()->first_select()->context.outer_context;
|
|
||||||
SELECT_LEX_UNIT *unit= select_lex->master_unit();
|
SELECT_LEX_UNIT *unit= select_lex->master_unit();
|
||||||
SELECT_LEX *fake= unit->fake_select_lex;
|
if (!unit->fake_select_lex && unit->add_fake_select_lex(lex->thd))
|
||||||
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 (thd->mem_root) SELECT_LEX()))
|
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
fake->include_standalone(unit,
|
select_lex->context.outer_context=
|
||||||
(SELECT_LEX_NODE**)&unit->fake_select_lex);
|
unit->first_select()->context.outer_context;
|
||||||
fake->select_number= INT_MAX;
|
|
||||||
fake->parent_lex= lex; /* Used in init_query. */
|
|
||||||
fake->make_empty_select();
|
|
||||||
fake->linkage= GLOBAL_OPTIONS_TYPE;
|
|
||||||
fake->select_limit= 0;
|
|
||||||
|
|
||||||
fake->context.outer_context= outer_context;
|
|
||||||
/* allow item list resolving in fake select for ORDER BY */
|
|
||||||
fake->context.resolve_in_select_list= TRUE;
|
|
||||||
fake->context.select_lex= fake;
|
|
||||||
/*
|
|
||||||
Remove the name resolution context of the fake select from the
|
|
||||||
context stack.
|
|
||||||
*/
|
|
||||||
lex->pop_context();
|
|
||||||
}
|
|
||||||
select_lex->context.outer_context= outer_context;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
select_lex->master_unit()->global_parameters= select_lex;
|
select_lex->master_unit()->global_parameters= select_lex;
|
||||||
@ -6357,6 +6326,67 @@ void st_select_lex::set_lock_for_tables(thr_lock_type lock_type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
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= 0;
|
||||||
|
|
||||||
|
fake_select_lex->context.outer_context= first_sl->context.outer_context;
|
||||||
|
/* allow item list resolving in fake select for ORDER BY */
|
||||||
|
fake_select_lex->context.resolve_in_select_list= TRUE;
|
||||||
|
fake_select_lex->context.select_lex= fake_select_lex;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
thd->lex->pop_context();
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Push a new name resolution context for a JOIN ... ON clause to the
|
Push a new name resolution context for a JOIN ... ON clause to the
|
||||||
context stack of a query block.
|
context stack of a query block.
|
||||||
|
@ -224,7 +224,7 @@ bool handle_select(THD *thd, LEX *lex, select_result *result,
|
|||||||
register SELECT_LEX *select_lex = &lex->select_lex;
|
register SELECT_LEX *select_lex = &lex->select_lex;
|
||||||
DBUG_ENTER("handle_select");
|
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, setup_tables_done_option);
|
res= mysql_union(thd, lex, result, &lex->unit, setup_tables_done_option);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -202,7 +202,7 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
|
|||||||
|
|
||||||
thd_arg->lex->current_select= sl= first_sl;
|
thd_arg->lex->current_select= sl= first_sl;
|
||||||
found_rows_for_union= first_sl->options & OPTION_FOUND_ROWS;
|
found_rows_for_union= first_sl->options & OPTION_FOUND_ROWS;
|
||||||
is_union= test(first_sl->next_select());
|
is_union= test(first_select->next_select() || fake_select_lex);
|
||||||
|
|
||||||
/* Global option */
|
/* Global option */
|
||||||
|
|
||||||
|
@ -5697,14 +5697,32 @@ order_clause:
|
|||||||
ORDER_SYM BY
|
ORDER_SYM BY
|
||||||
{
|
{
|
||||||
LEX *lex=Lex;
|
LEX *lex=Lex;
|
||||||
if (lex->current_select->linkage != GLOBAL_OPTIONS_TYPE &&
|
SELECT_LEX *sel= lex->current_select;
|
||||||
lex->current_select->olap !=
|
SELECT_LEX_UNIT *unit= sel-> master_unit();
|
||||||
UNSPECIFIED_OLAP_TYPE)
|
if (sel->linkage != GLOBAL_OPTIONS_TYPE &&
|
||||||
|
sel->olap != UNSPECIFIED_OLAP_TYPE)
|
||||||
{
|
{
|
||||||
my_error(ER_WRONG_USAGE, MYF(0),
|
my_error(ER_WRONG_USAGE, MYF(0),
|
||||||
"CUBE/ROLLUP", "ORDER BY");
|
"CUBE/ROLLUP", "ORDER BY");
|
||||||
YYABORT;
|
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;
|
||||||
|
|
||||||
order_list:
|
order_list:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user