summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/subselect.result6
-rw-r--r--mysql-test/t/subselect.test7
-rw-r--r--sql/item.cc33
-rw-r--r--sql/item_cmpfunc.cc5
-rw-r--r--sql/item_func.cc5
-rw-r--r--sql/item_row.cc18
-rw-r--r--sql/item_subselect.cc4
-rw-r--r--sql/item_sum.cc10
-rw-r--r--sql/log_event.cc4
-rw-r--r--sql/set_var.cc2
-rw-r--r--sql/sql_base.cc3
-rw-r--r--sql/sql_class.cc6
-rw-r--r--sql/sql_handler.cc6
13 files changed, 73 insertions, 36 deletions
diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result
index 03bb588fec9..1b96faa04af 100644
--- a/mysql-test/r/subselect.result
+++ b/mysql-test/r/subselect.result
@@ -1624,3 +1624,9 @@ select 2 in (select * from t1);
1
SET SQL_SELECT_LIMIT=default;
drop table t1;
+create table t1(val varchar(10));
+insert into t1 values ('aaa'), ('bbb'),('eee'),('mmm'),('ppp');
+select count(*) from t1 as w1 where w1.val in (select w2.val from t1 as w2 where w2.val like 'm%') and w1.val in (select w3.val from t1 as w3 where w3.val like 'e%');
+count(*)
+0
+drop table if exists t1;
diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test
index 1a33890360d..191e12bef5d 100644
--- a/mysql-test/t/subselect.test
+++ b/mysql-test/t/subselect.test
@@ -1066,3 +1066,10 @@ select 2 in (select * from t1);
SET SQL_SELECT_LIMIT=default;
drop table t1;
+#
+# Item_cond fix field
+#
+create table t1(val varchar(10));
+insert into t1 values ('aaa'), ('bbb'),('eee'),('mmm'),('ppp');
+select count(*) from t1 as w1 where w1.val in (select w2.val from t1 as w2 where w2.val like 'm%') and w1.val in (select w3.val from t1 as w3 where w3.val like 'e%');
+drop table if exists t1;
diff --git a/sql/item.cc b/sql/item.cc
index 5aaeffff5d2..fb8fbbd8556 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -928,6 +928,10 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
(char *)field_name);
if (!rf)
return 1;
+ /*
+ rf is Item_ref => never substitute other items (in this case)
+ during fix_fields() => we can use rf after fix_fields()
+ */
if (rf->fix_fields(thd, tables, ref) || rf->check_cols(1))
return 1;
@@ -946,6 +950,10 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
(char *)field_name);
if (!rf)
return 1;
+ /*
+ rf is Item_ref => never substitute other items (in this case)
+ during fix_fields() => we can use rf after fix_fields()
+ */
return rf->fix_fields(thd, tables, ref) || rf->check_cols(1);
}
}
@@ -1658,16 +1666,15 @@ bool Item_default_value::eq(const Item *item, bool binary_cmp) const
}
-bool Item_default_value::fix_fields(THD *thd, struct st_table_list *table_list, Item **items)
+bool Item_default_value::fix_fields(THD *thd,
+ struct st_table_list *table_list,
+ Item **items)
{
if (!arg)
- return false;
- bool res= arg->fix_fields(thd, table_list, items);
- if (res)
- return res;
- /* arg->type() can be only REF_ITEM or FIELD_ITEM for it defined as
- simple_ident in sql_yacc.yy
- */
+ return 0;
+ if (arg->fix_fields(thd, table_list, &arg))
+ return 1;
+
if (arg->type() == REF_ITEM)
{
Item_ref *ref= (Item_ref *)arg;
@@ -1711,13 +1718,9 @@ bool Item_insert_value::fix_fields(THD *thd,
struct st_table_list *table_list,
Item **items)
{
- bool res= arg->fix_fields(thd, table_list, items);
- if (res)
- return res;
- /*
- arg->type() can be only REF_ITEM or FIELD_ITEM as arg is
- a simple_ident in sql_yacc.yy
- */
+ if (arg->fix_fields(thd, table_list, &arg))
+ return 1;
+
if (arg->type() == REF_ITEM)
{
Item_ref *ref= (Item_ref *)arg;
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index f0bc73e9501..b56ad6febd4 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -1775,8 +1775,11 @@ Item_cond::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
}
if (abort_on_null)
item->top_level_item();
+
+ // item can be substituted in fix_fields
if ((!item->fixed &&
- item->fix_fields(thd, tables, li.ref())) || item->check_cols(1))
+ item->fix_fields(thd, tables, li.ref())) ||
+ (item= *li.ref())->check_cols(1))
return 1; /* purecov: inspected */
used_tables_cache|= item->used_tables();
tmp_table_map= item->not_null_tables();
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 0327204dbfd..817bd2b866b 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -1469,8 +1469,11 @@ udf_handler::fix_fields(THD *thd, TABLE_LIST *tables, Item_result_field *func,
arg != arg_end ;
arg++,i++)
{
+ if ((*arg)->fix_fields(thd, tables, arg))
+ return 1;
+ // we can't assign 'item' before, because fix_fields() can change arg
Item *item= *arg;
- if (item->fix_fields(thd, tables, arg) || item->check_cols(1))
+ if (item->check_cols(1))
return 1;
/*
TODO: We should think about this. It is not always
diff --git a/sql/item_row.cc b/sql/item_row.cc
index 7f847bd1d4e..2b0cd38e3c1 100644
--- a/sql/item_row.cc
+++ b/sql/item_row.cc
@@ -62,19 +62,21 @@ bool Item_row::fix_fields(THD *thd, TABLE_LIST *tabl, Item **ref)
{
if ((*arg)->fix_fields(thd, tabl, arg))
return 1;
- used_tables_cache |= (*arg)->used_tables();
- if (const_item_cache&= (*arg)->const_item() && !with_null)
+ // we can't assign 'item' before, because fix_fields() can change arg
+ Item *item= *arg;
+ used_tables_cache |= item->used_tables();
+ if (const_item_cache&= item->const_item() && !with_null)
{
- if ((*arg)->cols() > 1)
- with_null|= (*arg)->null_inside();
+ if (item->cols() > 1)
+ with_null|= item->null_inside();
else
{
- (*arg)->val_int();
- with_null|= (*arg)->null_value;
+ item->val_int();
+ with_null|= item->null_value;
}
}
- maybe_null|= (*arg)->maybe_null;
- with_sum_func= with_sum_func || (*arg)->with_sum_func;
+ maybe_null|= item->maybe_null;
+ with_sum_func= with_sum_func || item->with_sum_func;
}
return 0;
}
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index 372f086d464..323eb70e258 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -650,8 +650,8 @@ Item_in_subselect::single_value_transformer(JOIN *join,
*select_lex->ref_pointer_array= item;
select_lex->item_list.empty();
select_lex->item_list.push_back(item);
-
- if (item->fix_fields(thd, join->tables_list, &item))
+
+ if (item->fix_fields(thd, join->tables_list, )select_lex->item_list.head_ref())
goto err;
subs= new Item_singlerow_subselect(select_lex);
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index 879c5f99ebd..77a910ae5d6 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -191,17 +191,21 @@ Item_sum_num::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
bool
Item_sum_hybrid::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
{
- Item *item=args[0];
+ Item *item= args[0];
if (!thd->allow_sum_func)
{
my_error(ER_INVALID_GROUP_FUNC_USE,MYF(0));
return 1;
}
thd->allow_sum_func=0; // No included group funcs
+
+ // 'item' can be changed during fix_fields
if (!item->fixed &&
- item->fix_fields(thd, tables, args) || item->check_cols(1))
+ item->fix_fields(thd, tables, args) ||
+ (item= args[0])->check_cols(1))
return 1;
- hybrid_type=item->result_type();
+
+ hybrid_type= item->result_type();
if (hybrid_type == INT_RESULT)
{
cmp_charset= &my_charset_bin;
diff --git a/sql/log_event.cc b/sql/log_event.cc
index a128b5809b2..0bcaff22f0f 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -2344,6 +2344,10 @@ int User_var_log_event::exec_event(struct st_relay_log_info* rli)
}
}
Item_func_set_user_var e(user_var_name, it);
+ /*
+ Item_func_set_user_var can't substitute something else on its place =>
+ 0 can be passed as last argument (reference on item)
+ */
e.fix_fields(thd, 0, 0);
e.update_hash(val, val_len, type, charset, DERIVATION_NONE);
free_root(&thd->mem_root,0);
diff --git a/sql/set_var.cc b/sql/set_var.cc
index 04fe2a8ea46..90c42035a91 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -2500,7 +2500,7 @@ int set_var_user::check(THD *thd)
{
/*
Item_func_set_user_var can't substitute something else on its place =>
- 0 can be passed as last argument
+ 0 can be passed as last argument (reference on item)
*/
return (user_var_item->fix_fields(thd, 0, (Item**) 0) ||
user_var_item->check()) ? -1 : 0;
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 37767c555e8..bdbb14f0819 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -2141,9 +2141,8 @@ int setup_fields(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
while ((item= it++))
{
if (item->fix_fields(thd, tables, it.ref()) ||
- item->check_cols(1))
+ (item= *(it.ref()))->check_cols(1))
DBUG_RETURN(-1); /* purecov: inspected */
- item= *(it.ref()); //Item can be changed in fix fields
if (ref)
*(ref++)= item;
if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM &&
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 95374b691c8..945414f532b 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -1169,8 +1169,12 @@ int select_dumpvar::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
{
ls= gl++;
Item_func_set_user_var *xx = new Item_func_set_user_var(*ls,item);
+ /*
+ Item_func_set_user_var can't substitute something else on its place =>
+ 0 can be passed as last argument (reference on item)
+ */
xx->fix_fields(thd,(TABLE_LIST*) thd->lex->select_lex.table_list.first,
- &item);
+ 0);
xx->fix_length_and_dec();
vars.push_back(xx);
}
diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc
index d0f241b3291..881f75566cd 100644
--- a/sql/sql_handler.cc
+++ b/sql/sql_handler.cc
@@ -207,11 +207,13 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
MYF(0),keyinfo->key_parts);
goto err;
}
- List_iterator_fast<Item> it_ke(*key_expr);
+ List_iterator<Item> it_ke(*key_expr);
Item *item;
for (key_len=0 ; (item=it_ke++) ; key_part++)
{
- if (item->fix_fields(thd, tables, &item))
+ // 'item' can be changed by fix_fields() call
+ if (item->fix_fields(thd, tables, it_ke.ref()) ||
+ (item= *it_ke.ref())->check_cols(1))
goto err;
if (item->used_tables() & ~RAND_TABLE_BIT)
{