Fix of problem with WHERE/HAVING consist of alone outer reference field by wrapping it.
sql/item.cc: Wrapper added. sql/item.h: Wrapper added. sql/mysql_priv.h: Wrap function added. sql/sql_base.cc: Wrap function added. Fix of problem with WHERE consist of alone outer reference field by wrapping it. sql/sql_select.cc: Fix of problem with HAVING consist of alone outer reference field by wrapping it.
This commit is contained in:
parent
2038256bed
commit
481cd2dbf1
34
sql/item.cc
34
sql/item.cc
@ -6619,6 +6619,40 @@ bool Item_direct_ref::get_date(MYSQL_TIME *ltime,uint fuzzydate)
|
||||
}
|
||||
|
||||
|
||||
Item* Item_direct_ref_to_ident::transform(Item_transformer transformer,
|
||||
uchar *argument)
|
||||
{
|
||||
DBUG_ASSERT(!current_thd->is_stmt_prepare());
|
||||
|
||||
Item *new_item= ident->transform(transformer, argument);
|
||||
if (!new_item)
|
||||
return 0;
|
||||
DBUG_ASSERT(new_item->type() == FIELD_ITEM || new_item->type() == REF_ITEM);
|
||||
|
||||
if (ident != new_item)
|
||||
current_thd->change_item_tree((Item**)&ident, new_item);
|
||||
return (this->*transformer)(argument);
|
||||
}
|
||||
|
||||
|
||||
Item* Item_direct_ref_to_ident::compile(Item_analyzer analyzer, uchar **arg_p,
|
||||
Item_transformer transformer,
|
||||
uchar *arg_t)
|
||||
{
|
||||
if (!(this->*analyzer)(arg_p))
|
||||
return 0;
|
||||
|
||||
uchar *arg_v= *arg_p;
|
||||
Item *new_item= ident->compile(analyzer, &arg_v, transformer, arg_t);
|
||||
if (new_item && ident != new_item)
|
||||
{
|
||||
DBUG_ASSERT(new_item->type() == FIELD_ITEM || new_item->type() == REF_ITEM);
|
||||
current_thd->change_item_tree((Item**)&ident, new_item);
|
||||
}
|
||||
return (this->*transformer)(arg_t);
|
||||
}
|
||||
|
||||
|
||||
Item_cache_wrapper::~Item_cache_wrapper()
|
||||
{
|
||||
delete expr_cache;
|
||||
|
41
sql/item.h
41
sql/item.h
@ -518,7 +518,7 @@ public:
|
||||
SUBSELECT_ITEM, ROW_ITEM, CACHE_ITEM, TYPE_HOLDER,
|
||||
PARAM_ITEM, TRIGGER_FIELD_ITEM, DECIMAL_ITEM,
|
||||
XPATH_NODESET, XPATH_NODESET_CMP,
|
||||
VIEW_FIXER_ITEM, EXPR_CACHE_ITEM};
|
||||
VIEW_FIXER_ITEM, EXPR_CACHE_ITEM, UNKNOWN_ITEM};
|
||||
|
||||
enum cond_result { COND_UNDEF,COND_OK,COND_TRUE,COND_FALSE };
|
||||
|
||||
@ -612,7 +612,7 @@ public:
|
||||
virtual Item_result cast_to_int_type() const { return result_type(); }
|
||||
virtual enum_field_types string_field_type() const;
|
||||
virtual enum_field_types field_type() const;
|
||||
virtual enum Type type() const =0;
|
||||
virtual enum Type type() const { return UNKNOWN_ITEM; };
|
||||
|
||||
/*
|
||||
Return information about function monotonicity. See comment for
|
||||
@ -2609,6 +2609,43 @@ public:
|
||||
virtual Ref_Type ref_type() { return DIRECT_REF; }
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
This class is the same as Item_direct_ref but created to wrap Item_ident
|
||||
before fix_fields() call
|
||||
*/
|
||||
|
||||
class Item_direct_ref_to_ident :public Item_direct_ref
|
||||
{
|
||||
Item_ident *ident;
|
||||
public:
|
||||
Item_direct_ref_to_ident(Item_ident *item)
|
||||
:Item_direct_ref(item->context, (Item**)&item, item->table_name, item->field_name,
|
||||
FALSE)
|
||||
{
|
||||
ident= item;
|
||||
ref= (Item**)&ident;
|
||||
}
|
||||
|
||||
bool fix_fields(THD *thd, Item **it)
|
||||
{
|
||||
DBUG_ASSERT(ident->type() == FIELD_ITEM || ident->type() == REF_ITEM);
|
||||
if ((!ident->fixed && ident->fix_fields(thd, ref)) ||
|
||||
ident->check_cols(1))
|
||||
return TRUE;
|
||||
set_properties();
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
virtual void print(String *str, enum_query_type query_type)
|
||||
{ ident->print(str, query_type); }
|
||||
|
||||
virtual Item* transform(Item_transformer transformer, uchar *arg);
|
||||
virtual Item* compile(Item_analyzer analyzer, uchar **arg_p,
|
||||
Item_transformer transformer, uchar *arg_t);
|
||||
};
|
||||
|
||||
|
||||
class Expression_cache;
|
||||
class Item_cache;
|
||||
|
||||
|
@ -1612,6 +1612,7 @@ inline bool setup_fields_with_no_wrap(THD *thd, Item **ref_pointer_array,
|
||||
}
|
||||
int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves,
|
||||
COND **conds);
|
||||
void wrap_ident(THD *thd, Item **conds);
|
||||
int setup_ftfuncs(SELECT_LEX* select);
|
||||
int init_ftfuncs(THD *thd, SELECT_LEX* select, bool no_order);
|
||||
void wait_for_condition(THD *thd, pthread_mutex_t *mutex,
|
||||
|
@ -8120,6 +8120,29 @@ insert_fields(THD *thd, Name_resolution_context *context, const char *db_name,
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Wrap Item_ident
|
||||
|
||||
@param thd thread handle
|
||||
@param conds pointer to the condition which should be wrapped
|
||||
*/
|
||||
|
||||
void wrap_ident(THD *thd, Item **conds)
|
||||
{
|
||||
Item_direct_ref_to_ident *wrapper;
|
||||
DBUG_ASSERT((*conds)->type() == Item::FIELD_ITEM || (*conds)->type() == Item::REF_ITEM);
|
||||
Query_arena *arena= thd->stmt_arena, backup;
|
||||
if (arena->is_conventional())
|
||||
arena= 0;
|
||||
else
|
||||
thd->set_n_backup_active_arena(arena, &backup);
|
||||
if ((wrapper= new Item_direct_ref_to_ident((Item_ident *)(*conds))))
|
||||
(*conds)= (Item*) wrapper;
|
||||
if (arena)
|
||||
thd->restore_active_arena(arena, &backup);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Fix all conditions and outer join expressions.
|
||||
|
||||
@ -8183,6 +8206,12 @@ int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves,
|
||||
print_where(*conds,
|
||||
"WHERE in setup_conds",
|
||||
QT_ORDINARY););
|
||||
/*
|
||||
Wrap alone field in WHERE clause in case it will be outer field of subquery
|
||||
which need persistent pointer on it, but conds could be changed by optimizer
|
||||
*/
|
||||
if ((*conds)->type() == Item::FIELD_ITEM)
|
||||
wrap_ident(thd, conds);
|
||||
if ((!(*conds)->fixed && (*conds)->fix_fields(thd, conds)) ||
|
||||
(*conds)->check_cols(1))
|
||||
goto err_no_arena;
|
||||
|
@ -543,6 +543,13 @@ JOIN::prepare(Item ***rref_pointer_array,
|
||||
thd->where="having clause";
|
||||
thd->lex->allow_sum_func|= 1 << select_lex_arg->nest_level;
|
||||
select_lex->having_fix_field= 1;
|
||||
/*
|
||||
Wrap alone field in HAVING clause in case it will be outer field of subquery
|
||||
which need persistent pointer on it, but having could be changed by optimizer
|
||||
*/
|
||||
if (having->type() == Item::REF_ITEM &&
|
||||
((Item_ref *)having)->ref_type() == Item_ref::REF)
|
||||
wrap_ident(thd, &having);
|
||||
bool having_fix_rc= (!having->fixed &&
|
||||
(having->fix_fields(thd, &having) ||
|
||||
having->check_cols(1)));
|
||||
|
Loading…
x
Reference in New Issue
Block a user