12
12
You should have received a copy of the GNU General Public License
13
13
along with this program; if not, write to the Free Software
14
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
16
16
/* The hash functions used for saveing keys */
18
#include "heap_priv.h"
20
#include "drizzled/charset_info.h"
21
#include <drizzled/util/test.h>
28
using namespace drizzled;
31
static uint32_t hp_hashnr(register HP_KEYDEF *keydef, register const unsigned char *key);
32
static int hp_key_cmp(HP_KEYDEF *keydef, const unsigned char *rec, const unsigned char *key);
24
Find out how many rows there is in the given range
27
hp_rb_records_in_range()
30
min_key Min key. Is = 0 if no min range
31
max_key Max key. Is = 0 if no max range
34
min_key.flag can have one of the following values:
35
HA_READ_KEY_EXACT Include the key in the range
36
HA_READ_AFTER_KEY Don't include key in range
38
max_key.flag can have one of the following values:
39
HA_READ_BEFORE_KEY Don't include key in range
40
HA_READ_AFTER_KEY Include all 'end_key' values in the range
43
HA_POS_ERROR Something is wrong with the index tree.
44
0 There is no matching keys in the given range
45
number > 0 There is approximately 'number' matching rows in
49
ha_rows hp_rb_records_in_range(HP_INFO *info, int inx, key_range *min_key,
52
ha_rows start_pos, end_pos;
53
HP_KEYDEF *keyinfo= info->s->keydef + inx;
54
TREE *rb_tree = &keyinfo->rb_tree;
55
heap_rb_param custom_arg;
56
DBUG_ENTER("hp_rb_records_in_range");
59
custom_arg.keyseg= keyinfo->seg;
60
custom_arg.search_flag= SEARCH_FIND | SEARCH_SAME;
63
custom_arg.key_length= hp_rb_pack_key(keyinfo, (uchar*) info->recbuf,
64
(uchar*) min_key->key,
65
min_key->keypart_map);
66
start_pos= tree_record_pos(rb_tree, info->recbuf, min_key->flag,
76
custom_arg.key_length= hp_rb_pack_key(keyinfo, (uchar*) info->recbuf,
77
(uchar*) max_key->key,
78
max_key->keypart_map);
79
end_pos= tree_record_pos(rb_tree, info->recbuf, max_key->flag,
84
end_pos= rb_tree->elements_in_tree + (ha_rows)1;
87
DBUG_PRINT("info",("start_pos: %lu end_pos: %lu", (ulong) start_pos,
89
if (start_pos == HA_POS_ERROR || end_pos == HA_POS_ERROR)
90
DBUG_RETURN(HA_POS_ERROR);
91
DBUG_RETURN(end_pos < start_pos ? (ha_rows) 0 :
92
(end_pos == start_pos ? (ha_rows) 1 : end_pos - start_pos));
35
96
/* Search after a record based on a key */
36
97
/* Sets info->current_ptr to found record */
37
98
/* next_flag: Search=0, next=1, prev =2, same =3 */
39
unsigned char *hp_search(HP_INFO *info, HP_KEYDEF *keyinfo, const unsigned char *key,
100
uchar *hp_search(HP_INFO *info, HP_KEYDEF *keyinfo, const uchar *key,
42
103
register HASH_INFO *pos,*prev_ptr;
44
uint32_t old_nextflag;
45
HP_SHARE *share=info->getShare();
106
HP_SHARE *share=info->s;
107
DBUG_ENTER("hp_search");
46
108
old_nextflag=nextflag;
92
155
while ((pos=pos->next_key));
94
errno=HA_ERR_KEY_NOT_FOUND;
157
my_errno=HA_ERR_KEY_NOT_FOUND;
95
158
if (nextflag == 2 && ! info->current_ptr)
97
160
/* Do a previous from end */
98
161
info->current_hash_ptr=prev_ptr;
99
return(info->current_ptr=prev_ptr ? prev_ptr->ptr_to_rec : 0);
162
DBUG_RETURN(info->current_ptr=prev_ptr ? prev_ptr->ptr_to_rec : 0);
102
165
if (old_nextflag && nextflag)
103
errno=HA_ERR_RECORD_CHANGED; /* Didn't find old record */
104
info->current_hash_ptr=0;
105
return((info->current_ptr= 0));
166
my_errno=HA_ERR_RECORD_CHANGED; /* Didn't find old record */
167
DBUG_PRINT("exit",("Error: %d",my_errno));
168
info->current_hash_ptr=0;
169
DBUG_RETURN((info->current_ptr= 0));
111
175
since last read !
114
unsigned char *hp_search_next(HP_INFO *info, HP_KEYDEF *keyinfo, const unsigned char *key,
178
uchar *hp_search_next(HP_INFO *info, HP_KEYDEF *keyinfo, const uchar *key,
181
DBUG_ENTER("hp_search_next");
117
183
while ((pos= pos->next_key))
119
185
if (! hp_key_cmp(keyinfo, pos->ptr_to_rec, key))
121
187
info->current_hash_ptr=pos;
122
return (info->current_ptr= pos->ptr_to_rec);
188
DBUG_RETURN (info->current_ptr= pos->ptr_to_rec);
125
errno=HA_ERR_KEY_NOT_FOUND;
191
my_errno=HA_ERR_KEY_NOT_FOUND;
192
DBUG_PRINT("exit",("Error: %d",my_errno));
126
193
info->current_hash_ptr=0;
127
return ((info->current_ptr= 0));
194
DBUG_RETURN ((info->current_ptr= 0));
253
323
if (seg->type == HA_KEYTYPE_TEXT)
255
const CHARSET_INFO * const cs= seg->charset;
256
uint32_t char_length= seg->length;
325
CHARSET_INFO *cs= seg->charset;
326
uint char_length= seg->length;
257
327
if (cs->mbmaxlen > 1)
259
329
char_length= my_charpos(cs, pos, pos + char_length,
260
330
char_length / cs->mbmaxlen);
261
set_if_smaller(char_length, (uint32_t)seg->length); /* QQ: ok to remove? */
331
set_if_smaller(char_length, seg->length); /* QQ: ok to remove? */
263
333
cs->coll->hash_sort(cs, pos, char_length, &nr, &nr2);
265
335
else if (seg->type == HA_KEYTYPE_VARTEXT1) /* Any VARCHAR segments */
267
const CHARSET_INFO * const cs= seg->charset;
268
uint32_t pack_length= seg->bit_start;
269
uint32_t length= (pack_length == 1 ? (uint) *(unsigned char*) pos : uint2korr(pos));
337
CHARSET_INFO *cs= seg->charset;
338
uint pack_length= seg->bit_start;
339
uint length= (pack_length == 1 ? (uint) *(uchar*) pos : uint2korr(pos));
270
340
if (cs->mbmaxlen > 1)
272
uint32_t char_length;
273
343
char_length= my_charpos(cs, pos + pack_length,
274
344
pos + pack_length + length,
275
345
seg->length/cs->mbmaxlen);
282
352
for (; pos < end ; pos++)
284
nr^=(uint32_t) ((((uint) nr & 63)+nr2)*((uint) *pos))+ (nr << 8);
354
nr^=(ulong) ((((uint) nr & 63)+nr2)*((uint) *pos))+ (nr << 8);
359
DBUG_PRINT("exit", ("hash: 0x%lx", nr));
366
* Fowler/Noll/Vo hash
368
* The basis of the hash algorithm was taken from an idea sent by email to the
369
* IEEE Posix P1003.2 mailing list from Phong Vo (kpv@research.att.com) and
370
* Glenn Fowler (gsf@research.att.com). Landon Curt Noll (chongo@toad.com)
371
* later improved on their algorithm.
373
* The magic is in the interesting relationship between the special prime
374
* 16777619 (2^24 + 403) and 2^32 and 2^8.
376
* This hash produces the fewest collisions of any function that we've seen so
377
* far, and works well on both numbers and strings.
380
ulong hp_hashnr(register HP_KEYDEF *keydef, register const uchar *key)
383
Note, if a key consists of a combination of numeric and
384
a text columns, it most likely won't work well.
385
Making text columns work with NEW_HASH_FUNCTION
386
needs also changes in strings/ctype-xxx.c.
389
HA_KEYSEG *seg,*endseg;
391
for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
393
uchar *pos=(uchar*) key;
401
/* Add key pack length (2) to key for VARCHAR segments */
402
if (seg->type == HA_KEYTYPE_VARTEXT1)
408
if (seg->type == HA_KEYTYPE_TEXT)
410
seg->charset->coll->hash_sort(seg->charset, pos, ((uchar*)key)-pos,
413
else if (seg->type == HA_KEYTYPE_VARTEXT1) /* Any VARCHAR segments */
415
uint pack_length= 2; /* Key packing is constant */
416
uint length= uint2korr(pos);
417
seg->charset->coll->hash_sort(seg->charset, pos+pack_length, length,
423
for ( ; pos < (uchar*) key ; pos++)
430
DBUG_PRINT("exit", ("hash: 0x%lx", nr));
434
/* Calc hashvalue for a key in a record */
436
ulong hp_rec_hashnr(register HP_KEYDEF *keydef, register const uchar *rec)
439
HA_KEYSEG *seg,*endseg;
441
for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
443
uchar *pos=(uchar*) rec+seg->start;
446
if (rec[seg->null_pos] & seg->null_bit)
452
if (seg->type == HA_KEYTYPE_TEXT)
454
uint char_length= seg->length; /* TODO: fix to use my_charpos() */
455
seg->charset->coll->hash_sort(seg->charset, pos, char_length,
458
else if (seg->type == HA_KEYTYPE_VARTEXT1) /* Any VARCHAR segments */
460
uint pack_length= seg->bit_start;
461
uint length= (pack_length == 1 ? (uint) *(uchar*) pos : uint2korr(pos));
462
seg->charset->coll->hash_sort(seg->charset, pos+pack_length,
467
uchar *end= pos+seg->length;
468
for ( ; pos < end ; pos++)
475
DBUG_PRINT("exit", ("hash: 0x%lx", nr));
293
483
Compare keys for two records. Returns 0 if they are identical
327
517
if (seg->type == HA_KEYTYPE_TEXT)
329
const CHARSET_INFO * const cs= seg->charset;
330
uint32_t char_length1;
331
uint32_t char_length2;
332
unsigned char *pos1= (unsigned char*)rec1 + seg->start;
333
unsigned char *pos2= (unsigned char*)rec2 + seg->start;
519
CHARSET_INFO *cs= seg->charset;
522
uchar *pos1= (uchar*)rec1 + seg->start;
523
uchar *pos2= (uchar*)rec2 + seg->start;
334
524
if (cs->mbmaxlen > 1)
336
uint32_t char_length= seg->length / cs->mbmaxlen;
526
uint char_length= seg->length / cs->mbmaxlen;
337
527
char_length1= my_charpos(cs, pos1, pos1 + seg->length, char_length);
338
set_if_smaller(char_length1, (uint32_t)seg->length);
528
set_if_smaller(char_length1, seg->length);
339
529
char_length2= my_charpos(cs, pos2, pos2 + seg->length, char_length);
340
set_if_smaller(char_length2, (uint32_t)seg->length);
530
set_if_smaller(char_length2, seg->length);
420
610
if (seg->type == HA_KEYTYPE_TEXT)
422
const CHARSET_INFO * const cs= seg->charset;
423
uint32_t char_length_key;
424
uint32_t char_length_rec;
425
unsigned char *pos= (unsigned char*) rec + seg->start;
612
CHARSET_INFO *cs= seg->charset;
613
uint char_length_key;
614
uint char_length_rec;
615
uchar *pos= (uchar*) rec + seg->start;
426
616
if (cs->mbmaxlen > 1)
428
uint32_t char_length= seg->length / cs->mbmaxlen;
618
uint char_length= seg->length / cs->mbmaxlen;
429
619
char_length_key= my_charpos(cs, key, key + seg->length, char_length);
430
set_if_smaller(char_length_key, (uint32_t)seg->length);
620
set_if_smaller(char_length_key, seg->length);
431
621
char_length_rec= my_charpos(cs, pos, pos + seg->length, char_length);
432
set_if_smaller(char_length_rec, (uint32_t)seg->length);
622
set_if_smaller(char_length_rec, seg->length);
436
626
char_length_key= seg->length;
437
627
char_length_rec= seg->length;
440
630
if (seg->charset->coll->strnncollsp(seg->charset,
441
(unsigned char*) pos, char_length_rec,
442
(unsigned char*) key, char_length_key, 0))
631
(uchar*) pos, char_length_rec,
632
(uchar*) key, char_length_key, 0))
445
635
else if (seg->type == HA_KEYTYPE_VARTEXT1) /* Any VARCHAR segments */
447
unsigned char *pos= (unsigned char*) rec + seg->start;
448
const CHARSET_INFO * const cs= seg->charset;
449
uint32_t pack_length= seg->bit_start;
450
uint32_t char_length_rec= (pack_length == 1 ? (uint) *(unsigned char*) pos :
637
uchar *pos= (uchar*) rec + seg->start;
638
CHARSET_INFO *cs= seg->charset;
639
uint pack_length= seg->bit_start;
640
uint char_length_rec= (pack_length == 1 ? (uint) *(uchar*) pos :
452
642
/* Key segments are always packed with 2 bytes */
453
uint32_t char_length_key= uint2korr(key);
643
uint char_length_key= uint2korr(key);
454
644
pos+= pack_length;
455
645
key+= 2; /* skip key pack length */
456
646
if (cs->mbmaxlen > 1)
458
uint32_t char_length1, char_length2;
459
char_length1= char_length2= seg->length / cs->mbmaxlen;
648
uint char_length1, char_length2;
649
char_length1= char_length2= seg->length / cs->mbmaxlen;
460
650
char_length1= my_charpos(cs, key, key + char_length_key, char_length1);
461
651
set_if_smaller(char_length_key, char_length1);
462
652
char_length2= my_charpos(cs, pos, pos + char_length_rec, char_length2);
481
671
/* Copy a key from a record to a keybuffer */
483
void hp_make_key(HP_KEYDEF *keydef, unsigned char *key, const unsigned char *rec)
673
void hp_make_key(HP_KEYDEF *keydef, uchar *key, const uchar *rec)
485
675
HA_KEYSEG *seg,*endseg;
487
677
for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
489
const CHARSET_INFO * const cs= seg->charset;
490
uint32_t char_length= seg->length;
491
unsigned char *pos= (unsigned char*) rec + seg->start;
679
CHARSET_INFO *cs= seg->charset;
680
uint char_length= seg->length;
681
uchar *pos= (uchar*) rec + seg->start;
492
682
if (seg->null_bit)
493
683
*key++= test(rec[seg->null_pos] & seg->null_bit);
494
684
if (cs->mbmaxlen > 1)
496
686
char_length= my_charpos(cs, pos, pos + seg->length,
497
687
char_length / cs->mbmaxlen);
498
set_if_smaller(char_length, (uint32_t)seg->length); /* QQ: ok to remove? */
688
set_if_smaller(char_length, seg->length); /* QQ: ok to remove? */
500
690
if (seg->type == HA_KEYTYPE_VARTEXT1)
501
691
char_length+= seg->bit_start; /* Copy also length */
511
701
set_if_smaller(char_length,length); \
705
uint hp_rb_make_key(HP_KEYDEF *keydef, uchar *key,
706
const uchar *rec, uchar *recpos)
708
uchar *start_key= key;
709
HA_KEYSEG *seg, *endseg;
711
for (seg= keydef->seg, endseg= seg + keydef->keysegs; seg < endseg; seg++)
716
if (!(*key++= 1 - test(rec[seg->null_pos] & seg->null_bit)))
719
if (seg->flag & HA_SWAP_KEY)
721
uint length= seg->length;
722
uchar *pos= (uchar*) rec + seg->start;
725
if (seg->type == HA_KEYTYPE_FLOAT)
731
/* Replace NAN with zero */
737
else if (seg->type == HA_KEYTYPE_DOUBLE)
757
if (seg->flag & HA_VAR_LENGTH_PART)
759
uchar *pos= (uchar*) rec + seg->start;
760
uint length= seg->length;
761
uint pack_length= seg->bit_start;
762
uint tmp_length= (pack_length == 1 ? (uint) *(uchar*) pos :
764
CHARSET_INFO *cs= seg->charset;
765
char_length= length/cs->mbmaxlen;
767
pos+= pack_length; /* Skip VARCHAR length */
768
set_if_smaller(length,tmp_length);
769
FIX_LENGTH(cs, pos, length, char_length);
770
store_key_length_inc(key,char_length);
771
memcpy((uchar*) key,(uchar*) pos,(size_t) char_length);
776
char_length= seg->length;
777
if (seg->charset->mbmaxlen > 1)
779
char_length= my_charpos(seg->charset,
780
rec + seg->start, rec + seg->start + char_length,
781
char_length / seg->charset->mbmaxlen);
782
set_if_smaller(char_length, seg->length); /* QQ: ok to remove? */
783
if (char_length < seg->length)
784
seg->charset->cset->fill(seg->charset, (char*) key + char_length,
785
seg->length - char_length, ' ');
787
memcpy(key, rec + seg->start, (size_t) char_length);
790
memcpy(key, &recpos, sizeof(uchar*));
791
return (uint) (key - start_key);
795
uint hp_rb_pack_key(HP_KEYDEF *keydef, uchar *key, const uchar *old,
796
key_part_map keypart_map)
798
HA_KEYSEG *seg, *endseg;
799
uchar *start_key= key;
801
for (seg= keydef->seg, endseg= seg + keydef->keysegs;
802
seg < endseg && keypart_map; old+= seg->length, seg++)
808
if (!(*key++= (char) 1 - *old++))
811
if (seg->flag & HA_SWAP_KEY)
813
uint length= seg->length;
814
uchar *pos= (uchar*) old + length;
822
if (seg->flag & (HA_VAR_LENGTH_PART | HA_BLOB_PART))
824
/* Length of key-part used with heap_rkey() always 2 */
825
uint tmp_length=uint2korr(old);
826
uint length= seg->length;
827
CHARSET_INFO *cs= seg->charset;
828
char_length= length/cs->mbmaxlen;
831
set_if_smaller(length,tmp_length); /* Safety */
832
FIX_LENGTH(cs, old, length, char_length);
833
store_key_length_inc(key,char_length);
834
memcpy((uchar*) key, old,(size_t) char_length);
838
char_length= seg->length;
839
if (seg->charset->mbmaxlen > 1)
841
char_length= my_charpos(seg->charset, old, old+char_length,
842
char_length / seg->charset->mbmaxlen);
843
set_if_smaller(char_length, seg->length); /* QQ: ok to remove? */
844
if (char_length < seg->length)
845
seg->charset->cset->fill(seg->charset, (char*) key + char_length,
846
seg->length - char_length, ' ');
848
memcpy(key, old, (size_t) char_length);
851
return (uint) (key - start_key);
855
uint hp_rb_key_length(HP_KEYDEF *keydef,
856
const uchar *key __attribute__((unused)))
858
return keydef->length;
862
uint hp_rb_null_key_length(HP_KEYDEF *keydef, const uchar *key)
864
const uchar *start_key= key;
865
HA_KEYSEG *seg, *endseg;
867
for (seg= keydef->seg, endseg= seg + keydef->keysegs; seg < endseg; seg++)
869
if (seg->null_bit && !*key++)
873
return (uint) (key - start_key);
877
uint hp_rb_var_key_length(HP_KEYDEF *keydef, const uchar *key)
879
const uchar *start_key= key;
880
HA_KEYSEG *seg, *endseg;
882
for (seg= keydef->seg, endseg= seg + keydef->keysegs; seg < endseg; seg++)
884
uint length= seg->length;
885
if (seg->null_bit && !*key++)
887
if (seg->flag & (HA_VAR_LENGTH_PART | HA_BLOB_PART))
889
get_key_length(length, key);
893
return (uint) (key - start_key);
515
898
Test if any of the key parts are NULL.
547
void heap_update_auto_increment(HP_INFO *info, const unsigned char *record)
930
void heap_update_auto_increment(HP_INFO *info, const uchar *record)
549
uint64_t value= 0; /* Store unsigned values here */
550
int64_t s_value= 0; /* Store signed values here */
552
HA_KEYSEG *keyseg= info->getShare()->keydef[info->getShare()->auto_key - 1].seg;
553
const unsigned char *key= (unsigned char*) record + keyseg->start;
555
switch (info->getShare()->auto_key_type) {
932
ulonglong value= 0; /* Store unsigned values here */
933
longlong s_value= 0; /* Store signed values here */
935
HA_KEYSEG *keyseg= info->s->keydef[info->s->auto_key - 1].seg;
936
const uchar *key= (uchar*) record + keyseg->start;
938
switch (info->s->auto_key_type) {
939
case HA_KEYTYPE_INT8:
940
s_value= (longlong) *(char*)key;
556
942
case HA_KEYTYPE_BINARY:
557
value=(uint64_t) *(unsigned char*) key;
943
value=(ulonglong) *(uchar*) key;
945
case HA_KEYTYPE_SHORT_INT:
946
s_value= (longlong) sint2korr(key);
948
case HA_KEYTYPE_USHORT_INT:
949
value=(ulonglong) uint2korr(key);
559
951
case HA_KEYTYPE_LONG_INT:
560
s_value= (int64_t) sint4korr(key);
952
s_value= (longlong) sint4korr(key);
562
954
case HA_KEYTYPE_ULONG_INT:
563
value=(uint64_t) uint4korr(key);
955
value=(ulonglong) uint4korr(key);
957
case HA_KEYTYPE_INT24:
958
s_value= (longlong) sint3korr(key);
960
case HA_KEYTYPE_UINT24:
961
value=(ulonglong) uint3korr(key);
963
case HA_KEYTYPE_FLOAT: /* This shouldn't be used */
967
/* Ignore negative values */
968
value = (f_1 < (float) 0.0) ? 0 : (ulonglong) f_1;
565
971
case HA_KEYTYPE_DOUBLE: /* This shouldn't be used */
568
974
float8get(f_1,key);
569
975
/* Ignore negative values */
570
value = (f_1 < 0.0) ? 0 : (uint64_t) f_1;
976
value = (f_1 < 0.0) ? 0 : (ulonglong) f_1;
573
979
case HA_KEYTYPE_LONGLONG: