summaryrefslogtreecommitdiff
path: root/heap
diff options
context:
space:
mode:
authormonty@mysql.com <>2004-12-06 02:00:37 +0200
committermonty@mysql.com <>2004-12-06 02:00:37 +0200
commit67ce24796584e80cf843b37b09aeb794c9231190 (patch)
treeb75e098b12b8e91a3470008602bacbb5b3009e45 /heap
parent46089cfd144be3430f69e2a8b48b0aeee154d6fa (diff)
downloadmariadb-git-67ce24796584e80cf843b37b09aeb794c9231190.tar.gz
Add support for up to VARCHAR (size up to 65535)
Renamed HA_VAR_LENGTH to HA_VAR_LENGTH_PART Renamed in all files FIELD_TYPE_STRING and FIELD_TYPE_VAR_STRING to MYSQL_TYPE_STRING and MYSQL_TYPE_VAR_STRING to make it easy to catch all possible errors Added support for VARCHAR KEYS to heap Removed support for ISAM Now only long VARCHAR columns are changed to TEXT on demand (not CHAR) Internal temporary files can now use fixed length tables if the used VARCHAR columns are short
Diffstat (limited to 'heap')
-rw-r--r--heap/heapdef.h4
-rw-r--r--heap/hp_create.c16
-rw-r--r--heap/hp_delete.c2
-rw-r--r--heap/hp_hash.c185
-rw-r--r--heap/hp_rkey.c2
-rw-r--r--heap/hp_update.c4
-rw-r--r--heap/hp_write.c4
7 files changed, 199 insertions, 18 deletions
diff --git a/heap/heapdef.h b/heap/heapdef.h
index 083765334ab..68d9405138f 100644
--- a/heap/heapdef.h
+++ b/heap/heapdef.h
@@ -86,7 +86,8 @@ extern ulong hp_mask(ulong hashnr,ulong buffmax,ulong maxlength);
extern void hp_movelink(HASH_INFO *pos,HASH_INFO *next_link,
HASH_INFO *newlink);
extern int hp_rec_key_cmp(HP_KEYDEF *keydef,const byte *rec1,
- const byte *rec2);
+ const byte *rec2,
+ my_bool diff_if_only_endspace_difference);
extern int hp_key_cmp(HP_KEYDEF *keydef,const byte *rec,
const byte *key);
extern void hp_make_key(HP_KEYDEF *keydef,byte *key,const byte *rec);
@@ -94,6 +95,7 @@ extern uint hp_rb_make_key(HP_KEYDEF *keydef, byte *key,
const byte *rec, byte *recpos);
extern uint hp_rb_key_length(HP_KEYDEF *keydef, const byte *key);
extern uint hp_rb_null_key_length(HP_KEYDEF *keydef, const byte *key);
+extern uint hp_rb_var_key_length(HP_KEYDEF *keydef, const byte *key);
extern my_bool hp_if_null_in_key(HP_KEYDEF *keyinfo, const byte *record);
extern int hp_close(register HP_INFO *info);
extern void hp_clear(HP_SHARE *info);
diff --git a/heap/hp_create.c b/heap/hp_create.c
index 02725576c8f..dd16e3ee344 100644
--- a/heap/hp_create.c
+++ b/heap/hp_create.c
@@ -69,9 +69,21 @@ int heap_create(const char *name, uint keys, HP_KEYDEF *keydef,
case HA_KEYTYPE_UINT24:
case HA_KEYTYPE_INT8:
keyinfo->seg[j].flag|= HA_SWAP_KEY;
+ break;
+ case HA_KEYTYPE_VARBINARY:
+ /* Case-insensitiveness is handled in coll->hash_sort */
+ keyinfo->seg[j].type= HA_KEYTYPE_VARTEXT;
+ /* fall_through */
+ case HA_KEYTYPE_VARTEXT:
+ if (!my_binary_compare(keyinfo->seg[j].charset))
+ keyinfo->flag|= HA_END_SPACE_KEY;
+ keyinfo->flag|= HA_VAR_LENGTH_KEY;
+ break;
default:
break;
}
+ if (keyinfo->seg[j].flag & HA_END_SPACE_ARE_EQUAL)
+ keyinfo->flag|= HA_END_SPACE_KEY;
}
keyinfo->length= length;
length+= keyinfo->rb_tree.size_of_element +
@@ -82,7 +94,9 @@ int heap_create(const char *name, uint keys, HP_KEYDEF *keydef,
if (keyinfo->algorithm == HA_KEY_ALG_BTREE)
{
key_segs++; /* additional HA_KEYTYPE_END segment */
- if (keyinfo->flag & HA_NULL_PART_KEY)
+ if (keyinfo->flag & HA_VAR_LENGTH_KEY)
+ keyinfo->get_key_length= hp_rb_var_key_length;
+ else if (keyinfo->flag & HA_NULL_PART_KEY)
keyinfo->get_key_length= hp_rb_null_key_length;
else
keyinfo->get_key_length= hp_rb_key_length;
diff --git a/heap/hp_delete.c b/heap/hp_delete.c
index c918cf37f05..4c73db065e8 100644
--- a/heap/hp_delete.c
+++ b/heap/hp_delete.c
@@ -123,7 +123,7 @@ int hp_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo,
while (pos->ptr_to_rec != recpos)
{
- if (flag && !hp_rec_key_cmp(keyinfo, record, pos->ptr_to_rec))
+ if (flag && !hp_rec_key_cmp(keyinfo, record, pos->ptr_to_rec, 0))
last_ptr=pos; /* Previous same key */
gpos=pos;
if (!(pos=pos->next_key))
diff --git a/heap/hp_hash.c b/heap/hp_hash.c
index b54e76d79fe..d03c34b2fd7 100644
--- a/heap/hp_hash.c
+++ b/heap/hp_hash.c
@@ -246,14 +246,27 @@ ulong hp_hashnr(register HP_KEYDEF *keydef, register const byte *key)
if (seg->type == HA_KEYTYPE_TEXT)
{
CHARSET_INFO *cs= seg->charset;
- uint char_length= (uint) ((uchar*) key - pos);
+ uint length= seg->length;
if (cs->mbmaxlen > 1)
{
- uint length= char_length;
+ uint char_length;
char_length= my_charpos(cs, pos, pos + length, length/cs->mbmaxlen);
- set_if_smaller(char_length, length); /* QQ: ok to remove? */
+ set_if_smaller(length, char_length);
}
- cs->coll->hash_sort(cs, pos, char_length, &nr, &nr2);
+ cs->coll->hash_sort(cs, pos, length, &nr, &nr2);
+ }
+ else if (seg->type == HA_KEYTYPE_VARTEXT)
+ {
+ CHARSET_INFO *cs= seg->charset;
+ uint length= uint2korr(pos);
+ if (cs->mbmaxlen > 1)
+ {
+ uint char_length;
+ char_length= my_charpos(cs, pos +2, pos +2 + length,
+ seg->length/cs->mbmaxlen);
+ set_if_smaller(length, char_length);
+ }
+ cs->coll->hash_sort(cs, pos+2, length, &nr, &nr2);
}
else
{
@@ -298,6 +311,19 @@ ulong hp_rec_hashnr(register HP_KEYDEF *keydef, register const byte *rec)
}
cs->coll->hash_sort(cs, pos, char_length, &nr, &nr2);
}
+ else if (seg->type == HA_KEYTYPE_VARTEXT)
+ {
+ CHARSET_INFO *cs= seg->charset;
+ uint length= uint2korr(pos);
+ if (cs->mbmaxlen > 1)
+ {
+ uint char_length;
+ char_length= my_charpos(cs, pos + 2 , pos + 2 + length,
+ seg->length/cs->mbmaxlen);
+ set_if_smaller(length, char_length);
+ }
+ cs->coll->hash_sort(cs, pos+2, length, &nr, &nr2);
+ }
else
{
for (; pos < end ; pos++)
@@ -350,6 +376,11 @@ ulong hp_hashnr(register HP_KEYDEF *keydef, register const byte *key)
{
seg->charset->hash_sort(seg->charset,pos,((uchar*)key)-pos,&nr,NULL);
}
+ else if (seg->type == HA_KEYTYPE_VARTEXT)
+ {
+ uint length= uint2korr(pos);
+ seg->charset->hash_sort(seg->charset, pos+2, length, &nr, NULL);
+ }
else
{
for ( ; pos < (uchar*) key ; pos++)
@@ -384,6 +415,11 @@ ulong hp_rec_hashnr(register HP_KEYDEF *keydef, register const byte *rec)
{
seg->charset->hash_sort(seg->charset,pos,((uchar*)key)-pos,&nr,NULL);
}
+ else if (seg->type == HA_KEYTYPE_VARTEXT)
+ {
+ uint length= uint2korr(pos);
+ seg->charset->hash_sort(seg->charset, pos+2, length, &nr, NULL);
+ }
else
{
for ( ; pos < end ; pos++)
@@ -399,9 +435,28 @@ ulong hp_rec_hashnr(register HP_KEYDEF *keydef, register const byte *rec)
#endif
- /* Compare keys for two records. Returns 0 if they are identical */
+/*
+ Compare keys for two records. Returns 0 if they are identical
-int hp_rec_key_cmp(HP_KEYDEF *keydef, const byte *rec1, const byte *rec2)
+ SYNOPSIS
+ hp_rec_key_cmp()
+ keydef Key definition
+ rec1 Record to compare
+ rec2 Other record to compare
+ diff_if_only_endspace_difference
+ Different number of end space is significant
+
+ NOTES
+ diff_if_only_endspace_difference is used to allow us to insert
+ 'a' and 'a ' when there is an an unique key.
+
+ RETURN
+ 0 Key is identical
+ <> 0 Key differes
+*/
+
+int hp_rec_key_cmp(HP_KEYDEF *keydef, const byte *rec1, const byte *rec2,
+ my_bool diff_if_only_endspace_difference)
{
HA_KEYSEG *seg,*endseg;
@@ -426,9 +481,9 @@ int hp_rec_key_cmp(HP_KEYDEF *keydef, const byte *rec1, const byte *rec2)
{
uint char_length= seg->length / cs->mbmaxlen;
char_length1= my_charpos(cs, pos1, pos1 + seg->length, char_length);
- set_if_smaller(char_length1, seg->length); /* QQ: ok to remove? */
+ set_if_smaller(char_length1, seg->length);
char_length2= my_charpos(cs, pos2, pos2 + seg->length, char_length);
- set_if_smaller(char_length2, seg->length); /* QQ: ok to remove? */
+ set_if_smaller(char_length2, seg->length);
}
else
{
@@ -436,7 +491,30 @@ int hp_rec_key_cmp(HP_KEYDEF *keydef, const byte *rec1, const byte *rec2)
}
if (seg->charset->coll->strnncollsp(seg->charset,
pos1,char_length1,
- pos2,char_length2))
+ pos2,char_length2, 0))
+ return 1;
+ }
+ else if (seg->type == HA_KEYTYPE_VARTEXT)
+ {
+ uchar *pos1= (uchar*)rec1 + seg->start;
+ uchar *pos2= (uchar*)rec2 + seg->start;
+ uint char_length1= uint2korr(pos1);
+ uint char_length2= uint2korr(pos2);
+ CHARSET_INFO *cs= seg->charset;
+ if (cs->mbmaxlen > 1)
+ {
+ uint char_length= seg->length / cs->mbmaxlen;
+ char_length1= my_charpos(cs, pos1, pos1 + char_length1, char_length);
+ set_if_smaller(char_length1, seg->length);
+ char_length2= my_charpos(cs, pos2, pos2 + char_length2, char_length);
+ set_if_smaller(char_length2, seg->length);
+ }
+
+ if (cs->coll->strnncollsp(seg->charset,
+ pos1+2, char_length1,
+ pos2+2, char_length2,
+ seg->flag & HA_END_SPACE_ARE_EQUAL ?
+ 0 : diff_if_only_endspace_difference))
return 1;
}
else
@@ -488,7 +566,31 @@ int hp_key_cmp(HP_KEYDEF *keydef, const byte *rec, const byte *key)
if (seg->charset->coll->strnncollsp(seg->charset,
(uchar*) pos, char_length_rec,
- (uchar*) key, char_length_key))
+ (uchar*) key, char_length_key, 0))
+ return 1;
+ }
+ else if (seg->type == HA_KEYTYPE_VARTEXT)
+ {
+ uchar *pos= (uchar*) rec + seg->start;
+ CHARSET_INFO *cs= seg->charset;
+ uint char_length_rec= uint2korr(pos);
+ uint char_length_key= uint2korr(key);
+
+ if (cs->mbmaxlen > 1)
+ {
+ uint char_length= seg->length / cs->mbmaxlen;
+ char_length_key= my_charpos(cs, key+2, key +2 + char_length_key,
+ char_length);
+ set_if_smaller(char_length_key, seg->length);
+ char_length_rec= my_charpos(cs, pos +2 , pos + 2 + char_length_rec,
+ char_length);
+ set_if_smaller(char_length_rec, seg->length);
+ }
+
+
+ if (cs->coll->strnncollsp(seg->charset,
+ (uchar*) pos+2, char_length_rec,
+ (uchar*) key+2, char_length_key, 0))
return 1;
}
else
@@ -525,6 +627,13 @@ void hp_make_key(HP_KEYDEF *keydef, byte *key, const byte *rec)
}
}
+#define FIX_LENGTH(cs, pos, length, char_length) \
+ do { \
+ if (length > char_length) \
+ char_length= my_charpos(cs, pos, pos+length, char_length); \
+ set_if_smaller(char_length,length); \
+ } while(0)
+
uint hp_rb_make_key(HP_KEYDEF *keydef, byte *key,
const byte *rec, byte *recpos)
@@ -577,6 +686,24 @@ uint hp_rb_make_key(HP_KEYDEF *keydef, byte *key,
}
continue;
}
+
+ if (seg->flag & HA_VAR_LENGTH_PART)
+ {
+ uchar *pos= (uchar*) rec + seg->start;
+ uint length= seg->length;
+ uint tmp_length= uint2korr(pos);
+ CHARSET_INFO *cs= seg->charset;
+ char_length= length/cs->mbmaxlen;
+
+ pos+=2; /* Skip VARCHAR length */
+ set_if_smaller(length,tmp_length);
+ FIX_LENGTH(cs, pos, length, char_length);
+ store_key_length_inc(key,char_length);
+ memcpy((byte*) key,(byte*) pos,(size_t) char_length);
+ key+= char_length;
+ continue;
+ }
+
char_length= seg->length;
if (seg->charset->mbmaxlen > 1)
{
@@ -627,6 +754,23 @@ uint hp_rb_pack_key(HP_KEYDEF *keydef, uchar *key, const uchar *old,
}
continue;
}
+ if (seg->flag & (HA_VAR_LENGTH_PART | HA_BLOB_PART))
+ {
+ /* Length of key-part used with heap_rkey() always 2 */
+ uint tmp_length=uint2korr(old);
+ uint length= seg->length;
+ CHARSET_INFO *cs= seg->charset;
+ char_length= length/cs->mbmaxlen;
+
+ k_len-= 2+length;
+ old+= 2;
+ set_if_smaller(length,tmp_length); /* Safety */
+ FIX_LENGTH(cs, old, length, char_length);
+ store_key_length_inc(key,char_length);
+ memcpy((byte*) key, old,(size_t) char_length);
+ key+= char_length;
+ continue;
+ }
char_length= seg->length;
if (seg->charset->mbmaxlen > 1)
{
@@ -666,6 +810,27 @@ uint hp_rb_null_key_length(HP_KEYDEF *keydef, const byte *key)
return key - start_key;
}
+
+uint hp_rb_var_key_length(HP_KEYDEF *keydef, const byte *key)
+{
+ const byte *start_key= key;
+ HA_KEYSEG *seg, *endseg;
+
+ for (seg= keydef->seg, endseg= seg + keydef->keysegs; seg < endseg; seg++)
+ {
+ uint length= seg->length;
+ if (seg->null_bit && !*key++)
+ continue;
+ if (seg->flag & (HA_VAR_LENGTH_PART | HA_BLOB_PART))
+ {
+ get_key_length(length, key);
+ }
+ key+= length;
+ }
+ return key - start_key;
+}
+
+
/*
Test if any of the key parts are NULL.
Return:
diff --git a/heap/hp_rkey.c b/heap/hp_rkey.c
index 2c23d9d721e..a88139bbdee 100644
--- a/heap/hp_rkey.c
+++ b/heap/hp_rkey.c
@@ -64,7 +64,7 @@ int heap_rkey(HP_INFO *info, byte *record, int inx, const byte *key,
info->update= 0;
DBUG_RETURN(my_errno);
}
- if (!(keyinfo->flag & HA_NOSAME))
+ if (!(keyinfo->flag & HA_NOSAME) || (keyinfo->flag & HA_END_SPACE_KEY))
memcpy(info->lastkey, key, (size_t) keyinfo->length);
}
memcpy(record, pos, (size_t) share->reclength);
diff --git a/heap/hp_update.c b/heap/hp_update.c
index 2ed0edf08de..2f4ea75f9aa 100644
--- a/heap/hp_update.c
+++ b/heap/hp_update.c
@@ -37,7 +37,7 @@ int heap_update(HP_INFO *info, const byte *old, const byte *heap_new)
p_lastinx= share->keydef + info->lastinx;
for (keydef= share->keydef, end= keydef + share->keys; keydef < end; keydef++)
{
- if (hp_rec_key_cmp(keydef, old, heap_new))
+ if (hp_rec_key_cmp(keydef, old, heap_new, 0))
{
if ((*keydef->delete_key)(info, keydef, old, pos, keydef == p_lastinx) ||
(*keydef->write_key)(info, keydef, heap_new, pos))
@@ -74,7 +74,7 @@ int heap_update(HP_INFO *info, const byte *old, const byte *heap_new)
}
while (keydef >= share->keydef)
{
- if (hp_rec_key_cmp(keydef, old, heap_new))
+ if (hp_rec_key_cmp(keydef, old, heap_new, 0))
{
if ((*keydef->delete_key)(info, keydef, heap_new, pos, 0) ||
(*keydef->write_key)(info, keydef, old, pos))
diff --git a/heap/hp_write.c b/heap/hp_write.c
index 3b0ec76d616..2ce06293407 100644
--- a/heap/hp_write.c
+++ b/heap/hp_write.c
@@ -106,7 +106,7 @@ int hp_rb_write_key(HP_INFO *info, HP_KEYDEF *keyinfo, const byte *record,
custom_arg.key_length= hp_rb_make_key(keyinfo, info->recbuf, record, recpos);
if (keyinfo->flag & HA_NOSAME)
{
- custom_arg.search_flag= SEARCH_FIND | SEARCH_SAME;
+ custom_arg.search_flag= SEARCH_FIND | SEARCH_SAME | SEARCH_UPDATE;
keyinfo->rb_tree.flag= TREE_NO_DUPS;
}
else
@@ -293,7 +293,7 @@ int hp_write_key(HP_INFO *info, HP_KEYDEF *keyinfo,
pos=empty;
do
{
- if (! hp_rec_key_cmp(keyinfo, record, pos->ptr_to_rec))
+ if (! hp_rec_key_cmp(keyinfo, record, pos->ptr_to_rec, 1))
{
DBUG_RETURN(my_errno=HA_ERR_FOUND_DUPP_KEY);
}