mirror of
https://github.com/MariaDB/server.git
synced 2025-01-31 02:51:44 +01:00
Abort procesing current item if it was substituted by view field (BUF#6894)
Post-review fixes
This commit is contained in:
parent
0ac11a0601
commit
9270c24f5f
2 changed files with 55 additions and 13 deletions
|
@ -1705,3 +1705,15 @@ select col1,group_concat(col2,col3) from t1 group by col1;
|
||||||
select col1,group_concat(col2,col3) from v1 group by col1;
|
select col1,group_concat(col2,col3) from v1 group by col1;
|
||||||
drop view v1;
|
drop view v1;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Item_ref resolved as view field (BUG#6894)
|
||||||
|
#
|
||||||
|
create table t1 (s1 int, s2 char);
|
||||||
|
create view v1 as select s1, s2 from t1;
|
||||||
|
-- error 1054
|
||||||
|
select s2 from v1 vq1 where 2 = (select count(*) from v1 vq2 having vq1.s2 = vq2.s2);
|
||||||
|
select s2 from v1 vq1 where 2 = (select count(*) aa from v1 vq2 having vq1.s2 = aa);
|
||||||
|
drop view v1;
|
||||||
|
drop table t1;
|
||||||
|
|
||||||
|
|
56
sql/item.cc
56
sql/item.cc
|
@ -2101,23 +2101,29 @@ bool Item_ref_null_helper::get_date(TIME *ltime, uint fuzzydate)
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Mark item and SELECT_LEXs as dependent if it is not outer resolving
|
Mark item and SELECT_LEXs as dependent if item was resolved in outer SELECT
|
||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
mark_as_dependent()
|
mark_as_dependent()
|
||||||
thd - thread handler
|
thd - thread handler
|
||||||
last - select from which current item depend
|
last - select from which current item depend
|
||||||
current - current select
|
current - current select
|
||||||
item - item which should be marked
|
resolved_item - item which was resolved in outer SELECT(for warning)
|
||||||
|
mark_item - item which should be marked (can be differ in case of
|
||||||
|
substitution)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void mark_as_dependent(THD *thd, SELECT_LEX *last, SELECT_LEX *current,
|
static void mark_as_dependent(THD *thd, SELECT_LEX *last, SELECT_LEX *current,
|
||||||
Item_ident *item)
|
Item_ident *resolved_item,
|
||||||
|
Item_ident *mark_item)
|
||||||
{
|
{
|
||||||
const char *db_name= item->db_name ? item->db_name : "";
|
const char *db_name= (resolved_item->db_name ?
|
||||||
const char *table_name= item->table_name ? item->table_name : "";
|
resolved_item->db_name : "");
|
||||||
|
const char *table_name= (resolved_item->table_name ?
|
||||||
|
resolved_item->table_name : "");
|
||||||
/* store pointer on SELECT_LEX from which item is dependent */
|
/* store pointer on SELECT_LEX from which item is dependent */
|
||||||
item->depended_from= last;
|
if (mark_item)
|
||||||
|
mark_item->depended_from= last;
|
||||||
current->mark_as_dependent(last);
|
current->mark_as_dependent(last);
|
||||||
if (thd->lex->describe & DESCRIBE_EXTENDED)
|
if (thd->lex->describe & DESCRIBE_EXTENDED)
|
||||||
{
|
{
|
||||||
|
@ -2125,7 +2131,7 @@ static void mark_as_dependent(THD *thd, SELECT_LEX *last, SELECT_LEX *current,
|
||||||
sprintf(warn_buff, ER(ER_WARN_FIELD_RESOLVED),
|
sprintf(warn_buff, ER(ER_WARN_FIELD_RESOLVED),
|
||||||
db_name, (db_name[0] ? "." : ""),
|
db_name, (db_name[0] ? "." : ""),
|
||||||
table_name, (table_name [0] ? "." : ""),
|
table_name, (table_name [0] ? "." : ""),
|
||||||
item->field_name,
|
resolved_item->field_name,
|
||||||
current->select_number, last->select_number);
|
current->select_number, last->select_number);
|
||||||
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
|
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
|
||||||
ER_WARN_FIELD_RESOLVED, warn_buff);
|
ER_WARN_FIELD_RESOLVED, warn_buff);
|
||||||
|
@ -2464,10 +2470,21 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **reference)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
Item::Type type= (*reference)->type();
|
||||||
prev_subselect_item->used_tables_cache|=
|
prev_subselect_item->used_tables_cache|=
|
||||||
(*reference)->used_tables();
|
(*reference)->used_tables();
|
||||||
prev_subselect_item->const_item_cache&=
|
prev_subselect_item->const_item_cache&=
|
||||||
(*reference)->const_item();
|
(*reference)->const_item();
|
||||||
|
mark_as_dependent(thd, last, current_sel, this,
|
||||||
|
((type == REF_ITEM || type == FIELD_ITEM) ?
|
||||||
|
(Item_ident*) (*reference) :
|
||||||
|
0));
|
||||||
|
/*
|
||||||
|
view reference found, we substituted it instead of this
|
||||||
|
Item (find_field_in_tables do it by assigning new value to
|
||||||
|
*reference), so can quit
|
||||||
|
*/
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -2545,12 +2562,12 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **reference)
|
||||||
if (rf->fix_fields(thd, tables, reference) || rf->check_cols(1))
|
if (rf->fix_fields(thd, tables, reference) || rf->check_cols(1))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
mark_as_dependent(thd, last, current_sel, rf);
|
mark_as_dependent(thd, last, current_sel, this, rf);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mark_as_dependent(thd, last, current_sel, this);
|
mark_as_dependent(thd, last, current_sel, this, this);
|
||||||
if (last->having_fix_field)
|
if (last->having_fix_field)
|
||||||
{
|
{
|
||||||
Item_ref *rf;
|
Item_ref *rf;
|
||||||
|
@ -2583,8 +2600,10 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **reference)
|
||||||
|
|
||||||
Also we suppose that view can't be changed during PS/SP life.
|
Also we suppose that view can't be changed during PS/SP life.
|
||||||
*/
|
*/
|
||||||
if (from_field != view_ref_found)
|
if (from_field == view_ref_found)
|
||||||
set_field(from_field);
|
return FALSE;
|
||||||
|
|
||||||
|
set_field(from_field);
|
||||||
}
|
}
|
||||||
else if (thd->set_query_id && field->query_id != thd->query_id)
|
else if (thd->set_query_id && field->query_id != thd->query_id)
|
||||||
{
|
{
|
||||||
|
@ -3596,10 +3615,21 @@ bool Item_ref::fix_fields(THD *thd, TABLE_LIST *tables, Item **reference)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
Item::Type type= (*reference)->type();
|
||||||
prev_subselect_item->used_tables_cache|=
|
prev_subselect_item->used_tables_cache|=
|
||||||
(*reference)->used_tables();
|
(*reference)->used_tables();
|
||||||
prev_subselect_item->const_item_cache&=
|
prev_subselect_item->const_item_cache&=
|
||||||
(*reference)->const_item();
|
(*reference)->const_item();
|
||||||
|
DBUG_ASSERT((*reference)->type() == REF_ITEM);
|
||||||
|
mark_as_dependent(thd, last, current_sel, this,
|
||||||
|
((type == REF_ITEM || type == FIELD_ITEM) ?
|
||||||
|
(Item_ident*) (*reference) :
|
||||||
|
0));
|
||||||
|
/*
|
||||||
|
view reference found, we substituted it instead of this
|
||||||
|
Item, so can quit
|
||||||
|
*/
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -3638,7 +3668,7 @@ bool Item_ref::fix_fields(THD *thd, TABLE_LIST *tables, Item **reference)
|
||||||
if (!(fld= new Item_field(from_field)))
|
if (!(fld= new Item_field(from_field)))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
thd->change_item_tree(reference, fld);
|
thd->change_item_tree(reference, fld);
|
||||||
mark_as_dependent(thd, last, thd->lex->current_select, fld);
|
mark_as_dependent(thd, last, thd->lex->current_select, this, fld);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
@ -3656,7 +3686,7 @@ bool Item_ref::fix_fields(THD *thd, TABLE_LIST *tables, Item **reference)
|
||||||
{
|
{
|
||||||
/* Should be checked in resolve_ref_in_select_and_group(). */
|
/* Should be checked in resolve_ref_in_select_and_group(). */
|
||||||
DBUG_ASSERT(*ref && (*ref)->fixed);
|
DBUG_ASSERT(*ref && (*ref)->fixed);
|
||||||
mark_as_dependent(thd, last, current_sel, this);
|
mark_as_dependent(thd, last, current_sel, this, this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
Loading…
Add table
Reference in a new issue