mirror of
https://github.com/MariaDB/server.git
synced 2025-01-18 13:02:28 +01:00
Merge weblab.(none):/home/marcsql/TREE/mysql-5.0-21904
into weblab.(none):/home/marcsql/TREE/mysql-5.1-21904-merge
This commit is contained in:
commit
df0fbdf535
3 changed files with 144 additions and 17 deletions
|
@ -51,6 +51,10 @@ Item_subselect::Item_subselect():
|
|||
void Item_subselect::init(st_select_lex *select_lex,
|
||||
select_subselect *result)
|
||||
{
|
||||
/*
|
||||
Please see Item_singlerow_subselect::invalidate_and_restore_select_lex(),
|
||||
which depends on alterations to the parse tree implemented here.
|
||||
*/
|
||||
|
||||
DBUG_ENTER("Item_subselect::init");
|
||||
DBUG_PRINT("enter", ("select_lex: 0x%lx", (long) select_lex));
|
||||
|
@ -91,6 +95,12 @@ void Item_subselect::init(st_select_lex *select_lex,
|
|||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
st_select_lex *
|
||||
Item_subselect::get_select_lex()
|
||||
{
|
||||
return unit->first_select();
|
||||
}
|
||||
|
||||
void Item_subselect::cleanup()
|
||||
{
|
||||
DBUG_ENTER("Item_subselect::cleanup");
|
||||
|
@ -307,6 +317,26 @@ Item_singlerow_subselect::Item_singlerow_subselect(st_select_lex *select_lex)
|
|||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
st_select_lex *
|
||||
Item_singlerow_subselect::invalidate_and_restore_select_lex()
|
||||
{
|
||||
DBUG_ENTER("Item_singlerow_subselect::invalidate_and_restore_select_lex");
|
||||
st_select_lex *result= get_select_lex();
|
||||
|
||||
DBUG_ASSERT(result);
|
||||
|
||||
/*
|
||||
This code restore the parse tree in it's state before the execution of
|
||||
Item_singlerow_subselect::Item_singlerow_subselect(),
|
||||
and in particular decouples this object from the SELECT_LEX,
|
||||
so that the SELECT_LEX can be used with a different flavor
|
||||
or Item_subselect instead, as part of query rewriting.
|
||||
*/
|
||||
unit->item= NULL;
|
||||
|
||||
DBUG_RETURN(result);
|
||||
}
|
||||
|
||||
Item_maxmin_subselect::Item_maxmin_subselect(THD *thd_param,
|
||||
Item_subselect *parent,
|
||||
st_select_lex *select_lex,
|
||||
|
|
|
@ -126,6 +126,12 @@ public:
|
|||
enum_parsing_place place() { return parsing_place; }
|
||||
bool walk(Item_processor processor, bool walk_subquery, byte *arg);
|
||||
|
||||
/**
|
||||
Get the SELECT_LEX structure associated with this Item.
|
||||
@return the SELECT_LEX structure associated with this Item
|
||||
*/
|
||||
st_select_lex* get_select_lex();
|
||||
|
||||
friend class select_subselect;
|
||||
friend class Item_in_optimizer;
|
||||
friend bool Item_field::fix_fields(THD *, Item **);
|
||||
|
@ -169,6 +175,16 @@ public:
|
|||
bool null_inside();
|
||||
void bring_value();
|
||||
|
||||
/**
|
||||
This method is used to implement a special case of semantic tree
|
||||
rewriting, mandated by a SQL:2003 exception in the specification.
|
||||
The only caller of this method is handle_sql2003_note184_exception(),
|
||||
see the code there for more details.
|
||||
Do not call this method for other purposes.
|
||||
@return the SELECT_LEX structure that was given in the constructor.
|
||||
*/
|
||||
st_select_lex* invalidate_and_restore_select_lex();
|
||||
|
||||
friend class select_singlerow_subselect;
|
||||
};
|
||||
|
||||
|
|
115
sql/sql_yacc.yy
115
sql/sql_yacc.yy
|
@ -310,6 +310,81 @@ void case_stmt_action_end_case(LEX *lex, bool simple)
|
|||
lex->sphead->do_cont_backpatch();
|
||||
}
|
||||
|
||||
/**
|
||||
Helper to resolve the SQL:2003 Syntax exception 1) in <in predicate>.
|
||||
See SQL:2003, Part 2, section 8.4 <in predicate>, Note 184, page 383.
|
||||
This function returns the proper item for the SQL expression
|
||||
<code>left [NOT] IN ( expr )</code>
|
||||
@param thd the current thread
|
||||
@param left the in predicand
|
||||
@param equal true for IN predicates, false for NOT IN predicates
|
||||
@param expr first and only expression of the in value list
|
||||
@return an expression representing the IN predicate.
|
||||
*/
|
||||
Item* handle_sql2003_note184_exception(THD *thd, Item* left, bool equal,
|
||||
Item *expr)
|
||||
{
|
||||
/*
|
||||
Relevant references for this issue:
|
||||
- SQL:2003, Part 2, section 8.4 <in predicate>, page 383,
|
||||
- SQL:2003, Part 2, section 7.2 <row value expression>, page 296,
|
||||
- SQL:2003, Part 2, section 6.3 <value expression primary>, page 174,
|
||||
- SQL:2003, Part 2, section 7.15 <subquery>, page 370,
|
||||
- SQL:2003 Feature F561, "Full value expressions".
|
||||
|
||||
The exception in SQL:2003 Note 184 means:
|
||||
Item_singlerow_subselect, which corresponds to a <scalar subquery>,
|
||||
should be re-interpreted as an Item_in_subselect, which corresponds
|
||||
to a <table subquery> when used inside an <in predicate>.
|
||||
|
||||
Our reading of Note 184 is reccursive, so that all:
|
||||
- IN (( <subquery> ))
|
||||
- IN ((( <subquery> )))
|
||||
- IN '('^N <subquery> ')'^N
|
||||
- etc
|
||||
should be interpreted as a <table subquery>, no matter how deep in the
|
||||
expression the <subquery> is.
|
||||
*/
|
||||
|
||||
Item *result;
|
||||
|
||||
DBUG_ENTER("handle_sql2003_note184_exception");
|
||||
|
||||
if (expr->type() == Item::SUBSELECT_ITEM)
|
||||
{
|
||||
Item_subselect *expr2 = (Item_subselect*) expr;
|
||||
|
||||
if (expr2->substype() == Item_subselect::SINGLEROW_SUBS)
|
||||
{
|
||||
Item_singlerow_subselect *expr3 = (Item_singlerow_subselect*) expr2;
|
||||
st_select_lex *subselect;
|
||||
|
||||
/*
|
||||
Implement the mandated change, by altering the semantic tree:
|
||||
left IN Item_singlerow_subselect(subselect)
|
||||
is modified to
|
||||
left IN (subselect)
|
||||
which is represented as
|
||||
Item_in_subselect(left, subselect)
|
||||
*/
|
||||
subselect= expr3->invalidate_and_restore_select_lex();
|
||||
result= new (thd->mem_root) Item_in_subselect(left, subselect);
|
||||
|
||||
if (! equal)
|
||||
result = negate_expression(thd, result);
|
||||
|
||||
DBUG_RETURN(result);
|
||||
}
|
||||
}
|
||||
|
||||
if (equal)
|
||||
result= new (thd->mem_root) Item_func_eq(left, expr);
|
||||
else
|
||||
result= new (thd->mem_root) Item_func_ne(left, expr);
|
||||
|
||||
DBUG_RETURN(result);
|
||||
}
|
||||
|
||||
%}
|
||||
%union {
|
||||
int num;
|
||||
|
@ -6168,31 +6243,37 @@ bool_pri:
|
|||
| predicate ;
|
||||
|
||||
predicate:
|
||||
bit_expr IN_SYM '(' subselect ')'
|
||||
{ $$= new Item_in_subselect($1, $4); }
|
||||
| bit_expr not IN_SYM '(' subselect ')'
|
||||
{ $$= negate_expression(YYTHD, new Item_in_subselect($1, $5)); }
|
||||
bit_expr IN_SYM '(' subselect ')'
|
||||
{
|
||||
$$= new (YYTHD->mem_root) Item_in_subselect($1, $4);
|
||||
}
|
||||
| bit_expr not IN_SYM '(' subselect ')'
|
||||
{
|
||||
THD *thd= YYTHD;
|
||||
Item *item= new (thd->mem_root) Item_in_subselect($1, $5);
|
||||
$$= negate_expression(thd, item);
|
||||
}
|
||||
| bit_expr IN_SYM '(' expr ')'
|
||||
{
|
||||
$$= new Item_func_eq($1, $4);
|
||||
$$= handle_sql2003_note184_exception(YYTHD, $1, true, $4);
|
||||
}
|
||||
| bit_expr IN_SYM '(' expr ',' expr_list ')'
|
||||
{
|
||||
$6->push_front($4);
|
||||
$6->push_front($1);
|
||||
$$= new Item_func_in(*$6);
|
||||
| bit_expr IN_SYM '(' expr ',' expr_list ')'
|
||||
{
|
||||
$6->push_front($4);
|
||||
$6->push_front($1);
|
||||
$$= new (YYTHD->mem_root) Item_func_in(*$6);
|
||||
}
|
||||
| bit_expr not IN_SYM '(' expr ')'
|
||||
{
|
||||
$$= new Item_func_ne($1, $5);
|
||||
$$= handle_sql2003_note184_exception(YYTHD, $1, false, $5);
|
||||
}
|
||||
| bit_expr not IN_SYM '(' expr ',' expr_list ')'
|
||||
| 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;
|
||||
$7->push_front($5);
|
||||
$7->push_front($1);
|
||||
Item_func_in *item = new (YYTHD->mem_root) Item_func_in(*$7);
|
||||
item->negate();
|
||||
$$= item;
|
||||
}
|
||||
| bit_expr BETWEEN_SYM bit_expr AND_SYM predicate
|
||||
{ $$= new Item_func_between($1,$3,$5); }
|
||||
|
|
Loading…
Reference in a new issue