From 1b40adcb064b96064bc71d975f054579b41fa378 Mon Sep 17 00:00:00 2001 From: "bar@mysql.com" <> Date: Thu, 4 Aug 2005 15:25:03 +0500 Subject: [PATCH 1/5] grant.result, grant.test: fixing tests accordingly item.cc: Bug #10892 user variables not auto cast for comparisons When mixing strings with different character sets, and coercibility is the same, we allow conversion if one character set is superset for other character set. --- mysql-test/r/grant.result | 3 +++ mysql-test/t/grant.test | 7 +++++++ sql/item.cc | 10 ++++++---- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/grant.result b/mysql-test/r/grant.result index e9e1d4cd620..a50293752ec 100644 --- a/mysql-test/r/grant.result +++ b/mysql-test/r/grant.result @@ -440,3 +440,6 @@ insert into tables_priv values ('','test_db','mysqltest_1','test_table','test_gr flush privileges; delete from tables_priv where host = '' and user = 'mysqltest_1'; flush privileges; +set @user123="non-existent"; +select * from mysql.db where user=@user123; +Host Db User Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Grant_priv References_priv Index_priv Alter_priv Create_tmp_table_priv Lock_tables_priv diff --git a/mysql-test/t/grant.test b/mysql-test/t/grant.test index 50255d515e0..b0de62e679c 100644 --- a/mysql-test/t/grant.test +++ b/mysql-test/t/grant.test @@ -402,4 +402,11 @@ flush privileges; delete from tables_priv where host = '' and user = 'mysqltest_1'; flush privileges; +# +# Bug #10892 user variables not auto cast for comparisons +# Check that we don't get illegal mix of collations +# +set @user123="non-existent"; +select * from mysql.db where user=@user123; + # End of 4.1 tests diff --git a/sql/item.cc b/sql/item.cc index 84dbc382a52..41cda365750 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -455,14 +455,16 @@ bool DTCollation::aggregate(DTCollation &dt, uint flags) ; // Do nothing } else if ((flags & MY_COLL_ALLOW_SUPERSET_CONV) && - derivation < dt.derivation && - collation->state & MY_CS_UNICODE) + derivation <= dt.derivation && + collation->state & MY_CS_UNICODE && + !(dt.collation->state & MY_CS_UNICODE)) { // Do nothing } else if ((flags & MY_COLL_ALLOW_SUPERSET_CONV) && - dt.derivation < derivation && - dt.collation->state & MY_CS_UNICODE) + dt.derivation <= derivation && + dt.collation->state & MY_CS_UNICODE && + !(collation->state & MY_CS_UNICODE)) { set(dt); } From 701703824fb43f37ba65b59b461bda0a19083b90 Mon Sep 17 00:00:00 2001 From: "monty@mishka.local" <> Date: Mon, 8 Aug 2005 13:18:18 +0300 Subject: [PATCH 2/5] Fix for BUG #11642: [Patch]es x86 Assembler and text relocations Changed assembler functions to not access global variables or variables in text segement Added wrapper function in C to longlong2str() to pass _dig_vec_upper as an argument --- mysql-test/r/bigint.result | 9 ++++++ mysql-test/t/bigint.test | 3 ++ strings/Makefile.am | 4 +-- strings/longlong2str-x86.s | 35 ++++++++++----------- strings/longlong2str_asm.c | 33 ++++++++++++++++++++ strings/my_strtoll10-x86.s | 62 ++++++++++++++++++++++++-------------- 6 files changed, 104 insertions(+), 42 deletions(-) create mode 100644 strings/longlong2str_asm.c diff --git a/mysql-test/r/bigint.result b/mysql-test/r/bigint.result index eb3d0da3f23..e9a457c9dfa 100644 --- a/mysql-test/r/bigint.result +++ b/mysql-test/r/bigint.result @@ -17,6 +17,15 @@ select 9223372036854775808+1; select -(0-3),round(-(0-3)), round(9999999999999999999); -(0-3) round(-(0-3)) round(9999999999999999999) 3 3 10000000000000000000 +select 1,11,101,1001,10001,100001,1000001,10000001,100000001,1000000001,10000000001,100000000001,1000000000001,10000000000001,100000000000001,1000000000000001,10000000000000001,100000000000000001,1000000000000000001,10000000000000000001; +1 11 101 1001 10001 100001 1000001 10000001 100000001 1000000001 10000000001 100000000001 1000000000001 10000000000001 100000000000001 1000000000000001 10000000000000001 100000000000000001 1000000000000000001 10000000000000000001 +1 11 101 1001 10001 100001 1000001 10000001 100000001 1000000001 10000000001 100000000001 1000000000001 10000000000001 100000000000001 1000000000000001 10000000000000001 100000000000000001 1000000000000000001 10000000000000000001 +select -1,-11,-101,-1001,-10001,-100001,-1000001,-10000001,-100000001,-1000000001,-10000000001,-100000000001,-1000000000001,-10000000000001,-100000000000001,-1000000000000001,-10000000000000001,-100000000000000001,-1000000000000000001,-10000000000000000001; +-1 -11 -101 -1001 -10001 -100001 -1000001 -10000001 -100000001 -1000000001 -10000000001 -100000000001 -1000000000001 -10000000000001 -100000000000001 -1000000000000001 -10000000000000001 -100000000000000001 -1000000000000000001 -10000000000000000001 +-1 -11 -101 -1001 -10001 -100001 -1000001 -10000001 -100000001 -1000000001 -10000000001 -100000000001 -1000000000001 -10000000000001 -100000000000001 -1000000000000001 -10000000000000001 -100000000000000001 -1000000000000000001 -10000000000000000000 +select conv(1,10,16),conv((1<<2)-1,10,16),conv((1<<10)-2,10,16),conv((1<<16)-3,10,16),conv((1<<25)-4,10,16),conv((1<<31)-5,10,16),conv((1<<36)-6,10,16),conv((1<<47)-7,10,16),conv((1<<48)-8,10,16),conv((1<<55)-9,10,16),conv((1<<56)-10,10,16),conv((1<<63)-11,10,16); +conv(1,10,16) conv((1<<2)-1,10,16) conv((1<<10)-2,10,16) conv((1<<16)-3,10,16) conv((1<<25)-4,10,16) conv((1<<31)-5,10,16) conv((1<<36)-6,10,16) conv((1<<47)-7,10,16) conv((1<<48)-8,10,16) conv((1<<55)-9,10,16) conv((1<<56)-10,10,16) conv((1<<63)-11,10,16) +1 3 3FE FFFD 1FFFFFC 7FFFFFFB FFFFFFFFA 7FFFFFFFFFF9 FFFFFFFFFFF8 7FFFFFFFFFFFF7 FFFFFFFFFFFFF6 7FFFFFFFFFFFFFF5 create table t1 (a bigint unsigned not null, primary key(a)); insert into t1 values (18446744073709551615), (0xFFFFFFFFFFFFFFFE), (18446744073709551613), (18446744073709551612); select * from t1; diff --git a/mysql-test/t/bigint.test b/mysql-test/t/bigint.test index 741c7ec360b..8a238d33e08 100644 --- a/mysql-test/t/bigint.test +++ b/mysql-test/t/bigint.test @@ -14,6 +14,9 @@ select +9999999999999999999,-9999999999999999999; select cast(9223372036854775808 as unsigned)+1; select 9223372036854775808+1; select -(0-3),round(-(0-3)), round(9999999999999999999); +select 1,11,101,1001,10001,100001,1000001,10000001,100000001,1000000001,10000000001,100000000001,1000000000001,10000000000001,100000000000001,1000000000000001,10000000000000001,100000000000000001,1000000000000000001,10000000000000000001; +select -1,-11,-101,-1001,-10001,-100001,-1000001,-10000001,-100000001,-1000000001,-10000000001,-100000000001,-1000000000001,-10000000000001,-100000000000001,-1000000000000001,-10000000000000001,-100000000000000001,-1000000000000000001,-10000000000000000001; +select conv(1,10,16),conv((1<<2)-1,10,16),conv((1<<10)-2,10,16),conv((1<<16)-3,10,16),conv((1<<25)-4,10,16),conv((1<<31)-5,10,16),conv((1<<36)-6,10,16),conv((1<<47)-7,10,16),conv((1<<48)-8,10,16),conv((1<<55)-9,10,16),conv((1<<56)-10,10,16),conv((1<<63)-11,10,16); # # In 3.23 we have to disable the test of column to bigint as diff --git a/strings/Makefile.am b/strings/Makefile.am index 3f954f3c6a0..97b35075277 100644 --- a/strings/Makefile.am +++ b/strings/Makefile.am @@ -23,7 +23,7 @@ pkglib_LIBRARIES = libmystrings.a # Exact one of ASSEMBLER_X if ASSEMBLER_x86 ASRCS = strings-x86.s longlong2str-x86.s my_strtoll10-x86.s -CSRCS = bfill.c bmove.c bmove512.c bchange.c strxnmov.c int2str.c str2int.c r_strinstr.c strtod.c bcmp.c strtol.c strtoul.c strtoll.c strtoull.c llstr.c strnlen.c ctype.c ctype-simple.c ctype-mb.c ctype-big5.c ctype-cp932.c ctype-czech.c ctype-euc_kr.c ctype-gb2312.c ctype-gbk.c ctype-sjis.c ctype-tis620.c ctype-ujis.c ctype-utf8.c ctype-ucs2.c ctype-uca.c ctype-win1250ch.c ctype-bin.c ctype-latin1.c my_vsnprintf.c xml.c ctype-extra.c +CSRCS = bfill.c bmove.c bmove512.c bchange.c strxnmov.c int2str.c str2int.c r_strinstr.c strtod.c bcmp.c strtol.c strtoul.c strtoll.c strtoull.c llstr.c strnlen.c ctype.c ctype-simple.c ctype-mb.c ctype-big5.c ctype-cp932.c ctype-czech.c ctype-euc_kr.c ctype-gb2312.c ctype-gbk.c ctype-sjis.c ctype-tis620.c ctype-ujis.c ctype-utf8.c ctype-ucs2.c ctype-uca.c ctype-win1250ch.c ctype-bin.c ctype-latin1.c my_vsnprintf.c xml.c ctype-extra.c longlong2str_asm.c else if ASSEMBLER_sparc32 # These file MUST all be on the same line!! Otherwise automake @@ -46,7 +46,7 @@ EXTRA_DIST = ctype-big5.c ctype-cp932.c ctype-czech.c ctype-euc_kr.c ctype-win1 ctype-gb2312.c ctype-gbk.c ctype-sjis.c ctype-utf8.c \ ctype-ucs2.c ctype-uca.c ctype-tis620.c ctype-ujis.c \ xml.c strto.c strings-x86.s \ - longlong2str.c longlong2str-x86.s \ + longlong2str.c longlong2str-x86.s longlong2str_asm.c \ my_strtoll10.c my_strtoll10-x86.s \ strxmov.c bmove_upp.c strappend.c strcont.c strend.c \ strfill.c strcend.c is_prefix.c strstr.c strinstr.c \ diff --git a/strings/longlong2str-x86.s b/strings/longlong2str-x86.s index fcc57810224..1840bab3f47 100644 --- a/strings/longlong2str-x86.s +++ b/strings/longlong2str-x86.s @@ -16,26 +16,26 @@ # Optimized longlong2str function for Intel 80x86 (gcc/gas syntax) # Some set sequences are optimized for pentuimpro II - .file "longlong2str.s" - .version "1.01" + .file "longlong2str-x86.s" + .version "1.02" .text .align 4 -.globl longlong2str - .type longlong2str,@function +.globl longlong2str_with_dig_vector + .type longlong2str_with_dig_vector,@function -longlong2str: +longlong2str_with_dig_vector: subl $80,%esp pushl %ebp pushl %esi pushl %edi pushl %ebx movl 100(%esp),%esi # Lower part of val - movl 104(%esp),%ebp # Higher part of val - movl 108(%esp),%edi # get dst movl 112(%esp),%ebx # Radix + movl 104(%esp),%ebp # Higher part of val movl %ebx,%eax + movl 108(%esp),%edi # get dst testl %eax,%eax jge .L144 @@ -69,6 +69,8 @@ longlong2str: .L150: leal 92(%esp),%ecx # End of buffer + movl %edi, 108(%esp) # Store possible modified dest + movl 116(%esp), %edi # dig_vec_upper jmp .L155 .align 4 @@ -83,7 +85,7 @@ longlong2str: divl %ebx decl %ecx movl %eax,%esi # quotent in ebp:esi - movb _dig_vec_upper(%edx),%al # al is faster than dl + movb (%edx,%edi),%al # al is faster than dl movb %al,(%ecx) # store value in buff .align 4 .L155: @@ -91,20 +93,22 @@ longlong2str: ja .L153 testl %esi,%esi # rest value jl .L153 - je .L10_mov # Ready + je .L160 # Ready movl %esi,%eax - movl $_dig_vec_upper,%ebp .align 4 .L154: # Do rest with integer precision cltd divl %ebx decl %ecx - movb (%edx,%ebp),%dl # bh is always zero as ebx=radix < 36 + movb (%edx,%edi),%dl # bh is always zero as ebx=radix < 36 testl %eax,%eax movb %dl,(%ecx) jne .L154 +.L160: + movl 108(%esp),%edi # get dst + .L10_mov: movl %ecx,%esi leal 92(%esp),%ecx # End of buffer @@ -129,7 +133,7 @@ longlong2str: jmp .L165 .Lfe3: - .size longlong2str,.Lfe3-longlong2str + .size longlong2str_with_dig_vector,.Lfe3-longlong2str_with_dig_vector # # This is almost equal to the above, except that we can do the final @@ -137,9 +141,6 @@ longlong2str: # .align 4 -.Ltmp: - .long 0xcccccccd - .align 4 .globl longlong10_to_str .type longlong10_to_str,@function @@ -202,8 +203,8 @@ longlong10_to_str: # The following code uses some tricks to change division by 10 to # multiplication and shifts - movl .Ltmp,%esi # set %esi to 0xcccccccd - + movl $0xcccccccd,%esi + .L10_40: movl %ebx,%eax mull %esi diff --git a/strings/longlong2str_asm.c b/strings/longlong2str_asm.c new file mode 100644 index 00000000000..e38a8328b91 --- /dev/null +++ b/strings/longlong2str_asm.c @@ -0,0 +1,33 @@ +/* Copyright (C) 2000 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +/* + Wrapper for longlong2str.s + + We need this because the assembler code can't access the local variable + _dig_vector in a portable manner. +*/ + +#include +#include "m_string.h" + +extern char *longlong2str_with_dig_vector(longlong val,char *dst,int radix, + const char *dig_vector); + +char *longlong2str(longlong val,char *dst,int radix) +{ + return longlong2str_with_dig_vector(val, dst, radix, _dig_vec_upper); +} diff --git a/strings/my_strtoll10-x86.s b/strings/my_strtoll10-x86.s index c04384667a7..1d8b8f2bbce 100644 --- a/strings/my_strtoll10-x86.s +++ b/strings/my_strtoll10-x86.s @@ -17,21 +17,8 @@ # For documentation, check my_strtoll.c .file "my_strtoll10-x86.s" - .version "01.01" -.data - .align 32 - .type lfactor,@object - .size lfactor,36 -lfactor: - .long 1 - .long 10 - .long 100 - .long 1000 - .long 10000 - .long 100000 - .long 1000000 - .long 10000000 - .long 100000000 + .version "01.02" + .text .align 4 @@ -209,14 +196,16 @@ my_strtoll10: jne .L500 cmpl -36(%ebp),%esi # Test if string is less than 18 digits jne .Lend_i_and_j - jmp .Lend3 # 18 digit string +.L499: + movl $1000000000,%eax + jmp .Lgot_factor # 18 digit string # Handle the possible next to last digit and store in ecx .L500: movb (%esi),%al addb $-48,%al cmpb $9,%al - ja .Lend3 + ja .L499 # 18 digit string incl %esi movzbl %al,%ecx @@ -315,14 +304,41 @@ my_strtoll10: .Lend_i_and_j: movl %esi,%ecx subl -12(%ebp),%ecx # ecx= number of digits in second part - movl lfactor(,%ecx,4),%eax - jmp .L523 - # Return -8(%ebp) * $1000000000 + edi + # Calculate %eax= 10 ** %cl, where %cl <= 8 + # With an array one could do this with: + # movl 10_factor_table(,%ecx,4),%eax + # We calculate the table here to avoid problems in + # position independent code (gcc -pic) + + cmpb $3,%cl + ja .L4_to_8 + movl $1000, %eax + je .Lgot_factor # %cl=3, eax= 1000 + movl $10, %eax + cmpb $1,%cl # %cl is here 0 - 2 + je .Lgot_factor # %cl=1, eax= 10 + movl $100, %eax + ja .Lgot_factor # %cl=2, eax=100 + movl $1, %eax + jmp .Lgot_factor # %cl=0, eax=1 + +.L4_to_8: # %cl is here 4-8 + cmpb $5,%cl + movl $100000, %eax + je .Lgot_factor # %cl=5, eax=100000 + movl $10000, %eax + jbe .Lgot_factor # %cl=4, eax=10000 + movl $10000000, %eax + cmpb $7,%cl + je .Lgot_factor # %cl=7, eax=10000000 + movl $100000000, %eax + ja .Lgot_factor # %cl=8, eax=100000000 + movl $1000000, %eax # %cl=6, eax=1000000 + + # Return -8(%ebp) * %eax + edi .p2align 4,,7 -.Lend3: - movl $1000000000,%eax -.L523: +.Lgot_factor: mull -8(%ebp) addl %edi,%eax adcl $0,%edx From 2c8fc886b91903d0cbb9064c64c7209ee816369e Mon Sep 17 00:00:00 2001 From: "bar@mysql.com" <> Date: Mon, 8 Aug 2005 16:20:46 +0500 Subject: [PATCH 3/5] item.cc: After review fix --- sql/item.cc | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/sql/item.cc b/sql/item.cc index 41cda365750..b3d2932acf6 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -455,16 +455,18 @@ bool DTCollation::aggregate(DTCollation &dt, uint flags) ; // Do nothing } else if ((flags & MY_COLL_ALLOW_SUPERSET_CONV) && - derivation <= dt.derivation && collation->state & MY_CS_UNICODE && - !(dt.collation->state & MY_CS_UNICODE)) + (derivation < dt.derivation || + (derivation == dt.derivation && + !(dt.collation->state & MY_CS_UNICODE)))) { // Do nothing } else if ((flags & MY_COLL_ALLOW_SUPERSET_CONV) && - dt.derivation <= derivation && dt.collation->state & MY_CS_UNICODE && - !(collation->state & MY_CS_UNICODE)) + (dt.derivation < derivation || + (dt.derivation == derivation && + !(collation->state & MY_CS_UNICODE)))) { set(dt); } From 6128521b5bd11f9a27520f25d5673f3042390e99 Mon Sep 17 00:00:00 2001 From: "patg@krsna.patg.net" <> Date: Mon, 8 Aug 2005 13:46:13 -0700 Subject: [PATCH 4/5] item_strfunc.cc: BUG #11104 Took out the offset-=delimiter_length-1 out of the for loop. It was causing basically this: select substring_index('the king of the the hill', 'the', -2) to not work. The first iteration, offset would be initialised to 24, then strstr would point at 'the king of the the* hill' ('*'means right before the character following), returning a offset of 16. The for loop would then decrement offset by two (3 - 1), to 14, now pointing at "the king of th*e the hill", _skipping_ past the 'e' in the second to last 'the', and therefore strstr would never have a chance of matching the second to last 'the', then moving on to the 'the' at the begginning of the string! In a nutshell, offset was being decremented by too great a value, preventing the second to last 'the' from being ever found, hence the result of 'king of the the hill' from the query that is reported in the bug report func_str.test: BUG #11104 Added tests to make sure fix addresses issues in original bug report func_str.result: BUG #11104 New results for new tests --- mysql-test/r/func_str.result | 117 +++++++++++++++++++++++++++++++++++ mysql-test/t/func_str.test | 39 ++++++++++++ sql/item_strfunc.cc | 16 ++++- 3 files changed, 170 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result index 4c3a03b8066..ae6578795f6 100644 --- a/mysql-test/r/func_str.result +++ b/mysql-test/r/func_str.result @@ -45,6 +45,123 @@ www. .se select substring_index('.tcx.se','.',-2),substring_index('.tcx.se','.tcx',-1); substring_index('.tcx.se','.',-2) substring_index('.tcx.se','.tcx',-1) tcx.se .se +select substring_index('aaaaaaaaa1','a',1); +substring_index('aaaaaaaaa1','a',1) + +select substring_index('aaaaaaaaa1','aa',1); +substring_index('aaaaaaaaa1','aa',1) + +select substring_index('aaaaaaaaa1','aa',2); +substring_index('aaaaaaaaa1','aa',2) +aa +select substring_index('aaaaaaaaa1','aa',3); +substring_index('aaaaaaaaa1','aa',3) +aaaa +select substring_index('aaaaaaaaa1','aa',4); +substring_index('aaaaaaaaa1','aa',4) +aaaaaa +select substring_index('aaaaaaaaa1','aa',5); +substring_index('aaaaaaaaa1','aa',5) +aaaaaaaaa1 +select substring_index('aaaaaaaaa1','aaa',1); +substring_index('aaaaaaaaa1','aaa',1) + +select substring_index('aaaaaaaaa1','aaa',2); +substring_index('aaaaaaaaa1','aaa',2) +aaa +select substring_index('aaaaaaaaa1','aaa',3); +substring_index('aaaaaaaaa1','aaa',3) +aaaaaa +select substring_index('aaaaaaaaa1','aaa',4); +substring_index('aaaaaaaaa1','aaa',4) +aaaaaaaaa1 +select substring_index('aaaaaaaaa1','aaaa',1); +substring_index('aaaaaaaaa1','aaaa',1) + +select substring_index('aaaaaaaaa1','aaaa',2); +substring_index('aaaaaaaaa1','aaaa',2) +aaaa +select substring_index('aaaaaaaaa1','1',1); +substring_index('aaaaaaaaa1','1',1) +aaaaaaaaa +select substring_index('aaaaaaaaa1','a',-1); +substring_index('aaaaaaaaa1','a',-1) +1 +select substring_index('aaaaaaaaa1','aa',-1); +substring_index('aaaaaaaaa1','aa',-1) +1 +select substring_index('aaaaaaaaa1','aa',-2); +substring_index('aaaaaaaaa1','aa',-2) +aa1 +select substring_index('aaaaaaaaa1','aa',-3); +substring_index('aaaaaaaaa1','aa',-3) +aaaa1 +select substring_index('aaaaaaaaa1','aa',-4); +substring_index('aaaaaaaaa1','aa',-4) +aaaaaa1 +select substring_index('aaaaaaaaa1','aa',-5); +substring_index('aaaaaaaaa1','aa',-5) +aaaaaaaaa1 +select substring_index('aaaaaaaaa1','aaa',-1); +substring_index('aaaaaaaaa1','aaa',-1) +1 +select substring_index('aaaaaaaaa1','aaa',-2); +substring_index('aaaaaaaaa1','aaa',-2) +aaa1 +select substring_index('aaaaaaaaa1','aaa',-3); +substring_index('aaaaaaaaa1','aaa',-3) +aaaaaa1 +select substring_index('aaaaaaaaa1','aaa',-4); +substring_index('aaaaaaaaa1','aaa',-4) + +select substring_index('the king of thethe hill','the',-2); +substring_index('the king of thethe hill','the',-2) +the hill +select substring_index('the king of the the hill','the',-2); +substring_index('the king of the the hill','the',-2) + the hill +select substring_index('the king of the the hill','the',-2); +substring_index('the king of the the hill','the',-2) + the hill +select substring_index('the king of the the hill',' the ',-1); +substring_index('the king of the the hill',' the ',-1) +hill +select substring_index('the king of the the hill',' the ',-2); +substring_index('the king of the the hill',' the ',-2) + the hill +select substring_index('the king of the the hill',' ',-1); +substring_index('the king of the the hill',' ',-1) +hill +select substring_index('the king of the the hill',' ',-2); +substring_index('the king of the the hill',' ',-2) +the hill +select substring_index('the king of the the hill',' ',-3); +substring_index('the king of the the hill',' ',-3) + the hill +select substring_index('the king of the the hill',' ',-4); +substring_index('the king of the the hill',' ',-4) +the the hill +select substring_index('the king of the the hill',' ',-5); +substring_index('the king of the the hill',' ',-5) +of the the hill +select substring_index('the king of the.the hill','the',-2); +substring_index('the king of the.the hill','the',-2) +.the hill +select substring_index('the king of thethethe.the hill','the',-3); +substring_index('the king of thethethe.the hill','the',-3) +the.the hill +select substring_index('the king of thethethe.the hill','the',-1); +substring_index('the king of thethethe.the hill','the',-1) + hill +select substring_index('the king of the the hill','the',1); +substring_index('the king of the the hill','the',1) + +select substring_index('the king of the the hill','the',2); +substring_index('the king of the the hill','the',2) +the king of +select substring_index('the king of the the hill','the',3); +substring_index('the king of the the hill','the',3) +the king of the select concat(':',ltrim(' left '),':',rtrim(' right '),':'); concat(':',ltrim(' left '),':',rtrim(' right '),':') :left : right: diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test index ddfc83e620a..8afbe673ce3 100644 --- a/mysql-test/t/func_str.test +++ b/mysql-test/t/func_str.test @@ -23,6 +23,45 @@ select concat('',left(right(concat('what ',concat('is ','happening')),9),4),'',s select substring_index('www.tcx.se','.',-2),substring_index('www.tcx.se','.',1); select substring_index('www.tcx.se','tcx',1),substring_index('www.tcx.se','tcx',-1); select substring_index('.tcx.se','.',-2),substring_index('.tcx.se','.tcx',-1); +select substring_index('aaaaaaaaa1','a',1); +select substring_index('aaaaaaaaa1','aa',1); +select substring_index('aaaaaaaaa1','aa',2); +select substring_index('aaaaaaaaa1','aa',3); +select substring_index('aaaaaaaaa1','aa',4); +select substring_index('aaaaaaaaa1','aa',5); +select substring_index('aaaaaaaaa1','aaa',1); +select substring_index('aaaaaaaaa1','aaa',2); +select substring_index('aaaaaaaaa1','aaa',3); +select substring_index('aaaaaaaaa1','aaa',4); +select substring_index('aaaaaaaaa1','aaaa',1); +select substring_index('aaaaaaaaa1','aaaa',2); +select substring_index('aaaaaaaaa1','1',1); +select substring_index('aaaaaaaaa1','a',-1); +select substring_index('aaaaaaaaa1','aa',-1); +select substring_index('aaaaaaaaa1','aa',-2); +select substring_index('aaaaaaaaa1','aa',-3); +select substring_index('aaaaaaaaa1','aa',-4); +select substring_index('aaaaaaaaa1','aa',-5); +select substring_index('aaaaaaaaa1','aaa',-1); +select substring_index('aaaaaaaaa1','aaa',-2); +select substring_index('aaaaaaaaa1','aaa',-3); +select substring_index('aaaaaaaaa1','aaa',-4); +select substring_index('the king of thethe hill','the',-2); +select substring_index('the king of the the hill','the',-2); +select substring_index('the king of the the hill','the',-2); +select substring_index('the king of the the hill',' the ',-1); +select substring_index('the king of the the hill',' the ',-2); +select substring_index('the king of the the hill',' ',-1); +select substring_index('the king of the the hill',' ',-2); +select substring_index('the king of the the hill',' ',-3); +select substring_index('the king of the the hill',' ',-4); +select substring_index('the king of the the hill',' ',-5); +select substring_index('the king of the.the hill','the',-2); +select substring_index('the king of thethethe.the hill','the',-3); +select substring_index('the king of thethethe.the hill','the',-1); +select substring_index('the king of the the hill','the',1); +select substring_index('the king of the the hill','the',2); +select substring_index('the king of the the hill','the',3); select concat(':',ltrim(' left '),':',rtrim(' right '),':'); select concat(':',trim(LEADING FROM ' left'),':',trim(TRAILING FROM ' right '),':'); diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index d316c7eaf72..52a2dedb67c 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -42,7 +42,7 @@ static void my_coll_agg_error(DTCollation &c1, DTCollation &c2, const char *fname) { my_error(ER_CANT_AGGREGATE_2COLLATIONS,MYF(0), - c1.collation->name,c1.derivation_name(), + c1.collation->name,c1.derivation_name(), c2.collation->name,c2.derivation_name(), fname); } @@ -1188,10 +1188,22 @@ String *Item_func_substr_index::val_str(String *str) } else { // Start counting at end - for (offset=res->length() ; ; offset-=delimeter_length-1) + /* + Negative index, start counting at the end + */ + for (offset=res->length(); offset ;) { + /* + this call will result in finding the position pointing to one + address space less than where the found substring is located + in res + */ if ((int) (offset=res->strrstr(*delimeter,offset)) < 0) return res; // Didn't find, return org string + /* + At this point, we've searched for the substring + the number of times as supplied by the index value + */ if (!++count) { offset+=delimeter_length; From 74c71689926802047d249684501d433ae86f324d Mon Sep 17 00:00:00 2001 From: "patg@krsna.patg.net" <> Date: Mon, 8 Aug 2005 13:50:10 -0700 Subject: [PATCH 5/5] BUG #12119 Removed unnecessary error message from mysql.cc (client program) --- client/mysql.cc | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/client/mysql.cc b/client/mysql.cc index 5454c76e720..63173aab20d 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -1563,11 +1563,8 @@ You can turn off this feature to get a quicker startup with -A\n\n"); mysql_free_result(fields); } else - { - tee_fprintf(stdout, - "Didn't find any fields in table '%s'\n",table_row[0]); field_names[i]= 0; - } + i++; } mysql_free_result(tables);