545
Update keys when record has changed.
546
This is much more efficent than using a delete & insert.
549
bool hash_update(HASH *hash, unsigned char *record, unsigned char *old_key,
550
size_t old_key_length)
552
uint32_t new_index,new_pos_index,blength,records,empty;
554
HASH_LINK org_link,*data,*previous,*pos;
556
if (HASH_UNIQUE & hash->flags)
558
HASH_SEARCH_STATE state;
559
unsigned char *found,
560
*new_key= (unsigned char*) hash_key(hash, record, &idx, 1);
562
if ((found= hash_first(hash, new_key, idx, &state)))
567
return(1); /* Duplicate entry */
569
while ((found= hash_next(hash, new_key, idx, &state)));
573
data=dynamic_element(&hash->array,0,HASH_LINK*);
574
blength=hash->blength; records=hash->records;
576
/* Search after record with key */
578
idx=hash_mask(calc_hash(hash, old_key,(old_key_length ?
582
new_index=hash_mask(rec_hashnr(hash,record),blength,records);
583
if (idx == new_index)
584
return(0); /* Nothing to do (No record check) */
589
if ((pos= data+idx)->data == record)
592
if ((idx=pos->next) == NO_RECORD)
593
return(1); /* Not found in links */
596
empty= static_cast<uint32_t>(idx);
598
/* Relink record from current chain */
602
if (pos->next != NO_RECORD)
605
*pos= data[pos->next];
609
previous->next=pos->next; /* unlink pos */
611
/* Move data to correct position */
612
if (new_index == empty)
615
At this point record is unlinked from the old chain, thus it holds
616
random position. By the chance this position is equal to position
617
for the first element in the new chain. That means updated record
618
is the only record in the new chain.
623
Record was moved while unlinking it from the old chain.
624
Copy data to a new position.
626
data[empty]= org_link;
628
data[empty].next= NO_RECORD;
632
new_pos_index=hash_rec_mask(hash,pos,blength,records);
633
if (new_index != new_pos_index)
634
{ /* Other record in wrong position */
636
movelink(data,new_index,new_pos_index,empty);
637
org_link.next=NO_RECORD;
638
data[new_index]= org_link;
641
{ /* Link in chain at right position */
642
org_link.next=data[new_index].next;
643
data[empty]=org_link;
644
data[new_index].next=empty;
650
526
unsigned char *hash_element(HASH *hash,uint32_t idx)
652
528
if (idx < hash->records)