~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/filesort.cc

  • Committer: Monty Taylor
  • Date: 2009-01-06 18:46:25 UTC
  • mto: This revision was merged to the branch mainline in revision 762.
  • Revision ID: mordred@inaugust.com-20090106184625-kqu7nsnwjwm5jv4s
Enabled dirty_close.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (C) 2000-2006 MySQL AB  
 
1
/* Copyright (C) 2000-2006 MySQL AB
2
2
 
3
3
   This program is free software; you can redistribute it and/or modify
4
4
   it under the terms of the GNU General Public License as published by
32
32
/* functions defined in this file */
33
33
 
34
34
static char **make_char_array(char **old_pos, register uint32_t fields,
35
 
                              uint32_t length, myf my_flag);
 
35
                              uint32_t length);
36
36
static unsigned char *read_buffpek_from_file(IO_CACHE *buffer_file, uint32_t count,
37
37
                                     unsigned char *buf);
38
38
static ha_rows find_all_keys(SORTPARAM *param,SQL_SELECT *select,
46
46
                       BUFFPEK *buffpek,
47
47
                       uint32_t maxbuffer,IO_CACHE *tempfile,
48
48
                       IO_CACHE *outfile);
49
 
static bool save_index(SORTPARAM *param,unsigned char **sort_keys, uint32_t count, 
 
49
static bool save_index(SORTPARAM *param,unsigned char **sort_keys, uint32_t count,
50
50
                       filesort_info_st *table_sort);
51
51
static uint32_t suffix_length(uint32_t string_length);
52
52
static uint32_t sortlength(Session *session, SORT_FIELD *sortorder, uint32_t s_length,
101
101
  BUFFPEK *buffpek;
102
102
  ha_rows records= HA_POS_ERROR;
103
103
  unsigned char **sort_keys= 0;
104
 
  IO_CACHE tempfile, buffpek_pointers, *selected_records_file, *outfile; 
 
104
  IO_CACHE tempfile, buffpek_pointers, *selected_records_file, *outfile;
105
105
  SORTPARAM param;
106
106
  bool multi_byte_charset;
107
107
 
117
117
  */
118
118
  ha_release_temporary_latches(session);
119
119
 
120
 
  /* 
121
 
    Don't use table->sort in filesort as it is also used by 
122
 
    QUICK_INDEX_MERGE_SELECT. Work with a copy and put it back at the end 
 
120
  /*
 
121
    Don't use table->sort in filesort as it is also used by
 
122
    QUICK_INDEX_MERGE_SELECT. Work with a copy and put it back at the end
123
123
    when index_merge select has finished with it.
124
124
  */
125
125
  memcpy(&table_sort, &table->sort, sizeof(filesort_info_st));
126
126
  table->sort.io_cache= NULL;
127
 
  
 
127
 
128
128
  outfile= table_sort.io_cache;
129
129
  my_b_clear(&tempfile);
130
130
  my_b_clear(&buffpek_pointers);
137
137
  param.addon_length= 0;
138
138
  if (!(table->file->ha_table_flags() & HA_FAST_KEY_READ) && !sort_positions)
139
139
  {
140
 
    /* 
141
 
      Get the descriptors of all fields whose values are appended 
 
140
    /*
 
141
      Get the descriptors of all fields whose values are appended
142
142
      to sorted fields and get its total length in param.spack_length.
143
143
    */
144
 
    param.addon_field= get_addon_fields(session, table->field, 
 
144
    param.addon_field= get_addon_fields(session, table->field,
145
145
                                        param.sort_length,
146
146
                                        &param.addon_length);
147
147
  }
153
153
  if (param.addon_field)
154
154
  {
155
155
    param.res_length= param.addon_length;
156
 
    if (!(table_sort.addon_buf= (unsigned char *) my_malloc(param.addon_length,
157
 
                                                    MYF(MY_WME))))
 
156
    if (!(table_sort.addon_buf= (unsigned char *) malloc(param.addon_length)))
158
157
      goto err;
159
158
  }
160
159
  else
161
160
  {
162
161
    param.res_length= param.ref_length;
163
 
    /* 
164
 
      The reference to the record is considered 
 
162
    /*
 
163
      The reference to the record is considered
165
164
      as an additional sorted field
166
165
    */
167
166
    param.sort_length+= param.ref_length;
189
188
  {
190
189
    records= table->file->estimate_rows_upper_bound();
191
190
    /*
192
 
      If number of records is not known, use as much of sort buffer 
193
 
      as possible. 
 
191
      If number of records is not known, use as much of sort buffer
 
192
      as possible.
194
193
    */
195
194
    if (records == HA_POS_ERROR)
196
195
      records--;  // we use 'records+1' below.
198
197
  }
199
198
 
200
199
  if (multi_byte_charset &&
201
 
      !(param.tmp_buffer= (char*) my_malloc(param.sort_length,MYF(MY_WME))))
 
200
      !(param.tmp_buffer= (char*) malloc(param.sort_length)))
202
201
    goto err;
203
202
 
204
203
  memavl= session->variables.sortbuff_size;
210
209
    param.keys=(uint32_t) cmin(records+1, keys);
211
210
    if ((table_sort.sort_keys=
212
211
         (unsigned char **) make_char_array((char **) table_sort.sort_keys,
213
 
                                    param.keys, param.rec_length, MYF(0))))
 
212
                                            param.keys, param.rec_length)))
214
213
      break;
215
214
    old_memavl=memavl;
216
215
    if ((memavl=memavl/4*3) < min_sort_memory && old_memavl > min_sort_memory)
360
359
/** Make a array of string pointers. */
361
360
 
362
361
static char **make_char_array(char **old_pos, register uint32_t fields,
363
 
                              uint32_t length, myf my_flag)
 
362
                              uint32_t length)
364
363
{
365
364
  register char **pos;
366
365
  char *char_pos;
367
366
 
368
367
  if (old_pos ||
369
 
      (old_pos= (char**) my_malloc((uint32_t) fields*(length+sizeof(char*)),
370
 
                                   my_flag)))
 
368
      (old_pos= (char**) malloc((uint32_t) fields*(length+sizeof(char*)))))
371
369
  {
372
370
    pos=old_pos; char_pos=((char*) (pos+fields)) -length;
373
371
    while (fields--) *(pos++) = (char_pos+= length);
387
385
  if (count > UINT_MAX/sizeof(BUFFPEK))
388
386
    return 0; /* sizeof(BUFFPEK)*count will overflow */
389
387
  if (!tmp)
390
 
    tmp= (unsigned char *)my_malloc(length, MYF(MY_WME));
 
388
    tmp= (unsigned char *)malloc(length);
391
389
  if (tmp)
392
390
  {
393
391
    if (reinit_io_cache(buffpek_pointers,READ_CACHE,0L,0,0) ||
581
579
 
582
580
  if (session->is_error())
583
581
    return(HA_POS_ERROR);
584
 
  
 
582
 
585
583
  /* Signal we should use orignal column read and write maps */
586
584
  sort_form->column_bitmaps_set(save_read_set, save_write_set);
587
585
 
816
814
          if (maybe_null)
817
815
          {
818
816
            if (item->null_value)
819
 
            { 
 
817
            {
820
818
              memset(to, 0, sort_field->length+1);
821
819
              to++;
822
820
              break;
845
843
          break;
846
844
        }
847
845
      case ROW_RESULT:
848
 
      default: 
 
846
      default:
849
847
        // This case should never be choosen
850
848
        assert(0);
851
849
        break;
868
866
 
869
867
  if (param->addon_field)
870
868
  {
871
 
    /* 
 
869
    /*
872
870
      Save field values appended to sorted fields.
873
871
      First null bit indicators are appended then field values follow.
874
872
      In this implementation we use fixed layout for field values -
954
952
}
955
953
 
956
954
 
957
 
static bool save_index(SORTPARAM *param, unsigned char **sort_keys, uint32_t count, 
 
955
static bool save_index(SORTPARAM *param, unsigned char **sort_keys, uint32_t count,
958
956
                       filesort_info_st *table_sort)
959
957
{
960
958
  uint32_t offset,res_length;
965
963
  offset= param->rec_length-res_length;
966
964
  if ((ha_rows) count > param->max_rows)
967
965
    count=(uint32_t) param->max_rows;
968
 
  if (!(to= table_sort->record_pointers= 
969
 
        (unsigned char*) my_malloc(res_length*count, MYF(MY_WME))))
 
966
  if (!(to= table_sort->record_pointers=
 
967
        (unsigned char*) malloc(res_length*count)))
970
968
    return(1);                 /* purecov: inspected */
971
969
  for (unsigned char **end= sort_keys+count ; sort_keys != end ; sort_keys++)
972
970
  {
1144
1142
 
1145
1143
  /* The following will fire if there is not enough space in sort_buffer */
1146
1144
  assert(maxcount!=0);
1147
 
  
 
1145
 
1148
1146
  if (param->unique_buff)
1149
1147
  {
1150
1148
    cmp= param->compare;
1172
1170
 
1173
1171
  if (param->unique_buff)
1174
1172
  {
1175
 
    /* 
 
1173
    /*
1176
1174
       Called by Unique::get()
1177
1175
       Copy the first argument to param->unique_buff for unique removal.
1178
1176
       Store it also in 'to_file'.
1291
1289
      for (end= strpos+buffpek->mem_count*rec_length ;
1292
1290
           strpos != end ;
1293
1291
           strpos+= rec_length)
1294
 
      {     
 
1292
      {
1295
1293
        if (my_b_write(to_file, (unsigned char *) strpos, res_length))
1296
1294
        {
1297
 
          error=1; goto err;                        
 
1295
          error=1; goto err;
1298
1296
        }
1299
1297
      }
1300
1298
    }
1392
1390
        sortorder->length=sortorder->item->max_length;
1393
1391
        set_if_smaller(sortorder->length, session->variables.max_sort_length);
1394
1392
        if (use_strnxfrm((cs=sortorder->item->collation.collation)))
1395
 
        { 
 
1393
        {
1396
1394
          sortorder->length= cs->coll->strnxfrmlen(cs, sortorder->length);
1397
1395
          sortorder->need_strxnfrm= 1;
1398
1396
          *multi_byte_charset= 1;
1409
1407
        break;
1410
1408
      case DECIMAL_RESULT:
1411
1409
        sortorder->length=
1412
 
          my_decimal_get_binary_size(sortorder->item->max_length - 
 
1410
          my_decimal_get_binary_size(sortorder->item->max_length -
1413
1411
                                     (sortorder->item->decimals ? 1 : 0),
1414
1412
                                     sortorder->item->decimals);
1415
1413
        break;
1417
1415
        sortorder->length=sizeof(double);
1418
1416
        break;
1419
1417
      case ROW_RESULT:
1420
 
      default: 
 
1418
      default:
1421
1419
        // This case should never be choosen
1422
1420
        assert(0);
1423
1421
        break;
1439
1437
 
1440
1438
  The function first finds out what fields are used in the result set.
1441
1439
  Then it calculates the length of the buffer to store the values of
1442
 
  these fields together with the value of sort values. 
 
1440
  these fields together with the value of sort values.
1443
1441
  If the calculated length is not greater than max_length_for_sort_data
1444
1442
  the function allocates memory for an array of descriptors containing
1445
1443
  layouts for the values of the non-sorted fields in the buffer and
1477
1475
    Note for future refinement:
1478
1476
    This this a too strong condition.
1479
1477
    Actually we need only the fields referred in the
1480
 
    result set. And for some of them it makes sense to use 
 
1478
    result set. And for some of them it makes sense to use
1481
1479
    the values directly from sorted fields.
1482
1480
  */
1483
1481
  *plength= 0;
1492
1490
    if (field->maybe_null())
1493
1491
      null_fields++;
1494
1492
    fields++;
1495
 
  } 
 
1493
  }
1496
1494
  if (!fields)
1497
1495
    return 0;
1498
1496
  length+= (null_fields+7)/8;
1499
1497
 
1500
1498
  if (length+sortlength > session->variables.max_length_for_sort_data ||
1501
 
      !(addonf= (SORT_ADDON_FIELD *) my_malloc(sizeof(SORT_ADDON_FIELD)*
1502
 
                                               (fields+1), MYF(MY_WME))))
 
1499
      !(addonf= (SORT_ADDON_FIELD *) malloc(sizeof(SORT_ADDON_FIELD)*
 
1500
                                            (fields+1))))
1503
1501
    return 0;
1504
1502
 
1505
1503
  *plength= length;
1527
1525
    addonf++;
1528
1526
  }
1529
1527
  addonf->field= 0;     // Put end marker
1530
 
  
 
1528
 
1531
1529
  return (addonf-fields);
1532
1530
}
1533
1531
 
1547
1545
    void.
1548
1546
*/
1549
1547
 
1550
 
static void 
 
1548
static void
1551
1549
unpack_addon_fields(struct st_sort_addon_field *addon_field, unsigned char *buff)
1552
1550
{
1553
1551
  Field *field;