From 1401c2c71c5a99a6ac8e340138c5569fabd3f42e Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 4 Jul 2006 13:28:30 +0400 Subject: [PATCH 1/2] Better comments for void Item::top_level_item() --- sql/item.h | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/sql/item.h b/sql/item.h index eca8ee184a1..3eab695cb5e 100644 --- a/sql/item.h +++ b/sql/item.h @@ -275,9 +275,16 @@ public: Any new item which can be NULL must implement this call. */ virtual bool is_null() { return 0; } + /* - it is "top level" item of WHERE clause and we do not need correct NULL - handling + Inform the item that there will be no distinction between its result + being FALSE or NULL. + + NOTE + This function will be called for eg. Items that are top-level AND-parts + of the WHERE clause. Items implementing this function (currently + Item_cond_and and subquery-related item) enable special optimizations + when they are "top level". */ virtual void top_level_item() {} /* From cf7627bce09928d66129280b7903f6ab42fe2983 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 6 Jul 2006 11:11:49 -0700 Subject: [PATCH 2/2] 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. --- mysql-test/r/func_str.result | 15 ++++++++++++++ mysql-test/t/func_str.test | 17 ++++++++++++++++ sql/item_strfunc.cc | 39 +++++++++++++++++++----------------- sql/item_strfunc.h | 1 + 4 files changed, 54 insertions(+), 18 deletions(-) diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result index 24e6bb6f38a..61a77c211d7 100644 --- a/mysql-test/r/func_str.result +++ b/mysql-test/r/func_str.result @@ -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 diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test index c36e15a08b9..9a1c75a8dc0 100644 --- a/mysql-test/t/func_str.test +++ b/mysql-test/t/func_str.test @@ -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 diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index ee585649f8c..7bc7956283b 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -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; } diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index 89bab4a909c..f800c17182b 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -100,6 +100,7 @@ public: 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 *);