MDEV-16385 ROW SP variable is allowed in unexpected context

The problem described in the bug report happened because the code
did not test check_cols(1) after fix_fields() in a few places.

Additionally, fix_fields() could be called multiple times for SP variables,
because they are all fixed at a early stage in append_for_log().

Solution:
1. Adding a few helper methods
   - fix_fields_if_needed()
   - fix_fields_if_needed_for_scalar()
   - fix_fields_if_needed_for_bool()
   - fix_fields_if_needed_for_order_by()
  and using it in many cases instead of fix_fields() where
  the "fixed" status is not definitely known to be "false".

2. Adding DBUG_ASSERT(!fixed) into Item_splocal*::fix_fields()
   to catch double execution.

3. Adding tests.

As a good side effect, the patch removes a lot of duplicate code (~60 lines):

   if (!item->fixed &&
       item->fix_fields(..) &&
       item->check_cols(1))
     return true;
This commit is contained in:
Alexander Barkov 2018-06-05 10:25:39 +04:00
parent b50685af82
commit 106f0b5798
32 changed files with 184 additions and 186 deletions

View File

@ -2281,3 +2281,28 @@ t1 CREATE TABLE `t1` (
`int11` int(11) DEFAULT NULL, `int11` int(11) DEFAULT NULL,
`text1` text DEFAULT NULL `text1` text DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1 ) ENGINE=MyISAM DEFAULT CHARSET=latin1
#
# MDEV-16385 ROW SP variable is allowed in unexpected context
#
CREATE TABLE t1 (a INT);
BEGIN NOT ATOMIC
DECLARE row ROW(a INT);
SELECT * FROM t1 ORDER BY row;
END;
$$
ERROR 21000: Operand should contain 1 column(s)
DROP TABLE t1;
CREATE TABLE t1 (a INT);
BEGIN NOT ATOMIC
DECLARE row ROW(a INT);
SELECT * FROM t1 HAVING row;
END;
$$
ERROR 21000: Operand should contain 1 column(s)
DROP TABLE t1;
BEGIN NOT ATOMIC
DECLARE a ROW(a INT);
SELECT 1 LIKE 2 ESCAPE a;
END;
$$
ERROR 21000: Operand should contain 1 column(s)

View File

@ -1504,3 +1504,38 @@ BEGIN NOT ATOMIC
END; END;
$$ $$
DELIMITER ;$$ DELIMITER ;$$
--echo #
--echo # MDEV-16385 ROW SP variable is allowed in unexpected context
--echo #
CREATE TABLE t1 (a INT);
DELIMITER $$;
--error ER_OPERAND_COLUMNS
BEGIN NOT ATOMIC
DECLARE row ROW(a INT);
SELECT * FROM t1 ORDER BY row;
END;
$$
DELIMITER ;$$
DROP TABLE t1;
CREATE TABLE t1 (a INT);
DELIMITER $$;
--error ER_OPERAND_COLUMNS
BEGIN NOT ATOMIC
DECLARE row ROW(a INT);
SELECT * FROM t1 HAVING row;
END;
$$
DELIMITER ;$$
DROP TABLE t1;
DELIMITER $$;
--error ER_OPERAND_COLUMNS
BEGIN NOT ATOMIC
DECLARE a ROW(a INT);
SELECT 1 LIKE 2 ESCAPE a;
END;
$$
DELIMITER ;$$

View File

@ -1827,6 +1827,7 @@ Item_field *Item_splocal::get_variable(sp_rcontext *ctx) const
bool Item_splocal::fix_fields(THD *thd, Item **ref) bool Item_splocal::fix_fields(THD *thd, Item **ref)
{ {
DBUG_ASSERT(!fixed);
Item *item= get_variable(thd->spcont); Item *item= get_variable(thd->spcont);
set_handler(item->type_handler()); set_handler(item->type_handler());
return fix_fields_from_item(thd, ref, item); return fix_fields_from_item(thd, ref, item);
@ -1954,6 +1955,7 @@ bool Item_splocal::check_cols(uint n)
bool Item_splocal_row_field::fix_fields(THD *thd, Item **ref) bool Item_splocal_row_field::fix_fields(THD *thd, Item **ref)
{ {
DBUG_ASSERT(!fixed);
Item *item= get_variable(thd->spcont)->element_index(m_field_idx); Item *item= get_variable(thd->spcont)->element_index(m_field_idx);
return fix_fields_from_item(thd, ref, item); return fix_fields_from_item(thd, ref, item);
} }
@ -2011,6 +2013,7 @@ bool Item_splocal_row_field::set_value(THD *thd, sp_rcontext *ctx, Item **it)
bool Item_splocal_row_field_by_name::fix_fields(THD *thd, Item **it) bool Item_splocal_row_field_by_name::fix_fields(THD *thd, Item **it)
{ {
DBUG_ASSERT(!fixed);
m_thd= thd; m_thd= thd;
if (get_rcontext(thd->spcont)->find_row_field_by_name_or_error(&m_field_idx, if (get_rcontext(thd->spcont)->find_row_field_by_name_or_error(&m_field_idx,
m_var_idx, m_var_idx,
@ -2231,10 +2234,8 @@ bool Item_name_const::fix_fields(THD *thd, Item **ref)
String s(buf, sizeof(buf), &my_charset_bin); String s(buf, sizeof(buf), &my_charset_bin);
s.length(0); s.length(0);
if ((!value_item->fixed && if (value_item->fix_fields_if_needed(thd, &value_item) ||
value_item->fix_fields(thd, &value_item)) || name_item->fix_fields_if_needed(thd, &name_item) ||
(!name_item->fixed &&
name_item->fix_fields(thd, &name_item)) ||
!value_item->const_item() || !value_item->const_item() ||
!name_item->const_item() || !name_item->const_item() ||
!(item_name= name_item->val_str(&s))) // Can't have a NULL name !(item_name= name_item->val_str(&s))) // Can't have a NULL name
@ -9022,8 +9023,7 @@ bool Item_direct_view_ref::fix_fields(THD *thd, Item **reference)
bitmap_set_bit(fld->table->read_set, fld->field_index); bitmap_set_bit(fld->table->read_set, fld->field_index);
} }
} }
else if (!(*ref)->fixed && else if ((*ref)->fix_fields_if_needed(thd, ref))
((*ref)->fix_fields(thd, ref)))
return TRUE; return TRUE;
if (Item_direct_ref::fix_fields(thd, reference)) if (Item_direct_ref::fix_fields(thd, reference))
@ -9051,7 +9051,7 @@ bool Item_outer_ref::fix_fields(THD *thd, Item **reference)
{ {
bool err; bool err;
/* outer_ref->check_cols() will be made in Item_direct_ref::fix_fields */ /* outer_ref->check_cols() will be made in Item_direct_ref::fix_fields */
if ((*ref) && !(*ref)->fixed && ((*ref)->fix_fields(thd, reference))) if ((*ref) && (*ref)->fix_fields_if_needed(thd, reference))
return TRUE; return TRUE;
err= Item_direct_ref::fix_fields(thd, reference); err= Item_direct_ref::fix_fields(thd, reference);
if (!outer_ref) if (!outer_ref)
@ -9290,7 +9290,7 @@ bool Item_default_value::fix_fields(THD *thd, Item **items)
fixed= 1; fixed= 1;
return FALSE; return FALSE;
} }
if (!arg->fixed && arg->fix_fields(thd, &arg)) if (arg->fix_fields_if_needed(thd, &arg))
goto error; goto error;
@ -9635,15 +9635,9 @@ bool Item_trigger_field::set_value(THD *thd, sp_rcontext * /*ctx*/, Item **it)
{ {
Item *item= thd->sp_prepare_func_item(it); Item *item= thd->sp_prepare_func_item(it);
if (!item) if (!item || fix_fields_if_needed(thd, NULL))
return true; return true;
if (!fixed)
{
if (fix_fields(thd, NULL))
return true;
}
// NOTE: field->table->copy_blobs should be false here, but let's // NOTE: field->table->copy_blobs should be false here, but let's
// remember the value at runtime to avoid subtle bugs. // remember the value at runtime to avoid subtle bugs.
bool copy_blobs_saved= field->table->copy_blobs; bool copy_blobs_saved= field->table->copy_blobs;

View File

@ -816,6 +816,23 @@ public:
void init_make_send_field(Send_field *tmp_field,enum enum_field_types type); void init_make_send_field(Send_field *tmp_field,enum enum_field_types type);
virtual void cleanup(); virtual void cleanup();
virtual void make_send_field(THD *thd, Send_field *field); virtual void make_send_field(THD *thd, Send_field *field);
bool fix_fields_if_needed(THD *thd, Item **ref)
{
return fixed ? false : fix_fields(thd, ref);
}
bool fix_fields_if_needed_for_scalar(THD *thd, Item **ref)
{
return fix_fields_if_needed(thd, ref) || check_cols(1);
}
bool fix_fields_if_needed_for_bool(THD *thd, Item **ref)
{
return fix_fields_if_needed_for_scalar(thd, ref);
}
bool fix_fields_if_needed_for_order_by(THD *thd, Item **ref)
{
return fix_fields_if_needed_for_scalar(thd, ref);
}
virtual bool fix_fields(THD *, Item **); virtual bool fix_fields(THD *, Item **);
/* /*
Fix after some tables has been pulled out. Basically re-calculate all Fix after some tables has been pulled out. Basically re-calculate all
@ -4941,8 +4958,7 @@ public:
bool fix_fields(THD *thd, Item **it) bool fix_fields(THD *thd, Item **it)
{ {
if ((!(*ref)->fixed && (*ref)->fix_fields(thd, ref)) || if ((*ref)->fix_fields_if_needed_for_scalar(thd, ref))
(*ref)->check_cols(1))
return TRUE; return TRUE;
return Item_ref::fix_fields(thd, it); return Item_ref::fix_fields(thd, it);
} }
@ -4980,8 +4996,7 @@ public:
bool fix_fields(THD *thd, Item **it) bool fix_fields(THD *thd, Item **it)
{ {
DBUG_ASSERT(ident->type() == FIELD_ITEM || ident->type() == REF_ITEM); DBUG_ASSERT(ident->type() == FIELD_ITEM || ident->type() == REF_ITEM);
if ((!ident->fixed && ident->fix_fields(thd, ref)) || if (ident->fix_fields_if_needed_for_scalar(thd, ref))
ident->check_cols(1))
return TRUE; return TRUE;
set_properties(); set_properties();
return FALSE; return FALSE;

View File

@ -1242,7 +1242,7 @@ bool Item_in_optimizer::fix_left(THD *thd)
ref0= &(((Item_in_subselect *)args[1])->left_expr); ref0= &(((Item_in_subselect *)args[1])->left_expr);
args[0]= ((Item_in_subselect *)args[1])->left_expr; args[0]= ((Item_in_subselect *)args[1])->left_expr;
} }
if ((!(*ref0)->fixed && (*ref0)->fix_fields(thd, ref0)) || if ((*ref0)->fix_fields_if_needed(thd, ref0) ||
(!cache && !(cache= (*ref0)->get_cache(thd)))) (!cache && !(cache= (*ref0)->get_cache(thd))))
DBUG_RETURN(1); DBUG_RETURN(1);
/* /*
@ -1327,7 +1327,7 @@ bool Item_in_optimizer::fix_fields(THD *thd, Item **ref)
if (args[0]->maybe_null) if (args[0]->maybe_null)
maybe_null=1; maybe_null=1;
if (!args[1]->fixed && args[1]->fix_fields(thd, args+1)) if (args[1]->fix_fields_if_needed(thd, args + 1))
return TRUE; return TRUE;
if (!invisible_mode() && if (!invisible_mode() &&
((sub && ((col= args[0]->cols()) != sub->engine->cols())) || ((sub && ((col= args[0]->cols()) != sub->engine->cols())) ||
@ -4586,11 +4586,9 @@ Item_cond::fix_fields(THD *thd, Item **ref)
thd->restore_active_arena(arena, &backup); thd->restore_active_arena(arena, &backup);
} }
// item can be substituted in fix_fields if (item->fix_fields_if_needed_for_bool(thd, li.ref()))
if ((!item->fixed &&
item->fix_fields(thd, li.ref())) ||
(item= *li.ref())->check_cols(1))
return TRUE; /* purecov: inspected */ return TRUE; /* purecov: inspected */
item= *li.ref(); // item can be substituted in fix_fields
used_tables_cache|= item->used_tables(); used_tables_cache|= item->used_tables();
if (item->const_item() && !item->with_param && if (item->const_item() && !item->with_param &&
!item->is_expensive() && !cond_has_datetime_is_null(item)) !item->is_expensive() && !cond_has_datetime_is_null(item))
@ -5306,7 +5304,7 @@ bool Item_func_like::fix_fields(THD *thd, Item **ref)
{ {
DBUG_ASSERT(fixed == 0); DBUG_ASSERT(fixed == 0);
if (Item_bool_func2::fix_fields(thd, ref) || if (Item_bool_func2::fix_fields(thd, ref) ||
escape_item->fix_fields(thd, &escape_item) || escape_item->fix_fields_if_needed_for_scalar(thd, &escape_item) ||
fix_escape_item(thd, escape_item, &cmp_value1, escape_used_in_parsing, fix_escape_item(thd, escape_item, &cmp_value1, escape_used_in_parsing,
cmp_collation.collation, &escape)) cmp_collation.collation, &escape))
return TRUE; return TRUE;

View File

@ -360,7 +360,7 @@ Item_func::fix_fields(THD *thd, Item **ref)
We can't yet set item to *arg as fix_fields may change *arg We can't yet set item to *arg as fix_fields may change *arg
We shouldn't call fix_fields() twice, so check 'fixed' field first We shouldn't call fix_fields() twice, so check 'fixed' field first
*/ */
if ((!(*arg)->fixed && (*arg)->fix_fields(thd, arg))) if ((*arg)->fix_fields_if_needed(thd, arg))
return TRUE; /* purecov: inspected */ return TRUE; /* purecov: inspected */
item= *arg; item= *arg;
@ -3279,13 +3279,10 @@ udf_handler::fix_fields(THD *thd, Item_func_or_sum *func,
arg != arg_end ; arg != arg_end ;
arg++,i++) arg++,i++)
{ {
if (!(*arg)->fixed && if ((*arg)->fix_fields_if_needed_for_scalar(thd, arg))
(*arg)->fix_fields(thd, arg)) DBUG_RETURN(true);
DBUG_RETURN(1);
// we can't assign 'item' before, because fix_fields() can change arg // we can't assign 'item' before, because fix_fields() can change arg
Item *item= *arg; Item *item= *arg;
if (item->check_cols(1))
DBUG_RETURN(TRUE);
/* /*
TODO: We should think about this. It is not always TODO: We should think about this. It is not always
right way just to set an UDF result to return my_charset_bin right way just to set an UDF result to return my_charset_bin

View File

@ -41,8 +41,7 @@ bool Item_row::fix_fields(THD *thd, Item **ref)
Item **arg, **arg_end; Item **arg, **arg_end;
for (arg= args, arg_end= args + arg_count; arg != arg_end ; arg++) for (arg= args, arg_end= args + arg_count; arg != arg_end ; arg++)
{ {
if (!(*arg)->fixed && if ((*arg)->fix_fields_if_needed(thd, arg))
(*arg)->fix_fields(thd, arg))
return TRUE; return TRUE;
// we can't assign 'item' before, because fix_fields() can change arg // we can't assign 'item' before, because fix_fields() can change arg
Item *item= *arg; Item *item= *arg;

View File

@ -302,8 +302,7 @@ bool Item_subselect::fix_fields(THD *thd_param, Item **ref)
engine->exclude(); engine->exclude();
substitution= 0; substitution= 0;
thd->where= "checking transformed subquery"; thd->where= "checking transformed subquery";
if (!(*ref)->fixed) res= (*ref)->fix_fields_if_needed(thd, ref);
res= (*ref)->fix_fields(thd, ref);
goto end; goto end;
} }
@ -2181,7 +2180,7 @@ Item_in_subselect::create_single_in_to_exists_cond(JOIN *join,
row_value_transformer? row_value_transformer?
*/ */
item->name= in_additional_cond; item->name= in_additional_cond;
if (!item->fixed && item->fix_fields(thd, 0)) if (item->fix_fields_if_needed(thd, 0))
DBUG_RETURN(true); DBUG_RETURN(true);
*where_item= item; *where_item= item;
} }
@ -2504,7 +2503,7 @@ Item_in_subselect::create_row_in_to_exists_cond(JOIN * join,
if (*where_item) if (*where_item)
{ {
if (!(*where_item)->fixed && (*where_item)->fix_fields(thd, 0)) if ((*where_item)->fix_fields_if_needed(thd, 0))
DBUG_RETURN(true); DBUG_RETURN(true);
(*where_item)->top_level_item(); (*where_item)->top_level_item();
} }
@ -2651,7 +2650,7 @@ bool Item_in_subselect::inject_in_to_exists_cond(JOIN *join_arg)
} }
where_item= and_items(thd, join_arg->conds, where_item); where_item= and_items(thd, join_arg->conds, where_item);
if (!where_item->fixed && where_item->fix_fields(thd, 0)) if (where_item->fix_fields_if_needed(thd, 0))
DBUG_RETURN(true); DBUG_RETURN(true);
// TIMOUR TODO: call optimize_cond() for the new where clause // TIMOUR TODO: call optimize_cond() for the new where clause
thd->change_item_tree(&select_lex->where, where_item); thd->change_item_tree(&select_lex->where, where_item);
@ -3117,7 +3116,7 @@ bool Item_exists_subselect::exists2in_processor(void *opt_arg)
exp= optimizer; exp= optimizer;
} }
upper_not->arguments()[0]= exp; upper_not->arguments()[0]= exp;
if (!exp->fixed && exp->fix_fields(thd, upper_not->arguments())) if (exp->fix_fields_if_needed(thd, upper_not->arguments()))
{ {
res= TRUE; res= TRUE;
goto out; goto out;
@ -3315,8 +3314,7 @@ bool Item_in_subselect::fix_fields(THD *thd_arg, Item **ref)
} }
} }
if (left_expr && !left_expr->fixed && if (left_expr && left_expr->fix_fields_if_needed(thd_arg, &left_expr))
left_expr->fix_fields(thd_arg, &left_expr))
goto err; goto err;
else else
if (Item_subselect::fix_fields(thd_arg, ref)) if (Item_subselect::fix_fields(thd_arg, ref))
@ -4999,8 +4997,8 @@ bool subselect_hash_sj_engine::init(List<Item> *tmp_columns, uint subquery_id)
Repeat name resolution for 'cond' since cond is not part of any Repeat name resolution for 'cond' since cond is not part of any
clause of the query, and it is not 'fixed' during JOIN::prepare. clause of the query, and it is not 'fixed' during JOIN::prepare.
*/ */
if (semi_join_conds && !semi_join_conds->fixed && if (semi_join_conds &&
semi_join_conds->fix_fields(thd, (Item**)&semi_join_conds)) semi_join_conds->fix_fields_if_needed(thd, (Item**)&semi_join_conds))
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
/* Let our engine reuse this query plan for materialization. */ /* Let our engine reuse this query plan for materialization. */
materialize_join= materialize_engine->join; materialize_join= materialize_engine->join;

View File

@ -1129,7 +1129,7 @@ Item_sum_num::fix_fields(THD *thd, Item **ref)
maybe_null= sum_func() != COUNT_FUNC; maybe_null= sum_func() != COUNT_FUNC;
for (uint i=0 ; i < arg_count ; i++) for (uint i=0 ; i < arg_count ; i++)
{ {
if (args[i]->fix_fields(thd, args + i) || args[i]->check_cols(1)) if (args[i]->fix_fields_if_needed_for_scalar(thd, &args[i]))
return TRUE; return TRUE;
set_if_bigger(decimals, args[i]->decimals); set_if_bigger(decimals, args[i]->decimals);
m_with_subquery|= args[i]->with_subquery(); m_with_subquery|= args[i]->with_subquery();
@ -1156,14 +1156,11 @@ Item_sum_hybrid::fix_fields(THD *thd, Item **ref)
DBUG_ENTER("Item_sum_hybrid::fix_fields"); DBUG_ENTER("Item_sum_hybrid::fix_fields");
DBUG_ASSERT(fixed == 0); DBUG_ASSERT(fixed == 0);
Item *item= args[0];
if (init_sum_func_check(thd)) if (init_sum_func_check(thd))
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
// 'item' can be changed during fix_fields // 'item' can be changed during fix_fields
if ((!item->fixed && item->fix_fields(thd, args)) || if (args[0]->fix_fields_if_needed_for_scalar(thd, &args[0]))
(item= args[0])->check_cols(1))
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
m_with_subquery= args[0]->with_subquery(); m_with_subquery= args[0]->with_subquery();
@ -1298,7 +1295,7 @@ Item_sum_sp::fix_fields(THD *thd, Item **ref)
for (uint i= 0 ; i < arg_count ; i++) for (uint i= 0 ; i < arg_count ; i++)
{ {
if (args[i]->fix_fields(thd, args + i) || args[i]->check_cols(1)) if (args[i]->fix_fields_if_needed_for_scalar(thd, &args[i]))
return TRUE; return TRUE;
set_if_bigger(decimals, args[i]->decimals); set_if_bigger(decimals, args[i]->decimals);
m_with_subquery|= args[i]->with_subquery(); m_with_subquery|= args[i]->with_subquery();
@ -3909,9 +3906,7 @@ Item_func_group_concat::fix_fields(THD *thd, Item **ref)
for (i=0 ; i < arg_count ; i++) for (i=0 ; i < arg_count ; i++)
{ {
if ((!args[i]->fixed && if (args[i]->fix_fields_if_needed_for_scalar(thd, &args[i]))
args[i]->fix_fields(thd, args + i)) ||
args[i]->check_cols(1))
return TRUE; return TRUE;
m_with_subquery|= args[i]->with_subquery(); m_with_subquery|= args[i]->with_subquery();
with_param|= args[i]->with_param; with_param|= args[i]->with_param;

View File

@ -327,10 +327,8 @@ bool Item_sum_hybrid_simple::fix_fields(THD *thd, Item **ref)
for (uint i= 0; i < arg_count; i++) for (uint i= 0; i < arg_count; i++)
{ {
Item *item= args[i];
// 'item' can be changed during fix_fields // 'item' can be changed during fix_fields
if ((!item->fixed && item->fix_fields(thd, args)) || if (args[i]->fix_fields_if_needed_for_scalar(thd, &args[i]))
(item= args[i])->check_cols(1))
return TRUE; return TRUE;
} }
Type_std_attributes::set(args[0]); Type_std_attributes::set(args[0]);

View File

@ -620,8 +620,8 @@ int check_and_do_in_subquery_rewrites(JOIN *join)
char const *save_where= thd->where; char const *save_where= thd->where;
thd->where= "IN/ALL/ANY subquery"; thd->where= "IN/ALL/ANY subquery";
bool failure= !in_subs->left_expr->fixed && bool failure= in_subs->left_expr->fix_fields_if_needed(thd,
in_subs->left_expr->fix_fields(thd, &in_subs->left_expr); &in_subs->left_expr);
thd->lex->current_select= current; thd->lex->current_select= current;
thd->where= save_where; thd->where= save_where;
if (failure) if (failure)
@ -1666,8 +1666,7 @@ static bool convert_subq_to_sj(JOIN *parent_join, Item_in_subselect *subq_pred)
*/ */
SELECT_LEX *save_lex= thd->lex->current_select; SELECT_LEX *save_lex= thd->lex->current_select;
thd->lex->current_select=subq_lex; thd->lex->current_select=subq_lex;
if (!subq_pred->left_expr->fixed && if (subq_pred->left_expr->fix_fields_if_needed(thd, &subq_pred->left_expr))
subq_pred->left_expr->fix_fields(thd, &subq_pred->left_expr))
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
thd->lex->current_select=save_lex; thd->lex->current_select=save_lex;
@ -1777,8 +1776,7 @@ static bool convert_subq_to_sj(JOIN *parent_join, Item_in_subselect *subq_pred)
to check for this at name resolution stage, but as a legacy of IN->EXISTS to check for this at name resolution stage, but as a legacy of IN->EXISTS
we have in here). we have in here).
*/ */
if (!sj_nest->sj_on_expr->fixed && if (sj_nest->sj_on_expr->fix_fields_if_needed(thd, &sj_nest->sj_on_expr))
sj_nest->sj_on_expr->fix_fields(thd, &sj_nest->sj_on_expr))
{ {
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
} }
@ -1804,8 +1802,7 @@ static bool convert_subq_to_sj(JOIN *parent_join, Item_in_subselect *subq_pred)
emb_tbl_nest->on_expr= and_items(thd, emb_tbl_nest->on_expr, emb_tbl_nest->on_expr= and_items(thd, emb_tbl_nest->on_expr,
sj_nest->sj_on_expr); sj_nest->sj_on_expr);
emb_tbl_nest->on_expr->top_level_item(); emb_tbl_nest->on_expr->top_level_item();
if (!emb_tbl_nest->on_expr->fixed && if (emb_tbl_nest->on_expr->fix_fields_if_needed(thd,
emb_tbl_nest->on_expr->fix_fields(thd,
&emb_tbl_nest->on_expr)) &emb_tbl_nest->on_expr))
{ {
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
@ -1822,9 +1819,7 @@ static bool convert_subq_to_sj(JOIN *parent_join, Item_in_subselect *subq_pred)
*/ */
save_lex= thd->lex->current_select; save_lex= thd->lex->current_select;
thd->lex->current_select=parent_join->select_lex; thd->lex->current_select=parent_join->select_lex;
if (!parent_join->conds->fixed && if (parent_join->conds->fix_fields_if_needed(thd, &parent_join->conds))
parent_join->conds->fix_fields(thd,
&parent_join->conds))
{ {
DBUG_RETURN(1); DBUG_RETURN(1);
} }
@ -3724,7 +3719,7 @@ bool setup_sj_materialization_part1(JOIN_TAB *sjm_tab)
re-executing it will not be prepared. To use the Items from its re-executing it will not be prepared. To use the Items from its
select list we have to prepare (fix_fields) them select list we have to prepare (fix_fields) them
*/ */
if (!item->fixed && item->fix_fields(thd, it.ref())) if (item->fix_fields_if_needed(thd, it.ref()))
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
item= *(it.ref()); // it can be changed by fix_fields item= *(it.ref()); // it can be changed by fix_fields
DBUG_ASSERT(!item->name.length || item->name.length == strlen(item->name.str)); DBUG_ASSERT(!item->name.length || item->name.length == strlen(item->name.str));
@ -5572,8 +5567,7 @@ bool setup_jtbm_semi_joins(JOIN *join, List<TABLE_LIST> *join_list,
Item *sj_conds= hash_sj_engine->semi_join_conds; Item *sj_conds= hash_sj_engine->semi_join_conds;
(*join_where)= and_items(thd, *join_where, sj_conds); (*join_where)= and_items(thd, *join_where, sj_conds);
if (!(*join_where)->fixed) (*join_where)->fix_fields_if_needed(thd, join_where);
(*join_where)->fix_fields(thd, join_where);
} }
table->table->maybe_null= MY_TEST(join->mixed_implicit_grouping); table->table->maybe_null= MY_TEST(join->mixed_implicit_grouping);
} }

View File

@ -768,8 +768,7 @@ int set_var::check(THD *thd)
if (!value) if (!value)
return 0; return 0;
if ((!value->fixed && if (value->fix_fields_if_needed_for_scalar(thd, &value))
value->fix_fields(thd, &value)) || value->check_cols(1))
return -1; return -1;
if (var->check_update_type(value)) if (var->check_update_type(value))
{ {
@ -803,8 +802,7 @@ int set_var::light_check(THD *thd)
if (type == OPT_GLOBAL && check_global_access(thd, SUPER_ACL)) if (type == OPT_GLOBAL && check_global_access(thd, SUPER_ACL))
return 1; return 1;
if (value && ((!value->fixed && value->fix_fields(thd, &value)) || if (value && value->fix_fields_if_needed_for_scalar(thd, &value))
value->check_cols(1)))
return -1; return -1;
return 0; return 0;
} }

View File

@ -99,7 +99,7 @@ sp_map_item_type(const Type_handler *handler)
bool Item_splocal::append_for_log(THD *thd, String *str) bool Item_splocal::append_for_log(THD *thd, String *str)
{ {
if (fix_fields(thd, NULL)) if (fix_fields_if_needed(thd, NULL))
return true; return true;
if (limit_clause_param) if (limit_clause_param)
@ -137,7 +137,7 @@ bool Item_splocal::append_value_for_log(THD *thd, String *str)
bool Item_splocal_row_field::append_for_log(THD *thd, String *str) bool Item_splocal_row_field::append_for_log(THD *thd, String *str)
{ {
if (fix_fields(thd, NULL)) if (fix_fields_if_needed(thd, NULL))
return true; return true;
if (limit_clause_param) if (limit_clause_param)
@ -373,16 +373,14 @@ Item *THD::sp_prepare_func_item(Item **it_addr, uint cols)
Item *THD::sp_fix_func_item(Item **it_addr) Item *THD::sp_fix_func_item(Item **it_addr)
{ {
DBUG_ENTER("THD::sp_fix_func_item"); DBUG_ENTER("THD::sp_fix_func_item");
if (!(*it_addr)->fixed && if ((*it_addr)->fix_fields_if_needed(this, it_addr))
(*it_addr)->fix_fields(this, it_addr))
{ {
DBUG_PRINT("info", ("fix_fields() failed")); DBUG_PRINT("info", ("fix_fields() failed"));
DBUG_RETURN(NULL); DBUG_RETURN(NULL);
} }
it_addr= (*it_addr)->this_item_addr(this, it_addr); it_addr= (*it_addr)->this_item_addr(this, it_addr);
if (!(*it_addr)->fixed && if ((*it_addr)->fix_fields_if_needed(this, it_addr))
(*it_addr)->fix_fields(this, it_addr))
{ {
DBUG_PRINT("info", ("fix_fields() failed")); DBUG_PRINT("info", ("fix_fields() failed"));
DBUG_RETURN(NULL); DBUG_RETURN(NULL);

View File

@ -88,7 +88,7 @@ proc_analyse_init(THD *thd, ORDER *param, select_result *result,
else if (param->next) else if (param->next)
{ {
// first parameter // first parameter
if (!(*param->item)->fixed && (*param->item)->fix_fields(thd, param->item)) if ((*param->item)->fix_fields_if_needed(thd, param->item))
{ {
DBUG_PRINT("info", ("fix_fields() for the first parameter failed")); DBUG_PRINT("info", ("fix_fields() for the first parameter failed"));
goto err; goto err;
@ -107,7 +107,7 @@ proc_analyse_init(THD *thd, ORDER *param, select_result *result,
goto err; goto err;
} }
// second parameter // second parameter
if (!(*param->item)->fixed && (*param->item)->fix_fields(thd, param->item)) if ((*param->item)->fix_fields_if_needed(thd, param->item))
{ {
DBUG_PRINT("info", ("fix_fields() for the second parameter failed")); DBUG_PRINT("info", ("fix_fields() for the second parameter failed"));
goto err; goto err;

View File

@ -5641,8 +5641,7 @@ find_field_in_natural_join(THD *thd, TABLE_LIST *table_ref, const char *name, si
calls fix_fields on that item), it's just a check during table calls fix_fields on that item), it's just a check during table
reopening for columns that was dropped by the concurrent connection. reopening for columns that was dropped by the concurrent connection.
*/ */
if (!nj_col->table_field->fixed && if (nj_col->table_field->fix_fields_if_needed(thd, &ref))
nj_col->table_field->fix_fields(thd, &ref))
{ {
DBUG_PRINT("info", ("column '%s' was dropped by the concurrent connection", DBUG_PRINT("info", ("column '%s' was dropped by the concurrent connection",
nj_col->table_field->name.str)); nj_col->table_field->name.str));
@ -7343,8 +7342,7 @@ bool setup_fields(THD *thd, Ref_ptr_array ref_pointer_array,
if (make_pre_fix) if (make_pre_fix)
pre_fix->push_back(item, thd->stmt_arena->mem_root); pre_fix->push_back(item, thd->stmt_arena->mem_root);
if ((!item->fixed && item->fix_fields(thd, it.ref())) || if (item->fix_fields_if_needed_for_scalar(thd, it.ref()))
(item= *(it.ref()))->check_cols(1))
{ {
thd->lex->current_select->is_item_list_lookup= save_is_item_list_lookup; thd->lex->current_select->is_item_list_lookup= save_is_item_list_lookup;
thd->lex->allow_sum_func= save_allow_sum_func; thd->lex->allow_sum_func= save_allow_sum_func;
@ -7352,6 +7350,7 @@ bool setup_fields(THD *thd, Ref_ptr_array ref_pointer_array,
DBUG_PRINT("info", ("thd->column_usage: %d", thd->column_usage)); DBUG_PRINT("info", ("thd->column_usage: %d", thd->column_usage));
DBUG_RETURN(TRUE); /* purecov: inspected */ DBUG_RETURN(TRUE); /* purecov: inspected */
} }
item= *(it.ref()); // Item might have changed in fix_fields()
if (!ref.is_null()) if (!ref.is_null())
{ {
ref[0]= item; ref[0]= item;
@ -7982,9 +7981,8 @@ bool setup_on_expr(THD *thd, TABLE_LIST *table, bool is_update)
{ {
thd->where="on clause"; thd->where="on clause";
embedded->on_expr->mark_as_condition_AND_part(embedded); embedded->on_expr->mark_as_condition_AND_part(embedded);
if ((!embedded->on_expr->fixed && if (embedded->on_expr->fix_fields_if_needed_for_bool(thd,
embedded->on_expr->fix_fields(thd, &embedded->on_expr)) || &embedded->on_expr))
embedded->on_expr->check_cols(1))
return TRUE; return TRUE;
} }
/* /*
@ -7994,7 +7992,7 @@ bool setup_on_expr(THD *thd, TABLE_LIST *table, bool is_update)
if (embedded->sj_subq_pred) if (embedded->sj_subq_pred)
{ {
Item **left_expr= &embedded->sj_subq_pred->left_expr; Item **left_expr= &embedded->sj_subq_pred->left_expr;
if (!(*left_expr)->fixed && (*left_expr)->fix_fields(thd, left_expr)) if ((*left_expr)->fix_fields_if_needed(thd, left_expr))
return TRUE; return TRUE;
} }
@ -8092,8 +8090,7 @@ int setup_conds(THD *thd, TABLE_LIST *tables, List<TABLE_LIST> &leaves,
if ((*conds)->type() == Item::FIELD_ITEM && !derived) if ((*conds)->type() == Item::FIELD_ITEM && !derived)
wrap_ident(thd, conds); wrap_ident(thd, conds);
(*conds)->mark_as_condition_AND_part(NO_JOIN_NEST); (*conds)->mark_as_condition_AND_part(NO_JOIN_NEST);
if ((!(*conds)->fixed && (*conds)->fix_fields(thd, conds)) || if ((*conds)->fix_fields_if_needed_for_bool(thd, conds))
(*conds)->check_cols(1))
goto err_no_arena; goto err_no_arena;
} }

View File

@ -465,9 +465,7 @@ bool mysql_derived_merge(THD *thd, LEX *lex, TABLE_LIST *derived)
derived->prep_on_expr= expr->copy_andor_structure(thd); derived->prep_on_expr= expr->copy_andor_structure(thd);
} }
if (derived->on_expr && if (derived->on_expr &&
((!derived->on_expr->fixed && derived->on_expr->fix_fields_if_needed_for_bool(thd, &derived->on_expr))
derived->on_expr->fix_fields(thd, &derived->on_expr)) ||
derived->on_expr->check_cols(1)))
{ {
res= TRUE; /* purecov: inspected */ res= TRUE; /* purecov: inspected */
goto exit_merge; goto exit_merge;

View File

@ -217,8 +217,7 @@ Condition_information::aggregate(THD *thd, const Diagnostics_area *da)
DBUG_ENTER("Condition_information::aggregate"); DBUG_ENTER("Condition_information::aggregate");
/* Prepare the expression for evaluation. */ /* Prepare the expression for evaluation. */
if (!m_cond_number_expr->fixed && if (m_cond_number_expr->fix_fields_if_needed(thd, &m_cond_number_expr))
m_cond_number_expr->fix_fields(thd, &m_cond_number_expr))
DBUG_RETURN(true); DBUG_RETURN(true);
cond_number= m_cond_number_expr->val_int(); cond_number= m_cond_number_expr->val_int();

View File

@ -630,8 +630,7 @@ mysql_ha_fix_cond_and_key(SQL_HANDLER *handler,
/* This can only be true for temp tables */ /* This can only be true for temp tables */
if (table->query_id != thd->query_id) if (table->query_id != thd->query_id)
cond->cleanup(); // File was reopened cond->cleanup(); // File was reopened
if ((!cond->fixed && if (cond->fix_fields_if_needed_for_bool(thd, &cond))
cond->fix_fields(thd, &cond)) || cond->check_cols(1))
return 1; return 1;
} }
@ -695,10 +694,9 @@ mysql_ha_fix_cond_and_key(SQL_HANDLER *handler,
{ {
my_bitmap_map *old_map; my_bitmap_map *old_map;
/* note that 'item' can be changed by fix_fields() call */ /* note that 'item' can be changed by fix_fields() call */
if ((!item->fixed && if (item->fix_fields_if_needed_for_scalar(thd, it_ke.ref()))
item->fix_fields(thd, it_ke.ref())) ||
(item= *it_ke.ref())->check_cols(1))
return 1; return 1;
item= *it_ke.ref();
if (item->used_tables() & ~(RAND_TABLE_BIT | PARAM_TABLE_BIT)) if (item->used_tables() & ~(RAND_TABLE_BIT | PARAM_TABLE_BIT))
{ {
my_error(ER_WRONG_ARGUMENTS,MYF(0),"HANDLER ... READ"); my_error(ER_WRONG_ARGUMENTS,MYF(0),"HANDLER ... READ");

View File

@ -611,8 +611,7 @@ int send_variant_2_list(MEM_ROOT *mem_root, Protocol *protocol,
SQL_SELECT *prepare_simple_select(THD *thd, Item *cond, SQL_SELECT *prepare_simple_select(THD *thd, Item *cond,
TABLE *table, int *error) TABLE *table, int *error)
{ {
if (!cond->fixed) cond->fix_fields_if_needed(thd, &cond); // can never fail
cond->fix_fields(thd, &cond); // can never fail
/* Assume that no indexes cover all required fields */ /* Assume that no indexes cover all required fields */
table->covering_keys.clear_all(); table->covering_keys.clear_all();

View File

@ -1317,7 +1317,7 @@ static bool check_view_insertability(THD * thd, TABLE_LIST *view)
/* check simplicity and prepare unique test of view */ /* check simplicity and prepare unique test of view */
for (trans= trans_start; trans != trans_end; trans++) for (trans= trans_start; trans != trans_end; trans++)
{ {
if (!trans->item->fixed && trans->item->fix_fields(thd, &trans->item)) if (trans->item->fix_fields_if_needed(thd, &trans->item))
{ {
thd->column_usage= saved_column_usage; thd->column_usage= saved_column_usage;
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);

View File

@ -2682,15 +2682,9 @@ ha_rows st_select_lex::get_offset()
if (offset_limit) if (offset_limit)
{ {
// see comment for st_select_lex::get_limit() // see comment for st_select_lex::get_limit()
bool fix_fields_successful= true; bool err= offset_limit->fix_fields_if_needed(master_unit()->thd, NULL);
if (!offset_limit->fixed) DBUG_ASSERT(!err);
{ val= err ? HA_POS_ERROR : offset_limit->val_uint();
fix_fields_successful= !offset_limit->fix_fields(master_unit()->thd,
NULL);
DBUG_ASSERT(fix_fields_successful);
}
val= fix_fields_successful ? offset_limit->val_uint() : HA_POS_ERROR;
} }
return (ha_rows)val; return (ha_rows)val;
@ -2729,15 +2723,9 @@ ha_rows st_select_lex::get_limit()
fix_fields() implementation. Also added runtime check against a result fix_fields() implementation. Also added runtime check against a result
of fix_fields() in order to handle error condition in non-debug build. of fix_fields() in order to handle error condition in non-debug build.
*/ */
bool fix_fields_successful= true; bool err= select_limit->fix_fields_if_needed(master_unit()->thd, NULL);
if (!select_limit->fixed) DBUG_ASSERT(!err);
{ val= err ? HA_POS_ERROR : select_limit->val_uint();
fix_fields_successful= !select_limit->fix_fields(master_unit()->thd,
NULL);
DBUG_ASSERT(fix_fields_successful);
}
val= fix_fields_successful ? select_limit->val_uint() : HA_POS_ERROR;
} }
return (ha_rows)val; return (ha_rows)val;

View File

@ -3328,7 +3328,7 @@ public:
List_iterator_fast<Item> param_it(prepared_stmt_params); List_iterator_fast<Item> param_it(prepared_stmt_params);
while (Item *param= param_it++) while (Item *param= param_it++)
{ {
if (param->fix_fields(thd, 0) || param->check_cols(1)) if (param->fix_fields_if_needed_for_scalar(thd, 0))
return true; return true;
} }
return false; return false;

View File

@ -3709,8 +3709,7 @@ mysql_execute_command(THD *thd)
Item **it= lex->value_list.head_ref(); Item **it= lex->value_list.head_ref();
if (!(*it)->basic_const_item() || if (!(*it)->basic_const_item() ||
(!(*it)->fixed && (*it)->fix_fields(lex->thd, it)) || (*it)->fix_fields_if_needed_for_scalar(lex->thd, it))
(*it)->check_cols(1))
{ {
my_message(ER_SET_CONSTANTS_ONLY, ER_THD(thd, ER_SET_CONSTANTS_ONLY), my_message(ER_SET_CONSTANTS_ONLY, ER_THD(thd, ER_SET_CONSTANTS_ONLY),
MYF(0)); MYF(0));
@ -3819,8 +3818,7 @@ mysql_execute_command(THD *thd)
goto error; goto error;
/* PURGE MASTER LOGS BEFORE 'data' */ /* PURGE MASTER LOGS BEFORE 'data' */
it= (Item *)lex->value_list.head(); it= (Item *)lex->value_list.head();
if ((!it->fixed && it->fix_fields(lex->thd, &it)) || if (it->fix_fields_if_needed_for_scalar(lex->thd, &it))
it->check_cols(1))
{ {
my_error(ER_WRONG_ARGUMENTS, MYF(0), "PURGE LOGS BEFORE"); my_error(ER_WRONG_ARGUMENTS, MYF(0), "PURGE LOGS BEFORE");
goto error; goto error;
@ -5680,7 +5678,7 @@ end_with_restore_list:
if (lex->kill_type == KILL_TYPE_ID || lex->kill_type == KILL_TYPE_QUERY) if (lex->kill_type == KILL_TYPE_ID || lex->kill_type == KILL_TYPE_QUERY)
{ {
Item *it= (Item *)lex->value_list.head(); Item *it= (Item *)lex->value_list.head();
if ((!it->fixed && it->fix_fields(lex->thd, &it)) || it->check_cols(1)) if (it->fix_fields_if_needed_for_scalar(lex->thd, &it))
{ {
my_message(ER_SET_CONSTANTS_ONLY, ER_THD(thd, ER_SET_CONSTANTS_ONLY), my_message(ER_SET_CONSTANTS_ONLY, ER_THD(thd, ER_SET_CONSTANTS_ONLY),
MYF(0)); MYF(0));

View File

@ -146,7 +146,7 @@ Item* convert_charset_partition_constant(Item *item, CHARSET_INFO *cs)
item= item->safe_charset_converter(thd, cs); item= item->safe_charset_converter(thd, cs);
context->table_list= NULL; context->table_list= NULL;
thd->where= "convert character set partition constant"; thd->where= "convert character set partition constant";
if (!item || item->fix_fields(thd, (Item**)NULL)) if (item->fix_fields_if_needed(thd, (Item**)NULL))
item= NULL; item= NULL;
thd->where= save_where; thd->where= save_where;
context->table_list= save_list; context->table_list= save_list;
@ -859,7 +859,7 @@ static bool fix_fields_part_func(THD *thd, Item* func_expr, TABLE *table,
const nesting_map saved_allow_sum_func= thd->lex->allow_sum_func; const nesting_map saved_allow_sum_func= thd->lex->allow_sum_func;
thd->lex->allow_sum_func= 0; thd->lex->allow_sum_func= 0;
if (likely(!(error= func_expr->fix_fields(thd, (Item**)&func_expr)))) if (likely(!(error= func_expr->fix_fields_if_needed(thd, (Item**)&func_expr))))
func_expr->walk(&Item::post_fix_fields_part_expr_processor, 0, NULL); func_expr->walk(&Item::post_fix_fields_part_expr_processor, 0, NULL);
/* /*

View File

@ -1656,8 +1656,7 @@ static bool mysql_test_call_fields(Prepared_statement *stmt,
while ((item= it++)) while ((item= it++))
{ {
if ((!item->fixed && item->fix_fields(thd, it.ref())) || if (item->fix_fields_if_needed_for_scalar(thd, it.ref()))
item->check_cols(1))
goto err; goto err;
} }
DBUG_RETURN(FALSE); DBUG_RETURN(FALSE);
@ -2665,8 +2664,7 @@ end:
bool LEX::get_dynamic_sql_string(LEX_CSTRING *dst, String *buffer) bool LEX::get_dynamic_sql_string(LEX_CSTRING *dst, String *buffer)
{ {
if (prepared_stmt_code->fix_fields(thd, NULL) || if (prepared_stmt_code->fix_fields_if_needed_for_scalar(thd, NULL))
prepared_stmt_code->check_cols(1))
return true; return true;
const String *str= prepared_stmt_code->val_str(buffer); const String *str= prepared_stmt_code->val_str(buffer);

View File

@ -531,7 +531,7 @@ fix_inner_refs(THD *thd, List<Item> &all_fields, SELECT_LEX *select,
ref->outer_ref= new_ref; ref->outer_ref= new_ref;
ref->ref= &ref->outer_ref; ref->ref= &ref->outer_ref;
if (!ref->fixed && ref->fix_fields(thd, 0)) if (ref->fix_fields_if_needed(thd, 0))
return TRUE; return TRUE;
thd->lex->used_tables|= item->used_tables(); thd->lex->used_tables|= item->used_tables();
thd->lex->current_select->select_list_tables|= item->used_tables(); thd->lex->current_select->select_list_tables|= item->used_tables();
@ -1140,9 +1140,7 @@ JOIN::prepare(TABLE_LIST *tables_init,
if (having->type() == Item::REF_ITEM && if (having->type() == Item::REF_ITEM &&
((Item_ref *)having)->ref_type() == Item_ref::REF) ((Item_ref *)having)->ref_type() == Item_ref::REF)
wrap_ident(thd, &having); wrap_ident(thd, &having);
bool having_fix_rc= (!having->fixed && bool having_fix_rc= having->fix_fields_if_needed_for_bool(thd, &having);
(having->fix_fields(thd, &having) ||
having->check_cols(1)));
select_lex->having_fix_field= 0; select_lex->having_fix_field= 0;
if (unlikely(having_fix_rc || thd->is_error())) if (unlikely(having_fix_rc || thd->is_error()))
@ -2667,10 +2665,10 @@ bool JOIN::add_having_as_table_cond(JOIN_TAB *tab)
sort_table_cond))) sort_table_cond)))
DBUG_RETURN(true); DBUG_RETURN(true);
} }
if (tab->select->cond && !tab->select->cond->fixed) if (tab->select->cond)
tab->select->cond->fix_fields(thd, 0); tab->select->cond->fix_fields_if_needed(thd, 0);
if (tab->pre_idx_push_select_cond && !tab->pre_idx_push_select_cond->fixed) if (tab->pre_idx_push_select_cond)
tab->pre_idx_push_select_cond->fix_fields(thd, 0); tab->pre_idx_push_select_cond->fix_fields_if_needed(thd, 0);
tab->select->pre_idx_push_select_cond= tab->pre_idx_push_select_cond; tab->select->pre_idx_push_select_cond= tab->pre_idx_push_select_cond;
tab->set_select_cond(tab->select->cond, __LINE__); tab->set_select_cond(tab->select->cond, __LINE__);
tab->select_cond->top_level_item(); tab->select_cond->top_level_item();
@ -9340,7 +9338,7 @@ bool JOIN::inject_cond_into_where(Item *injected_cond)
} }
where_item= and_items(thd, conds, where_item); where_item= and_items(thd, conds, where_item);
if (!where_item->fixed && where_item->fix_fields(thd, 0)) if (where_item->fix_fields_if_needed(thd, 0))
return true; return true;
thd->change_item_tree(&select_lex->where, where_item); thd->change_item_tree(&select_lex->where, where_item);
select_lex->where->top_level_item(); select_lex->where->top_level_item();
@ -22896,8 +22894,8 @@ find_order_in_list(THD *thd, Ref_ptr_array ref_pointer_array,
original field name, we should additionally check if we have conflict original field name, we should additionally check if we have conflict
for this name (in case if we would perform lookup in all tables). for this name (in case if we would perform lookup in all tables).
*/ */
if (resolution == RESOLVED_BEHIND_ALIAS && !order_item->fixed && if (resolution == RESOLVED_BEHIND_ALIAS &&
order_item->fix_fields(thd, order->item)) order_item->fix_fields_if_needed_for_order_by(thd, order->item))
return TRUE; return TRUE;
/* Lookup the current GROUP field in the FROM clause. */ /* Lookup the current GROUP field in the FROM clause. */
@ -22978,11 +22976,10 @@ find_order_in_list(THD *thd, Ref_ptr_array ref_pointer_array,
We check order_item->fixed because Item_func_group_concat can put We check order_item->fixed because Item_func_group_concat can put
arguments for which fix_fields already was called. arguments for which fix_fields already was called.
*/ */
if (!order_item->fixed && if (order_item->fix_fields_if_needed_for_order_by(thd, order->item) ||
(order_item->fix_fields(thd, order->item) || thd->is_error())
(order_item= *order->item)->check_cols(1) ||
thd->is_error()))
return TRUE; /* Wrong field. */ return TRUE; /* Wrong field. */
order_item= *order->item; // Item can change during fix_fields()
if (!add_to_all_fields) if (!add_to_all_fields)
return FALSE; return FALSE;
@ -24280,7 +24277,7 @@ static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab)
{ {
Item *new_cond= and_conds(thd, cond_copy, Item *new_cond= and_conds(thd, cond_copy,
join_tab->select->pre_idx_push_select_cond); join_tab->select->pre_idx_push_select_cond);
if (!new_cond->fixed && new_cond->fix_fields(thd, &new_cond)) if (new_cond->fix_fields_if_needed(thd, &new_cond))
error= 1; error= 1;
join_tab->pre_idx_push_select_cond= join_tab->pre_idx_push_select_cond=
join_tab->select->pre_idx_push_select_cond= new_cond; join_tab->select->pre_idx_push_select_cond= new_cond;

View File

@ -8455,8 +8455,7 @@ int mysql_schema_table(THD *thd, LEX *lex, TABLE_LIST *table_list)
Field_translator *end= table_list->field_translation_end; Field_translator *end= table_list->field_translation_end;
for (transl= table_list->field_translation; transl < end; transl++) for (transl= table_list->field_translation; transl < end; transl++)
{ {
if (!transl->item->fixed && if (transl->item->fix_fields_if_needed(thd, &transl->item))
transl->item->fix_fields(thd, &transl->item))
DBUG_RETURN(1); DBUG_RETURN(1);
} }
DBUG_RETURN(0); DBUG_RETURN(0);
@ -8473,11 +8472,9 @@ int mysql_schema_table(THD *thd, LEX *lex, TABLE_LIST *table_list)
{ {
transl->item= item; transl->item= item;
transl->name= item->name; transl->name= item->name;
if (!item->fixed && item->fix_fields(thd, &transl->item)) if (item->fix_fields_if_needed(thd, &transl->item))
{
DBUG_RETURN(1); DBUG_RETURN(1);
} }
}
table_list->field_translation= org_transl; table_list->field_translation= org_transl;
table_list->field_translation_end= transl; table_list->field_translation_end= transl;
} }

View File

@ -218,16 +218,9 @@ int Sql_cmd_common_signal::eval_signal_informations(THD *thd, Sql_condition *con
i <= LAST_DIAG_SET_PROPERTY; i <= LAST_DIAG_SET_PROPERTY;
i++) i++)
{ {
set= m_set_signal_information.m_item[i]; if ((set= m_set_signal_information.m_item[i]) &&
if (set) set->fix_fields_if_needed(thd, &m_set_signal_information.m_item[i]))
{
if (! set->fixed)
{
if (set->fix_fields(thd, & set))
goto end; goto end;
m_set_signal_information.m_item[i]= set;
}
}
} }
/* /*

View File

@ -797,8 +797,7 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables,
*/ */
trg_field->setup_field(thd, table, NULL); trg_field->setup_field(thd, table, NULL);
if (!trg_field->fixed && if (trg_field->fix_fields_if_needed(thd, (Item **)0))
trg_field->fix_fields(thd, (Item **)0))
DBUG_RETURN(true); DBUG_RETURN(true);
} }

View File

@ -1938,7 +1938,7 @@ bool check_key_in_view(THD *thd, TABLE_LIST *view)
DBUG_PRINT("info", ("thd->column_usage: %d", thd->column_usage)); DBUG_PRINT("info", ("thd->column_usage: %d", thd->column_usage));
for (Field_translator *fld= trans; fld < end_of_trans; fld++) for (Field_translator *fld= trans; fld < end_of_trans; fld++)
{ {
if (!fld->item->fixed && fld->item->fix_fields(thd, &fld->item)) if (fld->item->fix_fields_if_needed(thd, &fld->item))
{ {
thd->column_usage= saved_column_usage; thd->column_usage= saved_column_usage;
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);

View File

@ -4886,10 +4886,8 @@ bool TABLE_LIST::prep_where(THD *thd, Item **conds,
{ {
if (where->fixed) if (where->fixed)
where->update_used_tables(); where->update_used_tables();
if (!where->fixed && where->fix_fields(thd, &where)) else if (where->fix_fields(thd, &where))
{
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
}
/* /*
check that it is not VIEW in which we insert with INSERT SELECT check that it is not VIEW in which we insert with INSERT SELECT
@ -4919,12 +4917,12 @@ bool TABLE_LIST::prep_where(THD *thd, Item **conds,
} }
if (tbl == 0) if (tbl == 0)
{ {
if (*conds && !(*conds)->fixed) if (*conds)
res= (*conds)->fix_fields(thd, conds); res= (*conds)->fix_fields_if_needed_for_bool(thd, conds);
if (!res) if (!res)
*conds= and_conds(thd, *conds, where->copy_andor_structure(thd)); *conds= and_conds(thd, *conds, where->copy_andor_structure(thd));
if (*conds && !(*conds)->fixed && !res) if (*conds && !res)
res= (*conds)->fix_fields(thd, conds); res= (*conds)->fix_fields_if_needed_for_bool(thd, conds);
} }
if (arena) if (arena)
thd->restore_active_arena(arena, &backup); thd->restore_active_arena(arena, &backup);
@ -5071,12 +5069,8 @@ bool TABLE_LIST::prep_check_option(THD *thd, uint8 check_opt_type)
{ {
const char *save_where= thd->where; const char *save_where= thd->where;
thd->where= "check option"; thd->where= "check option";
if ((!check_option->fixed && if (check_option->fix_fields_if_needed_for_bool(thd, &check_option))
check_option->fix_fields(thd, &check_option)) ||
check_option->check_cols(1))
{
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
}
thd->where= save_where; thd->where= save_where;
} }
DBUG_RETURN(FALSE); DBUG_RETURN(FALSE);
@ -8933,7 +8927,7 @@ bool Vers_history_point::resolve_unit(THD *thd)
{ {
if (!item) if (!item)
return false; return false;
if (!item->fixed && item->fix_fields(thd, &item)) if (item->fix_fields_if_needed(thd, &item))
return true; return true;
return item->this_item()->type_handler_for_system_time()-> return item->this_item()->type_handler_for_system_time()->
Vers_history_point_resolve_unit(thd, this); Vers_history_point_resolve_unit(thd, this);

View File

@ -1082,9 +1082,8 @@ static bool make_empty_rec(THD *thd, uchar *buff, uint table_options,
field->real_field_type() == MYSQL_TYPE_GEOMETRY)) field->real_field_type() == MYSQL_TYPE_GEOMETRY))
{ {
Item *expr= field->default_value->expr; Item *expr= field->default_value->expr;
// may be already fixed if ALTER TABLE
int res= !expr->fixed && // may be already fixed if ALTER TABLE int res= expr->fix_fields_if_needed(thd, &expr);
expr->fix_fields(thd, &expr);
if (!res) if (!res)
res= expr->save_in_field(regfield, 1); res= expr->save_in_field(regfield, 1);
if (!res && (field->flags & BLOB_FLAG)) if (!res && (field->flags & BLOB_FLAG))