summaryrefslogtreecommitdiff
path: root/sql/item_func.cc
diff options
context:
space:
mode:
authorJorgen Loland <jorgen.loland@oracle.com>2011-03-04 15:46:17 +0100
committerJorgen Loland <jorgen.loland@oracle.com>2011-03-04 15:46:17 +0100
commit40d72add32c94a4e891966ee46deb58f19c609d1 (patch)
treed344171eb27cd61a824d74c757654e16caf999bb /sql/item_func.cc
parente13c75a6d7998150cb211bafd54b0cda7eea27b4 (diff)
downloadmariadb-git-40d72add32c94a4e891966ee46deb58f19c609d1.tar.gz
BUG#11766317: FIND_IN_SET won't work normaly after upgrade
from 5.1 to 5.5 (Former 59405) In this bug, args[0] in an Item_func_find_in_set stored an Item_func_weekday that was constant. In Item_func_find_in_set::fix_length_and_dec(), args[0]->val_str() was called. Later, when Item_func_find_in_set::val_int() was called, args[0]->null_value was checked. However, the Item_func_weekday in args[0] had now been replaced with an Item_cache. No val_*() calls had been made to this Item_cache, thus null_value was incorrectly 'true', resulting in missing rows in the result set. enum_value gets a value in fix_length_and_dec() iff args[0] is both constant and non-null. It is therefore unnecessary to check the null_value of args[0] in val_int(). An alternative fix would be to call args[0]->val_int() inside Item_func_find_in_set::val_int(). This would ensure args[0]->null_value was set correctly (always false in this case), but that would have to be done for every record this const value is checked against.
Diffstat (limited to 'sql/item_func.cc')
-rw-r--r--sql/item_func.cc19
1 files changed, 16 insertions, 3 deletions
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 9b8ba6968b3..1908eda7d99 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -3003,6 +3003,8 @@ void Item_func_find_in_set::fix_length_and_dec()
String *find=args[0]->val_str(&value);
if (find)
{
+ // find is not NULL pointer so args[0] is not a null-value
+ DBUG_ASSERT(!args[0]->null_value);
enum_value= find_type(((Field_enum*) field)->typelib,find->ptr(),
find->length(), 0);
enum_bit=0;
@@ -3021,11 +3023,22 @@ longlong Item_func_find_in_set::val_int()
DBUG_ASSERT(fixed == 1);
if (enum_value)
{
- ulonglong tmp=(ulonglong) args[1]->val_int();
- if (!(null_value=args[1]->null_value || args[0]->null_value))
+ // enum_value is set iff args[0]->const_item() in fix_length_and_dec().
+ DBUG_ASSERT(args[0]->const_item());
+
+ ulonglong tmp= (ulonglong) args[1]->val_int();
+ null_value= args[1]->null_value;
+ /*
+ No need to check args[0]->null_value since enum_value is set iff
+ args[0] is a non-null const item. Note: no DBUG_ASSERT on
+ args[0]->null_value here because args[0] may have been replaced
+ by an Item_cache on which val_int() has not been called. See
+ BUG#11766317
+ */
+ if (!null_value)
{
if (tmp & enum_bit)
- return enum_value;
+ return enum_value;
}
return 0L;
}