~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/heap/hp_hash.cc

  • Committer: Monty Taylor
  • Date: 2010-01-12 21:34:24 UTC
  • mto: This revision was merged to the branch mainline in revision 1268.
  • Revision ID: mordred@inaugust.com-20100112213424-6mslywtlca49mvnk
Updated to pandora-buld v0.94

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