mirror of
https://github.com/MariaDB/server.git
synced 2026-05-04 14:15:33 +02:00
Merge gkodinov@bk-internal.mysql.com:/home/bk/mysql-5.0-opt
into rakia.(none):/home/kgeorge/mysql/autopush/B14654-5.0-opt mysql-test/r/subselect.result: Auto merged mysql-test/t/subselect.test: Auto merged sql/sql_yacc.yy: Auto merged
This commit is contained in:
commit
a0e959271d
3 changed files with 123 additions and 70 deletions
|
|
@ -3368,3 +3368,28 @@ ORDER BY t1.t DESC LIMIT 1);
|
||||||
i1 i2 t i1 i2 t
|
i1 i2 t i1 i2 t
|
||||||
24 1 2005-05-27 12:40:30 24 1 2006-06-20 12:29:40
|
24 1 2005-05-27 12:40:30 24 1 2006-06-20 12:29:40
|
||||||
DROP TABLE t1, t2;
|
DROP TABLE t1, t2;
|
||||||
|
CREATE TABLE t1 (i INT);
|
||||||
|
(SELECT i FROM t1) UNION (SELECT i FROM t1);
|
||||||
|
i
|
||||||
|
SELECT sql_no_cache * FROM t1 WHERE NOT EXISTS
|
||||||
|
(
|
||||||
|
(SELECT i FROM t1) UNION
|
||||||
|
(SELECT i FROM t1)
|
||||||
|
);
|
||||||
|
i
|
||||||
|
SELECT * FROM t1
|
||||||
|
WHERE NOT EXISTS (((SELECT i FROM t1) UNION (SELECT i FROM t1)));
|
||||||
|
i
|
||||||
|
explain select ((select t11.i from t1 t11) union (select t12.i from t1 t12))
|
||||||
|
from t1;
|
||||||
|
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'union (select t12.i from t1 t12))
|
||||||
|
from t1' at line 1
|
||||||
|
explain select * from t1 where not exists
|
||||||
|
((select t11.i from t1 t11) union (select t12.i from t1 t12));
|
||||||
|
id select_type table type possible_keys key key_len ref rows Extra
|
||||||
|
1 PRIMARY t1 system NULL NULL NULL NULL 0 const row not found
|
||||||
|
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL No tables used
|
||||||
|
3 SUBQUERY NULL NULL NULL NULL NULL NULL NULL no matching row in const table
|
||||||
|
4 UNION t12 system NULL NULL NULL NULL 0 const row not found
|
||||||
|
NULL UNION RESULT <union2,4> ALL NULL NULL NULL NULL NULL
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
|
||||||
|
|
@ -2280,3 +2280,29 @@ SELECT * FROM t1,t2
|
||||||
ORDER BY t1.t DESC LIMIT 1);
|
ORDER BY t1.t DESC LIMIT 1);
|
||||||
|
|
||||||
DROP TABLE t1, t2;
|
DROP TABLE t1, t2;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Bug#14654 : Cannot select from the same table twice within a UNION
|
||||||
|
# statement
|
||||||
|
#
|
||||||
|
CREATE TABLE t1 (i INT);
|
||||||
|
|
||||||
|
(SELECT i FROM t1) UNION (SELECT i FROM t1);
|
||||||
|
SELECT sql_no_cache * FROM t1 WHERE NOT EXISTS
|
||||||
|
(
|
||||||
|
(SELECT i FROM t1) UNION
|
||||||
|
(SELECT i FROM t1)
|
||||||
|
);
|
||||||
|
|
||||||
|
SELECT * FROM t1
|
||||||
|
WHERE NOT EXISTS (((SELECT i FROM t1) UNION (SELECT i FROM t1)));
|
||||||
|
|
||||||
|
#TODO:not supported
|
||||||
|
--error 1064
|
||||||
|
explain select ((select t11.i from t1 t11) union (select t12.i from t1 t12))
|
||||||
|
from t1;
|
||||||
|
#supported
|
||||||
|
explain select * from t1 where not exists
|
||||||
|
((select t11.i from t1 t11) union (select t12.i from t1 t12));
|
||||||
|
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
|
||||||
146
sql/sql_yacc.yy
146
sql/sql_yacc.yy
|
|
@ -725,8 +725,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
|
||||||
predicate bit_expr bit_term bit_factor value_expr term factor
|
predicate bit_expr bit_term bit_factor value_expr term factor
|
||||||
table_wild simple_expr udf_expr
|
table_wild simple_expr udf_expr
|
||||||
expr_or_default set_expr_or_default interval_expr
|
expr_or_default set_expr_or_default interval_expr
|
||||||
param_marker singlerow_subselect singlerow_subselect_init
|
param_marker geometry_function
|
||||||
exists_subselect exists_subselect_init geometry_function
|
|
||||||
signed_literal now_or_signed_literal opt_escape
|
signed_literal now_or_signed_literal opt_escape
|
||||||
sp_opt_default
|
sp_opt_default
|
||||||
simple_ident_nospvar simple_ident_q
|
simple_ident_nospvar simple_ident_q
|
||||||
|
|
@ -791,7 +790,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
|
||||||
|
|
||||||
%type <variable> internal_variable_name
|
%type <variable> internal_variable_name
|
||||||
|
|
||||||
%type <select_lex> in_subselect in_subselect_init
|
%type <select_lex> subselect subselect_init
|
||||||
get_select_lex
|
get_select_lex
|
||||||
|
|
||||||
%type <boolfunc2creator> comp_op
|
%type <boolfunc2creator> comp_op
|
||||||
|
|
@ -3914,12 +3913,14 @@ select_paren:
|
||||||
yyerror(ER(ER_SYNTAX_ERROR));
|
yyerror(ER(ER_SYNTAX_ERROR));
|
||||||
YYABORT;
|
YYABORT;
|
||||||
}
|
}
|
||||||
if (sel->linkage == UNION_TYPE &&
|
if (sel->linkage == UNION_TYPE &&
|
||||||
!sel->master_unit()->first_select()->braces)
|
!sel->master_unit()->first_select()->braces &&
|
||||||
{
|
sel->master_unit()->first_select()->linkage ==
|
||||||
yyerror(ER(ER_SYNTAX_ERROR));
|
UNION_TYPE)
|
||||||
YYABORT;
|
{
|
||||||
}
|
yyerror(ER(ER_SYNTAX_ERROR));
|
||||||
|
YYABORT;
|
||||||
|
}
|
||||||
/* select in braces, can't contain global parameters */
|
/* select in braces, can't contain global parameters */
|
||||||
if (sel->master_unit()->fake_select_lex)
|
if (sel->master_unit()->fake_select_lex)
|
||||||
sel->master_unit()->global_parameters=
|
sel->master_unit()->global_parameters=
|
||||||
|
|
@ -4177,37 +4178,37 @@ bool_pri:
|
||||||
| bool_pri EQUAL_SYM predicate { $$= new Item_func_equal($1,$3); }
|
| bool_pri EQUAL_SYM predicate { $$= new Item_func_equal($1,$3); }
|
||||||
| bool_pri comp_op predicate %prec EQ
|
| bool_pri comp_op predicate %prec EQ
|
||||||
{ $$= (*$2)(0)->create($1,$3); }
|
{ $$= (*$2)(0)->create($1,$3); }
|
||||||
| bool_pri comp_op all_or_any in_subselect %prec EQ
|
| bool_pri comp_op all_or_any '(' subselect ')' %prec EQ
|
||||||
{ $$= all_any_subquery_creator($1, $2, $3, $4); }
|
{ $$= all_any_subquery_creator($1, $2, $3, $5); }
|
||||||
| predicate ;
|
| predicate ;
|
||||||
|
|
||||||
predicate:
|
predicate:
|
||||||
bit_expr IN_SYM '(' expr_list ')'
|
bit_expr IN_SYM '(' subselect ')'
|
||||||
{
|
{ $$= new Item_in_subselect($1, $4); }
|
||||||
if ($4->elements == 1)
|
| bit_expr not IN_SYM '(' subselect ')'
|
||||||
$$= new Item_func_eq($1, $4->head());
|
{ $$= negate_expression(YYTHD, new Item_in_subselect($1, $5)); }
|
||||||
else
|
| bit_expr IN_SYM '(' expr ')'
|
||||||
{
|
|
||||||
$4->push_front($1);
|
|
||||||
$$= new Item_func_in(*$4);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
| bit_expr not IN_SYM '(' expr_list ')'
|
|
||||||
{
|
{
|
||||||
if ($5->elements == 1)
|
$$= new Item_func_eq($1, $4);
|
||||||
$$= new Item_func_ne($1, $5->head());
|
}
|
||||||
else
|
| bit_expr IN_SYM '(' expr ',' expr_list ')'
|
||||||
{
|
{
|
||||||
$5->push_front($1);
|
$6->push_front($4);
|
||||||
Item_func_in *item = new Item_func_in(*$5);
|
$6->push_front($1);
|
||||||
|
$$= new Item_func_in(*$6);
|
||||||
|
}
|
||||||
|
| bit_expr not IN_SYM '(' expr ')'
|
||||||
|
{
|
||||||
|
$$= new Item_func_ne($1, $5);
|
||||||
|
}
|
||||||
|
| bit_expr not IN_SYM '(' expr ',' expr_list ')'
|
||||||
|
{
|
||||||
|
$7->push_front($5);
|
||||||
|
$7->push_front($1);
|
||||||
|
Item_func_in *item = new Item_func_in(*$7);
|
||||||
item->negate();
|
item->negate();
|
||||||
$$= item;
|
$$= item;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
| bit_expr IN_SYM in_subselect
|
|
||||||
{ $$= new Item_in_subselect($1, $3); }
|
|
||||||
| bit_expr not IN_SYM in_subselect
|
|
||||||
{ $$= negate_expression(YYTHD, new Item_in_subselect($1, $4)); }
|
|
||||||
| bit_expr BETWEEN_SYM bit_expr AND_SYM predicate
|
| bit_expr BETWEEN_SYM bit_expr AND_SYM predicate
|
||||||
{ $$= new Item_func_between($1,$3,$5); }
|
{ $$= new Item_func_between($1,$3,$5); }
|
||||||
| bit_expr not BETWEEN_SYM bit_expr AND_SYM predicate
|
| bit_expr not BETWEEN_SYM bit_expr AND_SYM predicate
|
||||||
|
|
@ -4329,6 +4330,10 @@ simple_expr:
|
||||||
| '-' simple_expr %prec NEG { $$= new Item_func_neg($2); }
|
| '-' simple_expr %prec NEG { $$= new Item_func_neg($2); }
|
||||||
| '~' simple_expr %prec NEG { $$= new Item_func_bit_neg($2); }
|
| '~' simple_expr %prec NEG { $$= new Item_func_bit_neg($2); }
|
||||||
| not2 simple_expr %prec NEG { $$= negate_expression(YYTHD, $2); }
|
| not2 simple_expr %prec NEG { $$= negate_expression(YYTHD, $2); }
|
||||||
|
| '(' subselect ')'
|
||||||
|
{
|
||||||
|
$$= new Item_singlerow_subselect($2);
|
||||||
|
}
|
||||||
| '(' expr ')' { $$= $2; }
|
| '(' expr ')' { $$= $2; }
|
||||||
| '(' expr ',' expr_list ')'
|
| '(' expr ',' expr_list ')'
|
||||||
{
|
{
|
||||||
|
|
@ -4340,8 +4345,10 @@ simple_expr:
|
||||||
$5->push_front($3);
|
$5->push_front($3);
|
||||||
$$= new Item_row(*$5);
|
$$= new Item_row(*$5);
|
||||||
}
|
}
|
||||||
| EXISTS exists_subselect { $$= $2; }
|
| EXISTS '(' subselect ')'
|
||||||
| singlerow_subselect { $$= $1; }
|
{
|
||||||
|
$$= new Item_exists_subselect($3);
|
||||||
|
}
|
||||||
| '{' ident expr '}' { $$= $3; }
|
| '{' ident expr '}' { $$= $3; }
|
||||||
| MATCH ident_list_arg AGAINST '(' bit_expr fulltext_options ')'
|
| MATCH ident_list_arg AGAINST '(' bit_expr fulltext_options ')'
|
||||||
{ $2->push_front($5);
|
{ $2->push_front($5);
|
||||||
|
|
@ -8867,49 +8874,38 @@ union_option:
|
||||||
| ALL { $$=0; }
|
| ALL { $$=0; }
|
||||||
;
|
;
|
||||||
|
|
||||||
singlerow_subselect:
|
subselect:
|
||||||
subselect_start singlerow_subselect_init
|
SELECT_SYM subselect_start subselect_init subselect_end
|
||||||
subselect_end
|
{
|
||||||
{
|
$$= $3;
|
||||||
$$= $2;
|
}
|
||||||
};
|
| '(' subselect_start subselect ')'
|
||||||
|
{
|
||||||
|
LEX *lex= Lex;
|
||||||
|
THD *thd= YYTHD;
|
||||||
|
/*
|
||||||
|
note that a local variable can't be used for
|
||||||
|
$3 as it's used in local variable construction
|
||||||
|
and some compilers can't guarnatee the order
|
||||||
|
in which the local variables are initialized.
|
||||||
|
*/
|
||||||
|
List_iterator<Item> it($3->item_list);
|
||||||
|
Item *item;
|
||||||
|
/*
|
||||||
|
we must fill the items list for the "derived table".
|
||||||
|
*/
|
||||||
|
while ((item= it++))
|
||||||
|
add_item_to_list(thd, item);
|
||||||
|
}
|
||||||
|
union_clause subselect_end { $$= $3; };
|
||||||
|
|
||||||
singlerow_subselect_init:
|
subselect_init:
|
||||||
select_init2
|
|
||||||
{
|
|
||||||
$$= new Item_singlerow_subselect(Lex->current_select->
|
|
||||||
master_unit()->first_select());
|
|
||||||
};
|
|
||||||
|
|
||||||
exists_subselect:
|
|
||||||
subselect_start exists_subselect_init
|
|
||||||
subselect_end
|
|
||||||
{
|
|
||||||
$$= $2;
|
|
||||||
};
|
|
||||||
|
|
||||||
exists_subselect_init:
|
|
||||||
select_init2
|
|
||||||
{
|
|
||||||
$$= new Item_exists_subselect(Lex->current_select->master_unit()->
|
|
||||||
first_select());
|
|
||||||
};
|
|
||||||
|
|
||||||
in_subselect:
|
|
||||||
subselect_start in_subselect_init
|
|
||||||
subselect_end
|
|
||||||
{
|
|
||||||
$$= $2;
|
|
||||||
};
|
|
||||||
|
|
||||||
in_subselect_init:
|
|
||||||
select_init2
|
select_init2
|
||||||
{
|
{
|
||||||
$$= Lex->current_select->master_unit()->first_select();
|
$$= Lex->current_select->master_unit()->first_select();
|
||||||
};
|
};
|
||||||
|
|
||||||
subselect_start:
|
subselect_start:
|
||||||
'(' SELECT_SYM
|
|
||||||
{
|
{
|
||||||
LEX *lex=Lex;
|
LEX *lex=Lex;
|
||||||
if (lex->sql_command == (int)SQLCOM_HA_READ ||
|
if (lex->sql_command == (int)SQLCOM_HA_READ ||
|
||||||
|
|
@ -8918,12 +8914,18 @@ subselect_start:
|
||||||
yyerror(ER(ER_SYNTAX_ERROR));
|
yyerror(ER(ER_SYNTAX_ERROR));
|
||||||
YYABORT;
|
YYABORT;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
we are making a "derived table" for the parenthesis
|
||||||
|
as we need to have a lex level to fit the union
|
||||||
|
after the parenthesis, e.g.
|
||||||
|
(SELECT .. ) UNION ... becomes
|
||||||
|
SELECT * FROM ((SELECT ...) UNION ...)
|
||||||
|
*/
|
||||||
if (mysql_new_select(Lex, 1))
|
if (mysql_new_select(Lex, 1))
|
||||||
YYABORT;
|
YYABORT;
|
||||||
};
|
};
|
||||||
|
|
||||||
subselect_end:
|
subselect_end:
|
||||||
')'
|
|
||||||
{
|
{
|
||||||
LEX *lex=Lex;
|
LEX *lex=Lex;
|
||||||
lex->pop_context();
|
lex->pop_context();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue