~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/filesort.cc

  • Committer: Lee Bieber
  • Date: 2010-11-14 23:15:42 UTC
  • mfrom: (1929.1.42 warning-stack-frame)
  • Revision ID: kalebral@gmail.com-20101114231542-fnnu6ydd2p17n582
Merge Monty - fix bug 672372: some functions use > 32k stack

Show diffs side-by-side

added added

removed removed

Lines of Context:
28
28
 
29
29
#include <queue>
30
30
#include <algorithm>
31
 
#include <iostream>
32
31
 
33
32
#include "drizzled/drizzled.h"
34
33
#include "drizzled/sql_sort.h"
53
52
namespace drizzled
54
53
{
55
54
 
 
55
 
56
56
/* Defines used by filesort and uniques */
57
57
#define MERGEBUFF               7
58
58
#define MERGEBUFF2              15
381
381
      Use also the space previously used by string pointers in sort_buffer
382
382
      for temporary key storage.
383
383
    */
384
 
    param.keys=((param.keys*(param.rec_length+sizeof(char*))) / param.rec_length-1);
385
 
 
 
384
    param.keys=((param.keys*(param.rec_length+sizeof(char*))) /
 
385
                param.rec_length-1);
386
386
    maxbuffer--;                                // Offset from 0
387
387
    if (merge_many_buff(&param,(unsigned char*) sort_keys,buffpek_inst,&maxbuffer, &tempfile))
388
388
    {
418
418
 
419
419
  tempfile.close_cached_file();
420
420
  buffpek_pointers.close_cached_file();
421
 
 
422
421
  if (my_b_inited(outfile))
423
422
  {
424
423
    if (flush_io_cache(outfile))
426
425
      error=1;
427
426
    }
428
427
    {
429
 
      internal::my_off_t save_pos= outfile->pos_in_file;
 
428
      internal::my_off_t save_pos=outfile->pos_in_file;
430
429
      /* For following reads */
431
430
      if (outfile->reinit_io_cache(internal::READ_CACHE,0L,0,0))
432
431
      {
435
434
      outfile->end_of_file=save_pos;
436
435
    }
437
436
  }
438
 
 
439
437
  if (error)
440
438
  {
441
439
    my_message(ER_FILSORT_ABORT, ER(ER_FILSORT_ABORT),
564
562
  if (! indexfile && ! quick_select)
565
563
  {
566
564
    next_pos=(unsigned char*) 0;                        /* Find records in sequence */
567
 
    if (file->startTableScan(1))
568
 
      return(HA_POS_ERROR);
 
565
    file->startTableScan(1);
569
566
    file->extra_opt(HA_EXTRA_CACHE, getSession().variables.read_buff_size);
570
567
  }
571
568
 
575
572
    if (select->quick->reset())
576
573
      return(HA_POS_ERROR);
577
574
 
578
 
    if (read_record_info.init_read_record(&getSession(), select->quick->head, select, 1, 1))
579
 
      return(HA_POS_ERROR);
 
575
    read_record_info.init_read_record(&getSession(), select->quick->head, select, 1, 1);
580
576
  }
581
577
 
582
578
  /* Remember original bitmaps */
687
683
    sort_form->print_error(error,MYF(ME_ERROR | ME_WAITTANG));
688
684
    return(HA_POS_ERROR);
689
685
  }
690
 
 
691
 
  if (indexpos && idx && param->write_keys(sort_keys,idx,buffpek_pointers,tempfile))
692
 
  {
 
686
  if (indexpos && idx &&
 
687
      param->write_keys(sort_keys,idx,buffpek_pointers,tempfile))
693
688
    return(HA_POS_ERROR);
694
 
  }
695
 
 
696
689
  return(my_b_inited(tempfile) ?
697
690
              (ha_rows) (my_b_tell(tempfile)/param->rec_length) :
698
691
              idx);
819
812
    {                                           // Item
820
813
      Item *item=sort_field->item;
821
814
      maybe_null= item->maybe_null;
822
 
 
823
815
      switch (sort_field->result_type) {
824
816
      case STRING_RESULT:
825
 
        {
826
 
          const CHARSET_INFO * const cs=item->collation.collation;
827
 
          char fill_char= ((cs->state & MY_CS_BINSORT) ? (char) 0 : ' ');
828
 
          int diff;
829
 
          uint32_t sort_field_length;
 
817
      {
 
818
        const CHARSET_INFO * const cs=item->collation.collation;
 
819
        char fill_char= ((cs->state & MY_CS_BINSORT) ? (char) 0 : ' ');
 
820
        int diff;
 
821
        uint32_t sort_field_length;
830
822
 
 
823
        if (maybe_null)
 
824
          *to++=1;
 
825
        /* All item->str() to use some extra byte for end null.. */
 
826
        String tmp((char*) to,sort_field->length+4,cs);
 
827
        String *res= item->str_result(&tmp);
 
828
        if (!res)
 
829
        {
831
830
          if (maybe_null)
832
 
            *to++=1;
833
 
          /* All item->str() to use some extra byte for end null.. */
834
 
          String tmp((char*) to,sort_field->length+4,cs);
835
 
          String *res= item->str_result(&tmp);
836
 
          if (!res)
837
 
          {
838
 
            if (maybe_null)
839
 
              memset(to-1, 0, sort_field->length+1);
840
 
            else
841
 
            {
842
 
              /*
843
 
                This should only happen during extreme conditions if we run out
844
 
                of memory or have an item marked not null when it can be null.
845
 
                This code is here mainly to avoid a hard crash in this case.
846
 
              */
847
 
              assert(0);
848
 
              memset(to, 0, sort_field->length);        // Avoid crash
849
 
            }
850
 
            break;
851
 
          }
852
 
          length= res->length();
853
 
          sort_field_length= sort_field->length - sort_field->suffix_length;
854
 
          diff=(int) (sort_field_length - length);
855
 
          if (diff < 0)
856
 
          {
857
 
            diff=0;
858
 
            length= sort_field_length;
859
 
          }
860
 
          if (sort_field->suffix_length)
861
 
          {
862
 
            /* Store length last in result_string */
863
 
            store_length(to + sort_field_length, length,
864
 
                         sort_field->suffix_length);
865
 
          }
866
 
          if (sort_field->need_strxnfrm)
867
 
          {
868
 
            char *from=(char*) res->ptr();
869
 
            uint32_t tmp_length;
870
 
            if ((unsigned char*) from == to)
871
 
            {
872
 
              set_if_smaller(length,sort_field->length);
873
 
              memcpy(tmp_buffer,from,length);
874
 
              from= tmp_buffer;
875
 
            }
876
 
            tmp_length= my_strnxfrm(cs,to,sort_field->length,
877
 
                                    (unsigned char*) from, length);
878
 
            assert(tmp_length == sort_field->length);
879
 
          }
 
831
            memset(to-1, 0, sort_field->length+1);
880
832
          else
881
833
          {
882
 
            my_strnxfrm(cs,(unsigned char*)to,length,(const unsigned char*)res->ptr(),length);
883
 
            cs->cset->fill(cs, (char *)to+length,diff,fill_char);
 
834
            /*
 
835
              This should only happen during extreme conditions if we run out
 
836
              of memory or have an item marked not null when it can be null.
 
837
              This code is here mainly to avoid a hard crash in this case.
 
838
            */
 
839
            assert(0);
 
840
            memset(to, 0, sort_field->length);  // Avoid crash
884
841
          }
885
842
          break;
886
843
        }
 
844
        length= res->length();
 
845
        sort_field_length= sort_field->length - sort_field->suffix_length;
 
846
        diff=(int) (sort_field_length - length);
 
847
        if (diff < 0)
 
848
        {
 
849
          diff=0;
 
850
          length= sort_field_length;
 
851
        }
 
852
        if (sort_field->suffix_length)
 
853
        {
 
854
          /* Store length last in result_string */
 
855
          store_length(to + sort_field_length, length,
 
856
                       sort_field->suffix_length);
 
857
        }
 
858
        if (sort_field->need_strxnfrm)
 
859
        {
 
860
          char *from=(char*) res->ptr();
 
861
          uint32_t tmp_length;
 
862
          if ((unsigned char*) from == to)
 
863
          {
 
864
            set_if_smaller(length,sort_field->length);
 
865
            memcpy(tmp_buffer,from,length);
 
866
            from= tmp_buffer;
 
867
          }
 
868
          tmp_length= my_strnxfrm(cs,to,sort_field->length,
 
869
                                  (unsigned char*) from, length);
 
870
          assert(tmp_length == sort_field->length);
 
871
        }
 
872
        else
 
873
        {
 
874
          my_strnxfrm(cs,(unsigned char*)to,length,(const unsigned char*)res->ptr(),length);
 
875
          cs->cset->fill(cs, (char *)to+length,diff,fill_char);
 
876
        }
 
877
        break;
 
878
      }
887
879
      case INT_RESULT:
888
 
        {
 
880
        {
889
881
          int64_t value= item->val_int_result();
890
882
          if (maybe_null)
891
883
          {
892
 
            *to++=1;
 
884
            *to++=1;
893
885
            if (item->null_value)
894
886
            {
895
887
              if (maybe_null)
901
893
              break;
902
894
            }
903
895
          }
904
 
          to[7]= (unsigned char) value;
905
 
          to[6]= (unsigned char) (value >> 8);
906
 
          to[5]= (unsigned char) (value >> 16);
907
 
          to[4]= (unsigned char) (value >> 24);
908
 
          to[3]= (unsigned char) (value >> 32);
909
 
          to[2]= (unsigned char) (value >> 40);
910
 
          to[1]= (unsigned char) (value >> 48);
 
896
          to[7]= (unsigned char) value;
 
897
          to[6]= (unsigned char) (value >> 8);
 
898
          to[5]= (unsigned char) (value >> 16);
 
899
          to[4]= (unsigned char) (value >> 24);
 
900
          to[3]= (unsigned char) (value >> 32);
 
901
          to[2]= (unsigned char) (value >> 40);
 
902
          to[1]= (unsigned char) (value >> 48);
911
903
          if (item->unsigned_flag)                    /* Fix sign */
912
904
            to[0]= (unsigned char) (value >> 56);
913
905
          else
914
906
            to[0]= (unsigned char) (value >> 56) ^ 128; /* Reverse signbit */
915
 
          break;
916
 
        }
 
907
          break;
 
908
        }
917
909
      case DECIMAL_RESULT:
918
910
        {
919
 
          type::Decimal dec_buf, *dec_val= item->val_decimal_result(&dec_buf);
 
911
          my_decimal dec_buf, *dec_val= item->val_decimal_result(&dec_buf);
920
912
          if (maybe_null)
921
913
          {
922
914
            if (item->null_value)
927
919
            }
928
920
            *to++=1;
929
921
          }
930
 
          dec_val->val_binary(E_DEC_FATAL_ERROR, to,
931
 
                              item->max_length - (item->decimals ? 1:0),
932
 
                              item->decimals);
933
 
          break;
 
922
          my_decimal2binary(E_DEC_FATAL_ERROR, dec_val, to,
 
923
                            item->max_length - (item->decimals ? 1:0),
 
924
                            item->decimals);
 
925
         break;
934
926
        }
935
927
      case REAL_RESULT:
936
 
        {
 
928
        {
937
929
          double value= item->val_result();
938
 
          if (maybe_null)
 
930
          if (maybe_null)
939
931
          {
940
932
            if (item->null_value)
941
933
            {
943
935
              to++;
944
936
              break;
945
937
            }
946
 
            *to++=1;
 
938
            *to++=1;
947
939
          }
948
 
          change_double_for_sort(value,(unsigned char*) to);
949
 
          break;
950
 
        }
 
940
          change_double_for_sort(value,(unsigned char*) to);
 
941
          break;
 
942
        }
951
943
      case ROW_RESULT:
952
944
      default:
953
 
        // This case should never be choosen
954
 
        assert(0);
955
 
        break;
 
945
        // This case should never be choosen
 
946
        assert(0);
 
947
        break;
956
948
      }
957
949
    }
958
 
 
959
950
    if (sort_field->reverse)
960
951
    {                                                   /* Revers key */
961
952
      if (maybe_null)
968
959
      }
969
960
    }
970
961
    else
971
 
    {
972
962
      to+= sort_field->length;
973
 
    }
974
963
  }
975
964
 
976
965
  if (addon_field)
1035
1024
    if ((field= sort_field->field))
1036
1025
    {
1037
1026
      if (field->getTable() == table)
1038
 
        table->setReadSet(field->position());
 
1027
        table->setReadSet(field->field_index);
1039
1028
    }
1040
1029
    else
1041
1030
    {                                           // Item
1049
1038
    sort_addon_field *addonf= addon_field;
1050
1039
    Field *field;
1051
1040
    for ( ; (field= addonf->field) ; addonf++)
1052
 
      table->setReadSet(field->position());
 
1041
      table->setReadSet(field->field_index);
1053
1042
  }
1054
1043
  else
1055
1044
  {
1059
1048
}
1060
1049
 
1061
1050
 
1062
 
bool SortParam::save_index(unsigned char **sort_keys, uint32_t count, filesort_info *table_sort)
 
1051
bool SortParam::save_index(unsigned char **sort_keys, uint32_t count,
 
1052
                           filesort_info *table_sort)
1063
1053
{
1064
1054
  uint32_t offset;
1065
1055
  unsigned char *to;
1066
1056
 
1067
1057
  internal::my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, sort_length);
1068
1058
  offset= rec_length - res_length;
1069
 
 
1070
1059
  if ((ha_rows) count > max_rows)
1071
1060
    count=(uint32_t) max_rows;
1072
 
 
1073
 
  if (!(to= table_sort->record_pointers= (unsigned char*) malloc(res_length*count)))
 
1061
  if (!(to= table_sort->record_pointers=
 
1062
        (unsigned char*) malloc(res_length*count)))
1074
1063
    return true;
1075
1064
 
1076
1065
  for (unsigned char **end_ptr= sort_keys+count ; sort_keys != end_ptr ; sort_keys++)
1078
1067
    memcpy(to, *sort_keys+offset, res_length);
1079
1068
    to+= res_length;
1080
1069
  }
1081
 
 
1082
1070
  return false;
1083
1071
}
1084
1072
 
1183
1171
{
1184
1172
  qsort2_cmp key_compare;
1185
1173
  void *key_compare_arg;
1186
 
 
1187
1174
  public:
1188
 
  compare_functor(qsort2_cmp in_key_compare, void *in_compare_arg) :
1189
 
    key_compare(in_key_compare),
1190
 
    key_compare_arg(in_compare_arg)
1191
 
  { }
1192
 
  
 
1175
  compare_functor(qsort2_cmp in_key_compare, void *in_compare_arg)
 
1176
    : key_compare(in_key_compare), key_compare_arg(in_compare_arg) { }
1193
1177
  inline bool operator()(const buffpek *i, const buffpek *j) const
1194
1178
  {
1195
 
    int val= key_compare(key_compare_arg, &i->key, &j->key);
1196
 
 
 
1179
    int val= key_compare(key_compare_arg,
 
1180
                      &i->key, &j->key);
1197
1181
    return (val >= 0);
1198
1182
  }
1199
1183
};
1502
1486
      sortorder->result_type= sortorder->item->result_type();
1503
1487
      if (sortorder->item->result_as_int64_t())
1504
1488
        sortorder->result_type= INT_RESULT;
1505
 
 
1506
1489
      switch (sortorder->result_type) {
1507
1490
      case STRING_RESULT:
1508
 
        sortorder->length=sortorder->item->max_length;
 
1491
        sortorder->length=sortorder->item->max_length;
1509
1492
        set_if_smaller(sortorder->length,
1510
1493
                       getSession().variables.max_sort_length);
1511
 
        if (use_strnxfrm((cs=sortorder->item->collation.collation)))
1512
 
        {
 
1494
        if (use_strnxfrm((cs=sortorder->item->collation.collation)))
 
1495
        {
1513
1496
          sortorder->length= cs->coll->strnxfrmlen(cs, sortorder->length);
1514
 
          sortorder->need_strxnfrm= 1;
1515
 
          *multi_byte_charset= 1;
1516
 
        }
 
1497
          sortorder->need_strxnfrm= 1;
 
1498
          *multi_byte_charset= 1;
 
1499
        }
1517
1500
        else if (cs == &my_charset_bin)
1518
1501
        {
1519
1502
          /* Store length last to be able to sort blob/varbinary */
1520
1503
          sortorder->suffix_length= suffix_length(sortorder->length);
1521
1504
          sortorder->length+= sortorder->suffix_length;
1522
1505
        }
1523
 
        break;
 
1506
        break;
1524
1507
      case INT_RESULT:
1525
 
        sortorder->length=8;                    // Size of intern int64_t
1526
 
        break;
 
1508
        sortorder->length=8;                    // Size of intern int64_t
 
1509
        break;
1527
1510
      case DECIMAL_RESULT:
1528
1511
        sortorder->length=
1529
 
          class_decimal_get_binary_size(sortorder->item->max_length -
 
1512
          my_decimal_get_binary_size(sortorder->item->max_length -
1530
1513
                                     (sortorder->item->decimals ? 1 : 0),
1531
1514
                                     sortorder->item->decimals);
1532
1515
        break;
1533
1516
      case REAL_RESULT:
1534
 
        sortorder->length=sizeof(double);
1535
 
        break;
 
1517
        sortorder->length=sizeof(double);
 
1518
        break;
1536
1519
      case ROW_RESULT:
1537
 
        // This case should never be choosen
1538
 
        assert(0);
1539
 
        break;
 
1520
      default:
 
1521
        // This case should never be choosen
 
1522
        assert(0);
 
1523
        break;
1540
1524
      }
1541
1525
      if (sortorder->item->maybe_null)
1542
 
        length++;                               // Place for NULL marker
 
1526
        length++;                               // Place for NULL marker
1543
1527
    }
1544
1528
    set_if_smaller(sortorder->length, (size_t)getSession().variables.max_sort_length);
1545
1529
    length+=sortorder->length;