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"
20
#include <mystrings/m_ctype.h>
21
21
#include <drizzled/util/test.h>
24
23
#include <string.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);
26
Find out how many rows there is in the given range
29
hp_rb_records_in_range()
32
min_key Min key. Is = 0 if no min range
33
max_key Max key. Is = 0 if no max range
36
min_key.flag can have one of the following values:
37
HA_READ_KEY_EXACT Include the key in the range
38
HA_READ_AFTER_KEY Don't include key in range
40
max_key.flag can have one of the following values:
41
HA_READ_BEFORE_KEY Don't include key in range
42
HA_READ_AFTER_KEY Include all 'end_key' values in the range
45
HA_POS_ERROR Something is wrong with the index tree.
46
0 There is no matching keys in the given range
47
number > 0 There is approximately 'number' matching rows in
51
ha_rows hp_rb_records_in_range(HP_INFO *info, int inx, key_range *min_key,
54
ha_rows start_pos, end_pos;
55
HP_KEYDEF *keyinfo= info->s->keydef + inx;
56
TREE *rb_tree = &keyinfo->rb_tree;
57
heap_rb_param custom_arg;
60
custom_arg.keyseg= keyinfo->seg;
61
custom_arg.search_flag= SEARCH_FIND | SEARCH_SAME;
64
custom_arg.key_length= hp_rb_pack_key(keyinfo, (unsigned char*) info->recbuf,
65
(unsigned char*) min_key->key,
66
min_key->keypart_map);
67
start_pos= tree_record_pos(rb_tree, info->recbuf, min_key->flag,
77
custom_arg.key_length= hp_rb_pack_key(keyinfo, (unsigned char*) info->recbuf,
78
(unsigned char*) max_key->key,
79
max_key->keypart_map);
80
end_pos= tree_record_pos(rb_tree, info->recbuf, max_key->flag,
85
end_pos= rb_tree->elements_in_tree + (ha_rows)1;
88
if (start_pos == HA_POS_ERROR || end_pos == HA_POS_ERROR)
90
return(end_pos < start_pos ? (ha_rows) 0 :
91
(end_pos == start_pos ? (ha_rows) 1 : end_pos - start_pos));
35
95
/* Search after a record based on a key */
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++)
293
472
Compare keys for two records. Returns 0 if they are identical
511
690
set_if_smaller(char_length,length); \
694
uint32_t hp_rb_make_key(HP_KEYDEF *keydef, unsigned char *key,
695
const unsigned char *rec, unsigned char *recpos)
697
unsigned char *start_key= key;
698
HA_KEYSEG *seg, *endseg;
700
for (seg= keydef->seg, endseg= seg + keydef->keysegs; seg < endseg; seg++)
702
uint32_t char_length;
705
if (!(*key++= 1 - test(rec[seg->null_pos] & seg->null_bit)))
708
if (seg->flag & HA_SWAP_KEY)
710
uint32_t length= seg->length;
711
unsigned char *pos= (unsigned char*) rec + seg->start;
714
if (seg->type == HA_KEYTYPE_FLOAT)
720
/* Replace NAN with zero */
721
memset(key, 0, length);
726
else if (seg->type == HA_KEYTYPE_DOUBLE)
732
memset(key, 0, length);
746
if (seg->flag & HA_VAR_LENGTH_PART)
748
unsigned char *pos= (unsigned char*) rec + seg->start;
749
uint32_t length= seg->length;
750
uint32_t pack_length= seg->bit_start;
751
uint32_t tmp_length= (pack_length == 1 ? (uint) *(unsigned char*) pos :
753
const CHARSET_INFO * const cs= seg->charset;
754
char_length= length/cs->mbmaxlen;
756
pos+= pack_length; /* Skip VARCHAR length */
757
set_if_smaller(length,tmp_length);
758
FIX_LENGTH(cs, pos, length, char_length);
759
store_key_length_inc(key,char_length);
760
memcpy(key,pos,(size_t) char_length);
765
char_length= seg->length;
766
if (seg->charset->mbmaxlen > 1)
768
char_length= my_charpos(seg->charset,
769
rec + seg->start, rec + seg->start + char_length,
770
char_length / seg->charset->mbmaxlen);
771
set_if_smaller(char_length, (uint32_t)seg->length); /* QQ: ok to remove? */
772
if (char_length < seg->length)
773
seg->charset->cset->fill(seg->charset, (char*) key + char_length,
774
seg->length - char_length, ' ');
776
memcpy(key, rec + seg->start, (size_t) char_length);
779
memcpy(key, &recpos, sizeof(unsigned char*));
780
return (uint32_t) (key - start_key);
784
uint32_t hp_rb_pack_key(HP_KEYDEF *keydef, unsigned char *key, const unsigned char *old,
785
key_part_map keypart_map)
787
HA_KEYSEG *seg, *endseg;
788
unsigned char *start_key= key;
790
for (seg= keydef->seg, endseg= seg + keydef->keysegs;
791
seg < endseg && keypart_map; old+= seg->length, seg++)
793
uint32_t char_length;
797
if (!(*key++= (char) 1 - *old++))
800
if (seg->flag & HA_SWAP_KEY)
802
uint32_t length= seg->length;
803
unsigned char *pos= (unsigned char*) old + length;
811
if (seg->flag & (HA_VAR_LENGTH_PART | HA_BLOB_PART))
813
/* Length of key-part used with heap_rkey() always 2 */
814
uint32_t tmp_length=uint2korr(old);
815
uint32_t length= seg->length;
816
const CHARSET_INFO * const cs= seg->charset;
817
char_length= length/cs->mbmaxlen;
820
set_if_smaller(length,tmp_length); /* Safety */
821
FIX_LENGTH(cs, old, length, char_length);
822
store_key_length_inc(key,char_length);
823
memcpy(key, old,(size_t) char_length);
827
char_length= seg->length;
828
if (seg->charset->mbmaxlen > 1)
830
char_length= my_charpos(seg->charset, old, old+char_length,
831
char_length / seg->charset->mbmaxlen);
832
set_if_smaller(char_length, (uint32_t)seg->length); /* QQ: ok to remove? */
833
if (char_length < seg->length)
834
seg->charset->cset->fill(seg->charset, (char*) key + char_length,
835
seg->length - char_length, ' ');
837
memcpy(key, old, (size_t) char_length);
840
return (uint) (key - start_key);
844
uint32_t hp_rb_key_length(HP_KEYDEF *keydef, const unsigned char *not_used)
847
return keydef->length;
851
uint32_t hp_rb_null_key_length(HP_KEYDEF *keydef, const unsigned char *key)
853
const unsigned char *start_key= key;
854
HA_KEYSEG *seg, *endseg;
856
for (seg= keydef->seg, endseg= seg + keydef->keysegs; seg < endseg; seg++)
858
if (seg->null_bit && !*key++)
862
return (uint) (key - start_key);
866
uint32_t hp_rb_var_key_length(HP_KEYDEF *keydef, const unsigned char *key)
868
const unsigned char *start_key= key;
869
HA_KEYSEG *seg, *endseg;
871
for (seg= keydef->seg, endseg= seg + keydef->keysegs; seg < endseg; seg++)
873
uint32_t length= seg->length;
874
if (seg->null_bit && !*key++)
876
if (seg->flag & (HA_VAR_LENGTH_PART | HA_BLOB_PART))
878
get_key_length(length, key);
882
return (uint) (key - start_key);
515
887
Test if any of the key parts are NULL.
549
921
uint64_t value= 0; /* Store unsigned values here */
550
922
int64_t s_value= 0; /* Store signed values here */
552
HA_KEYSEG *keyseg= info->getShare()->keydef[info->getShare()->auto_key - 1].seg;
924
HA_KEYSEG *keyseg= info->s->keydef[info->s->auto_key - 1].seg;
553
925
const unsigned char *key= (unsigned char*) record + keyseg->start;
555
switch (info->getShare()->auto_key_type) {
927
switch (info->s->auto_key_type) {
928
case HA_KEYTYPE_INT8:
929
s_value= (int64_t) *(char*)key;
556
931
case HA_KEYTYPE_BINARY:
557
932
value=(uint64_t) *(unsigned char*) key;
934
case HA_KEYTYPE_SHORT_INT:
935
s_value= (int64_t) sint2korr(key);
937
case HA_KEYTYPE_USHORT_INT:
938
value=(uint64_t) uint2korr(key);
559
940
case HA_KEYTYPE_LONG_INT:
560
941
s_value= (int64_t) sint4korr(key);
562
943
case HA_KEYTYPE_ULONG_INT:
563
944
value=(uint64_t) uint4korr(key);
946
case HA_KEYTYPE_INT24:
947
s_value= (int64_t) sint3korr(key);
949
case HA_KEYTYPE_UINT24:
950
value=(uint64_t) uint3korr(key);
952
case HA_KEYTYPE_FLOAT: /* This shouldn't be used */
956
/* Ignore negative values */
957
value = (f_1 < (float) 0.0) ? 0 : (uint64_t) f_1;
565
960
case HA_KEYTYPE_DOUBLE: /* This shouldn't be used */