summaryrefslogtreecommitdiff
path: root/heap/hp_write.c
diff options
context:
space:
mode:
Diffstat (limited to 'heap/hp_write.c')
-rw-r--r--heap/hp_write.c89
1 files changed, 64 insertions, 25 deletions
diff --git a/heap/hp_write.c b/heap/hp_write.c
index 806f40e5be5..9edd897eb34 100644
--- a/heap/hp_write.c
+++ b/heap/hp_write.c
@@ -27,12 +27,12 @@
#define HIGHUSED 8
static byte *next_free_record_pos(HP_SHARE *info);
-static HASH_INFO *_hp_find_free_hash(HP_SHARE *info, HP_BLOCK *block,
+static HASH_INFO *hp_find_free_hash(HP_SHARE *info, HP_BLOCK *block,
ulong records);
int heap_write(HP_INFO *info, const byte *record)
{
- uint key;
+ HP_KEYDEF *keydef, *end;
byte *pos;
HP_SHARE *share=info->s;
DBUG_ENTER("heap_write");
@@ -47,9 +47,10 @@ int heap_write(HP_INFO *info, const byte *record)
DBUG_RETURN(my_errno);
share->changed=1;
- for (key=0 ; key < share->keys ; key++)
+ for (keydef = share->keydef, end = keydef + share->keys; keydef < end;
+ keydef++)
{
- if (_hp_write_key(share,share->keydef+key,record,pos))
+ if ((*keydef->write_key)(info, keydef, record, pos))
goto err;
}
@@ -60,15 +61,23 @@ int heap_write(HP_INFO *info, const byte *record)
info->current_ptr=pos;
info->current_hash_ptr=0;
info->update|=HA_STATE_AKTIV;
+ if (share->auto_key)
+ heap_update_auto_increment(info, record);
DBUG_RETURN(0);
err:
- DBUG_PRINT("info",("Duplicate key: %d",key));
- info->errkey= key;
- do
+ DBUG_PRINT("info",("Duplicate key: %d", keydef - share->keydef));
+ info->errkey= keydef - share->keydef;
+ if (keydef->algorithm == HA_KEY_ALG_BTREE)
{
- if (_hp_delete_key(info,share->keydef+key,record,pos,0))
+ /* we don't need to delete non-inserted key from rb-tree */
+ keydef--;
+ }
+ while (keydef >= share->keydef)
+ {
+ if ((*keydef->delete_key)(info, keydef, record, pos, 0))
break;
- } while (key-- > 0);
+ keydef--;
+ }
share->deleted++;
*((byte**) pos)=share->del_link;
@@ -77,6 +86,36 @@ err:
DBUG_RETURN(my_errno);
} /* heap_write */
+/*
+ Write a key to rb_tree-index
+*/
+
+int hp_rb_write_key(HP_INFO *info, HP_KEYDEF *keyinfo, const byte *record,
+ byte *recpos)
+{
+ heap_rb_param custom_arg;
+
+ info->last_pos= NULL; /* For heap_rnext/heap_rprev */
+ custom_arg.keyseg= keyinfo->seg;
+ 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;
+ keyinfo->rb_tree.flag= TREE_NO_DUPS;
+ }
+ else
+ {
+ custom_arg.search_flag= SEARCH_SAME;
+ keyinfo->rb_tree.flag= 0;
+ }
+ if (!tree_insert(&keyinfo->rb_tree, (void*)info->recbuf,
+ custom_arg.key_length, &custom_arg))
+ {
+ my_errno= HA_ERR_FOUND_DUPP_KEY;
+ return 1;
+ }
+ return 0;
+}
/* Find where to place new record */
@@ -102,7 +141,7 @@ static byte *next_free_record_pos(HP_SHARE *info)
my_errno=HA_ERR_RECORD_FILE_FULL;
DBUG_RETURN(NULL);
}
- if (_hp_get_new_block(&info->block,&length))
+ if (hp_get_new_block(&info->block,&length))
DBUG_RETURN(NULL);
info->data_length+=length;
}
@@ -113,12 +152,12 @@ static byte *next_free_record_pos(HP_SHARE *info)
block_pos*info->block.recbuffer);
}
-
/* Write a hash-key to the hash-index */
-int _hp_write_key(register HP_SHARE *info, HP_KEYDEF *keyinfo,
+int hp_write_key(HP_INFO *info, HP_KEYDEF *keyinfo,
const byte *record, byte *recpos)
{
+ HP_SHARE *share = info->s;
int flag;
ulong halfbuff,hashnr,first_index;
byte *ptr_to_rec,*ptr_to_rec2;
@@ -129,18 +168,18 @@ int _hp_write_key(register HP_SHARE *info, HP_KEYDEF *keyinfo,
LINT_INIT(ptr_to_rec); LINT_INIT(ptr_to_rec2);
flag=0;
- if (!(empty= _hp_find_free_hash(info,&keyinfo->block,info->records)))
+ if (!(empty= hp_find_free_hash(share,&keyinfo->block,share->records)))
DBUG_RETURN(-1); /* No more memory */
- halfbuff= (long) info->blength >> 1;
- pos= hp_find_hash(&keyinfo->block,(first_index=info->records-halfbuff));
+ halfbuff= (long) share->blength >> 1;
+ pos= hp_find_hash(&keyinfo->block,(first_index=share->records-halfbuff));
if (pos != empty) /* If some records */
{
do
{
- hashnr=_hp_rec_hashnr(keyinfo,pos->ptr_to_rec);
+ hashnr = hp_rec_hashnr(keyinfo, pos->ptr_to_rec);
if (flag == 0) /* First loop; Check if ok */
- if (_hp_mask(hashnr,info->blength,info->records) != first_index)
+ if (hp_mask(hashnr, share->blength, share->records) != first_index)
break;
if (!(hashnr & halfbuff))
{ /* Key will not move */
@@ -212,8 +251,8 @@ int _hp_write_key(register HP_SHARE *info, HP_KEYDEF *keyinfo,
}
/* Check if we are at the empty position */
- pos=hp_find_hash(&keyinfo->block,_hp_mask(_hp_rec_hashnr(keyinfo,record),
- info->blength,info->records+1));
+ pos=hp_find_hash(&keyinfo->block, hp_mask(hp_rec_hashnr(keyinfo, record),
+ share->blength, share->records + 1));
if (pos == empty)
{
pos->ptr_to_rec=recpos;
@@ -224,8 +263,8 @@ int _hp_write_key(register HP_SHARE *info, HP_KEYDEF *keyinfo,
/* Check if more records in same hash-nr family */
empty[0]=pos[0];
gpos=hp_find_hash(&keyinfo->block,
- _hp_mask(_hp_rec_hashnr(keyinfo,pos->ptr_to_rec),
- info->blength,info->records+1));
+ hp_mask(hp_rec_hashnr(keyinfo, pos->ptr_to_rec),
+ share->blength, share->records + 1));
if (pos == gpos)
{
pos->ptr_to_rec=recpos;
@@ -235,7 +274,7 @@ int _hp_write_key(register HP_SHARE *info, HP_KEYDEF *keyinfo,
{
pos->ptr_to_rec=recpos;
pos->next_key=0;
- _hp_movelink(pos,gpos,empty);
+ hp_movelink(pos, gpos, empty);
}
/* Check if duplicated keys */
@@ -246,7 +285,7 @@ int _hp_write_key(register HP_SHARE *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))
{
DBUG_RETURN(my_errno=HA_ERR_FOUND_DUPP_KEY);
}
@@ -258,7 +297,7 @@ int _hp_write_key(register HP_SHARE *info, HP_KEYDEF *keyinfo,
/* Returns ptr to block, and allocates block if neaded */
-static HASH_INFO *_hp_find_free_hash(HP_SHARE *info,
+static HASH_INFO *hp_find_free_hash(HP_SHARE *info,
HP_BLOCK *block, ulong records)
{
uint block_pos;
@@ -268,7 +307,7 @@ static HASH_INFO *_hp_find_free_hash(HP_SHARE *info,
return hp_find_hash(block,records);
if (!(block_pos=(records % block->records_in_block)))
{
- if (_hp_get_new_block(block,&length))
+ if (hp_get_new_block(block,&length))
return(NULL);
info->index_length+=length;
}