Commit 0e3d2daf authored by igor@olga.mysql.com's avatar igor@olga.mysql.com
Browse files

Fixed bug #18243.

The implementation of the method Item_func_reverse::val_str
for the REVERSE function modified the argument of the function.
This led to wrong results for expressions that contained
REVERSE(ref) if ref occurred somewhere else in the expressions.
parent 83bc48f3
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -1021,4 +1021,19 @@ select * from t1 where f1='test' and (f2= sha("TEST") or f2= sha("test"));
f1	f2
test	a94a8fe5ccb19ba61c4c0873d391e987982fbbd3
drop table t1;
CREATE TABLE t1 (a varchar(10));
INSERT INTO t1 VALUES ('abc'), ('xyz');
SELECT a, CONCAT(a,' ',a) AS c FROM t1
HAVING LEFT(c,LENGTH(c)-INSTR(REVERSE(c)," ")) = a;
a	c
abc	abc abc
xyz	xyz xyz
SELECT a, CONCAT(a,' ',a) AS c FROM t1
HAVING LEFT(CONCAT(a,' ',a),
LENGTH(CONCAT(a,' ',a))-
INSTR(REVERSE(CONCAT(a,' ',a))," ")) = a;
a	c
abc	abc abc
xyz	xyz xyz
DROP TABLE t1;
End of 4.1 tests
+17 −0
Original line number Diff line number Diff line
@@ -681,4 +681,21 @@ select * from t1 where f1='test' and (f2= sha("test") or f2= sha("TEST"));
select * from t1 where f1='test' and (f2= sha("TEST") or f2= sha("test"));
drop table t1;

#
# Bug#18243: REVERSE changes its argument
#

CREATE TABLE t1 (a varchar(10));
INSERT INTO t1 VALUES ('abc'), ('xyz');

SELECT a, CONCAT(a,' ',a) AS c FROM t1
  HAVING LEFT(c,LENGTH(c)-INSTR(REVERSE(c)," ")) = a;

SELECT a, CONCAT(a,' ',a) AS c FROM t1
  HAVING LEFT(CONCAT(a,' ',a),
              LENGTH(CONCAT(a,' ',a))-
                     INSTR(REVERSE(CONCAT(a,' ',a))," ")) = a;

DROP TABLE t1;
 
--echo End of 4.1 tests
+21 −18
Original line number Diff line number Diff line
@@ -709,44 +709,47 @@ String *Item_func_reverse::val_str(String *str)
{
  DBUG_ASSERT(fixed == 1);
  String *res = args[0]->val_str(str);
  char *ptr,*end;
  char *ptr, *end, *tmp;

  if ((null_value=args[0]->null_value))
    return 0;
  /* An empty string is a special case as the string pointer may be null */
  if (!res->length())
    return &my_empty_string;
  res=copy_if_not_alloced(str,res,res->length());
  if (tmp_value.alloced_length() < res->length() &&
      tmp_value.realloc(res->length()))
  {
    null_value= 1;
    return 0;
  }
  tmp_value.length(res->length());
  tmp_value.set_charset(res->charset());
  ptr= (char *) res->ptr();
  end= ptr + res->length();
  tmp= (char *) tmp_value.ptr() + tmp_value.length();
#ifdef USE_MB
  if (use_mb(res->charset()))
  {
    String tmpstr;
    tmpstr.copy(*res);
    char *tmp = (char *) tmpstr.ptr() + tmpstr.length();
    register uint32 l;
    while (ptr < end)
    {
      if ((l= my_ismbchar(res->charset(),ptr,end)))
        tmp-=l, memcpy(tmp,ptr,l), ptr+=l;
      {
        tmp-= l;
        memcpy(tmp,ptr,l);
        ptr+= l;
      }
      else
        *--tmp= *ptr++;
    }
    memcpy((char *) res->ptr(),(char *) tmpstr.ptr(), res->length());
  }
  else
#endif /* USE_MB */
  {
    char tmp;
    while (ptr < end)
    {
      tmp=*ptr;
      *ptr++=*--end;
      *end=tmp;
    }
      *--tmp= *ptr++;
  }
  return res;
  return &tmp_value;
}


+1 −0
Original line number Diff line number Diff line
@@ -100,6 +100,7 @@ class Item_func_concat_ws :public Item_str_func

class Item_func_reverse :public Item_str_func
{
  String tmp_value;
public:
  Item_func_reverse(Item *a) :Item_str_func(a) {}
  String *val_str(String *);