16
16
/* The hash functions used for saveing keys */
18
#include "heap_priv.h"
19
20
#include <mystrings/m_ctype.h>
21
#include <drizzled/util/test.h>
24
static uint32_t hp_hashnr(register HP_KEYDEF *keydef, register const unsigned char *key);
25
static int hp_key_cmp(HP_KEYDEF *keydef, const unsigned char *rec, const unsigned char *key);
24
28
Find out how many rows there is in the given range
59
63
custom_arg.search_flag= SEARCH_FIND | SEARCH_SAME;
62
custom_arg.key_length= hp_rb_pack_key(keyinfo, (uchar*) info->recbuf,
63
(uchar*) min_key->key,
66
custom_arg.key_length= hp_rb_pack_key(keyinfo, (unsigned char*) info->recbuf,
67
(unsigned char*) min_key->key,
64
68
min_key->keypart_map);
65
69
start_pos= tree_record_pos(rb_tree, info->recbuf, min_key->flag,
75
custom_arg.key_length= hp_rb_pack_key(keyinfo, (uchar*) info->recbuf,
76
(uchar*) max_key->key,
79
custom_arg.key_length= hp_rb_pack_key(keyinfo, (unsigned char*) info->recbuf,
80
(unsigned char*) max_key->key,
77
81
max_key->keypart_map);
78
82
end_pos= tree_record_pos(rb_tree, info->recbuf, max_key->flag,
94
98
/* Sets info->current_ptr to found record */
95
99
/* next_flag: Search=0, next=1, prev =2, same =3 */
97
uchar *hp_search(HP_INFO *info, HP_KEYDEF *keyinfo, const uchar *key,
101
unsigned char *hp_search(HP_INFO *info, HP_KEYDEF *keyinfo, const unsigned char *key,
100
104
register HASH_INFO *pos,*prev_ptr;
106
uint32_t old_nextflag;
103
107
HP_SHARE *share=info->s;
104
108
old_nextflag=nextflag;
228
#ifndef NEW_HASH_FUNCTION
230
232
/* Calc hashvalue for a key */
232
uint32_t hp_hashnr(register HP_KEYDEF *keydef, register const uchar *key)
234
static uint32_t hp_hashnr(register HP_KEYDEF *keydef, register const unsigned char *key)
235
237
uint32_t nr=1, nr2=4;
236
238
HA_KEYSEG *seg,*endseg;
238
240
for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
240
uchar *pos=(uchar*) key;
242
unsigned char *pos=(unsigned char*) key;
241
243
key+=seg->length;
242
244
if (seg->null_bit)
255
257
if (seg->type == HA_KEYTYPE_TEXT)
257
259
const CHARSET_INFO * const cs= seg->charset;
258
uint length= seg->length;
260
uint32_t length= seg->length;
259
261
if (cs->mbmaxlen > 1)
263
uint32_t char_length;
262
264
char_length= my_charpos(cs, pos, pos + length, length/cs->mbmaxlen);
263
265
set_if_smaller(length, char_length);
267
269
else if (seg->type == HA_KEYTYPE_VARTEXT1) /* Any VARCHAR segments */
269
271
const CHARSET_INFO * const cs= seg->charset;
270
uint pack_length= 2; /* Key packing is constant */
271
uint length= uint2korr(pos);
272
uint32_t pack_length= 2; /* Key packing is constant */
273
uint32_t length= uint2korr(pos);
272
274
if (cs->mbmaxlen > 1)
276
uint32_t char_length;
275
277
char_length= my_charpos(cs, pos +pack_length,
276
278
pos +pack_length + length,
277
279
seg->length/cs->mbmaxlen);
295
297
/* Calc hashvalue for a key in a record */
297
uint32_t hp_rec_hashnr(register HP_KEYDEF *keydef, register const uchar *rec)
299
uint32_t hp_rec_hashnr(register HP_KEYDEF *keydef, register const unsigned char *rec)
299
301
uint32_t nr=1, nr2=4;
300
302
HA_KEYSEG *seg,*endseg;
302
304
for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
304
uchar *pos=(uchar*) rec+seg->start,*end=pos+seg->length;
306
unsigned char *pos=(unsigned char*) rec+seg->start,*end=pos+seg->length;
305
307
if (seg->null_bit)
307
309
if (rec[seg->null_pos] & seg->null_bit)
313
315
if (seg->type == HA_KEYTYPE_TEXT)
315
317
const CHARSET_INFO * const cs= seg->charset;
316
uint char_length= seg->length;
318
uint32_t char_length= seg->length;
317
319
if (cs->mbmaxlen > 1)
319
321
char_length= my_charpos(cs, pos, pos + char_length,
320
322
char_length / cs->mbmaxlen);
321
set_if_smaller(char_length, seg->length); /* QQ: ok to remove? */
323
set_if_smaller(char_length, (uint32_t)seg->length); /* QQ: ok to remove? */
323
325
cs->coll->hash_sort(cs, pos, char_length, &nr, &nr2);
325
327
else if (seg->type == HA_KEYTYPE_VARTEXT1) /* Any VARCHAR segments */
327
329
const CHARSET_INFO * const cs= seg->charset;
328
uint pack_length= seg->bit_start;
329
uint length= (pack_length == 1 ? (uint) *(uchar*) pos : uint2korr(pos));
330
uint32_t pack_length= seg->bit_start;
331
uint32_t length= (pack_length == 1 ? (uint) *(unsigned char*) pos : uint2korr(pos));
330
332
if (cs->mbmaxlen > 1)
334
uint32_t char_length;
333
335
char_length= my_charpos(cs, pos + pack_length,
334
336
pos + pack_length + length,
335
337
seg->length/cs->mbmaxlen);
355
* Fowler/Noll/Vo hash
357
* The basis of the hash algorithm was taken from an idea sent by email to the
358
* IEEE Posix P1003.2 mailing list from Phong Vo (kpv@research.att.com) and
359
* Glenn Fowler (gsf@research.att.com). Landon Curt Noll (chongo@toad.com)
360
* later improved on their algorithm.
362
* The magic is in the interesting relationship between the special prime
363
* 16777619 (2^24 + 403) and 2^32 and 2^8.
365
* This hash produces the fewest collisions of any function that we've seen so
366
* far, and works well on both numbers and strings.
369
uint32_t hp_hashnr(register HP_KEYDEF *keydef, register const uchar *key)
372
Note, if a key consists of a combination of numeric and
373
a text columns, it most likely won't work well.
374
Making text columns work with NEW_HASH_FUNCTION
375
needs also changes in strings/ctype-xxx.c.
377
uint32_t nr= 1, nr2= 4;
378
HA_KEYSEG *seg,*endseg;
380
for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
382
uchar *pos=(uchar*) key;
390
/* Add key pack length (2) to key for VARCHAR segments */
391
if (seg->type == HA_KEYTYPE_VARTEXT1)
397
if (seg->type == HA_KEYTYPE_TEXT)
399
seg->charset->coll->hash_sort(seg->charset, pos, ((uchar*)key)-pos,
402
else if (seg->type == HA_KEYTYPE_VARTEXT1) /* Any VARCHAR segments */
404
uint pack_length= 2; /* Key packing is constant */
405
uint length= uint2korr(pos);
406
seg->charset->coll->hash_sort(seg->charset, pos+pack_length, length,
412
for ( ; pos < (uchar*) key ; pos++)
422
/* Calc hashvalue for a key in a record */
424
uint32_t hp_rec_hashnr(register HP_KEYDEF *keydef, register const uchar *rec)
426
uint32_t nr= 1, nr2= 4;
427
HA_KEYSEG *seg,*endseg;
429
for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
431
uchar *pos=(uchar*) rec+seg->start;
434
if (rec[seg->null_pos] & seg->null_bit)
440
if (seg->type == HA_KEYTYPE_TEXT)
442
uint char_length= seg->length; /* TODO: fix to use my_charpos() */
443
seg->charset->coll->hash_sort(seg->charset, pos, char_length,
446
else if (seg->type == HA_KEYTYPE_VARTEXT1) /* Any VARCHAR segments */
448
uint pack_length= seg->bit_start;
449
uint length= (pack_length == 1 ? (uint) *(uchar*) pos : uint2korr(pos));
450
seg->charset->coll->hash_sort(seg->charset, pos+pack_length,
455
uchar *end= pos+seg->length;
456
for ( ; pos < end ; pos++)
470
355
Compare keys for two records. Returns 0 if they are identical
504
389
if (seg->type == HA_KEYTYPE_TEXT)
506
391
const CHARSET_INFO * const cs= seg->charset;
509
uchar *pos1= (uchar*)rec1 + seg->start;
510
uchar *pos2= (uchar*)rec2 + seg->start;
392
uint32_t char_length1;
393
uint32_t char_length2;
394
unsigned char *pos1= (unsigned char*)rec1 + seg->start;
395
unsigned char *pos2= (unsigned char*)rec2 + seg->start;
511
396
if (cs->mbmaxlen > 1)
513
uint char_length= seg->length / cs->mbmaxlen;
398
uint32_t char_length= seg->length / cs->mbmaxlen;
514
399
char_length1= my_charpos(cs, pos1, pos1 + seg->length, char_length);
515
set_if_smaller(char_length1, seg->length);
400
set_if_smaller(char_length1, (uint32_t)seg->length);
516
401
char_length2= my_charpos(cs, pos2, pos2 + seg->length, char_length);
517
set_if_smaller(char_length2, seg->length);
402
set_if_smaller(char_length2, (uint32_t)seg->length);
528
413
else if (seg->type == HA_KEYTYPE_VARTEXT1) /* Any VARCHAR segments */
530
uchar *pos1= (uchar*) rec1 + seg->start;
531
uchar *pos2= (uchar*) rec2 + seg->start;
532
uint char_length1, char_length2;
533
uint pack_length= seg->bit_start;
415
unsigned char *pos1= (unsigned char*) rec1 + seg->start;
416
unsigned char *pos2= (unsigned char*) rec2 + seg->start;
417
uint32_t char_length1, char_length2;
418
uint32_t pack_length= seg->bit_start;
534
419
const CHARSET_INFO * const cs= seg->charset;
535
420
if (pack_length == 1)
537
char_length1= (uint) *(uchar*) pos1++;
538
char_length2= (uint) *(uchar*) pos2++;
422
char_length1= (uint) *(unsigned char*) pos1++;
423
char_length2= (uint) *(unsigned char*) pos2++;
547
432
if (cs->mbmaxlen > 1)
549
uint safe_length1= char_length1;
550
uint safe_length2= char_length2;
551
uint char_length= seg->length / cs->mbmaxlen;
434
uint32_t safe_length1= char_length1;
435
uint32_t safe_length2= char_length2;
436
uint32_t char_length= seg->length / cs->mbmaxlen;
552
437
char_length1= my_charpos(cs, pos1, pos1 + char_length1, char_length);
553
438
set_if_smaller(char_length1, safe_length1);
554
439
char_length2= my_charpos(cs, pos2, pos2 + char_length2, char_length);
597
482
if (seg->type == HA_KEYTYPE_TEXT)
599
484
const CHARSET_INFO * const cs= seg->charset;
600
uint char_length_key;
601
uint char_length_rec;
602
uchar *pos= (uchar*) rec + seg->start;
485
uint32_t char_length_key;
486
uint32_t char_length_rec;
487
unsigned char *pos= (unsigned char*) rec + seg->start;
603
488
if (cs->mbmaxlen > 1)
605
uint char_length= seg->length / cs->mbmaxlen;
490
uint32_t char_length= seg->length / cs->mbmaxlen;
606
491
char_length_key= my_charpos(cs, key, key + seg->length, char_length);
607
set_if_smaller(char_length_key, seg->length);
492
set_if_smaller(char_length_key, (uint32_t)seg->length);
608
493
char_length_rec= my_charpos(cs, pos, pos + seg->length, char_length);
609
set_if_smaller(char_length_rec, seg->length);
494
set_if_smaller(char_length_rec, (uint32_t)seg->length);
613
498
char_length_key= seg->length;
614
499
char_length_rec= seg->length;
617
502
if (seg->charset->coll->strnncollsp(seg->charset,
618
(uchar*) pos, char_length_rec,
619
(uchar*) key, char_length_key, 0))
503
(unsigned char*) pos, char_length_rec,
504
(unsigned char*) key, char_length_key, 0))
622
507
else if (seg->type == HA_KEYTYPE_VARTEXT1) /* Any VARCHAR segments */
624
uchar *pos= (uchar*) rec + seg->start;
509
unsigned char *pos= (unsigned char*) rec + seg->start;
625
510
const CHARSET_INFO * const cs= seg->charset;
626
uint pack_length= seg->bit_start;
627
uint char_length_rec= (pack_length == 1 ? (uint) *(uchar*) pos :
511
uint32_t pack_length= seg->bit_start;
512
uint32_t char_length_rec= (pack_length == 1 ? (uint) *(unsigned char*) pos :
629
514
/* Key segments are always packed with 2 bytes */
630
uint char_length_key= uint2korr(key);
515
uint32_t char_length_key= uint2korr(key);
631
516
pos+= pack_length;
632
517
key+= 2; /* skip key pack length */
633
518
if (cs->mbmaxlen > 1)
635
uint char_length1, char_length2;
636
char_length1= char_length2= seg->length / cs->mbmaxlen;
520
uint32_t char_length1, char_length2;
521
char_length1= char_length2= seg->length / cs->mbmaxlen;
637
522
char_length1= my_charpos(cs, key, key + char_length_key, char_length1);
638
523
set_if_smaller(char_length_key, char_length1);
639
524
char_length2= my_charpos(cs, pos, pos + char_length_rec, char_length2);
643
528
if (cs->coll->strnncollsp(seg->charset,
644
(uchar*) pos, char_length_rec,
645
(uchar*) key, char_length_key, 0))
529
(unsigned char*) pos, char_length_rec,
530
(unsigned char*) key, char_length_key, 0))
658
543
/* Copy a key from a record to a keybuffer */
660
void hp_make_key(HP_KEYDEF *keydef, uchar *key, const uchar *rec)
545
void hp_make_key(HP_KEYDEF *keydef, unsigned char *key, const unsigned char *rec)
662
547
HA_KEYSEG *seg,*endseg;
664
549
for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
666
551
const CHARSET_INFO * const cs= seg->charset;
667
uint char_length= seg->length;
668
uchar *pos= (uchar*) rec + seg->start;
552
uint32_t char_length= seg->length;
553
unsigned char *pos= (unsigned char*) rec + seg->start;
669
554
if (seg->null_bit)
670
555
*key++= test(rec[seg->null_pos] & seg->null_bit);
671
556
if (cs->mbmaxlen > 1)
673
558
char_length= my_charpos(cs, pos, pos + seg->length,
674
559
char_length / cs->mbmaxlen);
675
set_if_smaller(char_length, seg->length); /* QQ: ok to remove? */
560
set_if_smaller(char_length, (uint32_t)seg->length); /* QQ: ok to remove? */
677
562
if (seg->type == HA_KEYTYPE_VARTEXT1)
678
563
char_length+= seg->bit_start; /* Copy also length */
692
uint hp_rb_make_key(HP_KEYDEF *keydef, uchar *key,
693
const uchar *rec, uchar *recpos)
577
uint32_t hp_rb_make_key(HP_KEYDEF *keydef, unsigned char *key,
578
const unsigned char *rec, unsigned char *recpos)
695
uchar *start_key= key;
580
unsigned char *start_key= key;
696
581
HA_KEYSEG *seg, *endseg;
698
583
for (seg= keydef->seg, endseg= seg + keydef->keysegs; seg < endseg; seg++)
585
uint32_t char_length;
701
586
if (seg->null_bit)
703
588
if (!(*key++= 1 - test(rec[seg->null_pos] & seg->null_bit)))
706
591
if (seg->flag & HA_SWAP_KEY)
708
uint length= seg->length;
709
uchar *pos= (uchar*) rec + seg->start;
593
uint32_t length= seg->length;
594
unsigned char *pos= (unsigned char*) rec + seg->start;
711
596
#ifdef HAVE_ISNAN
712
if (seg->type == HA_KEYTYPE_FLOAT)
718
/* Replace NAN with zero */
719
memset(key, 0, length);
724
else if (seg->type == HA_KEYTYPE_DOUBLE)
597
if (seg->type == HA_KEYTYPE_DOUBLE)
727
600
float8get(nr, pos);
744
617
if (seg->flag & HA_VAR_LENGTH_PART)
746
uchar *pos= (uchar*) rec + seg->start;
747
uint length= seg->length;
748
uint pack_length= seg->bit_start;
749
uint tmp_length= (pack_length == 1 ? (uint) *(uchar*) pos :
619
unsigned char *pos= (unsigned char*) rec + seg->start;
620
uint32_t length= seg->length;
621
uint32_t pack_length= seg->bit_start;
622
uint32_t tmp_length= (pack_length == 1 ? (uint) *(unsigned char*) pos :
751
624
const CHARSET_INFO * const cs= seg->charset;
752
625
char_length= length/cs->mbmaxlen;
763
636
char_length= seg->length;
764
637
if (seg->charset->mbmaxlen > 1)
766
char_length= my_charpos(seg->charset,
639
char_length= my_charpos(seg->charset,
767
640
rec + seg->start, rec + seg->start + char_length,
768
641
char_length / seg->charset->mbmaxlen);
769
set_if_smaller(char_length, seg->length); /* QQ: ok to remove? */
642
set_if_smaller(char_length, (uint32_t)seg->length); /* QQ: ok to remove? */
770
643
if (char_length < seg->length)
771
644
seg->charset->cset->fill(seg->charset, (char*) key + char_length,
772
645
seg->length - char_length, ' ');
774
647
memcpy(key, rec + seg->start, (size_t) char_length);
775
648
key+= seg->length;
777
memcpy(key, &recpos, sizeof(uchar*));
778
return (uint) (key - start_key);
650
memcpy(key, &recpos, sizeof(unsigned char*));
651
return (uint32_t) (key - start_key);
782
uint hp_rb_pack_key(HP_KEYDEF *keydef, uchar *key, const uchar *old,
655
uint32_t hp_rb_pack_key(HP_KEYDEF *keydef, unsigned char *key, const unsigned char *old,
783
656
key_part_map keypart_map)
785
658
HA_KEYSEG *seg, *endseg;
786
uchar *start_key= key;
659
unsigned char *start_key= key;
788
661
for (seg= keydef->seg, endseg= seg + keydef->keysegs;
789
662
seg < endseg && keypart_map; old+= seg->length, seg++)
664
uint32_t char_length;
792
665
keypart_map>>= 1;
793
666
if (seg->null_bit)
809
682
if (seg->flag & (HA_VAR_LENGTH_PART | HA_BLOB_PART))
811
684
/* Length of key-part used with heap_rkey() always 2 */
812
uint tmp_length=uint2korr(old);
813
uint length= seg->length;
685
uint32_t tmp_length=uint2korr(old);
686
uint32_t length= seg->length;
814
687
const CHARSET_INFO * const cs= seg->charset;
815
688
char_length= length/cs->mbmaxlen;
828
701
char_length= my_charpos(seg->charset, old, old+char_length,
829
702
char_length / seg->charset->mbmaxlen);
830
set_if_smaller(char_length, seg->length); /* QQ: ok to remove? */
703
set_if_smaller(char_length, (uint32_t)seg->length); /* QQ: ok to remove? */
831
704
if (char_length < seg->length)
832
seg->charset->cset->fill(seg->charset, (char*) key + char_length,
705
seg->charset->cset->fill(seg->charset, (char*) key + char_length,
833
706
seg->length - char_length, ' ');
835
708
memcpy(key, old, (size_t) char_length);
842
uint hp_rb_key_length(HP_KEYDEF *keydef,
843
const uchar *key __attribute__((unused)))
715
uint32_t hp_rb_key_length(HP_KEYDEF *keydef, const unsigned char *not_used)
845
718
return keydef->length;
849
uint hp_rb_null_key_length(HP_KEYDEF *keydef, const uchar *key)
722
uint32_t hp_rb_null_key_length(HP_KEYDEF *keydef, const unsigned char *key)
851
const uchar *start_key= key;
724
const unsigned char *start_key= key;
852
725
HA_KEYSEG *seg, *endseg;
854
727
for (seg= keydef->seg, endseg= seg + keydef->keysegs; seg < endseg; seg++)
856
729
if (seg->null_bit && !*key++)
860
733
return (uint) (key - start_key);
864
uint hp_rb_var_key_length(HP_KEYDEF *keydef, const uchar *key)
737
uint32_t hp_rb_var_key_length(HP_KEYDEF *keydef, const unsigned char *key)
866
const uchar *start_key= key;
739
const unsigned char *start_key= key;
867
740
HA_KEYSEG *seg, *endseg;
869
742
for (seg= keydef->seg, endseg= seg + keydef->keysegs; seg < endseg; seg++)
871
uint length= seg->length;
744
uint32_t length= seg->length;
872
745
if (seg->null_bit && !*key++)
874
747
if (seg->flag & (HA_VAR_LENGTH_PART | HA_BLOB_PART))
917
void heap_update_auto_increment(HP_INFO *info, const uchar *record)
790
void heap_update_auto_increment(HP_INFO *info, const unsigned char *record)
919
792
uint64_t value= 0; /* Store unsigned values here */
920
793
int64_t s_value= 0; /* Store signed values here */
922
795
HA_KEYSEG *keyseg= info->s->keydef[info->s->auto_key - 1].seg;
923
const uchar *key= (uchar*) record + keyseg->start;
796
const unsigned char *key= (unsigned char*) record + keyseg->start;
925
798
switch (info->s->auto_key_type) {
926
case HA_KEYTYPE_INT8:
927
s_value= (int64_t) *(char*)key;
929
799
case HA_KEYTYPE_BINARY:
930
value=(uint64_t) *(uchar*) key;
932
case HA_KEYTYPE_SHORT_INT:
933
s_value= (int64_t) sint2korr(key);
935
case HA_KEYTYPE_USHORT_INT:
936
value=(uint64_t) uint2korr(key);
800
value=(uint64_t) *(unsigned char*) key;
938
802
case HA_KEYTYPE_LONG_INT:
939
803
s_value= (int64_t) sint4korr(key);
941
805
case HA_KEYTYPE_ULONG_INT:
942
806
value=(uint64_t) uint4korr(key);
944
case HA_KEYTYPE_INT24:
945
s_value= (int64_t) sint3korr(key);
947
808
case HA_KEYTYPE_UINT24:
948
809
value=(uint64_t) uint3korr(key);
950
case HA_KEYTYPE_FLOAT: /* This shouldn't be used */
954
/* Ignore negative values */
955
value = (f_1 < (float) 0.0) ? 0 : (uint64_t) f_1;
958
811
case HA_KEYTYPE_DOUBLE: /* This shouldn't be used */