Commit 05f21b21 authored by unknown's avatar unknown

Fixed LP BUG#615378 Incorrect processing of NULL result in Item_cache fixed.

parent b67be0b2
...@@ -3272,3 +3272,41 @@ FROM t2 ) AND table1 .`col_varchar_key` OR table1 .`pk` ; ...@@ -3272,3 +3272,41 @@ FROM t2 ) AND table1 .`col_varchar_key` OR table1 .`pk` ;
col_varchar_nokey col_varchar_nokey
drop table t1,t2; drop table t1,t2;
set @@optimizer_switch= default; set @@optimizer_switch= default;
# LP BUG#615378 (incorrect NULL result returning in Item_cache)
CREATE TABLE `t1` (
`pk` int(11) NOT NULL AUTO_INCREMENT,
`col_varchar_key` varchar(1) DEFAULT NULL,
PRIMARY KEY (`pk`),
KEY `col_varchar_key` (`col_varchar_key`)
) DEFAULT CHARSET=latin1;
INSERT INTO `t1` VALUES (10,'v');
INSERT INTO `t1` VALUES (11,'r');
CREATE TABLE `t2` (
`pk` int(11) NOT NULL AUTO_INCREMENT,
`col_varchar_key` varchar(1) DEFAULT NULL,
PRIMARY KEY (`pk`),
KEY `col_varchar_key` (`col_varchar_key`)
) DEFAULT CHARSET=latin1;
INSERT INTO `t2` VALUES (1,'r');
INSERT INTO `t2` VALUES (2,'c');
CREATE TABLE `t3` (
`pk` int(11) NOT NULL AUTO_INCREMENT,
`col_varchar_key` varchar(1) DEFAULT NULL,
PRIMARY KEY (`pk`),
KEY `col_varchar_key` (`col_varchar_key`)
) DEFAULT CHARSET=latin1;
INSERT INTO `t3` VALUES (1,'w');
SELECT SUM( DISTINCT table2 . `pk` ) AS field2 ,
(SELECT SUM( SUBQUERY1_t2 . `pk` ) AS SUBQUERY1_field1
FROM t2 AS SUBQUERY1_t2 STRAIGHT_JOIN
t3 AS SUBQUERY1_t3 ON (SUBQUERY1_t3 . `pk` = SUBQUERY1_t2 . `pk` )
WHERE table1 . `col_varchar_key` ) AS field3
FROM ( t1 AS table1 LEFT JOIN
( t2 AS table2 STRAIGHT_JOIN
t3 AS table3 ON (table3 . `pk` = table2 . `pk` ) )
ON (table3 . `col_varchar_key` = table1 . `col_varchar_key` ) )
WHERE ( table1 . `pk` < 5 ) OR ( table1 . `col_varchar_key` IS NOT NULL)
GROUP BY field3
HAVING (field3 <= 'h' AND field2 != 4) ;
field2 field3
drop tables t1, t2, t3;
...@@ -1566,3 +1566,48 @@ FROM t2 ) AND table1 .`col_varchar_key` OR table1 .`pk` ; ...@@ -1566,3 +1566,48 @@ FROM t2 ) AND table1 .`col_varchar_key` OR table1 .`pk` ;
drop table t1,t2; drop table t1,t2;
set @@optimizer_switch= default; set @@optimizer_switch= default;
#
--echo # LP BUG#615378 (incorrect NULL result returning in Item_cache)
#
# if bug present here will be valgrind warnings (due to attempt to process
# uninialized decimal value) but the result will be correct (due to
# Item::null_value)
CREATE TABLE `t1` (
`pk` int(11) NOT NULL AUTO_INCREMENT,
`col_varchar_key` varchar(1) DEFAULT NULL,
PRIMARY KEY (`pk`),
KEY `col_varchar_key` (`col_varchar_key`)
) DEFAULT CHARSET=latin1;
INSERT INTO `t1` VALUES (10,'v');
INSERT INTO `t1` VALUES (11,'r');
CREATE TABLE `t2` (
`pk` int(11) NOT NULL AUTO_INCREMENT,
`col_varchar_key` varchar(1) DEFAULT NULL,
PRIMARY KEY (`pk`),
KEY `col_varchar_key` (`col_varchar_key`)
) DEFAULT CHARSET=latin1;
INSERT INTO `t2` VALUES (1,'r');
INSERT INTO `t2` VALUES (2,'c');
CREATE TABLE `t3` (
`pk` int(11) NOT NULL AUTO_INCREMENT,
`col_varchar_key` varchar(1) DEFAULT NULL,
PRIMARY KEY (`pk`),
KEY `col_varchar_key` (`col_varchar_key`)
) DEFAULT CHARSET=latin1;
INSERT INTO `t3` VALUES (1,'w');
SELECT SUM( DISTINCT table2 . `pk` ) AS field2 ,
(SELECT SUM( SUBQUERY1_t2 . `pk` ) AS SUBQUERY1_field1
FROM t2 AS SUBQUERY1_t2 STRAIGHT_JOIN
t3 AS SUBQUERY1_t3 ON (SUBQUERY1_t3 . `pk` = SUBQUERY1_t2 . `pk` )
WHERE table1 . `col_varchar_key` ) AS field3
FROM ( t1 AS table1 LEFT JOIN
( t2 AS table2 STRAIGHT_JOIN
t3 AS table3 ON (table3 . `pk` = table2 . `pk` ) )
ON (table3 . `col_varchar_key` = table1 . `col_varchar_key` ) )
WHERE ( table1 . `pk` < 5 ) OR ( table1 . `col_varchar_key` IS NOT NULL)
GROUP BY field3
HAVING (field3 <= 'h' AND field2 != 4) ;
drop tables t1, t2, t3;
...@@ -7750,8 +7750,11 @@ void Item_cache_int::store_longlong(Item *item, longlong val_arg) ...@@ -7750,8 +7750,11 @@ void Item_cache_int::store_longlong(Item *item, longlong val_arg)
String *Item_cache_int::val_str(String *str) String *Item_cache_int::val_str(String *str)
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
if (!value_cached && !cache_value()) if ((!value_cached && !cache_value()) || null_value)
{
null_value= TRUE;
return NULL; return NULL;
}
str->set(value, default_charset()); str->set(value, default_charset());
return str; return str;
} }
...@@ -7760,8 +7763,11 @@ String *Item_cache_int::val_str(String *str) ...@@ -7760,8 +7763,11 @@ String *Item_cache_int::val_str(String *str)
my_decimal *Item_cache_int::val_decimal(my_decimal *decimal_val) my_decimal *Item_cache_int::val_decimal(my_decimal *decimal_val)
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
if (!value_cached && !cache_value()) if ((!value_cached && !cache_value()) || null_value)
{
null_value= TRUE;
return NULL; return NULL;
}
int2my_decimal(E_DEC_FATAL_ERROR, value, unsigned_flag, decimal_val); int2my_decimal(E_DEC_FATAL_ERROR, value, unsigned_flag, decimal_val);
return decimal_val; return decimal_val;
} }
...@@ -7769,16 +7775,22 @@ my_decimal *Item_cache_int::val_decimal(my_decimal *decimal_val) ...@@ -7769,16 +7775,22 @@ my_decimal *Item_cache_int::val_decimal(my_decimal *decimal_val)
double Item_cache_int::val_real() double Item_cache_int::val_real()
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
if (!value_cached && !cache_value()) if ((!value_cached && !cache_value()) || null_value)
{
null_value= TRUE;
return 0.0; return 0.0;
}
return (double) value; return (double) value;
} }
longlong Item_cache_int::val_int() longlong Item_cache_int::val_int()
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
if (!value_cached && !cache_value()) if ((!value_cached && !cache_value()) || null_value)
{
null_value= TRUE;
return 0; return 0;
}
return value; return value;
} }
...@@ -7796,16 +7808,22 @@ bool Item_cache_real::cache_value() ...@@ -7796,16 +7808,22 @@ bool Item_cache_real::cache_value()
double Item_cache_real::val_real() double Item_cache_real::val_real()
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
if (!value_cached && !cache_value()) if ((!value_cached && !cache_value()) || null_value)
{
null_value= TRUE;
return 0.0; return 0.0;
}
return value; return value;
} }
longlong Item_cache_real::val_int() longlong Item_cache_real::val_int()
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
if (!value_cached && !cache_value()) if ((!value_cached && !cache_value()) || null_value)
{
null_value= TRUE;
return 0; return 0;
}
return (longlong) rint(value); return (longlong) rint(value);
} }
...@@ -7813,8 +7831,11 @@ longlong Item_cache_real::val_int() ...@@ -7813,8 +7831,11 @@ longlong Item_cache_real::val_int()
String* Item_cache_real::val_str(String *str) String* Item_cache_real::val_str(String *str)
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
if (!value_cached && !cache_value()) if ((!value_cached && !cache_value()) || null_value)
{
null_value= TRUE;
return NULL; return NULL;
}
str->set_real(value, decimals, default_charset()); str->set_real(value, decimals, default_charset());
return str; return str;
} }
...@@ -7823,8 +7844,11 @@ String* Item_cache_real::val_str(String *str) ...@@ -7823,8 +7844,11 @@ String* Item_cache_real::val_str(String *str)
my_decimal *Item_cache_real::val_decimal(my_decimal *decimal_val) my_decimal *Item_cache_real::val_decimal(my_decimal *decimal_val)
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
if (!value_cached && !cache_value()) if ((!value_cached && !cache_value()) || null_value)
{
null_value= TRUE;
return NULL; return NULL;
}
double2my_decimal(E_DEC_FATAL_ERROR, value, decimal_val); double2my_decimal(E_DEC_FATAL_ERROR, value, decimal_val);
return decimal_val; return decimal_val;
} }
...@@ -7845,8 +7869,11 @@ double Item_cache_decimal::val_real() ...@@ -7845,8 +7869,11 @@ double Item_cache_decimal::val_real()
{ {
DBUG_ASSERT(fixed); DBUG_ASSERT(fixed);
double res; double res;
if (!value_cached && !cache_value()) if ((!value_cached && !cache_value()) || null_value)
{
null_value= TRUE;
return 0.0; return 0.0;
}
my_decimal2double(E_DEC_FATAL_ERROR, &decimal_value, &res); my_decimal2double(E_DEC_FATAL_ERROR, &decimal_value, &res);
return res; return res;
} }
...@@ -7855,8 +7882,11 @@ longlong Item_cache_decimal::val_int() ...@@ -7855,8 +7882,11 @@ longlong Item_cache_decimal::val_int()
{ {
DBUG_ASSERT(fixed); DBUG_ASSERT(fixed);
longlong res; longlong res;
if (!value_cached && !cache_value()) if ((!value_cached && !cache_value()) || null_value)
{
null_value= TRUE;
return 0; return 0;
}
my_decimal2int(E_DEC_FATAL_ERROR, &decimal_value, unsigned_flag, &res); my_decimal2int(E_DEC_FATAL_ERROR, &decimal_value, unsigned_flag, &res);
return res; return res;
} }
...@@ -7864,8 +7894,11 @@ longlong Item_cache_decimal::val_int() ...@@ -7864,8 +7894,11 @@ longlong Item_cache_decimal::val_int()
String* Item_cache_decimal::val_str(String *str) String* Item_cache_decimal::val_str(String *str)
{ {
DBUG_ASSERT(fixed); DBUG_ASSERT(fixed);
if (!value_cached && !cache_value()) if ((!value_cached && !cache_value()) || null_value)
{
null_value= TRUE;
return NULL; return NULL;
}
my_decimal_round(E_DEC_FATAL_ERROR, &decimal_value, decimals, FALSE, my_decimal_round(E_DEC_FATAL_ERROR, &decimal_value, decimals, FALSE,
&decimal_value); &decimal_value);
my_decimal2string(E_DEC_FATAL_ERROR, &decimal_value, 0, 0, 0, str); my_decimal2string(E_DEC_FATAL_ERROR, &decimal_value, 0, 0, 0, str);
...@@ -7875,8 +7908,11 @@ String* Item_cache_decimal::val_str(String *str) ...@@ -7875,8 +7908,11 @@ String* Item_cache_decimal::val_str(String *str)
my_decimal *Item_cache_decimal::val_decimal(my_decimal *val) my_decimal *Item_cache_decimal::val_decimal(my_decimal *val)
{ {
DBUG_ASSERT(fixed); DBUG_ASSERT(fixed);
if (!value_cached && !cache_value()) if ((!value_cached && !cache_value()) || null_value)
{
null_value= TRUE;
return NULL; return NULL;
}
return &decimal_value; return &decimal_value;
} }
...@@ -7911,12 +7947,13 @@ double Item_cache_str::val_real() ...@@ -7911,12 +7947,13 @@ double Item_cache_str::val_real()
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
int err_not_used; int err_not_used;
char *end_not_used; char *end_not_used;
if (!value_cached && !cache_value()) if ((!value_cached && !cache_value()) || null_value)
{
null_value= TRUE;
return 0.0; return 0.0;
if (value) }
return my_strntod(value->charset(), (char*) value->ptr(), return my_strntod(value->charset(), (char*) value->ptr(),
value->length(), &end_not_used, &err_not_used); value->length(), &end_not_used, &err_not_used);
return (double) 0;
} }
...@@ -7924,21 +7961,24 @@ longlong Item_cache_str::val_int() ...@@ -7924,21 +7961,24 @@ longlong Item_cache_str::val_int()
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
int err; int err;
if (!value_cached && !cache_value()) if ((!value_cached && !cache_value()) || null_value)
{
null_value= TRUE;
return 0; return 0;
if (value) }
return my_strntoll(value->charset(), value->ptr(), return my_strntoll(value->charset(), value->ptr(),
value->length(), 10, (char**) 0, &err); value->length(), 10, (char**) 0, &err);
else
return (longlong)0;
} }
String* Item_cache_str::val_str(String *str) String* Item_cache_str::val_str(String *str)
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
if (!value_cached && !cache_value()) if ((!value_cached && !cache_value()) || null_value)
{
null_value= TRUE;
return 0; return 0;
}
return value; return value;
} }
...@@ -7946,20 +7986,24 @@ String* Item_cache_str::val_str(String *str) ...@@ -7946,20 +7986,24 @@ String* Item_cache_str::val_str(String *str)
my_decimal *Item_cache_str::val_decimal(my_decimal *decimal_val) my_decimal *Item_cache_str::val_decimal(my_decimal *decimal_val)
{ {
DBUG_ASSERT(fixed == 1); DBUG_ASSERT(fixed == 1);
if (!value_cached && !cache_value()) if ((!value_cached && !cache_value()) || null_value)
{
null_value= TRUE;
return NULL; return NULL;
if (value) }
string2my_decimal(E_DEC_FATAL_ERROR, value, decimal_val); string2my_decimal(E_DEC_FATAL_ERROR, value, decimal_val);
else
decimal_val= 0;
return decimal_val; return decimal_val;
} }
int Item_cache_str::save_in_field(Field *field, bool no_conversions) int Item_cache_str::save_in_field(Field *field, bool no_conversions)
{ {
if (!value_cached && !cache_value()) if ((!value_cached && !cache_value()) || null_value)
{
field->set_notnull();
null_value= TRUE;
return 0; return 0;
}
int res= Item_cache::save_in_field(field, no_conversions); int res= Item_cache::save_in_field(field, no_conversions);
return (is_varbinary && field->type() == MYSQL_TYPE_STRING && return (is_varbinary && field->type() == MYSQL_TYPE_STRING &&
value->length() < field->field_length) ? 1 : res; value->length() < field->field_length) ? 1 : res;
......
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