diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result index a725f1fe7ab..ae60daef0ac 100644 --- a/mysql-test/r/func_str.result +++ b/mysql-test/r/func_str.result @@ -861,3 +861,18 @@ trackname artistname April In Paris Vernon Duke Vernon Duke Autumn In New York NULL DROP TABLE t1,t2,t3; +create table t1 (b varchar(5)); +insert t1 values ('ab'), ('abc'), ('abcd'), ('abcde'); +select *,substring(b,1),substring(b,-1),substring(b,-2),substring(b,-3),substring(b,-4),substring(b,-5) from t1; +b substring(b,1) substring(b,-1) substring(b,-2) substring(b,-3) substring(b,-4) substring(b,-5) +ab ab b ab +abc abc c bc abc +abcd abcd d cd bcd abcd +abcde abcde e de cde bcde abcde +select * from (select *,substring(b,1),substring(b,-1),substring(b,-2),substring(b,-3),substring(b,-4),substring(b,-5) from t1) t; +b substring(b,1) substring(b,-1) substring(b,-2) substring(b,-3) substring(b,-4) substring(b,-5) +ab ab b ab +abc abc c bc abc +abcd abcd d cd bcd abcd +abcde abcde e de cde bcde abcde +drop table t1; diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test index 2cb7dfe4824..9dc6014ec56 100644 --- a/mysql-test/t/func_str.test +++ b/mysql-test/t/func_str.test @@ -599,3 +599,12 @@ SELECT CONCAT_WS(' ', trackname, artistname) trackname, artistname WHERE CONCAT_WS(' ', trackname, artistname) LIKE '%In%'; DROP TABLE t1,t2,t3; + +# +# Correct length reporting from substring() (BUG#10269) +# +create table t1 (b varchar(5)); +insert t1 values ('ab'), ('abc'), ('abcd'), ('abcde'); +select *,substring(b,1),substring(b,-1),substring(b,-2),substring(b,-3),substring(b,-4),substring(b,-5) from t1; +select * from (select *,substring(b,1),substring(b,-1),substring(b,-2),substring(b,-3),substring(b,-4),substring(b,-5) from t1) t; +drop table t1; diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 1ad65fb6208..e972c590156 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1056,7 +1056,8 @@ void Item_func_substr::fix_length_and_dec() collation.set(args[0]->collation); if (args[1]->const_item()) { - int32 start=(int32) args[1]->val_int()-1; + int32 start= (int32) args[1]->val_int(); + start= (int32)((start < 0) ? max_length + start : start - 1); if (start < 0 || start >= (int32) max_length) max_length=0; /* purecov: inspected */ else