357
* Fowler/Noll/Vo hash
359
* The basis of the hash algorithm was taken from an idea sent by email to the
360
* IEEE Posix P1003.2 mailing list from Phong Vo (kpv@research.att.com) and
361
* Glenn Fowler (gsf@research.att.com). Landon Curt Noll (chongo@toad.com)
362
* later improved on their algorithm.
364
* The magic is in the interesting relationship between the special prime
365
* 16777619 (2^24 + 403) and 2^32 and 2^8.
367
* This hash produces the fewest collisions of any function that we've seen so
368
* far, and works well on both numbers and strings.
371
uint32_t hp_hashnr(register HP_KEYDEF *keydef, register const unsigned char *key)
374
Note, if a key consists of a combination of numeric and
375
a text columns, it most likely won't work well.
376
Making text columns work with NEW_HASH_FUNCTION
377
needs also changes in strings/ctype-xxx.c.
379
uint32_t nr= 1, nr2= 4;
380
HA_KEYSEG *seg,*endseg;
382
for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
384
unsigned char *pos=(unsigned char*) key;
392
/* Add key pack length (2) to key for VARCHAR segments */
393
if (seg->type == HA_KEYTYPE_VARTEXT1)
399
if (seg->type == HA_KEYTYPE_TEXT)
401
seg->charset->coll->hash_sort(seg->charset, pos, ((unsigned char*)key)-pos,
404
else if (seg->type == HA_KEYTYPE_VARTEXT1) /* Any VARCHAR segments */
406
uint32_t pack_length= 2; /* Key packing is constant */
407
uint32_t length= uint2korr(pos);
408
seg->charset->coll->hash_sort(seg->charset, pos+pack_length, length,
414
for ( ; pos < (unsigned char*) key ; pos++)
424
/* Calc hashvalue for a key in a record */
426
uint32_t hp_rec_hashnr(register HP_KEYDEF *keydef, register const unsigned char *rec)
428
uint32_t nr= 1, nr2= 4;
429
HA_KEYSEG *seg,*endseg;
431
for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
433
unsigned char *pos=(unsigned char*) rec+seg->start;
436
if (rec[seg->null_pos] & seg->null_bit)
442
if (seg->type == HA_KEYTYPE_TEXT)
444
uint32_t char_length= seg->length; /* TODO: fix to use my_charpos() */
445
seg->charset->coll->hash_sort(seg->charset, pos, char_length,
448
else if (seg->type == HA_KEYTYPE_VARTEXT1) /* Any VARCHAR segments */
450
uint32_t pack_length= seg->bit_start;
451
uint32_t length= (pack_length == 1 ? (uint) *(unsigned char*) pos : uint2korr(pos));
452
seg->charset->coll->hash_sort(seg->charset, pos+pack_length,
457
unsigned char *end= pos+seg->length;
458
for ( ; pos < end ; pos++)
472
355
Compare keys for two records. Returns 0 if they are identical