Commit 77e7f2ac authored by unknown's avatar unknown

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.


mysql-test/r/func_str.result:
  Added a test case for bug #18243.
mysql-test/t/func_str.test:
  Added a test case for bug #18243.
sql/item_strfunc.cc:
  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.
  
  The implementation of Item_func_reverse::val_str has been changed
  to make the argument intact.
sql/item_strfunc.h:
  Fixed bug #18243.
  Added tmp_value to the Item_func_reverse class to store
  the result of the function. It erroneously replaced the 
  argument before this fix.
parent 66db1156
......@@ -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
......@@ -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
......@@ -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());
ptr = (char *) res->ptr();
end=ptr+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;
if ((l= my_ismbchar(res->charset(),ptr,end)))
{
tmp-= l;
memcpy(tmp,ptr,l);
ptr+= l;
}
else
*--tmp=*ptr++;
*--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;
}
......
......@@ -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 *);
......
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