422
436
pos->data=(unsigned char*) record;
423
pos->next=(uint32_t) (empty - data);
437
pos->next=(uint) (empty - data);
427
441
pos->data=(unsigned char*) record;
428
442
pos->next=NO_RECORD;
429
movelink(data,(uint32_t) (pos-data),(uint32_t) (gpos-data),(uint32_t) (empty-data));
443
movelink(data,(uint) (pos-data),(uint) (gpos-data),(uint) (empty-data));
432
446
if (++info->records == info->blength)
500
514
{ /* pos is on wrong posit */
501
515
empty[0]=pos[0]; /* Save it here */
502
516
pos[0]=lastpos[0]; /* This should be here */
503
movelink(data,(uint32_t) (pos-data),(uint32_t) (pos3-data),empty_index);
517
movelink(data,(uint) (pos-data),(uint) (pos3-data),empty_index);
506
520
pos2= hash_mask(lastpos_hashnr,blength,hash->records+1);
509
523
if (pos2 != hash->records)
511
525
empty[0]=lastpos[0];
512
movelink(data,(uint32_t) (lastpos-data),(uint32_t) (pos-data),empty_index);
526
movelink(data,(uint) (lastpos-data),(uint) (pos-data),empty_index);
515
idx= (uint32_t) (pos-data); /* Link pos->next after lastpos */
529
idx= (uint) (pos-data); /* Link pos->next after lastpos */
517
531
else idx= NO_RECORD; /* Different positions merge */
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 */
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;
530
650
unsigned char *hash_element(HASH *hash,uint32_t idx)
532
652
if (idx < hash->records)