Commit 3190b21f authored by unknown's avatar unknown

Fix bug #14482 Wrongly applied optimization in resolve_const_item() caused

crash

resolve_const_item() substitutes item which will evaluate to constant with
equvalent constant item, basing on the item's result type. In this case
subselect was resolved as constant, and resolve_const_item() was substituting
it's result's Item_caches to Item_null. Later Item_cache's function was called
for Item_null object, which caused server crash.

resolve_const_item() now substitutes constants for items with 
result_type == ROW_RESULT only for Item_rows.


sql/item.cc:
  Fix bug #14482 Wrongly applied optimization in resolve_const_item() caused
  crash
  
  resolve_const_item() now applies optimization for items with
  result_type == ROW_RESULT only to Item_rows.
mysql-test/t/select.test:
  Test case for bug #14482 Wrongly applied optimization in resolve_const_item() caused crash
mysql-test/r/select.result:
  Test case for bug #14482 Wrongly applied optimization in resolve_const_item() caused crash
parent 1484d548
...@@ -2706,3 +2706,11 @@ select distinct count(f2) >0 from t1 left join t2 on f1=f3 group by f1; ...@@ -2706,3 +2706,11 @@ select distinct count(f2) >0 from t1 left join t2 on f1=f3 group by f1;
count(f2) >0 count(f2) >0
1 1
drop table t1,t2; drop table t1,t2;
create table t1 (f1 int,f2 int);
insert into t1 values(1,1);
create table t2 (f3 int, f4 int, primary key(f3,f4));
insert into t2 values(1,1);
select * from t1 where f1 in (select f3 from t2 where (f3,f4)= (select f3,f4 from t2));
f1 f2
1 1
drop table t1,t2;
...@@ -2237,4 +2237,15 @@ insert into t1 values (1,1); ...@@ -2237,4 +2237,15 @@ insert into t1 values (1,1);
insert into t2 values (1,1),(1,2); insert into t2 values (1,1),(1,2);
select distinct count(f2) >0 from t1 left join t2 on f1=f3 group by f1; select distinct count(f2) >0 from t1 left join t2 on f1=f3 group by f1;
drop table t1,t2; drop table t1,t2;
#
# Bug #14482 Server crash when subselecting from the same table
#
create table t1 (f1 int,f2 int);
insert into t1 values(1,1);
create table t2 (f3 int, f4 int, primary key(f3,f4));
insert into t2 values(1,1);
select * from t1 where f1 in (select f3 from t2 where (f3,f4)= (select f3,f4 from t2));
drop table t1,t2;
# End of 4.1 tests # End of 4.1 tests
...@@ -2863,7 +2863,7 @@ Item_result item_cmp_type(Item_result a,Item_result b) ...@@ -2863,7 +2863,7 @@ Item_result item_cmp_type(Item_result a,Item_result b)
void resolve_const_item(THD *thd, Item **ref, Item *comp_item) void resolve_const_item(THD *thd, Item **ref, Item *comp_item)
{ {
Item *item= *ref; Item *item= *ref;
Item *new_item; Item *new_item= NULL;
if (item->basic_const_item()) if (item->basic_const_item())
return; // Can't be better return; // Can't be better
Item_result res_type=item_cmp_type(comp_item->result_type(), Item_result res_type=item_cmp_type(comp_item->result_type(),
...@@ -2892,8 +2892,17 @@ void resolve_const_item(THD *thd, Item **ref, Item *comp_item) ...@@ -2892,8 +2892,17 @@ void resolve_const_item(THD *thd, Item **ref, Item *comp_item)
new_item= (null_value ? (Item*) new Item_null(name) : new_item= (null_value ? (Item*) new Item_null(name) :
(Item*) new Item_int(name, result, length)); (Item*) new Item_int(name, result, length));
} }
else if (res_type == ROW_RESULT) else if (res_type == ROW_RESULT && item->type() == Item::ROW_ITEM &&
comp_item->type() == Item::ROW_ITEM)
{ {
/*
Substitute constants only in Item_rows. Don't affect other Items
with ROW_RESULT (eg Item_singlerow_subselect).
For such Items more optimal is to detect if it is constant and replace
it with Item_row. This would optimize queries like this:
SELECT * FROM t1 WHERE (a,b) = (SELECT a,b FROM t2 LIMIT 1);
*/
Item_row *item_row= (Item_row*) item; Item_row *item_row= (Item_row*) item;
Item_row *comp_item_row= (Item_row*) comp_item; Item_row *comp_item_row= (Item_row*) comp_item;
uint col; uint col;
...@@ -2910,7 +2919,7 @@ void resolve_const_item(THD *thd, Item **ref, Item *comp_item) ...@@ -2910,7 +2919,7 @@ void resolve_const_item(THD *thd, Item **ref, Item *comp_item)
while (col-- > 0) while (col-- > 0)
resolve_const_item(thd, item_row->addr(col), comp_item_row->el(col)); resolve_const_item(thd, item_row->addr(col), comp_item_row->el(col));
} }
else else if (res_type == REAL_RESULT)
{ // It must REAL_RESULT { // It must REAL_RESULT
double result=item->val(); double result=item->val();
uint length=item->max_length,decimals=item->decimals; uint length=item->max_length,decimals=item->decimals;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment