Commit b6f6d5b2 authored by unknown's avatar unknown
Browse files

apply UNIQUE constrain correctly for multi-byte charsets

only MyISAM is fixed


include/m_ctype.h:
  my_charpos() macro
myisam/mi_key.c:
  apply UNIQUE constrain correctly for multi-byte charsets
mysql-test/r/binary.result:
  new test
mysql-test/r/key.result:
  apply UNIQUE constrain correctly for multi-byte charsets
mysql-test/t/binary.test:
  new test
mysql-test/t/func_gconcat.test:
  make test to pass w/o InnoDB
mysql-test/t/key.test:
  apply UNIQUE constrain correctly for multi-byte charsets
parent 4a0f586b
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -393,6 +393,8 @@ extern my_bool my_parse_charset_xml(const char *bug, uint len,
   ((s)->coll->like_range((s), (a), (b), (c), (d), (e), (f), (g), (h), (i), (j)))
#define my_wildcmp(cs,s,se,w,we,e,o,m) ((cs)->coll->wildcmp((cs),(s),(se),(w),(we),(e),(o),(m)))
#define my_strcasecmp(s, a, b)        ((s)->coll->strcasecmp((s), (a), (b)))
#define my_charpos(cs, b, e, num)     (cs)->cset->charpos((cs), (const char*) (b), (const char *)(e), (num))


#define use_mb(s)                     ((s)->cset->ismbchar != NULL)
#define my_ismbchar(s, a, b)          ((s)->cset->ismbchar((s), (a), (b)))
+52 −61
Original line number Diff line number Diff line
@@ -25,6 +25,10 @@

#define CHECK_KEYS

#define FIX_LENGTH if (length > char_length) \
                     char_length= my_charpos(cs, pos, pos+length, char_length); \
                   set_if_smaller(char_length,length); \

static int _mi_put_key_in_record(MI_INFO *info,uint keynr,byte *record);

	/*
@@ -32,15 +36,13 @@ static int _mi_put_key_in_record(MI_INFO *info,uint keynr,byte *record);
	** Ret: Length of key
	*/

#define my_charpos(cs, b, e, num)\
 (cs)->cset->charpos((cs), (const char*) (b), (const char *)(e), (num))

uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key,
		  const byte *record, my_off_t filepos)
{
  byte *pos,*end;
  uchar *start;
  reg1 HA_KEYSEG *keyseg;
  my_bool is_unique=info->s->keyinfo[keynr].flag & HA_NOSAME;
  DBUG_ENTER("_mi_make_key");

  if(info->s->keyinfo[keynr].flag & HA_SPATIAL)
@@ -61,7 +63,7 @@ uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key,
    enum ha_base_keytype type=(enum ha_base_keytype) keyseg->type;
    uint length=keyseg->length;
    uint char_length;
    CHARSET_INFO *cs;
    CHARSET_INFO *cs=keyseg->charset;

    if (keyseg->null_bit)
    {
@@ -73,14 +75,7 @@ uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key,
      *key++=1;					/* Not NULL */
    }

    char_length= (cs= keyseg->charset) && (cs->mbmaxlen > 1) ?
                 length / cs->mbmaxlen : 0;
    
    if (info->s->keyinfo[keynr].flag & HA_FULLTEXT)
    {
      /* Ask Serg to make a better fix */
      char_length= 0;
    }
    char_length= (is_unique && cs && cs->mbmaxlen > 1) ? length/cs->mbmaxlen : length;

    pos= (byte*) record+keyseg->start;
    if (keyseg->flag & HA_SPACE_PACK)
@@ -97,14 +92,10 @@ uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key,
	  pos++;
      }
      length=(uint) (end-pos);
      if (char_length && length > char_length)
      {
        char_length= my_charpos(cs, pos, pos+length, char_length);
        set_if_smaller(length, char_length);
      }
      store_key_length_inc(key,length);
      memcpy((byte*) key,(byte*) pos,(size_t) length);
      key+=length;
      FIX_LENGTH;
      store_key_length_inc(key,char_length);
      memcpy((byte*) key,(byte*) pos,(size_t) char_length);
      key+=char_length;
      continue;
    }
    if (keyseg->flag & HA_VAR_LENGTH)
@@ -112,9 +103,10 @@ uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key,
      uint tmp_length=uint2korr(pos);
      pos+=2;					/* Skip VARCHAR length */
      set_if_smaller(length,tmp_length);
      store_key_length_inc(key,length);
      memcpy((byte*) key, pos, length);
      key+= length;
      FIX_LENGTH;
      store_key_length_inc(key,char_length);
      memcpy((byte*) key,(byte*) pos,(size_t) char_length);
      key+= char_length;
      continue;
    }
    else if (keyseg->flag & HA_BLOB_PART)
@@ -122,16 +114,10 @@ uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key,
      uint tmp_length=_mi_calc_blob_length(keyseg->bit_start,pos);
      memcpy_fixed((byte*) &pos,pos+keyseg->bit_start,sizeof(char*));
      set_if_smaller(length,tmp_length);
#if NOT_YET_BLOB_PART
      if (char_length && length > char_length)
      {
        char_length= my_charpos(cs, pos, pos+length, char_length);
        set_if_smaller(length, char_length);
      }
#endif
      store_key_length_inc(key,length);
      memcpy((byte*) key, pos, length);
      key+= length;
      FIX_LENGTH;
      store_key_length_inc(key,char_length);
      memcpy((byte*) key,(byte*) pos,(size_t) char_length);
      key+= char_length;
      continue;
    }
    else if (keyseg->flag & HA_SWAP_KEY)
@@ -168,14 +154,10 @@ uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key,
      }
      continue;
    }
#ifdef NOT_YET_FIXED_LENGTH_KEY
    if (char_length && length > char_length)
    {
      char_length= my_charpos(cs, pos, pos+length, char_length);
      set_if_smaller(length, char_length);
    }
#endif
    memcpy((byte*) key, pos, length);
    FIX_LENGTH;
    memcpy((byte*) key, pos, char_length);
    if (length > char_length)
      bfill(key+char_length, length-char_length, ' ');
    key+= length;
  }
  _mi_dpointer(info,key,filepos);
@@ -209,19 +191,21 @@ uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key,
uint _mi_pack_key(register MI_INFO *info, uint keynr, uchar *key, uchar *old,
		  uint k_length, HA_KEYSEG **last_used_keyseg)
{
  uint length;
  uchar *pos,*end,*start_key=key;
  reg1 HA_KEYSEG *keyseg;
  enum ha_base_keytype type;
  uchar *start_key=key;
  HA_KEYSEG *keyseg;
  my_bool is_unique=info->s->keyinfo[keynr].flag & HA_NOSAME;
  DBUG_ENTER("_mi_pack_key");

  start_key=key;
  for (keyseg=info->s->keyinfo[keynr].seg ;
       keyseg->type && (int) k_length > 0;
       old+=keyseg->length, keyseg++)
  {
    length=min((uint) keyseg->length,(uint) k_length);
    type=(enum ha_base_keytype) keyseg->type;
    enum ha_base_keytype type=(enum ha_base_keytype) keyseg->type;
    uint length=min((uint) keyseg->length,(uint) k_length);
    uint char_length;
    uchar *pos;
    CHARSET_INFO *cs=keyseg->charset;

    if (keyseg->null_bit)
    {
      k_length--;
@@ -231,10 +215,11 @@ uint _mi_pack_key(register MI_INFO *info, uint keynr, uchar *key, uchar *old,
	continue;					/* Found NULL */
      }
    }
    char_length= (is_unique && cs && cs->mbmaxlen > 1) ? length/cs->mbmaxlen : length;
    pos=old;
    if (keyseg->flag & HA_SPACE_PACK)
    {
      end=pos+length;
      uchar *end=pos+length;
      if (type != HA_KEYTYPE_NUM)
      {
	while (end > pos && end[-1] == ' ')
@@ -247,9 +232,10 @@ uint _mi_pack_key(register MI_INFO *info, uint keynr, uchar *key, uchar *old,
      }
      k_length-=length;
      length=(uint) (end-pos);
      store_key_length_inc(key,length);
      memcpy((byte*) key,pos,(size_t) length);
      key+= length;
      FIX_LENGTH;
      store_key_length_inc(key,char_length);
      memcpy((byte*) key,pos,(size_t) char_length);
      key+= char_length;
      continue;
    }
    else if (keyseg->flag & (HA_VAR_LENGTH | HA_BLOB_PART))
@@ -257,11 +243,13 @@ uint _mi_pack_key(register MI_INFO *info, uint keynr, uchar *key, uchar *old,
      /* Length of key-part used with mi_rkey() always 2 */
      uint tmp_length=uint2korr(pos);
      k_length-= 2+length;
      pos+=2;
      set_if_smaller(length,tmp_length);	/* Safety */
      store_key_length_inc(key,length);
      FIX_LENGTH;
      store_key_length_inc(key,char_length);
      old+=2;					/* Skip length */
      memcpy((byte*) key, pos+2,(size_t) length);
      key+= length;
      memcpy((byte*) key, pos,(size_t) char_length);
      key+= char_length;
      continue;
    }
    else if (keyseg->flag & HA_SWAP_KEY)
@@ -274,7 +262,10 @@ uint _mi_pack_key(register MI_INFO *info, uint keynr, uchar *key, uchar *old,
      }
      continue;
    }
    memcpy((byte*) key,pos,(size_t) length);
    FIX_LENGTH;
    memcpy((byte*) key, pos, char_length);
    if (length > char_length)
      bfill(key+char_length, length-char_length, ' ');
    key+= length;
    k_length-=length;
  }
+4 −0
Original line number Diff line number Diff line
@@ -62,6 +62,10 @@ concat("-",a,"-",b,"-")
select concat("-",a,"-",b,"-") from t1 ignore index (b) where b="hello ";
concat("-",a,"-",b,"-")
alter table t1 modify b tinytext not null, drop key b, add key (b(100));
select concat("-",a,"-",b,"-") from t1;
concat("-",a,"-",b,"-")
-hello-hello-
-hello2-hello2-
select concat("-",a,"-",b,"-") from t1 where b="hello ";
concat("-",a,"-",b,"-")
-hello-hello-
+35 −3
Original line number Diff line number Diff line
@@ -76,13 +76,12 @@ CCident varchar(50) DEFAULT '' NOT NULL,
PRIMARY KEY (name,author,category)
);
INSERT INTO t1 VALUES
('patnom','patauteur',0,'p.favre@cryo-networks.fr',NULL,NULL,'#p2sndnq6ae5g1u6t','essai\nsalut','scol://195.242.78.119:patauteur.patnom',NULL,NULL,NULL,950036174,-882087474,NULL,3,0,3,'1','Pub/patnom/futur_divers.scs',NULL,'pat','CC1');
('patnom','patauteur',0,'p.favre@cryo-networks.fr',NULL,NULL,'#p2sndnq6ae5g1u6t','essai salut','scol://195.242.78.119:patauteur.patnom',NULL,NULL,NULL,950036174,-882087474,NULL,3,0,3,'1','Pub/patnom/futur_divers.scs',NULL,'pat','CC1');
INSERT INTO t1 VALUES
('LeNomDeMonSite','Marc',0,'m.barilley@cryo-networks.fr',NULL,NULL,NULL,NULL,'scol://195.242.78.119:Marc.LeNomDeMonSite',NULL,NULL,NULL,950560434,-881563214,NULL,3,0,3,'1','Pub/LeNomDeMonSite/domus_hibere.scs',NULL,'Marq','CC1');
select * from t1 where name='patnom' and author='patauteur' and category=0;
name	author	category	email	password	proxy	bitmap	msg	urlscol	urlhttp	timeout	nbcnx	creation	livinguntil	lang	type	subcat	subtype	reg	scs	capacity	userISP	CCident
patnom	patauteur	0	p.favre@cryo-networks.fr	NULL	NULL	#p2sndnq6ae5g1u6t	essai
salut	scol://195.242.78.119:patauteur.patnom	NULL	NULL	NULL	950036174	-882087474	NULL	3	0	3	1	Pub/patnom/futur_divers.scs	NULL	pat	CC1
patnom	patauteur	0	p.favre@cryo-networks.fr	NULL	NULL	#p2sndnq6ae5g1u6t	essai salut	scol://195.242.78.119:patauteur.patnom	NULL	NULL	NULL	950036174	-882087474	NULL	3	0	3	1	Pub/patnom/futur_divers.scs	NULL	pat	CC1
drop table t1;
create table t1
(
@@ -235,3 +234,36 @@ SELECT numeropost FROM t1 WHERE numreponse='1';
numeropost
1
drop table t1;
create table t1 (c varchar(30) character set utf8, t text character set utf8, unique (c(2)), unique (t(3))) engine=myisam;
show create table t1;
Table	Create Table
t1	CREATE TABLE `t1` (
  `c` varchar(30) character set utf8 default NULL,
  `t` text character set utf8,
  UNIQUE KEY `c` (`c`(2)),
  UNIQUE KEY `t` (`t`(3))
) ENGINE=MyISAM DEFAULT CHARSET=latin1
insert t1 values ('cccc', 'tttt'),
(0xD0B1212223D0B1D0B1D0B1D0B1D0B1, 0xD0B1D0B1212223D0B1D0B1D0B1D0B1),
(0xD0B1222123D0B1D0B1D0B1D0B1D0B1, 0xD0B1D0B1222123D0B1D0B1D0B1D0B1);
insert t1 (c) values ('cc22');
ERROR 23000: Duplicate entry 'cc22' for key 1
insert t1 (t) values ('ttt22');
ERROR 23000: Duplicate entry 'ttt22' for key 2
insert t1 (c) values (0xD0B1212322D0B1D0B1D0B1D0B1D0B1);
ERROR 23000: Duplicate entry 'б!#"' for key 1
insert t1 (t) values (0xD0B1D0B1212322D0B1D0B1D0B1D0B1);
ERROR 23000: Duplicate entry 'бб!#"б' for key 2
select c from t1 where c='cccc';
c
cccc
select t from t1 where t='tttt';
t
tttt
select c from t1 where c=0xD0B1212223D0B1D0B1D0B1D0B1D0B1;
c
?!"#?????
select t from t1 where t=0xD0B1D0B1212223D0B1D0B1D0B1D0B1;
t
??!"#????
drop table t1;
+1 −0
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@ select concat("-",a,"-",b,"-") from t1 where b="hello ";
select concat("-",a,"-",b,"-") from t1 ignore index (b) where b="hello ";
# blob test
alter table t1 modify b tinytext not null, drop key b, add key (b(100));
select concat("-",a,"-",b,"-") from t1;
select concat("-",a,"-",b,"-") from t1 where b="hello ";
select concat("-",a,"-",b,"-") from t1 ignore index (b) where b="hello ";
drop table t1;
Loading