~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/heap/hp_hash.cc

  • Committer: Jay Pipes
  • Date: 2010-03-09 20:02:29 UTC
  • mto: This revision was merged to the branch mainline in revision 1339.
  • Revision ID: jpipes@serialcoder-20100309200229-dfrliy4fads9vyf4
Fixes Bug #535296 by only incrementing ha_commit_count when its a normal transaction commit.

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