summaryrefslogtreecommitdiff
path: root/storage/maria/ma_delete.c
diff options
context:
space:
mode:
Diffstat (limited to 'storage/maria/ma_delete.c')
-rw-r--r--storage/maria/ma_delete.c428
1 files changed, 259 insertions, 169 deletions
diff --git a/storage/maria/ma_delete.c b/storage/maria/ma_delete.c
index 91106142204..c68a80a1fc9 100644
--- a/storage/maria/ma_delete.c
+++ b/storage/maria/ma_delete.c
@@ -18,11 +18,10 @@
#include "trnman.h"
#include "ma_key_recover.h"
-static int d_search(MARIA_HA *info,MARIA_KEYDEF *keyinfo,uint comp_flag,
- uchar *key, uint key_length,
+static int d_search(MARIA_HA *info, MARIA_KEY *key, uint32 comp_flag,
my_off_t page, uchar *anc_buff,
MARIA_PINNED_PAGE *anc_page_link);
-static int del(MARIA_HA *info,MARIA_KEYDEF *keyinfo, uchar *key,
+static int del(MARIA_HA *info, MARIA_KEY *key,
my_off_t anc_page, uchar *anc_buff, my_off_t leaf_page,
uchar *leaf_buff, MARIA_PINNED_PAGE *leaf_page_link,
uchar *keypos, my_off_t next_block, uchar *ret_key);
@@ -30,8 +29,8 @@ static int underflow(MARIA_HA *info,MARIA_KEYDEF *keyinfo,
my_off_t anc_page, uchar *anc_buff,
my_off_t leaf_page, uchar *leaf_buff,
MARIA_PINNED_PAGE *leaf_page_link, uchar *keypos);
-static uint remove_key(MARIA_KEYDEF *keyinfo,uint nod_flag,uchar *keypos,
- uchar *lastkey,uchar *page_end,
+static uint remove_key(MARIA_KEYDEF *keyinfo, uint page_flag, uint nod_flag,
+ uchar *keypos, uchar *lastkey, uchar *page_end,
my_off_t *next_block, MARIA_KEY_PARAM *s_temp);
/* @breif Remove a row from a MARIA table */
@@ -43,6 +42,7 @@ int maria_delete(MARIA_HA *info,const uchar *record)
int save_errno;
char lastpos[8];
MARIA_SHARE *share= info->s;
+ MARIA_KEYDEF *keyinfo;
DBUG_ENTER("maria_delete");
/* Test if record is in datafile */
@@ -72,23 +72,26 @@ int maria_delete(MARIA_HA *info,const uchar *record)
info->last_auto_increment= ~(ulonglong) 0;
/* Remove all keys from the index file */
- old_key= info->lastkey2;
- for (i=0 ; i < share->base.keys ; i++ )
+ old_key= info->lastkey_buff2;
+
+ for (i=0, keyinfo= share->keyinfo ; i < share->base.keys ; i++, keyinfo++)
{
if (maria_is_key_active(share->state.key_map, i))
{
- share->keyinfo[i].version++;
- if (share->keyinfo[i].flag & HA_FULLTEXT)
+ keyinfo->version++;
+ if (keyinfo->flag & HA_FULLTEXT)
{
if (_ma_ft_del(info, i, old_key, record, info->cur_row.lastpos))
goto err;
}
else
{
- if (share->keyinfo[i].ck_delete(info,i,old_key,
- _ma_make_key(info, i, old_key,
- record,
- info->cur_row.lastpos)))
+ MARIA_KEY key;
+ if (keyinfo->ck_delete(info,
+ (*keyinfo->make_key)(info, &key, i, old_key,
+ record,
+ info->cur_row.lastpos,
+ info->cur_row.trid)))
goto err;
}
/* The above changed info->lastkey2. Inform maria_rnext_same(). */
@@ -149,33 +152,41 @@ err:
} /* maria_delete */
-/* Remove a key from the btree index */
+/*
+ Remove a key from the btree index
+
+ TODO:
+ Change ma_ck_real_delete() to use another buffer for changed keys instead
+ of key->data. This would allows us to remove the copying of the key here.
+*/
-int _ma_ck_delete(register MARIA_HA *info, uint keynr, uchar *key,
- uint key_length)
+int _ma_ck_delete(register MARIA_HA *info, MARIA_KEY *key)
{
MARIA_SHARE *share= info->s;
int res;
LSN lsn= LSN_IMPOSSIBLE;
- my_off_t new_root= share->state.key_root[keynr];
- uchar key_buff[HA_MAX_KEY_BUFF];
+ my_off_t new_root= share->state.key_root[key->keyinfo->key_nr];
+ uchar key_buff[MARIA_MAX_KEY_BUFF], *save_key_data;
+ MARIA_KEY org_key;
DBUG_ENTER("_ma_ck_delete");
+ save_key_data= key->data;
if (share->now_transactional)
{
/* Save original value as the key may change */
- memcpy(key_buff, key, key_length + share->rec_reflength);
+ memcpy(key_buff, key->data, key->data_length + key->ref_length);
+ org_key= *key;
+ key->data= key_buff;
}
- res= _ma_ck_real_delete(info, share->keyinfo+keynr, key, key_length,
- &new_root);
+ res= _ma_ck_real_delete(info, key, &new_root);
+ key->data= save_key_data;
if (!res && share->now_transactional)
- res= _ma_write_undo_key_delete(info, keynr, key_buff, key_length,
- new_root, &lsn);
+ res= _ma_write_undo_key_delete(info, &org_key, new_root, &lsn);
else
{
- share->state.key_root[keynr]= new_root;
+ share->state.key_root[key->keyinfo->key_nr]= new_root;
_ma_fast_unlock_key_del(info);
}
_ma_unpin_all_pages_and_finalize_row(info, lsn);
@@ -183,14 +194,15 @@ int _ma_ck_delete(register MARIA_HA *info, uint keynr, uchar *key,
} /* _ma_ck_delete */
-int _ma_ck_real_delete(register MARIA_HA *info, MARIA_KEYDEF *keyinfo,
- uchar *key, uint key_length, my_off_t *root)
+int _ma_ck_real_delete(register MARIA_HA *info, MARIA_KEY *key,
+ my_off_t *root)
{
int error;
uint nod_flag;
my_off_t old_root;
uchar *root_buff;
MARIA_PINNED_PAGE *page_link;
+ MARIA_KEYDEF *keyinfo= key->keyinfo;
DBUG_ENTER("_ma_ck_real_delete");
if ((old_root=*root) == HA_OFFSET_ERROR)
@@ -199,7 +211,7 @@ int _ma_ck_real_delete(register MARIA_HA *info, MARIA_KEYDEF *keyinfo,
DBUG_RETURN(my_errno=HA_ERR_CRASHED);
}
if (!(root_buff= (uchar*) my_alloca((uint) keyinfo->block_length+
- HA_MAX_KEY_BUFF*2)))
+ MARIA_MAX_KEY_BUFF*2)))
{
DBUG_PRINT("error",("Couldn't allocate memory"));
DBUG_RETURN(my_errno=ENOMEM);
@@ -212,15 +224,15 @@ int _ma_ck_real_delete(register MARIA_HA *info, MARIA_KEYDEF *keyinfo,
error= -1;
goto err;
}
- if ((error=d_search(info,keyinfo,
- (keyinfo->flag & HA_FULLTEXT ?
- SEARCH_FIND | SEARCH_UPDATE : SEARCH_SAME),
- key, key_length, old_root, root_buff, page_link)) >0)
+ if ((error= d_search(info, key, (keyinfo->flag & HA_FULLTEXT ?
+ SEARCH_FIND | SEARCH_UPDATE | SEARCH_INSERT:
+ SEARCH_SAME),
+ old_root, root_buff, page_link)) > 0)
{
if (error == 2)
{
DBUG_PRINT("test",("Enlarging of root when deleting"));
- error= _ma_enlarge_root(info,keyinfo,key,root);
+ error= _ma_enlarge_root(info, key, root);
}
else /* error == 1 */
{
@@ -264,31 +276,31 @@ err:
@retval -1 On errors
*/
-static int d_search(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
- uint comp_flag, uchar *key, uint key_length,
+static int d_search(MARIA_HA *info, MARIA_KEY *key, uint32 comp_flag,
my_off_t anc_page, uchar *anc_buff,
MARIA_PINNED_PAGE *anc_page_link)
{
int flag,ret_value,save_flag;
- uint length,nod_flag,search_key_length;
+ uint nod_flag, page_flag;
my_bool last_key;
uchar *leaf_buff,*keypos;
my_off_t leaf_page,next_block;
- uchar lastkey[HA_MAX_KEY_BUFF];
+ uchar lastkey[MARIA_MAX_KEY_BUFF];
MARIA_PINNED_PAGE *leaf_page_link;
MARIA_KEY_PARAM s_temp;
MARIA_SHARE *share= info->s;
+ MARIA_KEYDEF *keyinfo= key->keyinfo;
DBUG_ENTER("d_search");
DBUG_DUMP("page",anc_buff,_ma_get_page_used(share, anc_buff));
- search_key_length= (comp_flag & SEARCH_FIND) ? key_length : USE_WHOLE_KEY;
- flag=(*keyinfo->bin_search)(info,keyinfo,anc_buff,key, search_key_length,
- comp_flag, &keypos, lastkey, &last_key);
+ flag=(*keyinfo->bin_search)(key, anc_buff, comp_flag, &keypos, lastkey,
+ &last_key);
if (flag == MARIA_FOUND_WRONG_KEY)
{
DBUG_PRINT("error",("Found wrong key"));
DBUG_RETURN(-1);
}
+ page_flag= _ma_get_keypage_flag(share, anc_buff);
nod_flag= _ma_test_if_nod(share, anc_buff);
if (!flag && (keyinfo->flag & HA_FULLTEXT))
@@ -311,8 +323,8 @@ static int d_search(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
else
{
/* we need exact match only if not in ft1->ft2 conversion mode */
- flag=(*keyinfo->bin_search)(info,keyinfo,anc_buff,key,USE_WHOLE_KEY,
- comp_flag, &keypos, lastkey, &last_key);
+ flag=(*keyinfo->bin_search)(key, anc_buff, comp_flag, &keypos,
+ lastkey, &last_key);
}
/* fall through to normal delete */
}
@@ -322,15 +334,19 @@ static int d_search(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
uint tmp_key_length;
my_off_t root;
uchar *kpos=keypos;
+ MARIA_KEY tmp_key;
- if (!(tmp_key_length=(*keyinfo->get_key)(keyinfo,nod_flag,&kpos,
- lastkey)))
+ tmp_key.data= lastkey;
+ tmp_key.keyinfo= keyinfo;
+
+ if (!(tmp_key_length=(*keyinfo->get_key)(&tmp_key, page_flag, nod_flag,
+ &kpos)))
{
maria_print_error(share, HA_ERR_CRASHED);
my_errno= HA_ERR_CRASHED;
DBUG_RETURN(-1);
}
- root= _ma_dpos(info,nod_flag,kpos);
+ root= _ma_row_pos_from_key(&tmp_key);
if (subkeys == -1)
{
/* the last entry in sub-tree */
@@ -340,14 +356,19 @@ static int d_search(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
}
else
{
+ MARIA_KEY word_key;
keyinfo=&share->ft2_keyinfo;
/* we'll modify key entry 'in vivo' */
kpos-=keyinfo->keylength+nod_flag;
- get_key_full_length_rdonly(off, key);
- key+=off;
- ret_value= _ma_ck_real_delete(info, &share->ft2_keyinfo,
- key, HA_FT_WLEN, &root);
- _ma_dpointer(info, kpos+HA_FT_WLEN, root);
+ get_key_full_length_rdonly(off, key->data);
+
+ word_key.data= key->data + off;
+ word_key.keyinfo= &share->ft2_keyinfo;
+ word_key.data_length= HA_FT_WLEN;
+ word_key.ref_length= 0;
+ word_key.flag= 0;
+ ret_value= _ma_ck_real_delete(info, &word_key, &root);
+ _ma_dpointer(share, kpos+HA_FT_WLEN, root);
subkeys++;
ft_intXstore(kpos, subkeys);
if (!ret_value)
@@ -369,7 +390,7 @@ static int d_search(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
/* Read left child page */
leaf_page= _ma_kpos(nod_flag,keypos);
if (!(leaf_buff= (uchar*) my_alloca((uint) keyinfo->block_length+
- HA_MAX_KEY_BUFF*2)))
+ MARIA_MAX_KEY_BUFF*2)))
{
DBUG_PRINT("error", ("Couldn't allocate memory"));
my_errno=ENOMEM;
@@ -391,14 +412,16 @@ static int d_search(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
goto err;
}
save_flag=0;
- ret_value=d_search(info, keyinfo, comp_flag, key, key_length,
- leaf_page, leaf_buff, leaf_page_link);
+ ret_value= d_search(info, key, comp_flag, leaf_page, leaf_buff,
+ leaf_page_link);
}
else
{ /* Found key */
uint tmp;
uint anc_buff_length= _ma_get_page_used(share, anc_buff);
- if (!(tmp= remove_key(keyinfo,nod_flag,keypos,lastkey,
+ uint anc_page_flag= _ma_get_keypage_flag(share, anc_buff);
+
+ if (!(tmp= remove_key(keyinfo, anc_page_flag, nod_flag, keypos, lastkey,
anc_buff + anc_buff_length,
&next_block, &s_temp)))
goto err;
@@ -433,7 +456,7 @@ static int d_search(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
DBUG_RETURN(0);
}
save_flag=1; /* Mark that anc_buff is changed */
- ret_value= del(info, keyinfo, key, anc_page, anc_buff,
+ ret_value= del(info, key, anc_page, anc_buff,
leaf_page, leaf_buff, leaf_page_link,
keypos, next_block, lastkey);
}
@@ -444,12 +467,17 @@ static int d_search(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
ret_value= underflow(info, keyinfo, anc_page, anc_buff,
leaf_page, leaf_buff, leaf_page_link, keypos);
else
- { /* This happens only with packed keys */
+ {
+ /* This can only happen with variable length keys */
+ MARIA_KEY last_key;
DBUG_PRINT("test",("Enlarging of key when deleting"));
- if (!_ma_get_last_key(info,keyinfo,anc_buff,lastkey,keypos,&length))
+
+ last_key.data= lastkey;
+ last_key.keyinfo= keyinfo;
+ if (!_ma_get_last_key(&last_key, anc_buff, keypos))
goto err;
- ret_value= _ma_insert(info, keyinfo, key, anc_buff, keypos, anc_page,
- lastkey, (my_off_t) 0, (uchar*) 0,
+ ret_value= _ma_insert(info, key, anc_buff, keypos, anc_page,
+ last_key.data, (my_off_t) 0, (uchar*) 0,
(MARIA_PINNED_PAGE*) 0, (uchar*) 0, (my_bool) 0);
}
}
@@ -458,7 +486,7 @@ static int d_search(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
{
/* parent buffer got too big ; We have to split the page */
save_flag=1;
- ret_value= _ma_split_page(info, keyinfo, key, anc_page, anc_buff,
+ ret_value= _ma_split_page(info, key, anc_page, anc_buff,
(uint) (keyinfo->block_length -
KEYPAGE_CHECKSUM_SIZE),
(uchar*) 0, 0, 0, lastkey, 0) | 2;
@@ -497,7 +525,7 @@ err:
@param leaf_buff_link Pinned page link for leaf_buff
@param keypos Pos to where deleted key was on anc_buff
@param next_block Page adress for nod after deleted key
- @param ret_key Key before keypos in anc_buff
+ @param ret_key_buff Key before keypos in anc_buff
@notes
leaf_buff must be written to disk if retval > 0
@@ -512,36 +540,43 @@ err:
@retval 2 key contains key to upper level (from split space)
*/
-static int del(register MARIA_HA *info, MARIA_KEYDEF *keyinfo,
- uchar *key, my_off_t anc_page, uchar *anc_buff,
+static int del(MARIA_HA *info, MARIA_KEY *key,
+ my_off_t anc_page, uchar *anc_buff,
my_off_t leaf_page, uchar *leaf_buff,
MARIA_PINNED_PAGE *leaf_page_link,
- uchar *keypos, my_off_t next_block, uchar *ret_key)
+ uchar *keypos, my_off_t next_block, uchar *ret_key_buff)
{
int ret_value,length;
- uint a_length, nod_flag, leaf_length, new_leaf_length, tmp;
+ uint a_length, page_flag, nod_flag, leaf_length, new_leaf_length;
my_off_t next_page;
- uchar keybuff[HA_MAX_KEY_BUFF],*endpos,*next_buff,*key_start, *prev_key;
- MARIA_SHARE *share= info->s;
+ uchar keybuff[MARIA_MAX_KEY_BUFF],*endpos,*next_buff,*key_start, *prev_key;
MARIA_KEY_PARAM s_temp;
MARIA_PINNED_PAGE *next_page_link;
+ MARIA_KEY tmp_key;
+ MARIA_SHARE *share= info->s;
+ MARIA_KEYDEF *keyinfo= key->keyinfo;
+ MARIA_KEY ret_key;
DBUG_ENTER("del");
DBUG_PRINT("enter",("leaf_page: %ld keypos: 0x%lx", (long) leaf_page,
(ulong) keypos));
- _ma_get_used_and_nod(share, leaf_buff, leaf_length, nod_flag);
+ page_flag= _ma_get_keypage_flag(share, leaf_buff);
+ _ma_get_used_and_nod_with_flag(share, page_flag, leaf_buff, leaf_length,
+ nod_flag);
DBUG_DUMP("leaf_buff", leaf_buff, leaf_length);
endpos= leaf_buff + leaf_length;
- if (!(key_start= _ma_get_last_key(info,keyinfo,leaf_buff,keybuff,endpos,
- &tmp)))
+ tmp_key.keyinfo= keyinfo;
+ tmp_key.data= keybuff;
+
+ if (!(key_start= _ma_get_last_key(&tmp_key, leaf_buff, endpos)))
DBUG_RETURN(-1);
if (nod_flag)
{
next_page= _ma_kpos(nod_flag,endpos);
if (!(next_buff= (uchar*) my_alloca((uint) keyinfo->block_length+
- HA_MAX_KEY_BUFF*2)))
+ MARIA_MAX_KEY_BUFF*2)))
DBUG_RETURN(-1);
if (!_ma_fetch_keypage(info, keyinfo, next_page, PAGECACHE_LOCK_WRITE,
DFLT_INIT_HITS, next_buff, 0, &next_page_link))
@@ -549,9 +584,9 @@ static int del(register MARIA_HA *info, MARIA_KEYDEF *keyinfo,
else
{
DBUG_DUMP("next_page", next_buff, _ma_get_page_used(share, next_buff));
- if ((ret_value= del(info, keyinfo, key, anc_page, anc_buff, next_page,
+ if ((ret_value= del(info, key, anc_page, anc_buff, next_page,
next_buff, next_page_link, keypos, next_block,
- ret_key)) >0)
+ ret_key_buff)) >0)
{
/* Get new length after key was deleted */
endpos=leaf_buff+_ma_get_page_used(share, leaf_buff);
@@ -563,23 +598,23 @@ static int del(register MARIA_HA *info, MARIA_KEYDEF *keyinfo,
_ma_get_page_used(share, leaf_buff) >
(uint) (keyinfo->block_length - KEYPAGE_CHECKSUM_SIZE))
{
- ret_value= (_ma_split_page(info, keyinfo, key,
+ ret_value= (_ma_split_page(info, key,
leaf_page, leaf_buff,
(uint) (keyinfo->block_length -
KEYPAGE_CHECKSUM_SIZE),
(uchar*) 0, 0, 0,
- ret_key, 0) | 2);
+ ret_key_buff, 0) | 2);
}
}
else
{
DBUG_PRINT("test",("Inserting of key when deleting"));
- if (!_ma_get_last_key(info,keyinfo,leaf_buff,keybuff,endpos,
- &tmp))
+ if (!_ma_get_last_key(&tmp_key, leaf_buff, endpos))
goto err;
- ret_value= _ma_insert(info, keyinfo, key, leaf_buff, endpos,
- leaf_page, keybuff, (my_off_t) 0, (uchar*) 0,
- (MARIA_PINNED_PAGE *) 0, (uchar*) 0, 0);
+ ret_value= _ma_insert(info, key, leaf_buff, endpos,
+ leaf_page, tmp_key.data, (my_off_t) 0,
+ (uchar*) 0, (MARIA_PINNED_PAGE *) 0,
+ (uchar*) 0, 0);
}
}
leaf_page_link->changed= 1;
@@ -629,18 +664,23 @@ static int del(register MARIA_HA *info, MARIA_KEYDEF *keyinfo,
}
/* Place last key in ancestor page on deleted key position */
-
a_length= _ma_get_page_used(share, anc_buff);
endpos=anc_buff+a_length;
- if (keypos != anc_buff+share->keypage_header + share->base.key_reflength &&
- !_ma_get_last_key(info,keyinfo,anc_buff,ret_key,keypos,&tmp))
- goto err;
- prev_key= (keypos == anc_buff + share->keypage_header +
- share->base.key_reflength ? 0 : ret_key);
- length=(*keyinfo->pack_key)(keyinfo,share->base.key_reflength,
- keypos == endpos ? (uchar*) 0 : keypos,
- prev_key, prev_key,
- keybuff,&s_temp);
+
+ ret_key.keyinfo= keyinfo;
+ ret_key.data= ret_key_buff;
+
+ prev_key= 0;
+ if (keypos != anc_buff+share->keypage_header + share->base.key_reflength)
+ {
+ if (!_ma_get_last_key(&ret_key, anc_buff, keypos))
+ goto err;
+ prev_key= ret_key.data;
+ }
+ length= (*keyinfo->pack_key)(&tmp_key, share->base.key_reflength,
+ keypos == endpos ? (uchar*) 0 : keypos,
+ prev_key, prev_key,
+ &s_temp);
if (length > 0)
bmove_upp(endpos+length,endpos,(uint) (endpos-keypos));
else
@@ -648,8 +688,9 @@ static int del(register MARIA_HA *info, MARIA_KEYDEF *keyinfo,
(*keyinfo->store_key)(keyinfo,keypos,&s_temp);
key_start= keypos;
- /* Save pointer to next leaf */
- if (!(*keyinfo->get_key)(keyinfo,share->base.key_reflength,&keypos,ret_key))
+ /* Save pointer to next leaf on parent page */
+ if (!(*keyinfo->get_key)(&ret_key, page_flag, share->base.key_reflength,
+ &keypos))
goto err;
_ma_kpointer(info,keypos - share->base.key_reflength,next_block);
_ma_store_page_used(share, anc_buff, a_length + length);
@@ -688,30 +729,33 @@ err:
@retval -1 error
*/
-static int underflow(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
+static int underflow(register MARIA_HA *info, MARIA_KEYDEF *keyinfo,
my_off_t anc_page, uchar *anc_buff,
my_off_t leaf_page, uchar *leaf_buff,
MARIA_PINNED_PAGE *leaf_page_link,
uchar *keypos)
{
int t_length;
- uint length,anc_length,buff_length,leaf_length,p_length,s_length,nod_flag;
- uint next_buff_length, new_buff_length, key_reflength, key_length;
+ uint anc_length,buff_length,leaf_length,p_length,s_length,nod_flag;
+ uint next_buff_length, new_buff_length, key_reflength;
uint unchanged_leaf_length, new_leaf_length, new_anc_length;
+ uint anc_page_flag, page_flag;
my_off_t next_page;
- uchar anc_key[HA_MAX_KEY_BUFF],leaf_key[HA_MAX_KEY_BUFF];
+ uchar anc_key_buff[MARIA_MAX_KEY_BUFF], leaf_key_buff[MARIA_MAX_KEY_BUFF];
uchar *buff,*endpos,*next_keypos,*anc_pos,*half_pos,*prev_key;
uchar *after_key, *anc_end_pos;
MARIA_KEY_PARAM key_deleted, key_inserted;
MARIA_SHARE *share= info->s;
MARIA_PINNED_PAGE *next_page_link;
my_bool first_key;
+ MARIA_KEY tmp_key, anc_key, leaf_key;
DBUG_ENTER("underflow");
DBUG_PRINT("enter",("leaf_page: %ld keypos: 0x%lx",(long) leaf_page,
(ulong) keypos));
DBUG_DUMP("anc_buff", anc_buff, _ma_get_page_used(share, anc_buff));
DBUG_DUMP("leaf_buff", leaf_buff, _ma_get_page_used(share, leaf_buff));
+ anc_page_flag= _ma_get_keypage_flag(share, anc_buff);
buff=info->buff;
info->keyread_buff_used=1;
next_keypos=keypos;
@@ -724,25 +768,34 @@ static int underflow(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
info->page_changed=1;
first_key= keypos == anc_buff + share->keypage_header + key_reflength;
+ tmp_key.data= buff;
+ anc_key.data= anc_key_buff;
+ leaf_key.data= leaf_key_buff;
+ tmp_key.keyinfo= leaf_key.keyinfo= anc_key.keyinfo= keyinfo;
+
if ((keypos < anc_buff + anc_length && (info->state->records & 1)) ||
first_key)
{
+ size_t tmp_length;
/* Use page right of anc-page */
DBUG_PRINT("test",("use right page"));
+ /*
+ Calculate position after the current key. Note that keydata itself is
+ not used
+ */
if (keyinfo->flag & HA_BINARY_PACK_KEY)
{
- if (!(next_keypos= _ma_get_key(info, keyinfo,
- anc_buff, buff, keypos, &length)))
+ if (!(next_keypos= _ma_get_key(&tmp_key, anc_buff, keypos)))
goto err;
}
else
{
/* Got to end of found key */
buff[0]=buff[1]=0; /* Avoid length error check if packed key */
- if (!(*keyinfo->get_key)(keyinfo,key_reflength,&next_keypos,
- buff))
- goto err;
+ if (!(*keyinfo->get_key)(&tmp_key, anc_page_flag, key_reflength,
+ &next_keypos))
+ goto err;
}
next_page= _ma_kpos(key_reflength,next_keypos);
if (!_ma_fetch_keypage(info,keyinfo, next_page, PAGECACHE_LOCK_WRITE,
@@ -754,29 +807,36 @@ static int underflow(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
/* find keys to make a big key-page */
bmove(next_keypos-key_reflength, buff + share->keypage_header,
key_reflength);
- if (!_ma_get_last_key(info,keyinfo,anc_buff,anc_key,next_keypos,&length) ||
- !_ma_get_last_key(info,keyinfo,leaf_buff,leaf_key,
- leaf_buff+leaf_length,&length))
+
+ if (!_ma_get_last_key(&anc_key, anc_buff, next_keypos) ||
+ !_ma_get_last_key(&leaf_key, leaf_buff, leaf_buff+leaf_length))
goto err;
/* merge pages and put parting key from anc_buff between */
- prev_key=(leaf_length == p_length ? (uchar*) 0 : leaf_key);
- t_length=(*keyinfo->pack_key)(keyinfo,nod_flag,buff+p_length,
- prev_key, prev_key,
- anc_key, &key_inserted);
- length= next_buff_length - p_length;
- endpos=buff+length+leaf_length+t_length;
+ prev_key= (leaf_length == p_length ? (uchar*) 0 : leaf_key.data);
+ t_length= (*keyinfo->pack_key)(&anc_key, nod_flag, buff+p_length,
+ prev_key, prev_key, &key_inserted);
+ tmp_length= next_buff_length - p_length;
+ endpos= buff+tmp_length+leaf_length+t_length;
/* buff will always be larger than before !*/
- bmove_upp(endpos, buff + next_buff_length, length);
+ bmove_upp(endpos, buff + next_buff_length, tmp_length);
memcpy(buff, leaf_buff,(size_t) leaf_length);
(*keyinfo->store_key)(keyinfo, buff+leaf_length, &key_inserted);
buff_length= (uint) (endpos-buff);
_ma_store_page_used(share, buff, buff_length);
+ /* Set page flag from combination of both key pages and parting key */
+ page_flag= (_ma_get_keypage_flag(share, buff) |
+ _ma_get_keypage_flag(share, leaf_buff));
+ if (anc_key.flag & (SEARCH_USER_KEY_HAS_TRANSID |
+ SEARCH_PAGE_KEY_HAS_TRANSID))
+ page_flag|= KEYPAGE_FLAG_HAS_TRANSID;
+ _ma_store_keypage_flag(share, buff, page_flag);
+
/* remove key from anc_buff */
- if (!(s_length=remove_key(keyinfo,key_reflength,keypos,anc_key,
- anc_buff+anc_length,(my_off_t *) 0,
- &key_deleted)))
+ if (!(s_length=remove_key(keyinfo, anc_page_flag, key_reflength, keypos,
+ anc_key_buff, anc_buff+anc_length,
+ (my_off_t *) 0, &key_deleted)))
goto err;
new_anc_length= anc_length - s_length;
@@ -821,29 +881,32 @@ static int underflow(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
MARIA_KEY_PARAM anc_key_inserted;
anc_end_pos= anc_buff + new_anc_length;
+
DBUG_PRINT("test",("anc_buff: 0x%lx anc_end_pos: 0x%lx",
(long) anc_buff, (long) anc_end_pos));
- if (!first_key &&
- !_ma_get_last_key(info,keyinfo,anc_buff,anc_key,keypos,&length))
+
+ if (!first_key && !_ma_get_last_key(&anc_key, anc_buff, keypos))
goto err;
- if (!(half_pos= _ma_find_half_pos(info, nod_flag, keyinfo, buff,
- leaf_key, &key_length, &after_key)))
+ if (!(half_pos= _ma_find_half_pos(info, &leaf_key, nod_flag, buff,
+ &after_key)))
goto err;
new_leaf_length= (uint) (half_pos-buff);
memcpy(leaf_buff, buff, (size_t) new_leaf_length);
_ma_store_page_used(share, leaf_buff, new_leaf_length);
+ _ma_store_keypage_flag(share, leaf_buff, page_flag);
/* Correct new keypointer to leaf_page */
half_pos=after_key;
- _ma_kpointer(info,leaf_key+key_length,next_page);
+ _ma_kpointer(info,
+ leaf_key.data+leaf_key.data_length + leaf_key.ref_length,
+ next_page);
/* Save key in anc_buff */
- prev_key= (first_key ? (uchar*) 0 : anc_key);
- t_length=(*keyinfo->pack_key)(keyinfo,key_reflength,
- (keypos == anc_end_pos ? (uchar*) 0 :
- keypos),
- prev_key, prev_key,
- leaf_key, &anc_key_inserted);
+ prev_key= (first_key ? (uchar*) 0 : anc_key.data);
+ t_length= (*keyinfo->pack_key)(&leaf_key, key_reflength,
+ (keypos == anc_end_pos ? (uchar*) 0 :
+ keypos),
+ prev_key, prev_key, &anc_key_inserted);
if (t_length >= 0)
bmove_upp(anc_end_pos+t_length, anc_end_pos,
(uint) (anc_end_pos - keypos));
@@ -852,22 +915,26 @@ static int underflow(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
(*keyinfo->store_key)(keyinfo,keypos, &anc_key_inserted);
new_anc_length+= t_length;
_ma_store_page_used(share, anc_buff, new_anc_length);
+ if (leaf_key.flag & (SEARCH_USER_KEY_HAS_TRANSID |
+ SEARCH_PAGE_KEY_HAS_TRANSID))
+ _ma_mark_page_with_transid(share, anc_buff);
/* Store key first in new page */
if (nod_flag)
bmove(buff+share->keypage_header, half_pos-nod_flag,
(size_t) nod_flag);
- if (!(*keyinfo->get_key)(keyinfo,nod_flag,&half_pos,leaf_key))
+ if (!(*keyinfo->get_key)(&leaf_key, page_flag, nod_flag, &half_pos))
goto err;
- t_length=(int) (*keyinfo->pack_key)(keyinfo, nod_flag, (uchar*) 0,
+ t_length=(int) (*keyinfo->pack_key)(&leaf_key, nod_flag, (uchar*) 0,
(uchar*) 0, (uchar*) 0,
- leaf_key, &key_inserted);
+ &key_inserted);
/* t_length will always be > 0 for a new page !*/
- length= (uint) ((buff + buff_length) - half_pos);
- bmove(buff+p_length+t_length, half_pos, (size_t) length);
+ tmp_length= (size_t) ((buff + buff_length) - half_pos);
+ bmove(buff+p_length+t_length, half_pos, tmp_length);
(*keyinfo->store_key)(keyinfo,buff+p_length, &key_inserted);
- new_buff_length= length + t_length + p_length;
+ new_buff_length= tmp_length + t_length + p_length;
_ma_store_page_used(share, buff, new_buff_length);
+ /* keypage flag is already up to date */
if (share->now_transactional)
{
@@ -940,7 +1007,7 @@ static int underflow(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
DBUG_PRINT("test",("use left page"));
- keypos= _ma_get_last_key(info,keyinfo,anc_buff,anc_key,keypos,&length);
+ keypos= _ma_get_last_key(&anc_key, anc_buff, keypos);
if (!keypos)
goto err;
next_page= _ma_kpos(key_reflength,keypos);
@@ -955,19 +1022,19 @@ static int underflow(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
bmove(next_keypos - key_reflength, leaf_buff + share->keypage_header,
key_reflength);
next_keypos=keypos;
- if (!(*keyinfo->get_key)(keyinfo,key_reflength,&next_keypos,
- anc_key))
+ if (!(*keyinfo->get_key)(&anc_key, anc_page_flag, key_reflength,
+ &next_keypos))
goto err;
- if (!_ma_get_last_key(info,keyinfo,buff,leaf_key,endpos,&length))
+ if (!_ma_get_last_key(&leaf_key, buff, endpos))
goto err;
/* merge pages and put parting key from anc_buff between */
- prev_key=(leaf_length == p_length ? (uchar*) 0 : leaf_key);
- t_length=(*keyinfo->pack_key)(keyinfo,nod_flag,
+ prev_key= (leaf_length == p_length ? (uchar*) 0 : leaf_key.data);
+ t_length=(*keyinfo->pack_key)(&anc_key, nod_flag,
(leaf_length == p_length ?
(uchar*) 0 : leaf_buff+p_length),
prev_key, prev_key,
- anc_key, &key_inserted);
+ &key_inserted);
if (t_length >= 0)
bmove(endpos+t_length, leaf_buff+p_length,
(size_t) (leaf_length-p_length));
@@ -984,9 +1051,17 @@ static int underflow(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
new_buff_length= buff_length + leaf_length - p_length + t_length;
_ma_store_page_used(share, buff, new_buff_length);
+ page_flag= (_ma_get_keypage_flag(share, buff) |
+ _ma_get_keypage_flag(share, leaf_buff));
+ if (anc_key.flag & (SEARCH_USER_KEY_HAS_TRANSID |
+ SEARCH_PAGE_KEY_HAS_TRANSID))
+ page_flag|= KEYPAGE_FLAG_HAS_TRANSID;
+ _ma_store_keypage_flag(share, buff, page_flag);
+
/* remove key from anc_buff */
- if (!(s_length= remove_key(keyinfo,key_reflength,keypos,anc_key,
- anc_buff+anc_length,(my_off_t *) 0,
+ if (!(s_length= remove_key(keyinfo, anc_page_flag, key_reflength, keypos,
+ anc_key_buff,
+ anc_buff+anc_length, (my_off_t *) 0,
&key_deleted)))
goto err;
@@ -1029,28 +1104,33 @@ static int underflow(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
- Shorten buff at 'endpos'
*/
MARIA_KEY_PARAM anc_key_inserted;
+ size_t tmp_length;
if (first_key)
anc_pos= 0; /* First key */
- else if (!_ma_get_last_key(info,keyinfo,anc_buff,anc_pos=anc_key,keypos,
- &length))
- goto err;
- if (!(endpos= _ma_find_half_pos(info, nod_flag, keyinfo, buff, leaf_key,
- &key_length, &half_pos)))
+ else
+ {
+ if (!_ma_get_last_key(&anc_key, anc_buff, keypos))
+ goto err;
+ anc_pos= anc_key.data;
+ }
+ if (!(endpos= _ma_find_half_pos(info, &leaf_key, nod_flag, buff,
+ &half_pos)))
goto err;
/* Correct new keypointer to leaf_page */
- _ma_kpointer(info,leaf_key+key_length,leaf_page);
+ _ma_kpointer(info,leaf_key.data + leaf_key.data_length +
+ leaf_key.ref_length, leaf_page);
/* Save key in anc_buff */
DBUG_DUMP("anc_buff", anc_buff, new_anc_length);
- DBUG_DUMP("key_to_anc",leaf_key,key_length);
+ DBUG_DUMP_KEY("key_to_anc", &leaf_key);
anc_end_pos= anc_buff + new_anc_length;
- t_length=(*keyinfo->pack_key)(keyinfo,key_reflength,
+ t_length=(*keyinfo->pack_key)(&leaf_key, key_reflength,
keypos == anc_end_pos ? (uchar*) 0
: keypos,
anc_pos, anc_pos,
- leaf_key, &anc_key_inserted);
+ &anc_key_inserted);
if (t_length >= 0)
bmove_upp(anc_end_pos+t_length, anc_end_pos,
(uint) (anc_end_pos-keypos));
@@ -1059,24 +1139,27 @@ static int underflow(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
(*keyinfo->store_key)(keyinfo,keypos, &anc_key_inserted);
new_anc_length+= t_length;
_ma_store_page_used(share, anc_buff, new_anc_length);
+ if (leaf_key.flag & (SEARCH_USER_KEY_HAS_TRANSID |
+ SEARCH_PAGE_KEY_HAS_TRANSID))
+ _ma_mark_page_with_transid(share, anc_buff);
/* Store first key on new page */
if (nod_flag)
bmove(leaf_buff + share->keypage_header, half_pos-nod_flag,
(size_t) nod_flag);
- if (!(length=(*keyinfo->get_key)(keyinfo,nod_flag,&half_pos,leaf_key)))
+ if (!(*keyinfo->get_key)(&leaf_key, page_flag, nod_flag, &half_pos))
goto err;
- DBUG_DUMP("key_to_leaf",leaf_key,length);
- t_length=(*keyinfo->pack_key)(keyinfo,nod_flag, (uchar*) 0,
- (uchar*) 0, (uchar*) 0, leaf_key,
- &key_inserted);
+ DBUG_DUMP_KEY("key_to_leaf", &leaf_key);
+ t_length=(*keyinfo->pack_key)(&leaf_key, nod_flag, (uchar*) 0,
+ (uchar*) 0, (uchar*) 0, &key_inserted);
/* t_length will always be > 0 for a new page !*/
- length= (uint) ((buff + new_buff_length) - half_pos);
- DBUG_PRINT("info",("t_length: %d length: %d",t_length,(int) length));
- bmove(leaf_buff+p_length+t_length, half_pos, (size_t) length);
+ tmp_length= (size_t) ((buff + new_buff_length) - half_pos);
+ DBUG_PRINT("info",("t_length: %d length: %d",t_length, (int) tmp_length));
+ bmove(leaf_buff+p_length+t_length, half_pos, tmp_length);
(*keyinfo->store_key)(keyinfo,leaf_buff+p_length, &key_inserted);
- new_leaf_length= length + t_length + p_length;
+ new_leaf_length= tmp_length + t_length + p_length;
_ma_store_page_used(share, leaf_buff, new_leaf_length);
+ _ma_store_keypage_flag(share, leaf_buff, page_flag);
new_buff_length= (uint) (endpos - buff);
_ma_store_page_used(share, buff, new_buff_length);
@@ -1145,8 +1228,9 @@ err:
@fn remove_key()
keyinfo Key handle
+ nod_flag Length of node ptr
keypos Where on page key starts
- lastkey Unpacked version of key to be removed
+ lastkey Buffer for storing keys to be removed
page_end Pointer to end of page
next_block If <> 0 and node-page, this is set to address of
next page
@@ -1164,7 +1248,7 @@ err:
@retval # How many chars was removed
*/
-static uint remove_key(MARIA_KEYDEF *keyinfo, uint nod_flag,
+static uint remove_key(MARIA_KEYDEF *keyinfo, uint page_flag, uint nod_flag,
uchar *keypos, uchar *lastkey,
uchar *page_end, my_off_t *next_block,
MARIA_KEY_PARAM *s_temp)
@@ -1179,16 +1263,23 @@ static uint remove_key(MARIA_KEYDEF *keyinfo, uint nod_flag,
s_temp->changed_length= 0;
if (!(keyinfo->flag &
(HA_PACK_KEY | HA_SPACE_PACK_USED | HA_VAR_LENGTH_KEY |
- HA_BINARY_PACK_KEY)))
+ HA_BINARY_PACK_KEY)) &&
+ !(page_flag & KEYPAGE_FLAG_HAS_TRANSID))
{
+ /* Static length key */
s_length=(int) (keyinfo->keylength+nod_flag);
if (next_block && nod_flag)
*next_block= _ma_kpos(nod_flag,keypos+s_length);
}
else
- { /* Let keypos point at next key */
+ {
+ /* Let keypos point at next key */
+ MARIA_KEY key;
+
/* Calculate length of key */
- if (!(*keyinfo->get_key)(keyinfo,nod_flag,&keypos,lastkey))
+ key.keyinfo= keyinfo;
+ key.data= lastkey;
+ if (!(*keyinfo->get_key)(&key, page_flag, nod_flag, &keypos))
DBUG_RETURN(0); /* Error */
if (next_block && nod_flag)
@@ -1386,8 +1477,7 @@ my_bool _ma_log_delete(MARIA_HA *info, my_off_t page, const uchar *buff,
Logging of undos
****************************************************************************/
-int _ma_write_undo_key_delete(MARIA_HA *info, uint keynr,
- const uchar *key, uint key_length,
+int _ma_write_undo_key_delete(MARIA_HA *info, const MARIA_KEY *key,
my_off_t new_root, LSN *res_lsn)
{
MARIA_SHARE *share= info->s;
@@ -1396,6 +1486,7 @@ int _ma_write_undo_key_delete(MARIA_HA *info, uint keynr,
LEX_CUSTRING log_array[TRANSLOG_INTERNAL_PARTS + 2];
struct st_msg_to_write_hook_for_undo_key msg;
enum translog_record_type log_type= LOGREC_UNDO_KEY_DELETE;
+ uint keynr= key->keyinfo->key_nr;
lsn_store(log_data, info->trn->undo_lsn);
key_nr_store(log_data + LSN_STORE_SIZE + FILEID_STORE_SIZE, keynr);
@@ -1415,12 +1506,11 @@ int _ma_write_undo_key_delete(MARIA_HA *info, uint keynr,
log_type= LOGREC_UNDO_KEY_DELETE_WITH_ROOT;
}
- /* Log also position to row */
- key_length+= share->rec_reflength;
log_array[TRANSLOG_INTERNAL_PARTS + 0].str= log_data;
log_array[TRANSLOG_INTERNAL_PARTS + 0].length= (uint) (log_pos - log_data);
- log_array[TRANSLOG_INTERNAL_PARTS + 1].str= key;
- log_array[TRANSLOG_INTERNAL_PARTS + 1].length= key_length;
+ log_array[TRANSLOG_INTERNAL_PARTS + 1].str= key->data;
+ log_array[TRANSLOG_INTERNAL_PARTS + 1].length= (key->data_length +
+ key->ref_length);
msg.root= &share->state.key_root[keynr];
msg.value= new_root;
@@ -1434,7 +1524,7 @@ int _ma_write_undo_key_delete(MARIA_HA *info, uint keynr,
info->trn, info,
(translog_size_t)
log_array[TRANSLOG_INTERNAL_PARTS + 0].length +
- key_length,
+ log_array[TRANSLOG_INTERNAL_PARTS + 1].length,
TRANSLOG_INTERNAL_PARTS + 2, log_array,
log_data + LSN_STORE_SIZE, &msg) ? -1 : 0;
}