~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/heap/hp_hash.cc

Merge in Stewart's FK work

Show diffs side-by-side

added added

removed removed

Lines of Context:
11
11
 
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 */
15
15
 
16
16
/* The hash functions used for saveing keys */
17
17
 
18
18
#include "heap_priv.h"
19
19
 
20
 
#include <drizzled/charset_info.h>
 
20
#include "drizzled/charset_info.h"
21
21
#include <drizzled/util/test.h>
22
22
 
23
23
#include <math.h>
31
31
static uint32_t hp_hashnr(register HP_KEYDEF *keydef, register const unsigned char *key);
32
32
static int hp_key_cmp(HP_KEYDEF *keydef, const unsigned char *rec, const unsigned char *key);
33
33
 
 
34
/*
 
35
  Find out how many rows there is in the given range
 
36
 
 
37
  SYNOPSIS
 
38
    hp_rb_records_in_range()
 
39
    info                HEAP handler
 
40
    inx                 Index to use
 
41
    min_key             Min key. Is = 0 if no min range
 
42
    max_key             Max key. Is = 0 if no max range
 
43
 
 
44
  NOTES
 
45
    min_key.flag can have one of the following values:
 
46
      HA_READ_KEY_EXACT         Include the key in the range
 
47
      HA_READ_AFTER_KEY         Don't include key in range
 
48
 
 
49
    max_key.flag can have one of the following values:
 
50
      HA_READ_BEFORE_KEY        Don't include key in range
 
51
      HA_READ_AFTER_KEY         Include all 'end_key' values in the range
 
52
 
 
53
  RETURN
 
54
   HA_POS_ERROR         Something is wrong with the index tree.
 
55
   0                    There is no matching keys in the given range
 
56
   number > 0           There is approximately 'number' matching rows in
 
57
                        the range.
 
58
*/
 
59
 
 
60
ha_rows hp_rb_records_in_range(HP_INFO *info, int inx,  key_range *min_key,
 
61
                               key_range *max_key)
 
62
{
 
63
  ha_rows start_pos, end_pos;
 
64
  HP_KEYDEF *keyinfo= info->s->keydef + inx;
 
65
  TREE *rb_tree = &keyinfo->rb_tree;
 
66
  heap_rb_param custom_arg;
 
67
 
 
68
  info->lastinx= inx;
 
69
  custom_arg.keyseg= keyinfo->seg;
 
70
  custom_arg.search_flag= SEARCH_FIND | SEARCH_SAME;
 
71
  if (min_key)
 
72
  {
 
73
    custom_arg.key_length= hp_rb_pack_key(keyinfo, (unsigned char*) info->recbuf,
 
74
                                          (unsigned char*) min_key->key,
 
75
                                          min_key->keypart_map);
 
76
    start_pos= tree_record_pos(rb_tree, info->recbuf, min_key->flag,
 
77
                               &custom_arg);
 
78
  }
 
79
  else
 
80
  {
 
81
    start_pos= 0;
 
82
  }
 
83
 
 
84
  if (max_key)
 
85
  {
 
86
    custom_arg.key_length= hp_rb_pack_key(keyinfo, (unsigned char*) info->recbuf,
 
87
                                          (unsigned char*) max_key->key,
 
88
                                          max_key->keypart_map);
 
89
    end_pos= tree_record_pos(rb_tree, info->recbuf, max_key->flag,
 
90
                             &custom_arg);
 
91
  }
 
92
  else
 
93
  {
 
94
    end_pos= rb_tree->elements_in_tree + (ha_rows)1;
 
95
  }
 
96
 
 
97
  if (start_pos == HA_POS_ERROR || end_pos == HA_POS_ERROR)
 
98
    return(HA_POS_ERROR);
 
99
  return(end_pos < start_pos ? (ha_rows) 0 :
 
100
              (end_pos == start_pos ? (ha_rows) 1 : end_pos - start_pos));
 
101
}
 
102
 
34
103
 
35
104
        /* Search after a record based on a key */
36
105
        /* Sets info->current_ptr to found record */
42
111
  register HASH_INFO *pos,*prev_ptr;
43
112
  int flag;
44
113
  uint32_t old_nextflag;
45
 
  HP_SHARE *share=info->getShare();
 
114
  HP_SHARE *share=info->s;
46
115
  old_nextflag=nextflag;
47
116
  flag=1;
48
117
  prev_ptr=0;
511
580
    set_if_smaller(char_length,length);                                 \
512
581
  } while(0)
513
582
 
 
583
 
 
584
uint32_t hp_rb_make_key(HP_KEYDEF *keydef, unsigned char *key,
 
585
                    const unsigned char *rec, unsigned char *recpos)
 
586
{
 
587
  unsigned char *start_key= key;
 
588
  HA_KEYSEG *seg, *endseg;
 
589
 
 
590
  for (seg= keydef->seg, endseg= seg + keydef->keysegs; seg < endseg; seg++)
 
591
  {
 
592
    uint32_t char_length;
 
593
    if (seg->null_bit)
 
594
    {
 
595
      if (!(*key++= 1 - test(rec[seg->null_pos] & seg->null_bit)))
 
596
        continue;
 
597
    }
 
598
    if (seg->flag & HA_SWAP_KEY)
 
599
    {
 
600
      uint32_t length= seg->length;
 
601
      unsigned char *pos= (unsigned char*) rec + seg->start;
 
602
 
 
603
      if (seg->type == HA_KEYTYPE_DOUBLE)
 
604
      {
 
605
        double nr;
 
606
        float8get(nr, pos);
 
607
        if (isnan(nr))
 
608
        {
 
609
          memset(key, 0, length);
 
610
          key+= length;
 
611
          continue;
 
612
        }
 
613
      }
 
614
      pos+= length;
 
615
      while (length--)
 
616
      {
 
617
        *key++= *--pos;
 
618
      }
 
619
      continue;
 
620
    }
 
621
 
 
622
    if (seg->flag & HA_VAR_LENGTH_PART)
 
623
    {
 
624
      unsigned char *pos=      (unsigned char*) rec + seg->start;
 
625
      uint32_t length=     seg->length;
 
626
      uint32_t pack_length= seg->bit_start;
 
627
      uint32_t tmp_length= (pack_length == 1 ? (uint) *(unsigned char*) pos :
 
628
                        uint2korr(pos));
 
629
      const CHARSET_INFO * const cs= seg->charset;
 
630
      char_length= length/cs->mbmaxlen;
 
631
 
 
632
      pos+= pack_length;                        /* Skip VARCHAR length */
 
633
      set_if_smaller(length,tmp_length);
 
634
      FIX_LENGTH(cs, pos, length, char_length);
 
635
      store_key_length_inc(key,char_length);
 
636
      memcpy(key,pos,(size_t) char_length);
 
637
      key+= char_length;
 
638
      continue;
 
639
    }
 
640
 
 
641
    char_length= seg->length;
 
642
    if (seg->charset->mbmaxlen > 1)
 
643
    {
 
644
      char_length= my_charpos(seg->charset,
 
645
                              rec + seg->start, rec + seg->start + char_length,
 
646
                              char_length / seg->charset->mbmaxlen);
 
647
      set_if_smaller(char_length, (uint32_t)seg->length); /* QQ: ok to remove? */
 
648
      if (char_length < seg->length)
 
649
        seg->charset->cset->fill(seg->charset, (char*) key + char_length,
 
650
                                 seg->length - char_length, ' ');
 
651
    }
 
652
    memcpy(key, rec + seg->start, (size_t) char_length);
 
653
    key+= seg->length;
 
654
  }
 
655
  memcpy(key, &recpos, sizeof(unsigned char*));
 
656
  return (uint32_t) (key - start_key);
 
657
}
 
658
 
 
659
 
 
660
uint32_t hp_rb_pack_key(HP_KEYDEF *keydef, unsigned char *key, const unsigned char *old,
 
661
                    key_part_map keypart_map)
 
662
{
 
663
  HA_KEYSEG *seg, *endseg;
 
664
  unsigned char *start_key= key;
 
665
 
 
666
  for (seg= keydef->seg, endseg= seg + keydef->keysegs;
 
667
       seg < endseg && keypart_map; old+= seg->length, seg++)
 
668
  {
 
669
    uint32_t char_length;
 
670
    keypart_map>>= 1;
 
671
    if (seg->null_bit)
 
672
    {
 
673
      if (!(*key++= (char) 1 - *old++))
 
674
        continue;
 
675
      }
 
676
    if (seg->flag & HA_SWAP_KEY)
 
677
    {
 
678
      uint32_t length= seg->length;
 
679
      unsigned char *pos= (unsigned char*) old + length;
 
680
 
 
681
      while (length--)
 
682
      {
 
683
        *key++= *--pos;
 
684
      }
 
685
      continue;
 
686
    }
 
687
    if (seg->flag & (HA_VAR_LENGTH_PART | HA_BLOB_PART))
 
688
    {
 
689
      /* Length of key-part used with heap_rkey() always 2 */
 
690
      uint32_t tmp_length=uint2korr(old);
 
691
      uint32_t length= seg->length;
 
692
      const CHARSET_INFO * const cs= seg->charset;
 
693
      char_length= length/cs->mbmaxlen;
 
694
 
 
695
      old+= 2;
 
696
      set_if_smaller(length,tmp_length);        /* Safety */
 
697
      FIX_LENGTH(cs, old, length, char_length);
 
698
      store_key_length_inc(key,char_length);
 
699
      memcpy(key, old,(size_t) char_length);
 
700
      key+= char_length;
 
701
      continue;
 
702
    }
 
703
    char_length= seg->length;
 
704
    if (seg->charset->mbmaxlen > 1)
 
705
    {
 
706
      char_length= my_charpos(seg->charset, old, old+char_length,
 
707
                              char_length / seg->charset->mbmaxlen);
 
708
      set_if_smaller(char_length, (uint32_t)seg->length); /* QQ: ok to remove? */
 
709
      if (char_length < seg->length)
 
710
        seg->charset->cset->fill(seg->charset, (char*) key + char_length,
 
711
                                 seg->length - char_length, ' ');
 
712
    }
 
713
    memcpy(key, old, (size_t) char_length);
 
714
    key+= seg->length;
 
715
  }
 
716
  return (uint) (key - start_key);
 
717
}
 
718
 
 
719
 
 
720
uint32_t hp_rb_key_length(HP_KEYDEF *keydef, const unsigned char *not_used)
 
721
{
 
722
  (void)not_used;
 
723
  return keydef->length;
 
724
}
 
725
 
 
726
 
 
727
uint32_t hp_rb_null_key_length(HP_KEYDEF *keydef, const unsigned char *key)
 
728
{
 
729
  const unsigned char *start_key= key;
 
730
  HA_KEYSEG *seg, *endseg;
 
731
 
 
732
  for (seg= keydef->seg, endseg= seg + keydef->keysegs; seg < endseg; seg++)
 
733
  {
 
734
    if (seg->null_bit && !*key++)
 
735
      continue;
 
736
    key+= seg->length;
 
737
  }
 
738
  return (uint) (key - start_key);
 
739
}
 
740
 
 
741
 
 
742
uint32_t hp_rb_var_key_length(HP_KEYDEF *keydef, const unsigned char *key)
 
743
{
 
744
  const unsigned char *start_key= key;
 
745
  HA_KEYSEG *seg, *endseg;
 
746
 
 
747
  for (seg= keydef->seg, endseg= seg + keydef->keysegs; seg < endseg; seg++)
 
748
  {
 
749
    uint32_t length= seg->length;
 
750
    if (seg->null_bit && !*key++)
 
751
      continue;
 
752
    if (seg->flag & (HA_VAR_LENGTH_PART | HA_BLOB_PART))
 
753
    {
 
754
      get_key_length(length, key);
 
755
    }
 
756
    key+= length;
 
757
  }
 
758
  return (uint) (key - start_key);
 
759
}
 
760
 
 
761
 
514
762
/*
515
763
  Test if any of the key parts are NULL.
516
764
  Return:
549
797
  uint64_t value= 0;                    /* Store unsigned values here */
550
798
  int64_t s_value= 0;                   /* Store signed values here */
551
799
 
552
 
  HA_KEYSEG *keyseg= info->getShare()->keydef[info->getShare()->auto_key - 1].seg;
 
800
  HA_KEYSEG *keyseg= info->s->keydef[info->s->auto_key - 1].seg;
553
801
  const unsigned char *key=  (unsigned char*) record + keyseg->start;
554
802
 
555
 
  switch (info->getShare()->auto_key_type) {
 
803
  switch (info->s->auto_key_type) {
556
804
  case HA_KEYTYPE_BINARY:
557
805
    value=(uint64_t)  *(unsigned char*) key;
558
806
    break;
562
810
  case HA_KEYTYPE_ULONG_INT:
563
811
    value=(uint64_t) uint4korr(key);
564
812
    break;
 
813
  case HA_KEYTYPE_UINT24:
 
814
    value=(uint64_t) uint3korr(key);
 
815
    break;
565
816
  case HA_KEYTYPE_DOUBLE:                       /* This shouldn't be used */
566
817
  {
567
818
    double f_1;
587
838
    and if s_value == 0 then value will contain either s_value or the
588
839
    correct value.
589
840
  */
590
 
  set_if_bigger(info->getShare()->auto_increment,
 
841
  set_if_bigger(info->s->auto_increment,
591
842
                (s_value > 0) ? (uint64_t) s_value : value);
592
843
}