Commit f5ce37d7 authored by unknown's avatar unknown
Browse files

Fix for bug #4340: find_in_set is case insensitive even on binary operators(for 4.1)

parent 61441468
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -56,3 +56,12 @@ id elt(two.val,'one','two')
2	one
4	two
drop table t1,t2;
select find_in_set(binary 'a',binary 'A,B,C');
find_in_set(binary 'a',binary 'A,B,C')
0
select find_in_set('a',binary 'A,B,C');
find_in_set('a',binary 'A,B,C')
0
select find_in_set(binary 'a', 'A,B,C');
find_in_set(binary 'a', 'A,B,C')
0
+8 −0
Original line number Diff line number Diff line
@@ -39,3 +39,11 @@ insert into t2 values (1,1),(2,1),(3,1),(4,2);
select one.id, elt(two.val,'one','two') from t1 one, t2 two where two.id=one.id;
select one.id, elt(two.val,'one','two') from t1 one, t2 two where two.id=one.id order by one.id;
drop table t1,t2;

#
# Bug4340: find_in_set is case insensitive even on binary operators
#

select find_in_set(binary 'a',binary 'A,B,C');
select find_in_set('a',binary 'A,B,C');
select find_in_set(binary 'a', 'A,B,C');
+34 −21
Original line number Diff line number Diff line
@@ -1435,30 +1435,43 @@ longlong Item_func_find_in_set::val_int()
  int diff;
  if ((diff=buffer->length() - find->length()) >= 0)
  {
    const char *f_pos=find->ptr();
    const char *f_end=f_pos+find->length();
    const char *str=buffer->ptr();
    const char *end=str+diff+1;
    const char *real_end=str+buffer->length();
    uint position=1;
    do
    {
      const char *pos= f_pos;
      while (pos != f_end)
      {
	if (my_toupper(cmp_collation.collation,*str) != 
	    my_toupper(cmp_collation.collation,*pos))
	  goto not_found;
	str++;
	pos++;
      }
      if (str == real_end || str[0] == separator)
	return (longlong) position;
  not_found:
      while (str < end && str[0] != separator)
	str++;
    my_wc_t wc;
    CHARSET_INFO *cs= cmp_collation.collation;
    const char *str_begin= buffer->ptr();
    const char *str_end= buffer->ptr();
    const char *real_end= str_end+buffer->length();
    const uchar *find_str= (const uchar *) find->ptr();
    uint find_str_len= find->length();
    int position= 0;
    while (1)
    {
      int symbol_len;
      if ((symbol_len= cs->cset->mb_wc(cs, &wc, (uchar*) str_end, 
                                       (uchar*) real_end)) > 0)
      {
        const char *substr_end= str_end + symbol_len;
        bool is_last_item= (substr_end == real_end);
        if (wc == (my_wc_t) separator || is_last_item)
        {
          position++;
    } while (++str <= end);
          if (is_last_item)
            str_end= substr_end;
          if (!my_strnncoll(cs, (const uchar *) str_begin,
                            str_end - str_begin,
                            find_str, find_str_len))
            return (longlong) position;
          else
            str_begin= substr_end;
        }
        str_end= substr_end;
      }
      else if (str_end - str_begin == 0 && 
               find_str_len == 0 && 
               wc == (my_wc_t) separator)
        return (longlong) ++position;
      else
        return (longlong) 0;
    }
  }
  return 0;
}