summaryrefslogtreecommitdiff
path: root/myisam/mi_key.c
diff options
context:
space:
mode:
authorunknown <serg@serg.mylan>2004-08-13 18:29:25 +0200
committerunknown <serg@serg.mylan>2004-08-13 18:29:25 +0200
commitb6f6d5b2fd920c5f8c8e611c9b58b43077b21f8d (patch)
tree9f1d56d26b0dc04c637b834bdb89d3d7be9af018 /myisam/mi_key.c
parent4a0f586bc735abb1b9d0129210ab349cfb629d40 (diff)
downloadmariadb-git-b6f6d5b2fd920c5f8c8e611c9b58b43077b21f8d.tar.gz
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
Diffstat (limited to 'myisam/mi_key.c')
-rw-r--r--myisam/mi_key.c113
1 files changed, 52 insertions, 61 deletions
diff --git a/myisam/mi_key.c b/myisam/mi_key.c
index a9b5a8b279f..a872787fecd 100644
--- a/myisam/mi_key.c
+++ b/myisam/mi_key.c
@@ -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,20 +36,18 @@ 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)
{
- /*
+ /*
TODO: nulls processing
*/
#ifdef HAVE_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,15 +75,8 @@ 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)
@@ -144,7 +130,7 @@ uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key,
if (isnan(nr))
{
/* Replace NAN with zero */
- bzero(key,length);
+ bzero(key,length);
key+=length;
continue;
}
@@ -155,7 +141,7 @@ uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key,
float8get(nr,pos);
if (isnan(nr))
{
- bzero(key,length);
+ bzero(key,length);
key+=length;
continue;
}
@@ -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);
@@ -203,25 +185,27 @@ uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key,
RETURN
length of packed key
- last_use_keyseg Store pointer to the keyseg after the last used one
+ last_use_keyseg Store pointer to the keyseg after the last used one
*/
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;
}