Below is the list of changes that have just been committed into a local
5.1 repository of bar. When bar does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html
ChangeSet@stripped, 2006-11-03 10:29:44+04:00, bar@stripped +14 -0
Merge mysql.com:/usr/home/bar/mysql-5.0-rpl
into mysql.com:/usr/home/bar/mysql-5.1-rpl
MERGE: 1.1810.2078.45
BitKeeper/etc/collapsed@stripped, 2006-11-03 10:24:26+04:00, bar@stripped +0 -1
auto-union
MERGE: 1.5.1.4
include/m_ctype.h@stripped, 2006-11-03 10:24:38+04:00, bar@stripped +0 -0
Auto merged
MERGE: 1.114.1.9
mysql-test/r/ctype_utf8.result@stripped, 2006-11-03 10:24:38+04:00,
bar@stripped +0 -0
Auto merged
MERGE: 1.85.5.12
mysql-test/t/rpl_ignore_table.test@stripped, 2006-11-03 10:29:39+04:00,
bar@stripped +1 -2
After merge fix.
MERGE: 1.1.1.1
sql/field.cc@stripped, 2006-11-03 10:24:38+04:00, bar@stripped +0 -0
Auto merged
MERGE: 1.256.1.71
sql/slave.cc@stripped, 2006-11-03 10:29:39+04:00, bar@stripped +0 -0
After merge fix
MERGE: 1.241.1.41
sql/sql_parse.cc@stripped, 2006-11-03 10:24:39+04:00, bar@stripped +0 -0
Auto merged
MERGE: 1.426.1.158
sql/sql_string.cc@stripped, 2006-11-03 10:24:39+04:00, bar@stripped +0 -0
Auto merged
MERGE: 1.91.1.3
storage/myisam/mi_open.c@stripped, 2006-11-03 10:24:39+04:00, bar@stripped
+0 -0
Auto merged
MERGE: 1.90.8.3
storage/myisam/mi_open.c@stripped, 2006-11-03 10:24:38+04:00,
bar@stripped +0 -0
Merge rename: myisam/mi_open.c -> storage/myisam/mi_open.c
strings/ctype-bin.c@stripped, 2006-11-03 10:24:39+04:00, bar@stripped +0 -0
Auto merged
MERGE: 1.66.1.5
strings/ctype-mb.c@stripped, 2006-11-03 10:24:39+04:00, bar@stripped +0 -0
Auto merged
MERGE: 1.47.1.5
strings/ctype-simple.c@stripped, 2006-11-03 10:24:39+04:00, bar@stripped +0
-0
Auto merged
MERGE: 1.75.1.3
strings/ctype-ucs2.c@stripped, 2006-11-03 10:24:39+04:00, bar@stripped +0
-0
Auto merged
MERGE: 1.50.1.13
strings/ctype-utf8.c@stripped, 2006-11-03 10:24:39+04:00, bar@stripped +0
-0
Auto merged
MERGE: 1.97.1.4
# This is a BitKeeper patch. What follows are the unified diffs for the
# set of deltas contained in the patch. The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User: bar
# Host: bar.intranet.mysql.r18.ru
# Root: /usr/home/bar/mysql-5.1-rpl/RESYNC
--- 1.128/include/m_ctype.h 2006-11-03 10:29:55 +04:00
+++ 1.129/include/m_ctype.h 2006-11-03 10:29:55 +04:00
@@ -190,8 +190,8 @@ typedef struct my_charset_handler_st
const unsigned char *s, const unsigned char *e);
/* Functions for case and sort conversion */
- void (*caseup_str)(struct charset_info_st *, char *);
- void (*casedn_str)(struct charset_info_st *, char *);
+ uint (*caseup_str)(struct charset_info_st *, char *);
+ uint (*casedn_str)(struct charset_info_st *, char *);
uint (*caseup)(struct charset_info_st *, char *src, uint srclen,
char *dst, uint dstlen);
uint (*casedn)(struct charset_info_st *, char *src, uint srclen,
@@ -324,8 +324,8 @@ extern uint my_instr_simple(struct chars
/* Functions for 8bit */
-extern void my_caseup_str_8bit(CHARSET_INFO *, char *);
-extern void my_casedn_str_8bit(CHARSET_INFO *, char *);
+extern uint my_caseup_str_8bit(CHARSET_INFO *, char *);
+extern uint my_casedn_str_8bit(CHARSET_INFO *, char *);
extern uint my_caseup_8bit(CHARSET_INFO *, char *src, uint srclen,
char *dst, uint dstlen);
extern uint my_casedn_8bit(CHARSET_INFO *, char *src, uint srclen,
@@ -415,8 +415,8 @@ int my_mbcharlen_8bit(CHARSET_INFO *, ui
/* Functions for multibyte charsets */
-extern void my_caseup_str_mb(CHARSET_INFO *, char *);
-extern void my_casedn_str_mb(CHARSET_INFO *, char *);
+extern uint my_caseup_str_mb(CHARSET_INFO *, char *);
+extern uint my_casedn_str_mb(CHARSET_INFO *, char *);
extern uint my_caseup_mb(CHARSET_INFO *, char *src, uint srclen,
char *dst, uint dstlen);
extern uint my_casedn_mb(CHARSET_INFO *, char *src, uint srclen,
--- 1.90.8.2/myisam/mi_open.c 2006-11-03 10:29:55 +04:00
+++ 1.106/storage/myisam/mi_open.c 2006-11-03 10:29:55 +04:00
@@ -95,7 +95,8 @@ MI_INFO *mi_open(const char *name, int m
head_length=sizeof(share_buff.state.header);
bzero((byte*) &info,sizeof(info));
- my_realpath(name_buff, fn_format(org_name,name,"",MI_NAME_IEXT,4),MYF(0));
+ my_realpath(name_buff, fn_format(org_name,name,"",MI_NAME_IEXT,
+ MY_UNPACK_FILENAME),MYF(0));
pthread_mutex_lock(&THR_LOCK_myisam);
if (!(old_info=test_if_reopen(name_buff)))
{
@@ -141,17 +142,27 @@ MI_INFO *mi_open(const char *name, int m
~(HA_OPTION_PACK_RECORD | HA_OPTION_PACK_KEYS |
HA_OPTION_COMPRESS_RECORD | HA_OPTION_READ_ONLY_DATA |
HA_OPTION_TEMP_COMPRESS_RECORD | HA_OPTION_CHECKSUM |
- HA_OPTION_TMP_TABLE | HA_OPTION_DELAY_KEY_WRITE))
+ HA_OPTION_TMP_TABLE | HA_OPTION_DELAY_KEY_WRITE |
+ HA_OPTION_RELIES_ON_SQL_LAYER))
{
DBUG_PRINT("error",("wrong options: 0x%lx", share->options));
my_errno=HA_ERR_OLD_FILE;
goto err;
}
+ if ((share->options & HA_OPTION_RELIES_ON_SQL_LAYER) &&
+ ! (open_flags & HA_OPEN_FROM_SQL_LAYER))
+ {
+ DBUG_PRINT("error", ("table cannot be openned from non-sql layer"));
+ my_errno= HA_ERR_UNSUPPORTED;
+ goto err;
+ }
/* Don't call realpath() if the name can't be a link */
if (!strcmp(name_buff, org_name) ||
my_readlink(index_name, org_name, MYF(0)) == -1)
(void) strmov(index_name, org_name);
- (void) fn_format(data_name,org_name,"",MI_NAME_DEXT,2+4+16);
+ *strrchr(org_name, '.')= '\0';
+ (void) fn_format(data_name,org_name,"",MI_NAME_DEXT,
+ MY_APPEND_EXT|MY_UNPACK_FILENAME|MY_RESOLVE_SYMLINKS);
info_length=mi_uint2korr(share->state.header.header_length);
base_pos=mi_uint2korr(share->state.header.base_pos);
@@ -197,9 +208,9 @@ MI_INFO *mi_open(const char *name, int m
if (len != MI_BASE_INFO_SIZE)
{
DBUG_PRINT("warning",("saved_base_info_length: %d base_info_length: %d",
- len,MI_BASE_INFO_SIZE))
+ len,MI_BASE_INFO_SIZE));
}
- disk_pos= (char*)
+ disk_pos= (char*)
my_n_base_info_read((uchar*) disk_cache + base_pos, &share->base);
share->state.state_length=base_pos;
@@ -287,10 +298,11 @@ MI_INFO *mi_open(const char *name, int m
&share->data_file_name,strlen(data_name)+1,
&share->state.key_root,keys*sizeof(my_off_t),
&share->state.key_del,
- (share->state.header.max_block_size*sizeof(my_off_t)),
+ (share->state.header.max_block_size_index*sizeof(my_off_t)),
#ifdef THREAD
&share->key_root_lock,sizeof(rw_lock_t)*keys,
#endif
+ &share->mmap_lock,sizeof(rw_lock_t),
NullS))
goto err;
errpos=4;
@@ -301,7 +313,7 @@ MI_INFO *mi_open(const char *name, int m
(char*) key_root, sizeof(my_off_t)*keys);
memcpy((char*) share->state.key_del,
(char*) key_del, (sizeof(my_off_t) *
- share->state.header.max_block_size));
+ share->state.header.max_block_size_index));
strmov(share->unique_file_name, name_buff);
share->unique_name_length= strlen(name_buff);
strmov(share->index_file_name, index_name);
@@ -422,6 +434,7 @@ MI_INFO *mi_open(const char *name, int m
pos->flag=0;
pos++;
}
+ share->ftparsers= 0;
}
disk_pos_assert(disk_pos + share->base.fields *MI_COLUMNDEF_SIZE, end_pos);
@@ -464,7 +477,6 @@ MI_INFO *mi_open(const char *name, int m
(keys ? MI_INDEX_BLOCK_MARGIN *
share->blocksize * keys : 0));
share->blocksize=min(IO_SIZE,myisam_block_size);
-
share->data_file_type=STATIC_RECORD;
if (share->options & HA_OPTION_COMPRESS_RECORD)
{
@@ -482,11 +494,13 @@ MI_INFO *mi_open(const char *name, int m
share->data_file_type = DYNAMIC_RECORD;
my_afree((gptr) disk_cache);
mi_setup_functions(share);
+ share->is_log_table= FALSE;
#ifdef THREAD
thr_lock_init(&share->lock);
VOID(pthread_mutex_init(&share->intern_lock,MY_MUTEX_INIT_FAST));
for (i=0; i<keys; i++)
VOID(my_rwlock_init(&share->key_root_lock[i], NULL));
+ VOID(my_rwlock_init(&share->mmap_lock, NULL));
if (!thr_lock_inited)
{
/* Probably a single threaded program; Don't use concurrent inserts */
@@ -741,6 +755,8 @@ void mi_setup_functions(register MYISAM_
share->compare_unique=_mi_cmp_static_unique;
share->calc_checksum= mi_static_checksum;
}
+ share->file_read= mi_nommap_pread;
+ share->file_write= mi_nommap_pwrite;
if (!(share->options & HA_OPTION_CHECKSUM))
share->calc_checksum=0;
return;
@@ -810,7 +826,7 @@ uint mi_state_info_write(File file, MI_S
uchar buff[MI_STATE_INFO_SIZE + MI_STATE_EXTRA_SIZE];
uchar *ptr=buff;
uint i, keys= (uint) state->header.keys,
- key_blocks=state->header.max_block_size;
+ key_blocks=state->header.max_block_size_index;
DBUG_ENTER("mi_state_info_write");
memcpy_fixed(ptr,&state->header,sizeof(state->header));
@@ -876,7 +892,7 @@ uchar *mi_state_info_read(uchar *ptr, MI
ptr +=sizeof(state->header);
keys=(uint) state->header.keys;
key_parts=mi_uint2korr(state->header.key_parts);
- key_blocks=state->header.max_block_size;
+ key_blocks=state->header.max_block_size_index;
state->open_count = mi_uint2korr(ptr); ptr +=2;
state->changed= (bool) *ptr++;
@@ -1049,9 +1065,11 @@ char *mi_keydef_read(char *ptr, MI_KEYDE
keydef->keylength = mi_uint2korr(ptr); ptr +=2;
keydef->minlength = mi_uint2korr(ptr); ptr +=2;
keydef->maxlength = mi_uint2korr(ptr); ptr +=2;
- keydef->block_size = keydef->block_length/MI_MIN_KEY_BLOCK_LENGTH-1;
+ keydef->block_size_index= keydef->block_length/MI_MIN_KEY_BLOCK_LENGTH-1;
keydef->underflow_block_length=keydef->block_length/3;
keydef->version = 0; /* Not saved */
+ keydef->parser = &ft_default_parser;
+ keydef->ftparser_nr = 0;
return ptr;
}
--- 1.585/sql/sql_parse.cc 2006-11-03 10:29:55 +04:00
+++ 1.586/sql/sql_parse.cc 2006-11-03 10:29:55 +04:00
@@ -2543,7 +2543,23 @@ mysql_execute_command(THD *thd)
{
/* we warn the slave SQL thread */
my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0));
- reset_one_shot_variables(thd);
+ if (thd->one_shot_set)
+ {
+ /*
+ It's ok to check thd->one_shot_set here:
+
+ The charsets in a MySQL 5.0 slave can change by both a binlogged
+ SET ONE_SHOT statement and the event-internal charset setting,
+ and these two ways to change charsets do not seems to work
+ together.
+
+ At least there seems to be problems in the rli cache for
+ charsets if we are using ONE_SHOT. Note that this is normally no
+ problem because either the >= 5.0 slave reads a 4.1 binlog (with
+ ONE_SHOT) *or* or 5.0 binlog (without ONE_SHOT) but never both."
+ */
+ reset_one_shot_variables(thd);
+ }
DBUG_RETURN(0);
}
}
@@ -6358,7 +6374,7 @@ TABLE_LIST *st_select_lex::add_table_to_
ptr->alias= alias_str;
if (lower_case_table_names && table->table.length)
- my_casedn_str(files_charset_info, table->table.str);
+ table->table.length= my_casedn_str(files_charset_info, table->table.str);
ptr->table_name=table->table.str;
ptr->table_name_length=table->table.length;
ptr->lock_type= lock_type;
--- 1.2/mysql-test/t/rpl_ignore_table.test 2006-11-03 10:29:55 +04:00
+++ 1.3/mysql-test/t/rpl_ignore_table.test 2006-11-03 10:29:55 +04:00
@@ -28,3 +28,25 @@ connection master;
DROP TABLE t1;
DROP TABLE t4;
sync_slave_with_master;
+
+#
+# bug#22877 replication character sets get out of sync
+# using replicate-wild-ignore-table
+#
+--disable_warnings
+DROP TABLE IF EXISTS t5;
+--enable_warnings
+CREATE TABLE t5 (
+ word varchar(50) collate utf8_unicode_ci NOT NULL default ''
+) DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
+SET @@session.character_set_client=33,@@session.collation_connection=192;
+CREATE TEMPORARY TABLE tmptbl504451f4258$1 (id INT NOT NULL) ENGINE=MEMORY;
+INSERT INTO t5 (word) VALUES ('TEST’');
+SELECT HEX(word) FROM t5;
+sync_slave_with_master;
+connection slave;
+SELECT HEX(word) FROM t5;
+--error 1146
+SELECT * FROM tmptbl504451f4258$1;
+connection master;
+DROP TABLE t5;
--- 1.72/strings/ctype-bin.c 2006-11-03 10:29:55 +04:00
+++ 1.73/strings/ctype-bin.c 2006-11-03 10:29:55 +04:00
@@ -211,9 +211,10 @@ static int my_strnncollsp_8bit_bin(CHARS
/* This function is used for all conversion functions */
-static void my_case_str_bin(CHARSET_INFO *cs __attribute__((unused)),
+static uint my_case_str_bin(CHARSET_INFO *cs __attribute__((unused)),
char *str __attribute__((unused)))
{
+ return 0;
}
static uint my_case_bin(CHARSET_INFO *cs __attribute__((unused)),
--- 1.63/strings/ctype-ucs2.c 2006-11-03 10:29:55 +04:00
+++ 1.64/strings/ctype-ucs2.c 2006-11-03 10:29:55 +04:00
@@ -159,13 +159,13 @@ static void my_hash_sort_ucs2(CHARSET_IN
}
-static void my_caseup_str_ucs2(CHARSET_INFO * cs __attribute__((unused)),
+static uint my_caseup_str_ucs2(CHARSET_INFO * cs __attribute__((unused)),
char * s __attribute__((unused)))
{
+ return 0;
}
-
static uint my_casedn_ucs2(CHARSET_INFO *cs, char *src, uint srclen,
char *dst __attribute__((unused)),
uint dstlen __attribute__((unused)))
@@ -188,9 +188,11 @@ static uint my_casedn_ucs2(CHARSET_INFO
return srclen;
}
-static void my_casedn_str_ucs2(CHARSET_INFO *cs __attribute__((unused)),
+
+static uint my_casedn_str_ucs2(CHARSET_INFO *cs __attribute__((unused)),
char * s __attribute__((unused)))
{
+ return 0;
}
--- 1.53/strings/ctype-mb.c 2006-11-03 10:29:55 +04:00
+++ 1.54/strings/ctype-mb.c 2006-11-03 10:29:55 +04:00
@@ -21,40 +21,44 @@
#ifdef USE_MB
-void my_caseup_str_mb(CHARSET_INFO * cs, char *str)
+uint my_caseup_str_mb(CHARSET_INFO * cs, char *str)
{
register uint32 l;
- register uchar *map=cs->to_upper;
+ register uchar *map= cs->to_upper;
+ char *str_orig= str;
while (*str)
{
/* Pointing after the '\0' is safe here. */
- if ((l=my_ismbchar(cs, str, str + cs->mbmaxlen)))
- str+=l;
+ if ((l= my_ismbchar(cs, str, str + cs->mbmaxlen)))
+ str+= l;
else
{
- *str=(char) map[(uchar)*str];
+ *str= (char) map[(uchar)*str];
str++;
}
}
+ return str - str_orig;
}
-void my_casedn_str_mb(CHARSET_INFO * cs, char *str)
+uint my_casedn_str_mb(CHARSET_INFO * cs, char *str)
{
register uint32 l;
- register uchar *map=cs->to_lower;
+ register uchar *map= cs->to_lower;
+ char *str_orig= str;
while (*str)
{
/* Pointing after the '\0' is safe here. */
- if ((l=my_ismbchar(cs, str, str + cs->mbmaxlen)))
- str+=l;
+ if ((l= my_ismbchar(cs, str, str + cs->mbmaxlen)))
+ str+= l;
else
{
- *str=(char) map[(uchar)*str];
+ *str= (char) map[(uchar)*str];
str++;
}
}
+ return str - str_orig;
}
uint my_caseup_mb(CHARSET_INFO * cs, char *src, uint srclen,
--- 1.80/strings/ctype-simple.c 2006-11-03 10:29:55 +04:00
+++ 1.81/strings/ctype-simple.c 2006-11-03 10:29:55 +04:00
@@ -188,19 +188,25 @@ int my_strnncollsp_simple(CHARSET_INFO *
}
-void my_caseup_str_8bit(CHARSET_INFO * cs,char *str)
+uint my_caseup_str_8bit(CHARSET_INFO * cs,char *str)
{
- register uchar *map=cs->to_upper;
- while ((*str = (char) map[(uchar) *str]) != 0)
+ register uchar *map= cs->to_upper;
+ char *str_orig= str;
+ while ((*str= (char) map[(uchar) *str]) != 0)
str++;
+ return str - str_orig;
}
-void my_casedn_str_8bit(CHARSET_INFO * cs,char *str)
+
+uint my_casedn_str_8bit(CHARSET_INFO * cs,char *str)
{
- register uchar *map=cs->to_lower;
- while ((*str = (char) map[(uchar)*str]) != 0)
+ register uchar *map= cs->to_lower;
+ char *str_orig= str;
+ while ((*str= (char) map[(uchar) *str]) != 0)
str++;
+ return str - str_orig;
}
+
uint my_caseup_8bit(CHARSET_INFO * cs, char *src, uint srclen,
char *dst __attribute__((unused)),
--- 1.106/strings/ctype-utf8.c 2006-11-03 10:29:55 +04:00
+++ 1.107/strings/ctype-utf8.c 2006-11-03 10:29:55 +04:00
@@ -2047,6 +2047,52 @@ static int my_utf8_uni(CHARSET_INFO *cs
return MY_CS_ILSEQ;
}
+
+/*
+ The same as above, but without range check
+ for example, for a null-terminated string
+*/
+static int my_utf8_uni_no_range(CHARSET_INFO *cs __attribute__((unused)),
+ my_wc_t * pwc, const uchar *s)
+{
+ unsigned char c;
+
+ c= s[0];
+ if (c < 0x80)
+ {
+ *pwc = c;
+ return 1;
+ }
+
+ if (c < 0xc2)
+ return MY_CS_ILSEQ;
+
+ if (c < 0xe0)
+ {
+ if (!((s[1] ^ 0x80) < 0x40))
+ return MY_CS_ILSEQ;
+
+ *pwc = ((my_wc_t) (c & 0x1f) << 6) | (my_wc_t) (s[1] ^ 0x80);
+ return 2;
+ }
+
+ if (c < 0xf0)
+ {
+ if (!((s[1] ^ 0x80) < 0x40 &&
+ (s[2] ^ 0x80) < 0x40 &&
+ (c >= 0xe1 || s[1] >= 0xa0)))
+ return MY_CS_ILSEQ;
+
+ *pwc= ((my_wc_t) (c & 0x0f) << 12) |
+ ((my_wc_t) (s[1] ^ 0x80) << 6) |
+ (my_wc_t) (s[2] ^ 0x80);
+
+ return 3;
+ }
+ return MY_CS_ILSEQ;
+}
+
+
static int my_uni_utf8 (CHARSET_INFO *cs __attribute__((unused)) ,
my_wc_t wc, uchar *r, uchar *e)
{
@@ -2093,6 +2139,34 @@ static int my_uni_utf8 (CHARSET_INFO *cs
}
+/*
+ The same as above, but without range check.
+*/
+static int my_uni_utf8_no_range(CHARSET_INFO *cs __attribute__((unused)),
+ my_wc_t wc, uchar *r)
+{
+ int count;
+
+ if (wc < 0x80)
+ count= 1;
+ else if (wc < 0x800)
+ count= 2;
+ else if (wc < 0x10000)
+ count= 3;
+ else
+ return MY_CS_ILUNI;
+
+ switch (count)
+ {
+ /* Fall through all cases!!! */
+ case 3: r[2]= (uchar) (0x80 | (wc & 0x3f)); wc= wc >> 6; wc |= 0x800;
+ case 2: r[1]= (uchar) (0x80 | (wc & 0x3f)); wc= wc >> 6; wc |= 0xc0;
+ case 1: r[0]= (uchar) wc;
+ }
+ return count;
+}
+
+
static uint my_caseup_utf8(CHARSET_INFO *cs, char *src, uint srclen,
char *dst, uint dstlen)
{
@@ -2143,10 +2217,26 @@ static void my_hash_sort_utf8(CHARSET_IN
}
-static void my_caseup_str_utf8(CHARSET_INFO * cs, char * s)
+static uint my_caseup_str_utf8(CHARSET_INFO *cs, char *src)
{
- uint len= (uint) strlen(s);
- my_caseup_utf8(cs, s, len, s, len);
+ my_wc_t wc;
+ int srcres, dstres;
+ char *dst= src, *dst0= src;
+ MY_UNICASE_INFO **uni_plane= cs->caseinfo;
+ DBUG_ASSERT(cs->caseup_multiply == 1);
+
+ while (*src &&
+ (srcres= my_utf8_uni_no_range(cs, &wc, (uchar *) src)) > 0)
+ {
+ int plane= (wc>>8) & 0xFF;
+ wc= uni_plane[plane] ? uni_plane[plane][wc & 0xFF].toupper : wc;
+ if ((dstres= my_uni_utf8_no_range(cs, wc, (uchar*) dst)) <= 0)
+ break;
+ src+= srcres;
+ dst+= dstres;
+ }
+ *dst= '\0';
+ return (uint) (dst - dst0);
}
@@ -2172,10 +2262,43 @@ static uint my_casedn_utf8(CHARSET_INFO
return (uint) (dst - dst0);
}
-static void my_casedn_str_utf8(CHARSET_INFO *cs, char * s)
+
+static uint my_casedn_str_utf8(CHARSET_INFO *cs, char *src)
{
- uint len= (uint) strlen(s);
- my_casedn_utf8(cs, s, len, s, len);
+ my_wc_t wc;
+ int srcres, dstres;
+ char *dst= src, *dst0= src;
+ MY_UNICASE_INFO **uni_plane= cs->caseinfo;
+ DBUG_ASSERT(cs->casedn_multiply == 1);
+
+ while (*src &&
+ (srcres= my_utf8_uni_no_range(cs, &wc, (uchar *) src)) > 0)
+ {
+ int plane= (wc>>8) & 0xFF;
+ wc= uni_plane[plane] ? uni_plane[plane][wc & 0xFF].tolower : wc;
+ if ((dstres= my_uni_utf8_no_range(cs, wc, (uchar*) dst)) <= 0)
+ break;
+ src+= srcres;
+ dst+= dstres;
+ }
+
+ /*
+ In rare cases lower string can be shorter than
+ the original string, for example:
+
+ "U+0130 LATIN CAPITAL LETTER I WITH DOT ABOVE"
+ (which is 0xC4B0 in utf8, i.e. two bytes)
+
+ is converted into
+
+ "U+0069 LATIN SMALL LETTER I"
+ (which is 0x69 in utf8, i.e. one byte)
+
+ So, we need to put '\0' terminator after converting.
+ */
+
+ *dst= '\0';
+ return (uint) (dst - dst0);
}
--- 1.10/BitKeeper/etc/collapsed 2006-11-03 10:29:55 +04:00
+++ 1.11/BitKeeper/etc/collapsed 2006-11-03 10:29:55 +04:00
@@ -8,3 +8,4 @@
4519a6c5BVUxEHTf5iJnjZkixMBs8g
451ab499rgdjXyOnUDqHu-wBDoS-OQ
452c6c6dAjuNghfc1ObZ_UQ5SCl85g
+4538a7b0EbDHHkWPbIwxO6ZIDdg6Dg
| Thread |
|---|
| • bk commit into 5.1 tree (bar:1.2329) | bar | 3 Nov |