~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/filesort.cc

Renamed namespace slot to namespace service.

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
 
17
17
/**
21
21
  Sorts a database
22
22
*/
23
23
 
24
 
#include <config.h>
25
 
 
26
 
#include <float.h>
27
 
#include <limits.h>
28
 
 
29
 
#include <queue>
30
 
#include <algorithm>
31
 
#include <iostream>
32
 
 
33
 
#include <drizzled/drizzled.h>
 
24
#include <drizzled/server_includes.h>
34
25
#include <drizzled/sql_sort.h>
35
 
#include <drizzled/filesort.h>
36
26
#include <drizzled/error.h>
37
27
#include <drizzled/probes.h>
38
28
#include <drizzled/session.h>
39
29
#include <drizzled/table.h>
40
30
#include <drizzled/table_list.h>
41
 
#include <drizzled/optimizer/range.h>
42
 
#include <drizzled/records.h>
43
 
#include <drizzled/internal/iocache.h>
44
 
#include <drizzled/internal/my_sys.h>
45
 
#include <plugin/myisam/myisam.h>
46
 
#include <drizzled/plugin/transactional_storage_engine.h>
47
 
#include <drizzled/atomics.h>
48
 
#include <drizzled/global_buffer.h>
49
 
 
50
 
#include <drizzled/sort_field.h>
51
 
 
 
31
 
 
32
#include <queue>
 
33
#include <algorithm>
52
34
 
53
35
using namespace std;
54
36
 
55
 
namespace drizzled
56
 
{
57
 
 
58
 
/* Defines used by filesort and uniques */
59
 
#define MERGEBUFF               7
60
 
#define MERGEBUFF2              15
61
 
 
62
 
class BufferCompareContext
63
 
{
64
 
public:
65
 
  qsort_cmp2 key_compare;
66
 
  void *key_compare_arg;
67
 
 
68
 
  BufferCompareContext() :
69
 
    key_compare(0),
70
 
    key_compare_arg(0)
71
 
  { }
72
 
 
73
 
};
74
 
 
75
 
class SortParam {
76
 
public:
77
 
  uint32_t rec_length;          /* Length of sorted records */
78
 
  uint32_t sort_length;                 /* Length of sorted columns */
79
 
  uint32_t ref_length;                  /* Length of record ref. */
80
 
  uint32_t addon_length;        /* Length of added packed fields */
81
 
  uint32_t res_length;          /* Length of records in final sorted file/buffer */
82
 
  uint32_t keys;                                /* Max keys / buffer */
83
 
  ha_rows max_rows,examined_rows;
84
 
  Table *sort_form;                     /* For quicker make_sortkey */
85
 
  SortField *local_sortorder;
86
 
  SortField *end;
87
 
  sort_addon_field *addon_field; /* Descriptors for companion fields */
88
 
  unsigned char *unique_buff;
89
 
  bool not_killable;
90
 
  char *tmp_buffer;
91
 
  /* The fields below are used only by Unique class */
92
 
  qsort2_cmp compare;
93
 
  BufferCompareContext cmp_context;
94
 
 
95
 
  SortParam() :
96
 
    rec_length(0),
97
 
    sort_length(0),
98
 
    ref_length(0),
99
 
    addon_length(0),
100
 
    res_length(0),
101
 
    keys(0),
102
 
    max_rows(0),
103
 
    examined_rows(0),
104
 
    sort_form(0),
105
 
    local_sortorder(0),
106
 
    end(0),
107
 
    addon_field(0),
108
 
    unique_buff(0),
109
 
    not_killable(0),
110
 
    tmp_buffer(0),
111
 
    compare(0)
112
 
  {
113
 
  }
114
 
 
115
 
  ~SortParam()
116
 
  {
117
 
    if (tmp_buffer)
118
 
      free(tmp_buffer);
119
 
  }
120
 
 
121
 
  int write_keys(unsigned char * *sort_keys,
122
 
                 uint32_t count,
123
 
                 internal::IO_CACHE *buffer_file,
124
 
                 internal::IO_CACHE *tempfile);
125
 
 
126
 
  void make_sortkey(unsigned char *to,
127
 
                    unsigned char *ref_pos);
128
 
  void register_used_fields();
129
 
  bool save_index(unsigned char **sort_keys,
130
 
                  uint32_t count,
131
 
                  filesort_info *table_sort);
132
 
 
133
 
};
134
 
 
135
37
/* functions defined in this file */
136
38
 
137
 
static char **make_char_array(char **old_pos, uint32_t fields,
 
39
static char **make_char_array(char **old_pos, register uint32_t fields,
138
40
                              uint32_t length);
139
 
 
140
 
static unsigned char *read_buffpek_from_file(internal::IO_CACHE *buffer_file,
141
 
                                             uint32_t count,
142
 
                                             unsigned char *buf);
143
 
 
 
41
static unsigned char *read_buffpek_from_file(IO_CACHE *buffer_file, uint32_t count,
 
42
                                     unsigned char *buf);
 
43
static ha_rows find_all_keys(SORTPARAM *param,SQL_SELECT *select,
 
44
                             unsigned char * *sort_keys, IO_CACHE *buffer_file,
 
45
                             IO_CACHE *tempfile,IO_CACHE *indexfile);
 
46
static int write_keys(SORTPARAM *param,unsigned char * *sort_keys,
 
47
                      uint32_t count, IO_CACHE *buffer_file, IO_CACHE *tempfile);
 
48
static void make_sortkey(SORTPARAM *param,unsigned char *to, unsigned char *ref_pos);
 
49
static void register_used_fields(SORTPARAM *param);
 
50
static int merge_index(SORTPARAM *param,unsigned char *sort_buffer,
 
51
                       BUFFPEK *buffpek,
 
52
                       uint32_t maxbuffer,IO_CACHE *tempfile,
 
53
                       IO_CACHE *outfile);
 
54
static bool save_index(SORTPARAM *param,unsigned char **sort_keys, uint32_t count,
 
55
                       filesort_info_st *table_sort);
144
56
static uint32_t suffix_length(uint32_t string_length);
145
 
static void unpack_addon_fields(sort_addon_field *addon_field,
 
57
static uint32_t sortlength(Session *session, SORT_FIELD *sortorder, uint32_t s_length,
 
58
                       bool *multi_byte_charset);
 
59
static SORT_ADDON_FIELD *get_addon_fields(Session *session, Field **ptabfield,
 
60
                                          uint32_t sortlength, uint32_t *plength);
 
61
static void unpack_addon_fields(struct st_sort_addon_field *addon_field,
146
62
                                unsigned char *buff);
147
 
 
148
 
FileSort::FileSort(Session &arg) :
149
 
  _session(arg)
150
 
151
 
}
152
 
 
153
63
/**
154
64
  Sort a table.
155
65
  Creates a set of pointers that can be used to read the rows
162
72
  The result set is stored in table->io_cache or
163
73
  table->record_pointers.
164
74
 
 
75
  @param session           Current thread
165
76
  @param table          Table to sort
166
77
  @param sortorder      How to sort the table
167
78
  @param s_length       Number of elements in sortorder
185
96
    examined_rows       will be set to number of examined rows
186
97
*/
187
98
 
188
 
ha_rows FileSort::run(Table *table, SortField *sortorder, uint32_t s_length,
189
 
                      optimizer::SqlSelect *select, ha_rows max_rows,
190
 
                      bool sort_positions, ha_rows &examined_rows)
 
99
ha_rows filesort(Session *session, Table *table, SORT_FIELD *sortorder, uint32_t s_length,
 
100
                 SQL_SELECT *select, ha_rows max_rows,
 
101
                 bool sort_positions, ha_rows *examined_rows)
191
102
{
192
 
  int error= 1;
193
 
  uint32_t memavl= 0, min_sort_memory;
 
103
  int error;
 
104
  uint32_t memavl, min_sort_memory;
194
105
  uint32_t maxbuffer;
195
 
  size_t allocated_sort_memory= 0;
196
 
  buffpek *buffpek_inst= 0;
 
106
  BUFFPEK *buffpek;
197
107
  ha_rows records= HA_POS_ERROR;
198
108
  unsigned char **sort_keys= 0;
199
 
  internal::IO_CACHE tempfile;
200
 
  internal::IO_CACHE buffpek_pointers;
201
 
  internal::IO_CACHE *selected_records_file;
202
 
  internal::IO_CACHE *outfile;
203
 
  SortParam param;
 
109
  IO_CACHE tempfile, buffpek_pointers, *selected_records_file, *outfile;
 
110
  SORTPARAM param;
204
111
  bool multi_byte_charset;
205
112
 
206
 
  /*
207
 
    Don't use table->sort in filesort as it is also used by
208
 
    QuickIndexMergeSelect. Work with a copy and put it back at the end
209
 
    when index_merge select has finished with it.
210
 
  */
211
 
  filesort_info table_sort(table->sort);
212
 
  table->sort.io_cache= NULL;
213
 
 
 
113
  filesort_info_st table_sort;
214
114
  TableList *tab= table->pos_in_table_list;
215
115
  Item_subselect *subselect= tab ? tab->containing_subselect() : 0;
216
116
 
217
 
  DRIZZLE_FILESORT_START(table->getShare()->getSchemaName(), table->getShare()->getTableName());
 
117
  DRIZZLE_FILESORT_START(table->s->db.str, table->s->table_name.str);
218
118
 
219
119
  /*
220
120
   Release InnoDB's adaptive hash index latch (if holding) before
221
121
   running a sort.
222
122
  */
223
 
  plugin::TransactionalStorageEngine::releaseTemporaryLatches(&getSession());
 
123
  ha_release_temporary_latches(session);
224
124
 
 
125
  /*
 
126
    Don't use table->sort in filesort as it is also used by
 
127
    QUICK_INDEX_MERGE_SELECT. Work with a copy and put it back at the end
 
128
    when index_merge select has finished with it.
 
129
  */
 
130
  memcpy(&table_sort, &table->sort, sizeof(filesort_info_st));
 
131
  table->sort.io_cache= NULL;
225
132
 
226
133
  outfile= table_sort.io_cache;
227
 
  assert(tempfile.buffer == 0);
228
 
  assert(buffpek_pointers.buffer == 0);
229
 
 
230
 
  param.sort_length= sortlength(sortorder, s_length, &multi_byte_charset);
231
 
  param.ref_length= table->cursor->ref_length;
232
 
 
233
 
  if (!(table->cursor->getEngine()->check_flag(HTON_BIT_FAST_KEY_READ)) && !sort_positions)
 
134
  my_b_clear(&tempfile);
 
135
  my_b_clear(&buffpek_pointers);
 
136
  buffpek=0;
 
137
  error= 1;
 
138
  memset(&param, 0, sizeof(param));
 
139
  param.sort_length= sortlength(session, sortorder, s_length, &multi_byte_charset);
 
140
  param.ref_length= table->file->ref_length;
 
141
  param.addon_field= 0;
 
142
  param.addon_length= 0;
 
143
  if (!(table->file->ha_table_flags() & HA_FAST_KEY_READ) && !sort_positions)
234
144
  {
235
145
    /*
236
146
      Get the descriptors of all fields whose values are appended
237
147
      to sorted fields and get its total length in param.spack_length.
238
148
    */
239
 
    param.addon_field= get_addon_fields(table->getFields(),
 
149
    param.addon_field= get_addon_fields(session, table->field,
240
150
                                        param.sort_length,
241
151
                                        &param.addon_length);
242
152
  }
249
159
  {
250
160
    param.res_length= param.addon_length;
251
161
    if (!(table_sort.addon_buf= (unsigned char *) malloc(param.addon_length)))
252
 
    {
253
162
      goto err;
254
 
    }
255
163
  }
256
164
  else
257
165
  {
267
175
 
268
176
  if (select && select->quick)
269
177
  {
270
 
    getSession().status_var.filesort_range_count++;
 
178
    status_var_increment(session->status_var.filesort_range_count);
271
179
  }
272
180
  else
273
181
  {
274
 
    getSession().status_var.filesort_scan_count++;
 
182
    status_var_increment(session->status_var.filesort_scan_count);
275
183
  }
276
184
#ifdef CAN_TRUST_RANGE
277
185
  if (select && select->quick && select->quick->records > 0L)
278
186
  {
279
187
    records= min((ha_rows) (select->quick->records*2+EXTRA_RECORDS*2),
280
 
                 table->cursor->stats.records)+EXTRA_RECORDS;
 
188
                 table->file->stats.records)+EXTRA_RECORDS;
281
189
    selected_records_file=0;
282
190
  }
283
191
  else
284
192
#endif
285
193
  {
286
 
    records= table->cursor->estimate_rows_upper_bound();
 
194
    records= table->file->estimate_rows_upper_bound();
287
195
    /*
288
196
      If number of records is not known, use as much of sort buffer
289
197
      as possible.
293
201
    selected_records_file= 0;
294
202
  }
295
203
 
296
 
  if (multi_byte_charset && !(param.tmp_buffer= (char*) malloc(param.sort_length)))
297
 
  {
 
204
  if (multi_byte_charset &&
 
205
      !(param.tmp_buffer= (char*) malloc(param.sort_length)))
298
206
    goto err;
299
 
  }
300
207
 
301
 
  memavl= getSession().variables.sortbuff_size;
 
208
  memavl= session->variables.sortbuff_size;
302
209
  min_sort_memory= max((uint32_t)MIN_SORT_MEMORY, param.sort_length*MERGEBUFF2);
303
210
  while (memavl >= min_sort_memory)
304
211
  {
305
212
    uint32_t old_memavl;
306
213
    uint32_t keys= memavl/(param.rec_length+sizeof(char*));
307
214
    param.keys= (uint32_t) min(records+1, (ha_rows)keys);
308
 
 
309
 
    allocated_sort_memory= param.keys * param.rec_length;
310
 
    if (not global_sort_buffer.add(allocated_sort_memory))
311
 
    {
312
 
      my_error(ER_OUT_OF_GLOBAL_SORTMEMORY, MYF(ME_ERROR+ME_WAITTANG));
313
 
      goto err;
314
 
    }
315
 
 
316
215
    if ((table_sort.sort_keys=
317
216
         (unsigned char **) make_char_array((char **) table_sort.sort_keys,
318
217
                                            param.keys, param.rec_length)))
319
218
      break;
320
 
 
321
 
    global_sort_buffer.sub(allocated_sort_memory);
322
219
    old_memavl= memavl;
323
220
    if ((memavl= memavl/4*3) < min_sort_memory && old_memavl > min_sort_memory)
324
221
      memavl= min_sort_memory;
329
226
    my_error(ER_OUT_OF_SORTMEMORY,MYF(ME_ERROR+ME_WAITTANG));
330
227
    goto err;
331
228
  }
332
 
 
333
 
  if (buffpek_pointers.open_cached_file(drizzle_tmpdir.c_str(),TEMP_PREFIX, DISK_BUFFER_SIZE, MYF(MY_WME)))
334
 
  {
 
229
  if (open_cached_file(&buffpek_pointers,drizzle_tmpdir,TEMP_PREFIX,
 
230
                       DISK_BUFFER_SIZE, MYF(MY_WME)))
335
231
    goto err;
336
 
  }
337
232
 
338
233
  param.keys--;                         /* TODO: check why we do this */
339
234
  param.sort_form= table;
340
235
  param.end=(param.local_sortorder=sortorder)+s_length;
341
 
  if ((records= find_all_keys(&param,select,sort_keys, &buffpek_pointers,
342
 
                              &tempfile, selected_records_file)) == HA_POS_ERROR)
343
 
  {
 
236
  if ((records=find_all_keys(&param,select,sort_keys, &buffpek_pointers,
 
237
                             &tempfile, selected_records_file)) ==
 
238
      HA_POS_ERROR)
344
239
    goto err;
345
 
  }
346
 
  maxbuffer= (uint32_t) (my_b_tell(&buffpek_pointers)/sizeof(*buffpek_inst));
 
240
  maxbuffer= (uint32_t) (my_b_tell(&buffpek_pointers)/sizeof(*buffpek));
347
241
 
348
242
  if (maxbuffer == 0)                   // The whole set is in memory
349
243
  {
350
 
    if (param.save_index(sort_keys,(uint32_t) records, &table_sort))
351
 
    {
 
244
    if (save_index(&param,sort_keys,(uint32_t) records, &table_sort))
352
245
      goto err;
353
 
    }
354
246
  }
355
247
  else
356
248
  {
358
250
    {
359
251
      if (table_sort.buffpek)
360
252
        free(table_sort.buffpek);
361
 
      table_sort.buffpek = 0;
 
253
      table_sort.buffpek= 0;
362
254
    }
363
255
    if (!(table_sort.buffpek=
364
 
          (unsigned char *) read_buffpek_from_file(&buffpek_pointers, maxbuffer, table_sort.buffpek)))
365
 
    {
 
256
          (unsigned char *) read_buffpek_from_file(&buffpek_pointers, maxbuffer,
 
257
                                 table_sort.buffpek)))
366
258
      goto err;
367
 
    }
368
 
    buffpek_inst= (buffpek *) table_sort.buffpek;
 
259
    buffpek= (BUFFPEK *) table_sort.buffpek;
369
260
    table_sort.buffpek_len= maxbuffer;
370
 
    buffpek_pointers.close_cached_file();
 
261
    close_cached_file(&buffpek_pointers);
371
262
        /* Open cached file if it isn't open */
372
 
    if (! my_b_inited(outfile) && outfile->open_cached_file(drizzle_tmpdir.c_str(),TEMP_PREFIX,READ_RECORD_BUFFER, MYF(MY_WME)))
373
 
    {
374
 
      goto err;
375
 
    }
376
 
 
377
 
    if (outfile->reinit_io_cache(internal::WRITE_CACHE,0L,0,0))
378
 
    {
379
 
      goto err;
380
 
    }
 
263
    if (! my_b_inited(outfile) &&
 
264
        open_cached_file(outfile,drizzle_tmpdir,TEMP_PREFIX,READ_RECORD_BUFFER,
 
265
                          MYF(MY_WME)))
 
266
      goto err;
 
267
    if (reinit_io_cache(outfile,WRITE_CACHE,0L,0,0))
 
268
      goto err;
381
269
 
382
270
    /*
383
271
      Use also the space previously used by string pointers in sort_buffer
384
272
      for temporary key storage.
385
273
    */
386
 
    param.keys=((param.keys*(param.rec_length+sizeof(char*))) / param.rec_length-1);
387
 
 
 
274
    param.keys=((param.keys*(param.rec_length+sizeof(char*))) /
 
275
                param.rec_length-1);
388
276
    maxbuffer--;                                // Offset from 0
389
 
    if (merge_many_buff(&param,(unsigned char*) sort_keys,buffpek_inst,&maxbuffer, &tempfile))
390
 
    {
391
 
      goto err;
392
 
    }
393
 
 
394
 
    if (flush_io_cache(&tempfile) || tempfile.reinit_io_cache(internal::READ_CACHE,0L,0,0))
395
 
    {
396
 
      goto err;
397
 
    }
398
 
 
399
 
    if (merge_index(&param,(unsigned char*) sort_keys,buffpek_inst,maxbuffer,&tempfile, outfile))
400
 
    {
401
 
      goto err;
402
 
    }
 
277
    if (merge_many_buff(&param,(unsigned char*) sort_keys,buffpek,&maxbuffer,
 
278
                        &tempfile))
 
279
      goto err;
 
280
    if (flush_io_cache(&tempfile) ||
 
281
        reinit_io_cache(&tempfile,READ_CACHE,0L,0,0))
 
282
      goto err;
 
283
    if (merge_index(&param,(unsigned char*) sort_keys,buffpek,maxbuffer,&tempfile,
 
284
                    outfile))
 
285
      goto err;
403
286
  }
404
 
 
405
287
  if (records > param.max_rows)
406
 
  {
407
 
    records= param.max_rows;
408
 
  }
 
288
    records=param.max_rows;
409
289
  error =0;
410
290
 
411
291
 err:
412
 
  if (not subselect || not subselect->is_uncacheable())
 
292
  if (param.tmp_buffer)
 
293
    if (param.tmp_buffer)
 
294
      free(param.tmp_buffer);
 
295
  if (!subselect || !subselect->is_uncacheable())
413
296
  {
414
 
    free(sort_keys);
 
297
    if ((unsigned char*) sort_keys)
 
298
      free((unsigned char*) sort_keys);
415
299
    table_sort.sort_keys= 0;
416
 
    free(buffpek_inst);
 
300
    if ((unsigned char*) buffpek)
 
301
      free((unsigned char*) buffpek);
417
302
    table_sort.buffpek= 0;
418
303
    table_sort.buffpek_len= 0;
419
304
  }
420
 
 
421
 
  tempfile.close_cached_file();
422
 
  buffpek_pointers.close_cached_file();
423
 
 
 
305
  close_cached_file(&tempfile);
 
306
  close_cached_file(&buffpek_pointers);
424
307
  if (my_b_inited(outfile))
425
308
  {
426
309
    if (flush_io_cache(outfile))
427
 
    {
428
310
      error=1;
429
 
    }
430
311
    {
431
 
      internal::my_off_t save_pos= outfile->pos_in_file;
 
312
      my_off_t save_pos=outfile->pos_in_file;
432
313
      /* For following reads */
433
 
      if (outfile->reinit_io_cache(internal::READ_CACHE,0L,0,0))
434
 
      {
 
314
      if (reinit_io_cache(outfile,READ_CACHE,0L,0,0))
435
315
        error=1;
436
 
      }
437
316
      outfile->end_of_file=save_pos;
438
317
    }
439
318
  }
440
 
 
441
319
  if (error)
442
 
  {
443
320
    my_message(ER_FILSORT_ABORT, ER(ER_FILSORT_ABORT),
444
321
               MYF(ME_ERROR+ME_WAITTANG));
445
 
  }
446
322
  else
447
 
  {
448
 
    getSession().status_var.filesort_rows+= (uint32_t) records;
449
 
  }
450
 
  examined_rows= param.examined_rows;
451
 
  global_sort_buffer.sub(allocated_sort_memory);
452
 
  table->sort= table_sort;
 
323
    statistic_add(session->status_var.filesort_rows,
 
324
                  (uint32_t) records, &LOCK_status);
 
325
  *examined_rows= param.examined_rows;
 
326
  memcpy(&table->sort, &table_sort, sizeof(filesort_info_st));
453
327
  DRIZZLE_FILESORT_DONE(error, records);
454
328
  return (error ? HA_POS_ERROR : records);
455
329
} /* filesort */
456
330
 
 
331
 
 
332
void Table::filesort_free_buffers(bool full)
 
333
{
 
334
  if (sort.record_pointers)
 
335
  {
 
336
    free((unsigned char*) sort.record_pointers);
 
337
    sort.record_pointers=0;
 
338
  }
 
339
  if (full)
 
340
  {
 
341
    if (sort.sort_keys )
 
342
    {
 
343
      if ((unsigned char*) sort.sort_keys)
 
344
        free((unsigned char*) sort.sort_keys);
 
345
      sort.sort_keys= 0;
 
346
    }
 
347
    if (sort.buffpek)
 
348
    {
 
349
      if ((unsigned char*) sort.buffpek)
 
350
        free((unsigned char*) sort.buffpek);
 
351
      sort.buffpek= 0;
 
352
      sort.buffpek_len= 0;
 
353
    }
 
354
  }
 
355
  if (sort.addon_buf)
 
356
  {
 
357
    free((char *) sort.addon_buf);
 
358
    free((char *) sort.addon_field);
 
359
    sort.addon_buf=0;
 
360
    sort.addon_field=0;
 
361
  }
 
362
}
 
363
 
457
364
/** Make a array of string pointers. */
458
365
 
459
 
static char **make_char_array(char **old_pos, uint32_t fields,
 
366
static char **make_char_array(char **old_pos, register uint32_t fields,
460
367
                              uint32_t length)
461
368
{
462
 
  char **pos;
 
369
  register char **pos;
463
370
  char *char_pos;
464
371
 
465
372
  if (old_pos ||
475
382
 
476
383
/** Read 'count' number of buffer pointers into memory. */
477
384
 
478
 
static unsigned char *read_buffpek_from_file(internal::IO_CACHE *buffpek_pointers, uint32_t count,
 
385
static unsigned char *read_buffpek_from_file(IO_CACHE *buffpek_pointers, uint32_t count,
479
386
                                     unsigned char *buf)
480
387
{
481
 
  uint32_t length= sizeof(buffpek)*count;
 
388
  uint32_t length= sizeof(BUFFPEK)*count;
482
389
  unsigned char *tmp= buf;
483
 
  if (count > UINT_MAX/sizeof(buffpek))
484
 
    return 0; /* sizeof(buffpek)*count will overflow */
 
390
  if (count > UINT_MAX/sizeof(BUFFPEK))
 
391
    return 0; /* sizeof(BUFFPEK)*count will overflow */
485
392
  if (!tmp)
486
393
    tmp= (unsigned char *)malloc(length);
487
394
  if (tmp)
488
395
  {
489
 
    if (buffpek_pointers->reinit_io_cache(internal::READ_CACHE,0L,0,0) ||
 
396
    if (reinit_io_cache(buffpek_pointers,READ_CACHE,0L,0,0) ||
490
397
        my_b_read(buffpek_pointers, (unsigned char*) tmp, length))
491
398
    {
492
399
      free((char*) tmp);
504
411
  @param param             Sorting parameter
505
412
  @param select            Use this to get source data
506
413
  @param sort_keys         Array of pointers to sort key + addon buffers.
507
 
  @param buffpek_pointers  File to write buffpeks describing sorted segments
 
414
  @param buffpek_pointers  File to write BUFFPEKs describing sorted segments
508
415
                           in tempfile.
509
416
  @param tempfile          File to write sorted sequences of sortkeys to.
510
417
  @param indexfile         If !NULL, use it for source data (contains rowids)
518
425
       {
519
426
         sort sort_keys buffer;
520
427
         dump sorted sequence to 'tempfile';
521
 
         dump buffpek describing sequence location into 'buffpek_pointers';
 
428
         dump BUFFPEK describing sequence location into 'buffpek_pointers';
522
429
       }
523
430
       put sort key into 'sort_keys';
524
431
     }
534
441
    HA_POS_ERROR on error.
535
442
*/
536
443
 
537
 
ha_rows FileSort::find_all_keys(SortParam *param, 
538
 
                                optimizer::SqlSelect *select,
539
 
                                unsigned char **sort_keys,
540
 
                                internal::IO_CACHE *buffpek_pointers,
541
 
                                internal::IO_CACHE *tempfile, internal::IO_CACHE *indexfile)
 
444
static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select,
 
445
                             unsigned char **sort_keys,
 
446
                             IO_CACHE *buffpek_pointers,
 
447
                             IO_CACHE *tempfile, IO_CACHE *indexfile)
542
448
{
543
449
  int error,flag,quick_select;
544
450
  uint32_t idx,indexpos,ref_length;
545
451
  unsigned char *ref_pos,*next_pos,ref_buff[MAX_REFLENGTH];
546
 
  internal::my_off_t record;
 
452
  my_off_t record;
547
453
  Table *sort_form;
548
 
  volatile Session::killed_state_t *killed= getSession().getKilledPtr();
549
 
  Cursor *file;
550
 
  boost::dynamic_bitset<> *save_read_set= NULL;
551
 
  boost::dynamic_bitset<> *save_write_set= NULL;
 
454
  Session *session= current_session;
 
455
  volatile Session::killed_state *killed= &session->killed;
 
456
  handler *file;
 
457
  MyBitmap *save_read_set, *save_write_set;
552
458
 
553
459
  idx=indexpos=0;
554
460
  error=quick_select=0;
555
461
  sort_form=param->sort_form;
556
 
  file= sort_form->cursor;
 
462
  file=sort_form->file;
557
463
  ref_length=param->ref_length;
558
464
  ref_pos= ref_buff;
559
465
  quick_select=select && select->quick;
560
466
  record=0;
561
 
  flag= ((!indexfile && ! file->isOrdered())
 
467
  flag= ((!indexfile && file->ha_table_flags() & HA_REC_NOT_IN_SEQ)
562
468
         || quick_select);
563
469
  if (indexfile || flag)
564
470
    ref_pos= &file->ref[0];
566
472
  if (! indexfile && ! quick_select)
567
473
  {
568
474
    next_pos=(unsigned char*) 0;                        /* Find records in sequence */
569
 
    if (file->startTableScan(1))
570
 
      return(HA_POS_ERROR);
571
 
    file->extra_opt(HA_EXTRA_CACHE, getSession().variables.read_buff_size);
 
475
    file->ha_rnd_init(1);
 
476
    file->extra_opt(HA_EXTRA_CACHE,
 
477
                    current_session->variables.read_buff_size);
572
478
  }
573
479
 
574
 
  ReadRecord read_record_info;
 
480
  READ_RECORD read_record_info;
575
481
  if (quick_select)
576
482
  {
577
483
    if (select->quick->reset())
578
484
      return(HA_POS_ERROR);
579
 
 
580
 
    if (read_record_info.init_read_record(&getSession(), select->quick->head, select, 1, 1))
581
 
      return(HA_POS_ERROR);
 
485
    init_read_record(&read_record_info, current_session, select->quick->head,
 
486
                     select, 1, 1);
582
487
  }
583
488
 
584
489
  /* Remember original bitmaps */
585
490
  save_read_set=  sort_form->read_set;
586
491
  save_write_set= sort_form->write_set;
587
492
  /* Set up temporary column read map for columns used by sort */
588
 
  sort_form->tmp_set.reset();
 
493
  sort_form->tmp_set.clearAll();
589
494
  /* Temporary set for register_used_fields and register_field_in_read_map */
590
495
  sort_form->read_set= &sort_form->tmp_set;
591
 
  param->register_used_fields();
 
496
  register_used_fields(param);
592
497
  if (select && select->cond)
593
498
    select->cond->walk(&Item::register_field_in_read_map, 1,
594
499
                       (unsigned char*) sort_form);
595
 
  sort_form->column_bitmaps_set(sort_form->tmp_set, sort_form->tmp_set);
 
500
  sort_form->column_bitmaps_set(&sort_form->tmp_set, &sort_form->tmp_set);
596
501
 
597
502
  for (;;)
598
503
  {
603
508
        error= HA_ERR_END_OF_FILE;
604
509
        break;
605
510
      }
606
 
      file->position(sort_form->getInsertRecord());
 
511
      file->position(sort_form->record[0]);
607
512
    }
608
513
    else                                        /* Not quick-select */
609
514
    {
611
516
      {
612
517
        if (my_b_read(indexfile,(unsigned char*) ref_pos,ref_length))
613
518
        {
614
 
          error= errno ? errno : -1;            /* Abort */
 
519
          error= my_errno ? my_errno : -1;              /* Abort */
615
520
          break;
616
521
        }
617
 
        error=file->rnd_pos(sort_form->getInsertRecord(),next_pos);
 
522
        error=file->rnd_pos(sort_form->record[0],next_pos);
618
523
      }
619
524
      else
620
525
      {
621
 
        error=file->rnd_next(sort_form->getInsertRecord());
 
526
        error=file->rnd_next(sort_form->record[0]);
622
527
 
623
528
        if (!flag)
624
529
        {
625
 
          internal::my_store_ptr(ref_pos,ref_length,record); // Position to row
626
 
          record+= sort_form->getShare()->db_record_offset;
 
530
          my_store_ptr(ref_pos,ref_length,record); // Position to row
 
531
          record+= sort_form->s->db_record_offset;
627
532
        }
628
533
        else if (!error)
629
 
          file->position(sort_form->getInsertRecord());
 
534
          file->position(sort_form->record[0]);
630
535
      }
631
536
      if (error && error != HA_ERR_RECORD_DELETED)
632
537
        break;
637
542
      if (!indexfile && !quick_select)
638
543
      {
639
544
        (void) file->extra(HA_EXTRA_NO_CACHE);
640
 
        file->endTableScan();
 
545
        file->ha_rnd_end();
641
546
      }
642
547
      return(HA_POS_ERROR);
643
548
    }
647
552
    {
648
553
      if (idx == param->keys)
649
554
      {
650
 
        if (param->write_keys(sort_keys, idx, buffpek_pointers, tempfile))
 
555
        if (write_keys(param,sort_keys,idx,buffpek_pointers,tempfile))
651
556
          return(HA_POS_ERROR);
652
557
        idx=0;
653
558
        indexpos++;
654
559
      }
655
 
      param->make_sortkey(sort_keys[idx++], ref_pos);
 
560
      make_sortkey(param,sort_keys[idx++],ref_pos);
656
561
    }
657
562
    else
658
 
    {
659
563
      file->unlock_row();
660
 
    }
661
 
 
662
564
    /* It does not make sense to read more keys in case of a fatal error */
663
 
    if (getSession().is_error())
 
565
    if (session->is_error())
664
566
      break;
665
567
  }
666
568
  if (quick_select)
669
571
      index_merge quick select uses table->sort when retrieving rows, so free
670
572
      resoures it has allocated.
671
573
    */
672
 
    read_record_info.end_read_record();
 
574
    end_read_record(&read_record_info);
673
575
  }
674
576
  else
675
577
  {
676
578
    (void) file->extra(HA_EXTRA_NO_CACHE);      /* End cacheing of records */
677
579
    if (!next_pos)
678
 
      file->endTableScan();
 
580
      file->ha_rnd_end();
679
581
  }
680
582
 
681
 
  if (getSession().is_error())
 
583
  if (session->is_error())
682
584
    return(HA_POS_ERROR);
683
585
 
684
586
  /* Signal we should use orignal column read and write maps */
685
 
  sort_form->column_bitmaps_set(*save_read_set, *save_write_set);
 
587
  sort_form->column_bitmaps_set(save_read_set, save_write_set);
686
588
 
687
589
  if (error != HA_ERR_END_OF_FILE)
688
590
  {
689
 
    sort_form->print_error(error,MYF(ME_ERROR | ME_WAITTANG));
690
 
    return(HA_POS_ERROR);
691
 
  }
692
 
 
693
 
  if (indexpos && idx && param->write_keys(sort_keys,idx,buffpek_pointers,tempfile))
694
 
  {
695
 
    return(HA_POS_ERROR);
696
 
  }
697
 
 
 
591
    file->print_error(error,MYF(ME_ERROR | ME_WAITTANG));
 
592
    return(HA_POS_ERROR);
 
593
  }
 
594
  if (indexpos && idx &&
 
595
      write_keys(param,sort_keys,idx,buffpek_pointers,tempfile))
 
596
    return(HA_POS_ERROR);
698
597
  return(my_b_inited(tempfile) ?
699
598
              (ha_rows) (my_b_tell(tempfile)/param->rec_length) :
700
599
              idx);
705
604
  @details
706
605
  Sort the buffer and write:
707
606
  -# the sorted sequence to tempfile
708
 
  -# a buffpek describing the sorted sequence position to buffpek_pointers
 
607
  -# a BUFFPEK describing the sorted sequence position to buffpek_pointers
709
608
 
710
609
    (was: Skriver en buffert med nycklar till filen)
711
610
 
712
611
  @param param             Sort parameters
713
612
  @param sort_keys         Array of pointers to keys to sort
714
613
  @param count             Number of elements in sort_keys array
715
 
  @param buffpek_pointers  One 'buffpek' struct will be written into this file.
716
 
                           The buffpek::{file_pos, count} will indicate where
 
614
  @param buffpek_pointers  One 'BUFFPEK' struct will be written into this file.
 
615
                           The BUFFPEK::{file_pos, count} will indicate where
717
616
                           the sorted data was stored.
718
617
  @param tempfile          The sorted sequence will be written into this file.
719
618
 
723
622
    1 Error
724
623
*/
725
624
 
726
 
int SortParam::write_keys(unsigned char **sort_keys, uint32_t count,
727
 
                          internal::IO_CACHE *buffpek_pointers, internal::IO_CACHE *tempfile)
 
625
static int
 
626
write_keys(SORTPARAM *param, register unsigned char **sort_keys, uint32_t count,
 
627
           IO_CACHE *buffpek_pointers, IO_CACHE *tempfile)
728
628
{
729
 
  buffpek buffpek;
 
629
  size_t sort_length, rec_length;
 
630
  unsigned char **end;
 
631
  BUFFPEK buffpek;
730
632
 
731
 
  internal::my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, sort_length);
 
633
  sort_length= param->sort_length;
 
634
  rec_length= param->rec_length;
 
635
  my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, sort_length);
732
636
  if (!my_b_inited(tempfile) &&
733
 
      tempfile->open_cached_file(drizzle_tmpdir.c_str(), TEMP_PREFIX, DISK_BUFFER_SIZE, MYF(MY_WME)))
734
 
  {
735
 
    return 1;
736
 
  }
 
637
      open_cached_file(tempfile, drizzle_tmpdir, TEMP_PREFIX, DISK_BUFFER_SIZE,
 
638
                       MYF(MY_WME)))
 
639
    goto err;
737
640
  /* check we won't have more buffpeks than we can possibly keep in memory */
738
 
  if (my_b_tell(buffpek_pointers) + sizeof(buffpek) > (uint64_t)UINT_MAX)
739
 
  {
740
 
    return 1;
741
 
  }
742
 
 
 
641
  if (my_b_tell(buffpek_pointers) + sizeof(BUFFPEK) > (uint64_t)UINT_MAX)
 
642
    goto err;
743
643
  buffpek.file_pos= my_b_tell(tempfile);
744
 
  if ((ha_rows) count > max_rows)
745
 
    count=(uint32_t) max_rows;
746
 
 
 
644
  if ((ha_rows) count > param->max_rows)
 
645
    count=(uint32_t) param->max_rows;
747
646
  buffpek.count=(ha_rows) count;
748
 
 
749
 
  for (unsigned char **ptr= sort_keys + count ; sort_keys != ptr ; sort_keys++)
750
 
  {
 
647
  for (end=sort_keys+count ; sort_keys != end ; sort_keys++)
751
648
    if (my_b_write(tempfile, (unsigned char*) *sort_keys, (uint32_t) rec_length))
752
 
    {
753
 
      return 1;
754
 
    }
755
 
  }
756
 
 
 
649
      goto err;
757
650
  if (my_b_write(buffpek_pointers, (unsigned char*) &buffpek, sizeof(buffpek)))
758
 
  {
759
 
    return 1;
760
 
  }
 
651
    goto err;
 
652
  return(0);
761
653
 
762
 
  return 0;
 
654
err:
 
655
  return(1);
763
656
} /* write_keys */
764
657
 
765
658
 
788
681
 
789
682
/** Make a sort-key from record. */
790
683
 
791
 
void SortParam::make_sortkey(unsigned char *to, unsigned char *ref_pos)
 
684
static void make_sortkey(register SORTPARAM *param,
 
685
                         register unsigned char *to, unsigned char *ref_pos)
792
686
{
793
 
  Field *field;
794
 
  SortField *sort_field;
 
687
  register Field *field;
 
688
  register SORT_FIELD *sort_field;
795
689
  size_t length;
796
690
 
797
 
  for (sort_field= local_sortorder ;
798
 
       sort_field != end ;
 
691
  for (sort_field=param->local_sortorder ;
 
692
       sort_field != param->end ;
799
693
       sort_field++)
800
694
  {
801
695
    bool maybe_null=0;
821
715
    {                                           // Item
822
716
      Item *item=sort_field->item;
823
717
      maybe_null= item->maybe_null;
824
 
 
825
718
      switch (sort_field->result_type) {
826
719
      case STRING_RESULT:
827
 
        {
828
 
          const CHARSET_INFO * const cs=item->collation.collation;
829
 
          char fill_char= ((cs->state & MY_CS_BINSORT) ? (char) 0 : ' ');
830
 
          int diff;
831
 
          uint32_t sort_field_length;
 
720
      {
 
721
        const CHARSET_INFO * const cs=item->collation.collation;
 
722
        char fill_char= ((cs->state & MY_CS_BINSORT) ? (char) 0 : ' ');
 
723
        int diff;
 
724
        uint32_t sort_field_length;
832
725
 
 
726
        if (maybe_null)
 
727
          *to++=1;
 
728
        /* All item->str() to use some extra byte for end null.. */
 
729
        String tmp((char*) to,sort_field->length+4,cs);
 
730
        String *res= item->str_result(&tmp);
 
731
        if (!res)
 
732
        {
833
733
          if (maybe_null)
834
 
            *to++=1;
835
 
          /* All item->str() to use some extra byte for end null.. */
836
 
          String tmp((char*) to,sort_field->length+4,cs);
837
 
          String *res= item->str_result(&tmp);
838
 
          if (!res)
839
 
          {
840
 
            if (maybe_null)
841
 
              memset(to-1, 0, sort_field->length+1);
842
 
            else
843
 
            {
844
 
              /*
845
 
                This should only happen during extreme conditions if we run out
846
 
                of memory or have an item marked not null when it can be null.
847
 
                This code is here mainly to avoid a hard crash in this case.
848
 
              */
849
 
              assert(0);
850
 
              memset(to, 0, sort_field->length);        // Avoid crash
851
 
            }
852
 
            break;
853
 
          }
854
 
          length= res->length();
855
 
          sort_field_length= sort_field->length - sort_field->suffix_length;
856
 
          diff=(int) (sort_field_length - length);
857
 
          if (diff < 0)
858
 
          {
859
 
            diff=0;
860
 
            length= sort_field_length;
861
 
          }
862
 
          if (sort_field->suffix_length)
863
 
          {
864
 
            /* Store length last in result_string */
865
 
            store_length(to + sort_field_length, length,
866
 
                         sort_field->suffix_length);
867
 
          }
868
 
          if (sort_field->need_strxnfrm)
869
 
          {
870
 
            char *from=(char*) res->ptr();
871
 
            uint32_t tmp_length;
872
 
            if ((unsigned char*) from == to)
873
 
            {
874
 
              set_if_smaller(length,sort_field->length);
875
 
              memcpy(tmp_buffer,from,length);
876
 
              from= tmp_buffer;
877
 
            }
878
 
            tmp_length= my_strnxfrm(cs,to,sort_field->length,
879
 
                                    (unsigned char*) from, length);
880
 
            assert(tmp_length == sort_field->length);
881
 
          }
 
734
            memset(to-1, 0, sort_field->length+1);
882
735
          else
883
736
          {
884
 
            my_strnxfrm(cs,(unsigned char*)to,length,(const unsigned char*)res->ptr(),length);
885
 
            cs->cset->fill(cs, (char *)to+length,diff,fill_char);
 
737
            /*
 
738
              This should only happen during extreme conditions if we run out
 
739
              of memory or have an item marked not null when it can be null.
 
740
              This code is here mainly to avoid a hard crash in this case.
 
741
            */
 
742
            assert(0);
 
743
            memset(to, 0, sort_field->length);  // Avoid crash
886
744
          }
887
745
          break;
888
746
        }
 
747
        length= res->length();
 
748
        sort_field_length= sort_field->length - sort_field->suffix_length;
 
749
        diff=(int) (sort_field_length - length);
 
750
        if (diff < 0)
 
751
        {
 
752
          diff=0;
 
753
          length= sort_field_length;
 
754
        }
 
755
        if (sort_field->suffix_length)
 
756
        {
 
757
          /* Store length last in result_string */
 
758
          store_length(to + sort_field_length, length,
 
759
                       sort_field->suffix_length);
 
760
        }
 
761
        if (sort_field->need_strxnfrm)
 
762
        {
 
763
          char *from=(char*) res->ptr();
 
764
          uint32_t tmp_length;
 
765
          if ((unsigned char*) from == to)
 
766
          {
 
767
            set_if_smaller(length,sort_field->length);
 
768
            memcpy(param->tmp_buffer,from,length);
 
769
            from=param->tmp_buffer;
 
770
          }
 
771
          tmp_length= my_strnxfrm(cs,to,sort_field->length,
 
772
                                  (unsigned char*) from, length);
 
773
          assert(tmp_length == sort_field->length);
 
774
        }
 
775
        else
 
776
        {
 
777
          my_strnxfrm(cs,(unsigned char*)to,length,(const unsigned char*)res->ptr(),length);
 
778
          cs->cset->fill(cs, (char *)to+length,diff,fill_char);
 
779
        }
 
780
        break;
 
781
      }
889
782
      case INT_RESULT:
890
 
        {
 
783
        {
891
784
          int64_t value= item->val_int_result();
892
785
          if (maybe_null)
893
786
          {
894
 
            *to++=1;
 
787
            *to++=1;
895
788
            if (item->null_value)
896
789
            {
897
790
              if (maybe_null)
903
796
              break;
904
797
            }
905
798
          }
906
 
          to[7]= (unsigned char) value;
907
 
          to[6]= (unsigned char) (value >> 8);
908
 
          to[5]= (unsigned char) (value >> 16);
909
 
          to[4]= (unsigned char) (value >> 24);
910
 
          to[3]= (unsigned char) (value >> 32);
911
 
          to[2]= (unsigned char) (value >> 40);
912
 
          to[1]= (unsigned char) (value >> 48);
 
799
          to[7]= (unsigned char) value;
 
800
          to[6]= (unsigned char) (value >> 8);
 
801
          to[5]= (unsigned char) (value >> 16);
 
802
          to[4]= (unsigned char) (value >> 24);
 
803
          to[3]= (unsigned char) (value >> 32);
 
804
          to[2]= (unsigned char) (value >> 40);
 
805
          to[1]= (unsigned char) (value >> 48);
913
806
          if (item->unsigned_flag)                    /* Fix sign */
914
807
            to[0]= (unsigned char) (value >> 56);
915
808
          else
916
809
            to[0]= (unsigned char) (value >> 56) ^ 128; /* Reverse signbit */
917
 
          break;
918
 
        }
 
810
          break;
 
811
        }
919
812
      case DECIMAL_RESULT:
920
813
        {
921
 
          type::Decimal dec_buf, *dec_val= item->val_decimal_result(&dec_buf);
 
814
          my_decimal dec_buf, *dec_val= item->val_decimal_result(&dec_buf);
922
815
          if (maybe_null)
923
816
          {
924
817
            if (item->null_value)
929
822
            }
930
823
            *to++=1;
931
824
          }
932
 
          dec_val->val_binary(E_DEC_FATAL_ERROR, to,
933
 
                              item->max_length - (item->decimals ? 1:0),
934
 
                              item->decimals);
935
 
          break;
 
825
          my_decimal2binary(E_DEC_FATAL_ERROR, dec_val, to,
 
826
                            item->max_length - (item->decimals ? 1:0),
 
827
                            item->decimals);
 
828
         break;
936
829
        }
937
830
      case REAL_RESULT:
938
 
        {
 
831
        {
939
832
          double value= item->val_result();
940
 
          if (maybe_null)
 
833
          if (maybe_null)
941
834
          {
942
835
            if (item->null_value)
943
836
            {
945
838
              to++;
946
839
              break;
947
840
            }
948
 
            *to++=1;
 
841
            *to++=1;
949
842
          }
950
 
          change_double_for_sort(value,(unsigned char*) to);
951
 
          break;
952
 
        }
 
843
          change_double_for_sort(value,(unsigned char*) to);
 
844
          break;
 
845
        }
953
846
      case ROW_RESULT:
954
847
      default:
955
 
        // This case should never be choosen
956
 
        assert(0);
957
 
        break;
 
848
        // This case should never be choosen
 
849
        assert(0);
 
850
        break;
958
851
      }
959
852
    }
960
 
 
961
853
    if (sort_field->reverse)
962
854
    {                                                   /* Revers key */
963
855
      if (maybe_null)
970
862
      }
971
863
    }
972
864
    else
973
 
    {
974
865
      to+= sort_field->length;
975
 
    }
976
866
  }
977
867
 
978
 
  if (addon_field)
 
868
  if (param->addon_field)
979
869
  {
980
870
    /*
981
871
      Save field values appended to sorted fields.
983
873
      In this implementation we use fixed layout for field values -
984
874
      the same for all records.
985
875
    */
986
 
    sort_addon_field *addonf= addon_field;
 
876
    SORT_ADDON_FIELD *addonf= param->addon_field;
987
877
    unsigned char *nulls= to;
988
878
    assert(addonf != 0);
989
879
    memset(nulls, 0, addonf->offset);
993
883
      if (addonf->null_bit && field->is_null())
994
884
      {
995
885
        nulls[addonf->null_offset]|= addonf->null_bit;
996
 
#ifdef HAVE_VALGRIND
 
886
#ifdef HAVE_purify
997
887
        memset(to, 0, addonf->length);
998
888
#endif
999
889
      }
1000
890
      else
1001
891
      {
1002
 
#ifdef HAVE_VALGRIND
 
892
#ifdef HAVE_purify
1003
893
        unsigned char *end= field->pack(to, field->ptr);
1004
 
        uint32_t local_length= (uint32_t) ((to + addonf->length) - end);
1005
 
        assert((int) local_length >= 0);
1006
 
        if (local_length)
1007
 
          memset(end, 0, local_length);
 
894
        uint32_t length= (uint32_t) ((to + addonf->length) - end);
 
895
        assert((int) length >= 0);
 
896
        if (length)
 
897
          memset(end, 0, length);
1008
898
#else
1009
899
        (void) field->pack(to, field->ptr);
1010
900
#endif
1015
905
  else
1016
906
  {
1017
907
    /* Save filepos last */
1018
 
    memcpy(to, ref_pos, (size_t) ref_length);
 
908
    memcpy(to, ref_pos, (size_t) param->ref_length);
1019
909
  }
 
910
  return;
1020
911
}
1021
912
 
1022
913
 
1023
914
/*
1024
 
  fields used by sorting in the sorted table's read set
 
915
  Register fields used by sorting in the sorted table's read set
1025
916
*/
1026
917
 
1027
 
void SortParam::register_used_fields()
 
918
static void register_used_fields(SORTPARAM *param)
1028
919
{
1029
 
  SortField *sort_field;
1030
 
  Table *table= sort_form;
 
920
  register SORT_FIELD *sort_field;
 
921
  Table *table=param->sort_form;
1031
922
 
1032
 
  for (sort_field= local_sortorder ;
1033
 
       sort_field != end ;
 
923
  for (sort_field= param->local_sortorder ;
 
924
       sort_field != param->end ;
1034
925
       sort_field++)
1035
926
  {
1036
927
    Field *field;
1037
928
    if ((field= sort_field->field))
1038
929
    {
1039
 
      if (field->getTable() == table)
1040
 
        table->setReadSet(field->position());
 
930
      if (field->table == table)
 
931
        table->setReadSet(field->field_index);
1041
932
    }
1042
933
    else
1043
934
    {                                           // Item
1046
937
    }
1047
938
  }
1048
939
 
1049
 
  if (addon_field)
 
940
  if (param->addon_field)
1050
941
  {
1051
 
    sort_addon_field *addonf= addon_field;
 
942
    SORT_ADDON_FIELD *addonf= param->addon_field;
1052
943
    Field *field;
1053
944
    for ( ; (field= addonf->field) ; addonf++)
1054
 
      table->setReadSet(field->position());
 
945
      table->setReadSet(field->field_index);
1055
946
  }
1056
947
  else
1057
948
  {
1061
952
}
1062
953
 
1063
954
 
1064
 
bool SortParam::save_index(unsigned char **sort_keys, uint32_t count, filesort_info *table_sort)
 
955
static bool save_index(SORTPARAM *param, unsigned char **sort_keys, uint32_t count,
 
956
                       filesort_info_st *table_sort)
1065
957
{
1066
 
  uint32_t offset;
 
958
  uint32_t offset,res_length;
1067
959
  unsigned char *to;
1068
960
 
1069
 
  internal::my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, sort_length);
1070
 
  offset= rec_length - res_length;
1071
 
 
1072
 
  if ((ha_rows) count > max_rows)
1073
 
    count=(uint32_t) max_rows;
1074
 
 
1075
 
  if (!(to= table_sort->record_pointers= (unsigned char*) malloc(res_length*count)))
1076
 
    return true;
1077
 
 
1078
 
  for (unsigned char **end_ptr= sort_keys+count ; sort_keys != end_ptr ; sort_keys++)
 
961
  my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, param->sort_length);
 
962
  res_length= param->res_length;
 
963
  offset= param->rec_length-res_length;
 
964
  if ((ha_rows) count > param->max_rows)
 
965
    count=(uint32_t) param->max_rows;
 
966
  if (!(to= table_sort->record_pointers=
 
967
        (unsigned char*) malloc(res_length*count)))
 
968
    return(1);
 
969
  for (unsigned char **end= sort_keys+count ; sort_keys != end ; sort_keys++)
1079
970
  {
1080
971
    memcpy(to, *sort_keys+offset, res_length);
1081
972
    to+= res_length;
1082
973
  }
1083
 
 
1084
 
  return false;
 
974
  return(0);
1085
975
}
1086
976
 
1087
977
 
1088
978
/** Merge buffers to make < MERGEBUFF2 buffers. */
1089
979
 
1090
 
int FileSort::merge_many_buff(SortParam *param, unsigned char *sort_buffer,
1091
 
                              buffpek *buffpek_inst, uint32_t *maxbuffer, internal::IO_CACHE *t_file)
 
980
int merge_many_buff(SORTPARAM *param, unsigned char *sort_buffer,
 
981
                    BUFFPEK *buffpek, uint32_t *maxbuffer, IO_CACHE *t_file)
1092
982
{
1093
 
  internal::IO_CACHE t_file2,*from_file,*to_file,*temp;
1094
 
  buffpek *lastbuff;
 
983
  register uint32_t i;
 
984
  IO_CACHE t_file2,*from_file,*to_file,*temp;
 
985
  BUFFPEK *lastbuff;
1095
986
 
1096
987
  if (*maxbuffer < MERGEBUFF2)
1097
 
    return 0;
 
988
    return(0);
1098
989
  if (flush_io_cache(t_file) ||
1099
 
      t_file2.open_cached_file(drizzle_tmpdir.c_str(),TEMP_PREFIX,DISK_BUFFER_SIZE, MYF(MY_WME)))
1100
 
  {
1101
 
    return 1;
1102
 
  }
 
990
      open_cached_file(&t_file2,drizzle_tmpdir,TEMP_PREFIX,DISK_BUFFER_SIZE,
 
991
                        MYF(MY_WME)))
 
992
    return(1);
1103
993
 
1104
994
  from_file= t_file ; to_file= &t_file2;
1105
995
  while (*maxbuffer >= MERGEBUFF2)
1106
996
  {
1107
 
    uint32_t i;
1108
 
 
1109
 
    if (from_file->reinit_io_cache(internal::READ_CACHE,0L,0,0))
1110
 
    {
1111
 
      break;
1112
 
    }
1113
 
 
1114
 
    if (to_file->reinit_io_cache(internal::WRITE_CACHE,0L,0,0))
1115
 
    {
1116
 
      break;
1117
 
    }
1118
 
 
1119
 
    lastbuff=buffpek_inst;
 
997
    if (reinit_io_cache(from_file,READ_CACHE,0L,0,0))
 
998
      goto cleanup;
 
999
    if (reinit_io_cache(to_file,WRITE_CACHE,0L,0,0))
 
1000
      goto cleanup;
 
1001
    lastbuff=buffpek;
1120
1002
    for (i=0 ; i <= *maxbuffer-MERGEBUFF*3/2 ; i+=MERGEBUFF)
1121
1003
    {
1122
1004
      if (merge_buffers(param,from_file,to_file,sort_buffer,lastbuff++,
1123
 
                        buffpek_inst+i,buffpek_inst+i+MERGEBUFF-1,0))
1124
 
      {
1125
 
        goto cleanup;
1126
 
      }
 
1005
                        buffpek+i,buffpek+i+MERGEBUFF-1,0))
 
1006
      goto cleanup;
1127
1007
    }
1128
 
 
1129
1008
    if (merge_buffers(param,from_file,to_file,sort_buffer,lastbuff++,
1130
 
                      buffpek_inst+i,buffpek_inst+ *maxbuffer,0))
1131
 
    {
 
1009
                      buffpek+i,buffpek+ *maxbuffer,0))
1132
1010
      break;
1133
 
    }
1134
 
 
1135
1011
    if (flush_io_cache(to_file))
1136
 
    {
1137
1012
      break;
1138
 
    }
1139
 
 
1140
1013
    temp=from_file; from_file=to_file; to_file=temp;
1141
 
    from_file->setup_io_cache();
1142
 
    to_file->setup_io_cache();
1143
 
    *maxbuffer= (uint32_t) (lastbuff-buffpek_inst)-1;
 
1014
    setup_io_cache(from_file);
 
1015
    setup_io_cache(to_file);
 
1016
    *maxbuffer= (uint32_t) (lastbuff-buffpek)-1;
1144
1017
  }
1145
 
 
1146
1018
cleanup:
1147
 
  to_file->close_cached_file();                 // This holds old result
 
1019
  close_cached_file(to_file);                   // This holds old result
1148
1020
  if (to_file == t_file)
1149
1021
  {
1150
1022
    *t_file=t_file2;                            // Copy result file
1151
 
    t_file->setup_io_cache();
 
1023
    setup_io_cache(t_file);
1152
1024
  }
1153
1025
 
1154
1026
  return(*maxbuffer >= MERGEBUFF2);     /* Return 1 if interrupted */
1162
1034
    (uint32_t)-1 if something goes wrong
1163
1035
*/
1164
1036
 
1165
 
uint32_t FileSort::read_to_buffer(internal::IO_CACHE *fromfile, buffpek *buffpek_inst, uint32_t rec_length)
 
1037
uint32_t read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek,
 
1038
                        uint32_t rec_length)
1166
1039
{
1167
 
  uint32_t count;
 
1040
  register uint32_t count;
1168
1041
  uint32_t length;
1169
1042
 
1170
 
  if ((count= (uint32_t) min((ha_rows) buffpek_inst->max_keys,buffpek_inst->count)))
 
1043
  if ((count= (uint32_t) min((ha_rows) buffpek->max_keys,buffpek->count)))
1171
1044
  {
1172
 
    if (pread(fromfile->file,(unsigned char*) buffpek_inst->base, (length= rec_length*count),buffpek_inst->file_pos) == 0)
 
1045
    if (pread(fromfile->file,(unsigned char*) buffpek->base, (length= rec_length*count),buffpek->file_pos) == 0)
1173
1046
      return((uint32_t) -1);
1174
1047
 
1175
 
    buffpek_inst->key= buffpek_inst->base;
1176
 
    buffpek_inst->file_pos+= length;                    /* New filepos */
1177
 
    buffpek_inst->count-= count;
1178
 
    buffpek_inst->mem_count= count;
 
1048
    buffpek->key= buffpek->base;
 
1049
    buffpek->file_pos+= length;                 /* New filepos */
 
1050
    buffpek->count-= count;
 
1051
    buffpek->mem_count= count;
1179
1052
  }
1180
1053
  return (count*rec_length);
1181
1054
} /* read_to_buffer */
1185
1058
{
1186
1059
  qsort2_cmp key_compare;
1187
1060
  void *key_compare_arg;
1188
 
 
1189
1061
  public:
1190
 
  compare_functor(qsort2_cmp in_key_compare, void *in_compare_arg) :
1191
 
    key_compare(in_key_compare),
1192
 
    key_compare_arg(in_compare_arg)
1193
 
  { }
1194
 
  
1195
 
  inline bool operator()(const buffpek *i, const buffpek *j) const
 
1062
  compare_functor(qsort2_cmp in_key_compare, void *in_compare_arg)
 
1063
    : key_compare(in_key_compare), key_compare_arg(in_compare_arg) { }
 
1064
  inline bool operator()(const BUFFPEK *i, const BUFFPEK *j) const
1196
1065
  {
1197
 
    int val= key_compare(key_compare_arg, &i->key, &j->key);
1198
 
 
 
1066
    int val= key_compare(key_compare_arg,
 
1067
                      &i->key, &j->key);
1199
1068
    return (val >= 0);
1200
1069
  }
1201
1070
};
1205
1074
  Merge buffers to one buffer.
1206
1075
 
1207
1076
  @param param        Sort parameter
1208
 
  @param from_file    File with source data (buffpeks point to this file)
 
1077
  @param from_file    File with source data (BUFFPEKs point to this file)
1209
1078
  @param to_file      File to write the sorted result data.
1210
1079
  @param sort_buffer  Buffer for data to store up to MERGEBUFF2 sort keys.
1211
 
  @param lastbuff     OUT Store here buffpek describing data written to to_file
1212
 
  @param Fb           First element in source buffpeks array
1213
 
  @param Tb           Last element in source buffpeks array
 
1080
  @param lastbuff     OUT Store here BUFFPEK describing data written to to_file
 
1081
  @param Fb           First element in source BUFFPEKs array
 
1082
  @param Tb           Last element in source BUFFPEKs array
1214
1083
  @param flag
1215
1084
 
1216
1085
  @retval
1219
1088
    other  error
1220
1089
*/
1221
1090
 
1222
 
int FileSort::merge_buffers(SortParam *param, internal::IO_CACHE *from_file,
1223
 
                            internal::IO_CACHE *to_file, unsigned char *sort_buffer,
1224
 
                            buffpek *lastbuff, buffpek *Fb, buffpek *Tb,
1225
 
                            int flag)
 
1091
int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
 
1092
                  IO_CACHE *to_file, unsigned char *sort_buffer,
 
1093
                  BUFFPEK *lastbuff, BUFFPEK *Fb, BUFFPEK *Tb,
 
1094
                  int flag)
1226
1095
{
1227
1096
  int error;
1228
1097
  uint32_t rec_length,res_length,offset;
1229
1098
  size_t sort_length;
1230
1099
  uint32_t maxcount;
1231
1100
  ha_rows max_rows,org_max_rows;
1232
 
  internal::my_off_t to_start_filepos;
 
1101
  my_off_t to_start_filepos;
1233
1102
  unsigned char *strpos;
1234
 
  buffpek *buffpek_inst;
 
1103
  BUFFPEK *buffpek;
1235
1104
  qsort2_cmp cmp;
1236
1105
  void *first_cmp_arg;
1237
 
  volatile Session::killed_state_t *killed= getSession().getKilledPtr();
1238
 
  Session::killed_state_t not_killable;
 
1106
  volatile Session::killed_state *killed= &current_session->killed;
 
1107
  Session::killed_state not_killable;
1239
1108
 
1240
 
  getSession().status_var.filesort_merge_passes++;
 
1109
  status_var_increment(current_session->status_var.filesort_merge_passes);
1241
1110
  if (param->not_killable)
1242
1111
  {
1243
1112
    killed= &not_killable;
1264
1133
  }
1265
1134
  else
1266
1135
  {
1267
 
    cmp= internal::get_ptr_compare(sort_length);
 
1136
    cmp= get_ptr_compare(sort_length);
1268
1137
    first_cmp_arg= (void*) &sort_length;
1269
1138
  }
1270
 
  priority_queue<buffpek *, vector<buffpek *>, compare_functor >
 
1139
  priority_queue<BUFFPEK *, vector<BUFFPEK *>, compare_functor > 
1271
1140
    queue(compare_functor(cmp, first_cmp_arg));
1272
 
  for (buffpek_inst= Fb ; buffpek_inst <= Tb ; buffpek_inst++)
 
1141
  for (buffpek= Fb ; buffpek <= Tb ; buffpek++)
1273
1142
  {
1274
 
    buffpek_inst->base= strpos;
1275
 
    buffpek_inst->max_keys= maxcount;
1276
 
    strpos+= (uint32_t) (error= (int) read_to_buffer(from_file, buffpek_inst,
 
1143
    buffpek->base= strpos;
 
1144
    buffpek->max_keys= maxcount;
 
1145
    strpos+= (uint32_t) (error= (int) read_to_buffer(from_file, buffpek,
1277
1146
                                                                         rec_length));
1278
1147
    if (error == -1)
1279
 
      return -1;
1280
 
 
1281
 
    buffpek_inst->max_keys= buffpek_inst->mem_count;    // If less data in buffers than expected
1282
 
    queue.push(buffpek_inst);
 
1148
      goto err;
 
1149
    buffpek->max_keys= buffpek->mem_count;      // If less data in buffers than expected
 
1150
    queue.push(buffpek);
1283
1151
  }
1284
1152
 
1285
1153
  if (param->unique_buff)
1292
1160
       This is safe as we know that there is always more than one element
1293
1161
       in each block to merge (This is guaranteed by the Unique:: algorithm
1294
1162
    */
1295
 
    buffpek_inst= queue.top();
1296
 
    memcpy(param->unique_buff, buffpek_inst->key, rec_length);
1297
 
    if (my_b_write(to_file, (unsigned char*) buffpek_inst->key, rec_length))
 
1163
    buffpek= queue.top();
 
1164
    memcpy(param->unique_buff, buffpek->key, rec_length);
 
1165
    if (my_b_write(to_file, (unsigned char*) buffpek->key, rec_length))
1298
1166
    {
1299
 
      return 1;
 
1167
      error=1; goto err;
1300
1168
    }
1301
 
    buffpek_inst->key+= rec_length;
1302
 
    buffpek_inst->mem_count--;
 
1169
    buffpek->key+= rec_length;
 
1170
    buffpek->mem_count--;
1303
1171
    if (!--max_rows)
1304
1172
    {
1305
1173
      error= 0;
1307
1175
    }
1308
1176
    /* Top element has been used */
1309
1177
    queue.pop();
1310
 
    queue.push(buffpek_inst);
 
1178
    queue.push(buffpek);
1311
1179
  }
1312
1180
  else
1313
 
  {
1314
1181
    cmp= 0;                                        // Not unique
1315
 
  }
1316
1182
 
1317
1183
  while (queue.size() > 1)
1318
1184
  {
1319
1185
    if (*killed)
1320
1186
    {
1321
 
      return 1;
 
1187
      error= 1; goto err;
1322
1188
    }
1323
1189
    for (;;)
1324
1190
    {
1325
 
      buffpek_inst= queue.top();
 
1191
      buffpek= queue.top();
1326
1192
      if (cmp)                                        // Remove duplicates
1327
1193
      {
1328
1194
        if (!(*cmp)(first_cmp_arg, &(param->unique_buff),
1329
 
                    (unsigned char**) &buffpek_inst->key))
 
1195
                    (unsigned char**) &buffpek->key))
1330
1196
              goto skip_duplicate;
1331
 
            memcpy(param->unique_buff, buffpek_inst->key, rec_length);
 
1197
            memcpy(param->unique_buff, buffpek->key, rec_length);
1332
1198
      }
1333
1199
      if (flag == 0)
1334
1200
      {
1335
 
        if (my_b_write(to_file,(unsigned char*) buffpek_inst->key, rec_length))
 
1201
        if (my_b_write(to_file,(unsigned char*) buffpek->key, rec_length))
1336
1202
        {
1337
 
          return 1;
 
1203
          error=1; goto err;
1338
1204
        }
1339
1205
      }
1340
1206
      else
1341
1207
      {
1342
 
        if (my_b_write(to_file, (unsigned char*) buffpek_inst->key+offset, res_length))
 
1208
        if (my_b_write(to_file, (unsigned char*) buffpek->key+offset, res_length))
1343
1209
        {
1344
 
          return 1;
 
1210
          error=1; goto err;
1345
1211
        }
1346
1212
      }
1347
1213
      if (!--max_rows)
1351
1217
      }
1352
1218
 
1353
1219
    skip_duplicate:
1354
 
      buffpek_inst->key+= rec_length;
1355
 
      if (! --buffpek_inst->mem_count)
 
1220
      buffpek->key+= rec_length;
 
1221
      if (! --buffpek->mem_count)
1356
1222
      {
1357
 
        if (!(error= (int) read_to_buffer(from_file,buffpek_inst,
 
1223
        if (!(error= (int) read_to_buffer(from_file,buffpek,
1358
1224
                                          rec_length)))
1359
1225
        {
1360
1226
          queue.pop();
1361
1227
          break;                        /* One buffer have been removed */
1362
1228
        }
1363
1229
        else if (error == -1)
1364
 
        {
1365
 
          return -1;
1366
 
        }
 
1230
          goto err;
1367
1231
      }
1368
1232
      /* Top element has been replaced */
1369
1233
      queue.pop();
1370
 
      queue.push(buffpek_inst);
 
1234
      queue.push(buffpek);
1371
1235
    }
1372
1236
  }
1373
 
  buffpek_inst= queue.top();
1374
 
  buffpek_inst->base= sort_buffer;
1375
 
  buffpek_inst->max_keys= param->keys;
 
1237
  buffpek= queue.top();
 
1238
  buffpek->base= sort_buffer;
 
1239
  buffpek->max_keys= param->keys;
1376
1240
 
1377
1241
  /*
1378
1242
    As we know all entries in the buffer are unique, we only have to
1380
1244
  */
1381
1245
  if (cmp)
1382
1246
  {
1383
 
    if (!(*cmp)(first_cmp_arg, &(param->unique_buff), (unsigned char**) &buffpek_inst->key))
 
1247
    if (!(*cmp)(first_cmp_arg, &(param->unique_buff), (unsigned char**) &buffpek->key))
1384
1248
    {
1385
 
      buffpek_inst->key+= rec_length;         // Remove duplicate
1386
 
      --buffpek_inst->mem_count;
 
1249
      buffpek->key+= rec_length;         // Remove duplicate
 
1250
      --buffpek->mem_count;
1387
1251
    }
1388
1252
  }
1389
1253
 
1390
1254
  do
1391
1255
  {
1392
 
    if ((ha_rows) buffpek_inst->mem_count > max_rows)
 
1256
    if ((ha_rows) buffpek->mem_count > max_rows)
1393
1257
    {                                        /* Don't write too many records */
1394
 
      buffpek_inst->mem_count= (uint32_t) max_rows;
1395
 
      buffpek_inst->count= 0;                        /* Don't read more */
 
1258
      buffpek->mem_count= (uint32_t) max_rows;
 
1259
      buffpek->count= 0;                        /* Don't read more */
1396
1260
    }
1397
 
    max_rows-= buffpek_inst->mem_count;
 
1261
    max_rows-= buffpek->mem_count;
1398
1262
    if (flag == 0)
1399
1263
    {
1400
 
      if (my_b_write(to_file,(unsigned char*) buffpek_inst->key,
1401
 
                     (rec_length*buffpek_inst->mem_count)))
 
1264
      if (my_b_write(to_file,(unsigned char*) buffpek->key,
 
1265
                     (rec_length*buffpek->mem_count)))
1402
1266
      {
1403
 
        return 1;
 
1267
        error= 1; goto err;
1404
1268
      }
1405
1269
    }
1406
1270
    else
1407
1271
    {
1408
 
      unsigned char *end;
1409
 
      strpos= buffpek_inst->key+offset;
1410
 
      for (end= strpos+buffpek_inst->mem_count*rec_length ;
 
1272
      register unsigned char *end;
 
1273
      strpos= buffpek->key+offset;
 
1274
      for (end= strpos+buffpek->mem_count*rec_length ;
1411
1275
           strpos != end ;
1412
1276
           strpos+= rec_length)
1413
1277
      {
1414
1278
        if (my_b_write(to_file, (unsigned char *) strpos, res_length))
1415
1279
        {
1416
 
          return 1;
 
1280
          error=1; goto err;
1417
1281
        }
1418
1282
      }
1419
1283
    }
1420
1284
  }
1421
 
 
1422
 
  while ((error=(int) read_to_buffer(from_file,buffpek_inst, rec_length))
 
1285
  while ((error=(int) read_to_buffer(from_file,buffpek, rec_length))
1423
1286
         != -1 && error != 0);
1424
1287
 
1425
1288
end:
1426
1289
  lastbuff->count= min(org_max_rows-max_rows, param->max_rows);
1427
1290
  lastbuff->file_pos= to_start_filepos;
1428
 
 
1429
 
  return error;
 
1291
err:
 
1292
  return(error);
1430
1293
} /* merge_buffers */
1431
1294
 
1432
1295
 
1433
1296
        /* Do a merge to output-file (save only positions) */
1434
1297
 
1435
 
int FileSort::merge_index(SortParam *param, unsigned char *sort_buffer,
1436
 
                          buffpek *buffpek_inst, uint32_t maxbuffer,
1437
 
                          internal::IO_CACHE *tempfile, internal::IO_CACHE *outfile)
 
1298
static int merge_index(SORTPARAM *param, unsigned char *sort_buffer,
 
1299
                       BUFFPEK *buffpek, uint32_t maxbuffer,
 
1300
                       IO_CACHE *tempfile, IO_CACHE *outfile)
1438
1301
{
1439
 
  if (merge_buffers(param,tempfile,outfile,sort_buffer,buffpek_inst,buffpek_inst,
1440
 
                    buffpek_inst+maxbuffer,1))
1441
 
    return 1;
1442
 
 
1443
 
  return 0;
 
1302
  if (merge_buffers(param,tempfile,outfile,sort_buffer,buffpek,buffpek,
 
1303
                    buffpek+maxbuffer,1))
 
1304
    return(1);
 
1305
  return(0);
1444
1306
} /* merge_index */
1445
1307
 
1446
1308
 
1460
1322
/**
1461
1323
  Calculate length of sort key.
1462
1324
 
 
1325
  @param session                          Thread handler
1463
1326
  @param sortorder                Order of items to sort
1464
1327
  @param s_length                 Number of items to sort
1465
1328
  @param[out] multi_byte_charset Set to 1 if we are using multi-byte charset
1474
1337
    Total length of sort buffer in bytes
1475
1338
*/
1476
1339
 
1477
 
uint32_t FileSort::sortlength(SortField *sortorder, uint32_t s_length, bool *multi_byte_charset)
 
1340
static uint32_t
 
1341
sortlength(Session *session, SORT_FIELD *sortorder, uint32_t s_length,
 
1342
           bool *multi_byte_charset)
1478
1343
{
1479
 
  uint32_t length;
 
1344
  register uint32_t length;
1480
1345
  const CHARSET_INFO *cs;
1481
1346
  *multi_byte_charset= 0;
1482
1347
 
1504
1369
      sortorder->result_type= sortorder->item->result_type();
1505
1370
      if (sortorder->item->result_as_int64_t())
1506
1371
        sortorder->result_type= INT_RESULT;
1507
 
 
1508
1372
      switch (sortorder->result_type) {
1509
1373
      case STRING_RESULT:
1510
 
        sortorder->length=sortorder->item->max_length;
 
1374
        sortorder->length=sortorder->item->max_length;
1511
1375
        set_if_smaller(sortorder->length,
1512
 
                       getSession().variables.max_sort_length);
1513
 
        if (use_strnxfrm((cs=sortorder->item->collation.collation)))
1514
 
        {
 
1376
                       session->variables.max_sort_length);
 
1377
        if (use_strnxfrm((cs=sortorder->item->collation.collation)))
 
1378
        {
1515
1379
          sortorder->length= cs->coll->strnxfrmlen(cs, sortorder->length);
1516
 
          sortorder->need_strxnfrm= 1;
1517
 
          *multi_byte_charset= 1;
1518
 
        }
 
1380
          sortorder->need_strxnfrm= 1;
 
1381
          *multi_byte_charset= 1;
 
1382
        }
1519
1383
        else if (cs == &my_charset_bin)
1520
1384
        {
1521
1385
          /* Store length last to be able to sort blob/varbinary */
1522
1386
          sortorder->suffix_length= suffix_length(sortorder->length);
1523
1387
          sortorder->length+= sortorder->suffix_length;
1524
1388
        }
1525
 
        break;
 
1389
        break;
1526
1390
      case INT_RESULT:
1527
 
        sortorder->length=8;                    // Size of intern int64_t
1528
 
        break;
 
1391
        sortorder->length=8;                    // Size of intern int64_t
 
1392
        break;
1529
1393
      case DECIMAL_RESULT:
1530
1394
        sortorder->length=
1531
 
          class_decimal_get_binary_size(sortorder->item->max_length -
 
1395
          my_decimal_get_binary_size(sortorder->item->max_length -
1532
1396
                                     (sortorder->item->decimals ? 1 : 0),
1533
1397
                                     sortorder->item->decimals);
1534
1398
        break;
1535
1399
      case REAL_RESULT:
1536
 
        sortorder->length=sizeof(double);
1537
 
        break;
 
1400
        sortorder->length=sizeof(double);
 
1401
        break;
1538
1402
      case ROW_RESULT:
1539
 
        // This case should never be choosen
1540
 
        assert(0);
1541
 
        break;
 
1403
      default:
 
1404
        // This case should never be choosen
 
1405
        assert(0);
 
1406
        break;
1542
1407
      }
1543
1408
      if (sortorder->item->maybe_null)
1544
 
        length++;                               // Place for NULL marker
 
1409
        length++;                               // Place for NULL marker
1545
1410
    }
1546
 
    set_if_smaller(sortorder->length, (size_t)getSession().variables.max_sort_length);
 
1411
    set_if_smaller(sortorder->length,
 
1412
                   (size_t)session->variables.max_sort_length);
1547
1413
    length+=sortorder->length;
1548
1414
  }
1549
1415
  sortorder->field= (Field*) 0;                 // end marker
1563
1429
  layouts for the values of the non-sorted fields in the buffer and
1564
1430
  fills them.
1565
1431
 
 
1432
  @param session                 Current thread
1566
1433
  @param ptabfield           Array of references to the table fields
1567
1434
  @param sortlength          Total length of sorted fields
1568
1435
  @param[out] plength        Total length of appended fields
1577
1444
    NULL   if we do not store field values with sort data.
1578
1445
*/
1579
1446
 
1580
 
sort_addon_field *FileSort::get_addon_fields(Field **ptabfield, uint32_t sortlength_arg, uint32_t *plength)
 
1447
static SORT_ADDON_FIELD *
 
1448
get_addon_fields(Session *session, Field **ptabfield, uint32_t sortlength, uint32_t *plength)
1581
1449
{
1582
1450
  Field **pfield;
1583
1451
  Field *field;
1584
 
  sort_addon_field *addonf;
 
1452
  SORT_ADDON_FIELD *addonf;
1585
1453
  uint32_t length= 0;
1586
1454
  uint32_t fields= 0;
1587
1455
  uint32_t null_fields= 0;
1612
1480
    return 0;
1613
1481
  length+= (null_fields+7)/8;
1614
1482
 
1615
 
  if (length+sortlength_arg > getSession().variables.max_length_for_sort_data ||
1616
 
      !(addonf= (sort_addon_field *) malloc(sizeof(sort_addon_field)*
 
1483
  if (length+sortlength > session->variables.max_length_for_sort_data ||
 
1484
      !(addonf= (SORT_ADDON_FIELD *) malloc(sizeof(SORT_ADDON_FIELD)*
1617
1485
                                            (fields+1))))
1618
1486
    return 0;
1619
1487
 
1663
1531
*/
1664
1532
 
1665
1533
static void
1666
 
unpack_addon_fields(sort_addon_field *addon_field, unsigned char *buff)
 
1534
unpack_addon_fields(struct st_sort_addon_field *addon_field, unsigned char *buff)
1667
1535
{
1668
1536
  Field *field;
1669
 
  sort_addon_field *addonf= addon_field;
 
1537
  SORT_ADDON_FIELD *addonf= addon_field;
1670
1538
 
1671
1539
  for ( ; (field= addonf->field) ; addonf++)
1672
1540
  {
1727
1595
    }
1728
1596
  }
1729
1597
}
1730
 
 
1731
 
} /* namespace drizzled */