Commit e7300f13 authored by unknown's avatar unknown
Browse files

Bug#8610: The ucs2_turkish_ci collation fails with upper('i')

  UPPER/LOWER now can return a string with different length.

mi_test1.c:
  Adding new arguments.
Many files:
  Changeing caseup/casedn to return a result with different
  length than argument.
sql_string.h:
  Removing unused method,
mysql_priv.h:
  Removing unused method


strings/ctype-big5.c:
  Changeing caseup/casedn to return a result with different length than argument.
strings/ctype-bin.c:
  Changeing caseup/casedn to return a result with different length than argument.
strings/ctype-cp932.c:
  Changeing caseup/casedn to return a result with different length than argument.
strings/ctype-czech.c:
  Changeing caseup/casedn to return a result with different length than argument.
strings/ctype-euc_kr.c:
  Changeing caseup/casedn to return a result with different length than argument.
strings/ctype-extra.c:
  Changeing caseup/casedn to return a result with different length than argument.
strings/ctype-eucjpms.c:
  Changeing caseup/casedn to return a result with different length than argument.
strings/ctype-gb2312.c:
  Changeing caseup/casedn to return a result with different length than argument.
strings/ctype-gbk.c:
  Changeing caseup/casedn to return a result with different length than argument.
strings/ctype-latin1.c:
  Changeing caseup/casedn to return a result with different length than argument.
strings/ctype-mb.c:
  Changeing caseup/casedn to return a result with different length than argument.
strings/ctype-simple.c:
  Changeing caseup/casedn to return a result with different length than argument.
strings/ctype-sjis.c:
  Changeing caseup/casedn to return a result with different length than argument.
strings/ctype-tis620.c:
  Changeing caseup/casedn to return a result with different length than argument.
strings/ctype-uca.c:
  Changeing caseup/casedn to return a result with different length than argument.
strings/ctype-ucs2.c:
  Changeing caseup/casedn to return a result with different length than argument.
strings/ctype-ujis.c:
  Changeing caseup/casedn to return a result with different length than argument.
strings/ctype-utf8.c:
  Changeing caseup/casedn to return a result with different length than argument.
strings/ctype-win1250ch.c:
  Changeing caseup/casedn to return a result with different length than argument.
sql/item_strfunc.cc:
  Changeing caseup/casedn to return a result with different length than argument.
sql/item_strfunc.h:
  Changeing caseup/casedn to return a result with different length than argument.
sql/mysql_priv.h:
  Removing unused method
sql/sql_string.h:
  Removing unused method,
client/sql_string.h:
  Changeing caseup/casedn to return a result with different length than argument.
include/m_ctype.h:
  Changeing caseup/casedn to return a result with different length than argument.
myisam/mi_test1.c:
  Adding new arguments.
mysql-test/r/ctype_uca.result:
  UPPER/LOWER now can return a string with different length.
mysql-test/t/ctype_uca.test:
  UPPER/LOWER now can return a string with different length.
parent 29f18223
Loading
Loading
Loading
Loading
+0 −2
Original line number Diff line number Diff line
@@ -260,8 +260,6 @@ class String
  }
  bool fill(uint32 max_length,char fill);
  void strip_sp();
  inline void caseup() { my_caseup(str_charset,Ptr,str_length); }
  inline void casedn() { my_casedn(str_charset,Ptr,str_length); }
  friend int sortcmp(const String *a,const String *b, CHARSET_INFO *cs);
  friend int stringcmp(const String *a,const String *b);
  friend String *copy_if_not_alloced(String *a,String *b,uint32 arg_length);
+18 −8
Original line number Diff line number Diff line
@@ -44,6 +44,9 @@ typedef struct unicase_info_st
  uint16 sort;
} MY_UNICASE_INFO;

extern MY_UNICASE_INFO *my_unicase_default[256];
extern MY_UNICASE_INFO *my_unicase_turkish[256];

#define MY_CS_ILSEQ	0
#define MY_CS_ILUNI	0
#define MY_CS_TOOSMALL	-1
@@ -164,8 +167,10 @@ typedef struct my_charset_handler_st
  /* Functions for case and sort convertion */
  void    (*caseup_str)(struct charset_info_st *, char *);
  void    (*casedn_str)(struct charset_info_st *, char *);
  void    (*caseup)(struct charset_info_st *, char *, uint);
  void    (*casedn)(struct charset_info_st *, char *, uint);
  uint    (*caseup)(struct charset_info_st *, char *src, uint srclen,
                                              char *dst, uint dstlen);
  uint    (*casedn)(struct charset_info_st *, char *src, uint srclen,
                                              char *dst, uint dstlen);
  
  /* Charset dependant snprintf() */
  int  (*snprintf)(struct charset_info_st *, char *to, uint n, const char *fmt,
@@ -216,9 +221,12 @@ typedef struct charset_info_st
  uint16   **sort_order_big;
  uint16      *tab_to_uni;
  MY_UNI_IDX  *tab_from_uni;
  MY_UNICASE_INFO **caseinfo;
  uchar     *state_map;
  uchar     *ident_map;
  uint      strxfrm_multiply;
  uchar     caseup_multiply;
  uchar     casedn_multiply;
  uint      mbminlen;
  uint      mbmaxlen;
  uint16    min_sort_char;
@@ -286,8 +294,10 @@ extern uint my_instr_simple(struct charset_info_st *,
/* Functions for 8bit */
extern void my_caseup_str_8bit(CHARSET_INFO *, char *);
extern void my_casedn_str_8bit(CHARSET_INFO *, char *);
extern void my_caseup_8bit(CHARSET_INFO *, char *, uint);
extern void my_casedn_8bit(CHARSET_INFO *, char *, uint);
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,
                                           char *dst, uint dstlen);

extern int my_strcasecmp_8bit(CHARSET_INFO * cs, const char *, const char *);

@@ -359,8 +369,10 @@ int my_mbcharlen_8bit(CHARSET_INFO *, uint c);
/* Functions for multibyte charsets */
extern void my_caseup_str_mb(CHARSET_INFO *, char *);
extern void my_casedn_str_mb(CHARSET_INFO *, char *);
extern void my_caseup_mb(CHARSET_INFO *, char *, uint);
extern void my_casedn_mb(CHARSET_INFO *, char *, uint);
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,
                                         char *dst, uint dstlen);
extern int my_strcasecmp_mb(CHARSET_INFO * cs,const char *, const char *);

int my_wildcmp_mb(CHARSET_INFO *,
@@ -441,8 +453,6 @@ my_bool my_propagate_complex(CHARSET_INFO *cs, const uchar *str, uint len);
#define my_mbcharlen(s, a)            1
#endif

#define my_caseup(s, a, l)            ((s)->cset->caseup((s), (a), (l)))
#define my_casedn(s, a, l)            ((s)->cset->casedn((s), (a), (l)))
#define my_caseup_str(s, a)           ((s)->cset->caseup_str((s), (a)))
#define my_casedn_str(s, a)           ((s)->cset->casedn_str((s), (a)))
#define my_strntol(s, a, b, c, d, e)  ((s)->cset->strntol((s),(a),(b),(c),(d),(e)))
+8 −3
Original line number Diff line number Diff line
@@ -471,20 +471,25 @@ static void update_record(char *record)
    ptr=blob_key;
    memcpy_fixed(pos+4,&ptr,sizeof(char*));	/* Store pointer to new key */
    if (keyinfo[0].seg[0].type != HA_KEYTYPE_NUM)
      my_casedn(default_charset_info,blob_key,length);
      default_charset_info->cset->casedn(default_charset_info,
                                         blob_key, length, blob_key, length);
    pos+=recinfo[1].length;
  }
  else if (recinfo[1].type == FIELD_VARCHAR)
  {
    uint pack_length= HA_VARCHAR_PACKLENGTH(recinfo[1].length-1);
    uint length= pack_length == 1 ? (uint) *(uchar*) pos : uint2korr(pos);
    my_casedn(default_charset_info,pos+pack_length,length);
    default_charset_info->cset->casedn(default_charset_info,
                                       pos + pack_length, length,
                                       pos + pack_length, length);
    pos+=recinfo[1].length;
  }
  else
  {
    if (keyinfo[0].seg[0].type != HA_KEYTYPE_NUM)
      my_casedn(default_charset_info,pos,keyinfo[0].seg[0].length);
      default_charset_info->cset->casedn(default_charset_info,
                                         pos, keyinfo[0].seg[0].length,
                                         pos, keyinfo[0].seg[0].length);
    pos+=recinfo[1].length;
  }

+24 −0
Original line number Diff line number Diff line
@@ -2396,3 +2396,27 @@ utf8_unicode_ci 6109
utf8_unicode_ci	61
utf8_unicode_ci	6120
drop table t1;
CREATE TABLE t1 (id int, a varchar(30) character set utf8);
INSERT INTO t1 VALUES (1, _ucs2 0x01310069), (2, _ucs2 0x01310131);
INSERT INTO t1 VALUES (3, _ucs2 0x00690069), (4, _ucs2 0x01300049);
INSERT INTO t1 VALUES (5, _ucs2 0x01300130), (6, _ucs2 0x00490049);
SELECT a, length(a) la, @l:=lower(a) l, length(@l) ll, @u:=upper(a) u, length(@u) lu
FROM t1 ORDER BY id;
a	la	l	ll	u	lu
ıi	3	ıi	3	II	2
ıı	4	ıı	4	II	2
ii	2	ii	2	II	2
İI	3	ii	2	İI	3
İİ	4	ii	2	İİ	4
II	2	ii	2	II	2
ALTER TABLE t1 MODIFY a VARCHAR(30) character set utf8 collate utf8_turkish_ci;
SELECT a, length(a) la, @l:=lower(a) l, length(@l) ll, @u:=upper(a) u, length(@u) lu
FROM t1 ORDER BY id;
a	la	l	ll	u	lu
ıi	3	ıi	3	Iİ	3
ıı	4	ıı	4	II	2
ii	2	ii	2	İİ	4
İI	3	iı	3	İI	3
İİ	4	ii	2	İİ	4
II	2	ıı	4	II	2
DROP TABLE t1;
+15 −0
Original line number Diff line number Diff line
@@ -455,3 +455,18 @@ drop table t1;

SET collation_connection='utf8_unicode_ci';
-- source include/ctype_filesort.inc

#
# Check UPPER/LOWER changeing length
#
# Result shorter than argument
CREATE TABLE t1 (id int, a varchar(30) character set utf8);
INSERT INTO t1 VALUES (1, _ucs2 0x01310069), (2, _ucs2 0x01310131);
INSERT INTO t1 VALUES (3, _ucs2 0x00690069), (4, _ucs2 0x01300049);
INSERT INTO t1 VALUES (5, _ucs2 0x01300130), (6, _ucs2 0x00490049);
SELECT a, length(a) la, @l:=lower(a) l, length(@l) ll, @u:=upper(a) u, length(@u) lu
FROM t1 ORDER BY id;
ALTER TABLE t1 MODIFY a VARCHAR(30) character set utf8 collate utf8_turkish_ci;
SELECT a, length(a) la, @l:=lower(a) l, length(@l) ll, @u:=upper(a) u, length(@u) lu
FROM t1 ORDER BY id;
DROP TABLE t1;
Loading