1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-29 05:21:33 +03:00

Bug#4521: unique key prefix interacts poorly with utf8.

Fix for binary collations for MyISAM and HEAP BTREE.
This patch also changes trailing spaces behaviour for
binary collations. Binary collations now have PAD 
characteristic too.
This commit is contained in:
bar@mysql.com
2004-08-19 15:15:10 +05:00
parent 6b90806a4a
commit 2496e85b84
11 changed files with 384 additions and 41 deletions

View File

@ -68,31 +68,10 @@ static uchar bin_char_array[] =
/*
Compare two strings. Result is sign(first_argument - second_argument)
SYNOPSIS
my_strnncoll_binary()
cs Chararacter set
s String to compare
slen Length of 's'
t String to compare
tlen Length of 't'
NOTE
This is used also when comparing with end space removal, as end space
is significant for binary strings
RETURN
< 0 s < t
0 s == t
> 0 s > t
*/
static int my_strnncoll_binary(CHARSET_INFO * cs __attribute__((unused)),
const uchar *s, uint slen,
const uchar *t, uint tlen,
my_bool t_is_prefix)
const uchar *s, uint slen,
const uchar *t, uint tlen,
my_bool t_is_prefix)
{
uint len=min(slen,tlen);
int cmp= memcmp(s,t,len);
@ -100,14 +79,105 @@ static int my_strnncoll_binary(CHARSET_INFO * cs __attribute__((unused)),
}
/*
Compare two strings. Result is sign(first_argument - second_argument)
SYNOPSIS
my_strnncollsp_binary()
cs Chararacter set
s String to compare
slen Length of 's'
t String to compare
tlen Length of 't'
NOTE
This function is used for real binary strings, i.e. for
BLOB, BINARY(N) and VARBINARY(N).
It does not ignore trailing spaces.
RETURN
< 0 s < t
0 s == t
> 0 s > t
*/
static int my_strnncollsp_binary(CHARSET_INFO * cs __attribute__((unused)),
const uchar *s, uint slen,
const uchar *t, uint tlen)
const uchar *s, uint slen,
const uchar *t, uint tlen)
{
return my_strnncoll_binary(cs,s,slen,t,tlen,0);
}
static int my_strnncoll_8bit_bin(CHARSET_INFO * cs __attribute__((unused)),
const uchar *s, uint slen,
const uchar *t, uint tlen,
my_bool t_is_prefix)
{
uint len=min(slen,tlen);
int cmp= memcmp(s,t,len);
return cmp ? cmp : (int)((t_is_prefix ? len : slen) - tlen);
}
/*
Compare two strings. Result is sign(first_argument - second_argument)
SYNOPSIS
my_strnncollsp_8bit_bin()
cs Chararacter set
s String to compare
slen Length of 's'
t String to compare
tlen Length of 't'
NOTE
This function is used for character strings with binary collations.
It ignores trailing spaces.
RETURN
< 0 s < t
0 s == t
> 0 s > t
*/
static int my_strnncollsp_8bit_bin(CHARSET_INFO * cs __attribute__((unused)),
const uchar *a, uint a_length,
const uchar *b, uint b_length)
{
const uchar *end;
uint length;
end= a + (length= min(a_length, b_length));
while (a < end)
{
if (*a++ != *b++)
return ((int) a[-1] - (int) b[-1]);
}
if (a_length != b_length)
{
int swap= 0;
/*
Check the next not space character of the longer key. If it's < ' ',
then it's smaller than the other key.
*/
if (a_length < b_length)
{
/* put shorter key in s */
a_length= b_length;
a= b;
swap= -1; /* swap sign of result */
}
for (end= a + a_length-length; a < end ; a++)
{
if (*a != ' ')
return ((int) *a - (int) ' ') ^ swap;
}
}
return 0;
}
/* This function is used for all conversion functions */
static void my_case_str_bin(CHARSET_INFO *cs __attribute__((unused)),
@ -342,6 +412,20 @@ skip:
MY_COLLATION_HANDLER my_collation_8bit_bin_handler =
{
NULL, /* init */
my_strnncoll_8bit_bin,
my_strnncollsp_8bit_bin,
my_strnxfrm_bin,
my_like_range_simple,
my_wildcmp_bin,
my_strcasecmp_bin,
my_instr_bin,
my_hash_sort_bin
};
static MY_COLLATION_HANDLER my_collation_binary_handler =
{
NULL, /* init */
my_strnncoll_binary,
@ -407,5 +491,5 @@ CHARSET_INFO my_charset_bin =
0, /* min_sort_char */
255, /* max_sort_char */
&my_charset_handler,
&my_collation_8bit_bin_handler
&my_collation_binary_handler
};

View File

@ -360,11 +360,62 @@ static int my_strnncoll_mb_bin(CHARSET_INFO * cs __attribute__((unused)),
return cmp ? cmp : (int) ((t_is_prefix ? len : slen) - tlen);
}
/*
Compare two strings.
SYNOPSIS
my_strnncollsp_mb_bin()
cs Chararacter set
s String to compare
slen Length of 's'
t String to compare
tlen Length of 't'
NOTE
This function is used for character strings with binary collations.
It ignores trailing spaces.
RETURN
A negative number if s < t
A positive number if s > t
0 if strings are equal
*/
static int my_strnncollsp_mb_bin(CHARSET_INFO * cs __attribute__((unused)),
const uchar *s, uint slen,
const uchar *t, uint tlen)
const uchar *a, uint a_length,
const uchar *b, uint b_length)
{
return my_strnncoll_mb_bin(cs,s,slen,t,tlen,0);
const uchar *end;
uint length;
end= a + (length= min(a_length, b_length));
while (a < end)
{
if (*a++ != *b++)
return ((int) a[-1] - (int) b[-1]);
}
if (a_length != b_length)
{
int swap= 0;
/*
Check the next not space character of the longer key. If it's < ' ',
then it's smaller than the other key.
*/
if (a_length < b_length)
{
/* put shorter key in s */
a_length= b_length;
a= b;
swap= -1; /* swap sign of result */
}
for (end= a + a_length-length; a < end ; a++)
{
if (*a != ' ')
return ((int) *a - (int) ' ') ^ swap;
}
}
return 0;
}