~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/heap/hp_hash.cc

  • Committer: Stewart Smith
  • Date: 2010-08-12 16:48:46 UTC
  • mto: This revision was merged to the branch mainline in revision 1707.
  • Revision ID: stewart@flamingspork.com-20100812164846-s9bhy47g60bvqs41
bug lp:611379 Equivalent queries with Impossible where return different results

The following two equivalent queries return different results in maria 5.2 and 5.3 (and identical results in mysql 5.5.5) :

SELECT SUM( DISTINCT table1 .`pk` ) FROM B table1 STRAIGHT_JOIN ( BB table2 JOIN CC ON table2 .`col_varchar_key` ) ON table2 .`pk` ;

SELECT * FROM ( SELECT SUM( DISTINCT table1 .`pk` ) FROM B table1 STRAIGHT_JOIN ( BB table2 JOIN CC ON table2 .`col_varchar_key` ) ON table2 .`pk` );

MariaDB returns 0 on the second query and NULL on the first, whereas MySQL returns NULL on both. In MariaDB, both EXPLAIN plans agree that "Impossible WHERE noticed after reading const tables"



We have some slightly different output in drizzle:

main.bug_lp611379 [ fail ]
drizzletest: At line 9: query 'explain select * from (select sum(distinct t1.a) from t1,t2 where t1.a=t2.a)
as t' failed: 1048: Column 'sum(distinct t1.a)' cannot be null

but the fix gets us the correct query results, although with slightly different execution plans.



This fix is directly ported from MariaDB.

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
 
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
}