~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/filesort.cc

  • Committer: Brian Aker
  • Date: 2009-07-11 19:23:04 UTC
  • mfrom: (1089.1.14 merge)
  • Revision ID: brian@gaz-20090711192304-ootijyl5yf9jq9kd
Merge Brian

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
22
22
*/
23
23
 
24
24
#include <drizzled/server_includes.h>
25
 
#include "sql_sort.h"
26
 
#include <drizzled/drizzled_error_messages.h>
27
 
 
28
 
/// How to write record_ref.
29
 
#define WRITE_REF(file,from) \
30
 
if (my_b_write((file),(uchar*) (from),param->ref_length)) \
31
 
  return(1);
32
 
 
33
 
        /* functions defined in this file */
34
 
 
35
 
static char **make_char_array(char **old_pos, register uint fields,
36
 
                              uint length, myf my_flag);
37
 
static uchar *read_buffpek_from_file(IO_CACHE *buffer_file, uint count,
38
 
                                     uchar *buf);
 
25
#include <drizzled/sql_sort.h>
 
26
#include <drizzled/error.h>
 
27
#include <drizzled/probes.h>
 
28
#include <drizzled/session.h>
 
29
#include <drizzled/table.h>
 
30
#include <drizzled/table_list.h>
 
31
 
 
32
#include <queue>
 
33
#include <algorithm>
 
34
 
 
35
using namespace std;
 
36
 
 
37
/* functions defined in this file */
 
38
 
 
39
static char **make_char_array(char **old_pos, register uint32_t fields,
 
40
                              uint32_t length);
 
41
static unsigned char *read_buffpek_from_file(IO_CACHE *buffer_file, uint32_t count,
 
42
                                     unsigned char *buf);
39
43
static ha_rows find_all_keys(SORTPARAM *param,SQL_SELECT *select,
40
 
                             uchar * *sort_keys, IO_CACHE *buffer_file,
 
44
                             unsigned char * *sort_keys, IO_CACHE *buffer_file,
41
45
                             IO_CACHE *tempfile,IO_CACHE *indexfile);
42
 
static int write_keys(SORTPARAM *param,uchar * *sort_keys,
43
 
                      uint count, IO_CACHE *buffer_file, IO_CACHE *tempfile);
44
 
static void make_sortkey(SORTPARAM *param,uchar *to, uchar *ref_pos);
 
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);
45
49
static void register_used_fields(SORTPARAM *param);
46
 
static int merge_index(SORTPARAM *param,uchar *sort_buffer,
 
50
static int merge_index(SORTPARAM *param,unsigned char *sort_buffer,
47
51
                       BUFFPEK *buffpek,
48
 
                       uint maxbuffer,IO_CACHE *tempfile,
 
52
                       uint32_t maxbuffer,IO_CACHE *tempfile,
49
53
                       IO_CACHE *outfile);
50
 
static bool save_index(SORTPARAM *param,uchar **sort_keys, uint count, 
51
 
                       FILESORT_INFO *table_sort);
52
 
static uint suffix_length(uint32_t string_length);
53
 
static uint sortlength(THD *thd, SORT_FIELD *sortorder, uint s_length,
 
54
static bool save_index(SORTPARAM *param,unsigned char **sort_keys, uint32_t count,
 
55
                       filesort_info_st *table_sort);
 
56
static uint32_t suffix_length(uint32_t string_length);
 
57
static uint32_t sortlength(Session *session, SORT_FIELD *sortorder, uint32_t s_length,
54
58
                       bool *multi_byte_charset);
55
 
static SORT_ADDON_FIELD *get_addon_fields(THD *thd, Field **ptabfield,
56
 
                                          uint sortlength, uint *plength);
 
59
static SORT_ADDON_FIELD *get_addon_fields(Session *session, Field **ptabfield,
 
60
                                          uint32_t sortlength, uint32_t *plength);
57
61
static void unpack_addon_fields(struct st_sort_addon_field *addon_field,
58
 
                                uchar *buff);
 
62
                                unsigned char *buff);
59
63
/**
60
64
  Sort a table.
61
65
  Creates a set of pointers that can be used to read the rows
68
72
  The result set is stored in table->io_cache or
69
73
  table->record_pointers.
70
74
 
71
 
  @param thd           Current thread
 
75
  @param session           Current thread
72
76
  @param table          Table to sort
73
77
  @param sortorder      How to sort the table
74
78
  @param s_length       Number of elements in sortorder
75
79
  @param select         condition to apply to the rows
76
80
  @param max_rows       Return only this many rows
77
81
  @param sort_positions Set to 1 if we want to force sorting by position
78
 
                        (Needed by UPDATE/INSERT or ALTER TABLE)
 
82
                        (Needed by UPDATE/INSERT or ALTER Table)
79
83
  @param examined_rows  Store number of examined rows here
80
84
 
81
85
  @todo
92
96
    examined_rows       will be set to number of examined rows
93
97
*/
94
98
 
95
 
ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length,
 
99
ha_rows filesort(Session *session, Table *table, SORT_FIELD *sortorder, uint32_t s_length,
96
100
                 SQL_SELECT *select, ha_rows max_rows,
97
101
                 bool sort_positions, ha_rows *examined_rows)
98
102
{
99
103
  int error;
100
104
  uint32_t memavl, min_sort_memory;
101
 
  uint maxbuffer;
 
105
  uint32_t maxbuffer;
102
106
  BUFFPEK *buffpek;
103
107
  ha_rows records= HA_POS_ERROR;
104
 
  uchar **sort_keys= 0;
105
 
  IO_CACHE tempfile, buffpek_pointers, *selected_records_file, *outfile; 
 
108
  unsigned char **sort_keys= 0;
 
109
  IO_CACHE tempfile, buffpek_pointers, *selected_records_file, *outfile;
106
110
  SORTPARAM param;
107
111
  bool multi_byte_charset;
108
112
 
109
 
  FILESORT_INFO table_sort;
110
 
  TABLE_LIST *tab= table->pos_in_table_list;
 
113
  filesort_info_st table_sort;
 
114
  TableList *tab= table->pos_in_table_list;
111
115
  Item_subselect *subselect= tab ? tab->containing_subselect() : 0;
112
116
 
113
117
  DRIZZLE_FILESORT_START();
116
120
   Release InnoDB's adaptive hash index latch (if holding) before
117
121
   running a sort.
118
122
  */
119
 
  ha_release_temporary_latches(thd);
 
123
  ha_release_temporary_latches(session);
120
124
 
121
 
  /* 
122
 
    Don't use table->sort in filesort as it is also used by 
123
 
    QUICK_INDEX_MERGE_SELECT. Work with a copy and put it back at the end 
 
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
124
128
    when index_merge select has finished with it.
125
129
  */
126
 
  memcpy(&table_sort, &table->sort, sizeof(FILESORT_INFO));
 
130
  memcpy(&table_sort, &table->sort, sizeof(filesort_info_st));
127
131
  table->sort.io_cache= NULL;
128
 
  
 
132
 
129
133
  outfile= table_sort.io_cache;
130
134
  my_b_clear(&tempfile);
131
135
  my_b_clear(&buffpek_pointers);
132
136
  buffpek=0;
133
137
  error= 1;
134
138
  memset(&param, 0, sizeof(param));
135
 
  param.sort_length= sortlength(thd, sortorder, s_length, &multi_byte_charset);
 
139
  param.sort_length= sortlength(session, sortorder, s_length, &multi_byte_charset);
136
140
  param.ref_length= table->file->ref_length;
137
141
  param.addon_field= 0;
138
142
  param.addon_length= 0;
139
143
  if (!(table->file->ha_table_flags() & HA_FAST_KEY_READ) && !sort_positions)
140
144
  {
141
 
    /* 
142
 
      Get the descriptors of all fields whose values are appended 
 
145
    /*
 
146
      Get the descriptors of all fields whose values are appended
143
147
      to sorted fields and get its total length in param.spack_length.
144
148
    */
145
 
    param.addon_field= get_addon_fields(thd, table->field, 
 
149
    param.addon_field= get_addon_fields(session, table->field,
146
150
                                        param.sort_length,
147
151
                                        &param.addon_length);
148
152
  }
154
158
  if (param.addon_field)
155
159
  {
156
160
    param.res_length= param.addon_length;
157
 
    if (!(table_sort.addon_buf= (uchar *) my_malloc(param.addon_length,
158
 
                                                    MYF(MY_WME))))
 
161
    if (!(table_sort.addon_buf= (unsigned char *) malloc(param.addon_length)))
159
162
      goto err;
160
163
  }
161
164
  else
162
165
  {
163
166
    param.res_length= param.ref_length;
164
 
    /* 
165
 
      The reference to the record is considered 
 
167
    /*
 
168
      The reference to the record is considered
166
169
      as an additional sorted field
167
170
    */
168
171
    param.sort_length+= param.ref_length;
172
175
 
173
176
  if (select && select->quick)
174
177
  {
175
 
    status_var_increment(thd->status_var.filesort_range_count);
 
178
    status_var_increment(session->status_var.filesort_range_count);
176
179
  }
177
180
  else
178
181
  {
179
 
    status_var_increment(thd->status_var.filesort_scan_count);
 
182
    status_var_increment(session->status_var.filesort_scan_count);
180
183
  }
181
184
#ifdef CAN_TRUST_RANGE
182
185
  if (select && select->quick && select->quick->records > 0L)
183
186
  {
184
 
    records=min((ha_rows) (select->quick->records*2+EXTRA_RECORDS*2),
185
 
                table->file->stats.records)+EXTRA_RECORDS;
 
187
    records= min((ha_rows) (select->quick->records*2+EXTRA_RECORDS*2),
 
188
                 table->file->stats.records)+EXTRA_RECORDS;
186
189
    selected_records_file=0;
187
190
  }
188
191
  else
190
193
  {
191
194
    records= table->file->estimate_rows_upper_bound();
192
195
    /*
193
 
      If number of records is not known, use as much of sort buffer 
194
 
      as possible. 
 
196
      If number of records is not known, use as much of sort buffer
 
197
      as possible.
195
198
    */
196
199
    if (records == HA_POS_ERROR)
197
200
      records--;  // we use 'records+1' below.
199
202
  }
200
203
 
201
204
  if (multi_byte_charset &&
202
 
      !(param.tmp_buffer= (char*) my_malloc(param.sort_length,MYF(MY_WME))))
 
205
      !(param.tmp_buffer= (char*) malloc(param.sort_length)))
203
206
    goto err;
204
207
 
205
 
  memavl= thd->variables.sortbuff_size;
206
 
  min_sort_memory= max((uint)MIN_SORT_MEMORY, param.sort_length*MERGEBUFF2);
 
208
  memavl= session->variables.sortbuff_size;
 
209
  min_sort_memory= max((uint32_t)MIN_SORT_MEMORY, param.sort_length*MERGEBUFF2);
207
210
  while (memavl >= min_sort_memory)
208
211
  {
209
212
    uint32_t old_memavl;
210
213
    uint32_t keys= memavl/(param.rec_length+sizeof(char*));
211
 
    param.keys=(uint) min(records+1, keys);
 
214
    param.keys= (uint32_t) min(records+1, (ha_rows)keys);
212
215
    if ((table_sort.sort_keys=
213
 
         (uchar **) make_char_array((char **) table_sort.sort_keys,
214
 
                                    param.keys, param.rec_length, MYF(0))))
 
216
         (unsigned char **) make_char_array((char **) table_sort.sort_keys,
 
217
                                            param.keys, param.rec_length)))
215
218
      break;
216
 
    old_memavl=memavl;
217
 
    if ((memavl=memavl/4*3) < min_sort_memory && old_memavl > min_sort_memory)
 
219
    old_memavl= memavl;
 
220
    if ((memavl= memavl/4*3) < min_sort_memory && old_memavl > min_sort_memory)
218
221
      memavl= min_sort_memory;
219
222
  }
220
223
  sort_keys= table_sort.sort_keys;
223
226
    my_error(ER_OUT_OF_SORTMEMORY,MYF(ME_ERROR+ME_WAITTANG));
224
227
    goto err;
225
228
  }
226
 
  if (open_cached_file(&buffpek_pointers,mysql_tmpdir,TEMP_PREFIX,
 
229
  if (open_cached_file(&buffpek_pointers,drizzle_tmpdir,TEMP_PREFIX,
227
230
                       DISK_BUFFER_SIZE, MYF(MY_WME)))
228
231
    goto err;
229
232
 
234
237
                             &tempfile, selected_records_file)) ==
235
238
      HA_POS_ERROR)
236
239
    goto err;
237
 
  maxbuffer= (uint) (my_b_tell(&buffpek_pointers)/sizeof(*buffpek));
 
240
  maxbuffer= (uint32_t) (my_b_tell(&buffpek_pointers)/sizeof(*buffpek));
238
241
 
239
242
  if (maxbuffer == 0)                   // The whole set is in memory
240
243
  {
241
 
    if (save_index(&param,sort_keys,(uint) records, &table_sort))
 
244
    if (save_index(&param,sort_keys,(uint32_t) records, &table_sort))
242
245
      goto err;
243
246
  }
244
247
  else
245
248
  {
246
249
    if (table_sort.buffpek && table_sort.buffpek_len < maxbuffer)
247
250
    {
248
 
      x_free(table_sort.buffpek);
 
251
      if (table_sort.buffpek)
 
252
        free(table_sort.buffpek);
249
253
      table_sort.buffpek= 0;
250
254
    }
251
255
    if (!(table_sort.buffpek=
252
 
          (uchar *) read_buffpek_from_file(&buffpek_pointers, maxbuffer,
 
256
          (unsigned char *) read_buffpek_from_file(&buffpek_pointers, maxbuffer,
253
257
                                 table_sort.buffpek)))
254
258
      goto err;
255
259
    buffpek= (BUFFPEK *) table_sort.buffpek;
257
261
    close_cached_file(&buffpek_pointers);
258
262
        /* Open cached file if it isn't open */
259
263
    if (! my_b_inited(outfile) &&
260
 
        open_cached_file(outfile,mysql_tmpdir,TEMP_PREFIX,READ_RECORD_BUFFER,
 
264
        open_cached_file(outfile,drizzle_tmpdir,TEMP_PREFIX,READ_RECORD_BUFFER,
261
265
                          MYF(MY_WME)))
262
266
      goto err;
263
267
    if (reinit_io_cache(outfile,WRITE_CACHE,0L,0,0))
270
274
    param.keys=((param.keys*(param.rec_length+sizeof(char*))) /
271
275
                param.rec_length-1);
272
276
    maxbuffer--;                                // Offset from 0
273
 
    if (merge_many_buff(&param,(uchar*) sort_keys,buffpek,&maxbuffer,
 
277
    if (merge_many_buff(&param,(unsigned char*) sort_keys,buffpek,&maxbuffer,
274
278
                        &tempfile))
275
279
      goto err;
276
280
    if (flush_io_cache(&tempfile) ||
277
281
        reinit_io_cache(&tempfile,READ_CACHE,0L,0,0))
278
282
      goto err;
279
 
    if (merge_index(&param,(uchar*) sort_keys,buffpek,maxbuffer,&tempfile,
 
283
    if (merge_index(&param,(unsigned char*) sort_keys,buffpek,maxbuffer,&tempfile,
280
284
                    outfile))
281
285
      goto err;
282
286
  }
286
290
 
287
291
 err:
288
292
  if (param.tmp_buffer)
289
 
    x_free(param.tmp_buffer);
 
293
    if (param.tmp_buffer)
 
294
      free(param.tmp_buffer);
290
295
  if (!subselect || !subselect->is_uncacheable())
291
296
  {
292
 
    x_free((uchar*) sort_keys);
 
297
    if ((unsigned char*) sort_keys)
 
298
      free((unsigned char*) sort_keys);
293
299
    table_sort.sort_keys= 0;
294
 
    x_free((uchar*) buffpek);
 
300
    if ((unsigned char*) buffpek)
 
301
      free((unsigned char*) buffpek);
295
302
    table_sort.buffpek= 0;
296
303
    table_sort.buffpek_len= 0;
297
304
  }
313
320
    my_message(ER_FILSORT_ABORT, ER(ER_FILSORT_ABORT),
314
321
               MYF(ME_ERROR+ME_WAITTANG));
315
322
  else
316
 
    statistic_add(thd->status_var.filesort_rows,
 
323
    statistic_add(session->status_var.filesort_rows,
317
324
                  (uint32_t) records, &LOCK_status);
318
325
  *examined_rows= param.examined_rows;
319
 
  memcpy(&table->sort, &table_sort, sizeof(FILESORT_INFO));
 
326
  memcpy(&table->sort, &table_sort, sizeof(filesort_info_st));
320
327
  DRIZZLE_FILESORT_END();
321
328
  return(error ? HA_POS_ERROR : records);
322
329
} /* filesort */
323
330
 
324
331
 
325
 
void filesort_free_buffers(TABLE *table, bool full)
 
332
void filesort_free_buffers(Table *table, bool full)
326
333
{
327
334
  if (table->sort.record_pointers)
328
335
  {
329
 
    my_free((uchar*) table->sort.record_pointers,MYF(0));
 
336
    free((unsigned char*) table->sort.record_pointers);
330
337
    table->sort.record_pointers=0;
331
338
  }
332
339
  if (full)
333
340
  {
334
341
    if (table->sort.sort_keys )
335
342
    {
336
 
      x_free((uchar*) table->sort.sort_keys);
 
343
      if ((unsigned char*) table->sort.sort_keys)
 
344
        free((unsigned char*) table->sort.sort_keys);
337
345
      table->sort.sort_keys= 0;
338
346
    }
339
347
    if (table->sort.buffpek)
340
348
    {
341
 
      x_free((uchar*) table->sort.buffpek);
 
349
      if ((unsigned char*) table->sort.buffpek)
 
350
        free((unsigned char*) table->sort.buffpek);
342
351
      table->sort.buffpek= 0;
343
352
      table->sort.buffpek_len= 0;
344
353
    }
345
354
  }
346
355
  if (table->sort.addon_buf)
347
356
  {
348
 
    my_free((char *) table->sort.addon_buf, MYF(0));
349
 
    my_free((char *) table->sort.addon_field, MYF(MY_ALLOW_ZERO_PTR));
 
357
    free((char *) table->sort.addon_buf);
 
358
    free((char *) table->sort.addon_field);
350
359
    table->sort.addon_buf=0;
351
360
    table->sort.addon_field=0;
352
361
  }
354
363
 
355
364
/** Make a array of string pointers. */
356
365
 
357
 
static char **make_char_array(char **old_pos, register uint fields,
358
 
                              uint length, myf my_flag)
 
366
static char **make_char_array(char **old_pos, register uint32_t fields,
 
367
                              uint32_t length)
359
368
{
360
369
  register char **pos;
361
370
  char *char_pos;
362
371
 
363
372
  if (old_pos ||
364
 
      (old_pos= (char**) my_malloc((uint) fields*(length+sizeof(char*)),
365
 
                                   my_flag)))
 
373
      (old_pos= (char**) malloc((uint32_t) fields*(length+sizeof(char*)))))
366
374
  {
367
375
    pos=old_pos; char_pos=((char*) (pos+fields)) -length;
368
376
    while (fields--) *(pos++) = (char_pos+= length);
374
382
 
375
383
/** Read 'count' number of buffer pointers into memory. */
376
384
 
377
 
static uchar *read_buffpek_from_file(IO_CACHE *buffpek_pointers, uint count,
378
 
                                     uchar *buf)
 
385
static unsigned char *read_buffpek_from_file(IO_CACHE *buffpek_pointers, uint32_t count,
 
386
                                     unsigned char *buf)
379
387
{
380
388
  uint32_t length= sizeof(BUFFPEK)*count;
381
 
  uchar *tmp= buf;
 
389
  unsigned char *tmp= buf;
382
390
  if (count > UINT_MAX/sizeof(BUFFPEK))
383
391
    return 0; /* sizeof(BUFFPEK)*count will overflow */
384
392
  if (!tmp)
385
 
    tmp= (uchar *)my_malloc(length, MYF(MY_WME));
 
393
    tmp= (unsigned char *)malloc(length);
386
394
  if (tmp)
387
395
  {
388
396
    if (reinit_io_cache(buffpek_pointers,READ_CACHE,0L,0,0) ||
389
 
        my_b_read(buffpek_pointers, (uchar*) tmp, length))
 
397
        my_b_read(buffpek_pointers, (unsigned char*) tmp, length))
390
398
    {
391
 
      my_free((char*) tmp, MYF(0));
 
399
      free((char*) tmp);
392
400
      tmp=0;
393
401
    }
394
402
  }
434
442
*/
435
443
 
436
444
static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select,
437
 
                             uchar **sort_keys,
 
445
                             unsigned char **sort_keys,
438
446
                             IO_CACHE *buffpek_pointers,
439
447
                             IO_CACHE *tempfile, IO_CACHE *indexfile)
440
448
{
441
449
  int error,flag,quick_select;
442
 
  uint idx,indexpos,ref_length;
443
 
  uchar *ref_pos,*next_pos,ref_buff[MAX_REFLENGTH];
 
450
  uint32_t idx,indexpos,ref_length;
 
451
  unsigned char *ref_pos,*next_pos,ref_buff[MAX_REFLENGTH];
444
452
  my_off_t record;
445
 
  TABLE *sort_form;
446
 
  THD *thd= current_thd;
447
 
  volatile THD::killed_state *killed= &thd->killed;
 
453
  Table *sort_form;
 
454
  Session *session= current_session;
 
455
  volatile Session::killed_state *killed= &session->killed;
448
456
  handler *file;
449
457
  MY_BITMAP *save_read_set, *save_write_set;
450
458
 
463
471
  next_pos=ref_pos;
464
472
  if (! indexfile && ! quick_select)
465
473
  {
466
 
    next_pos=(uchar*) 0;                        /* Find records in sequence */
 
474
    next_pos=(unsigned char*) 0;                        /* Find records in sequence */
467
475
    file->ha_rnd_init(1);
468
476
    file->extra_opt(HA_EXTRA_CACHE,
469
 
                    current_thd->variables.read_buff_size);
 
477
                    current_session->variables.read_buff_size);
470
478
  }
471
479
 
472
480
  READ_RECORD read_record_info;
474
482
  {
475
483
    if (select->quick->reset())
476
484
      return(HA_POS_ERROR);
477
 
    init_read_record(&read_record_info, current_thd, select->quick->head,
 
485
    init_read_record(&read_record_info, current_session, select->quick->head,
478
486
                     select, 1, 1);
479
487
  }
480
488
 
488
496
  register_used_fields(param);
489
497
  if (select && select->cond)
490
498
    select->cond->walk(&Item::register_field_in_read_map, 1,
491
 
                       (uchar*) sort_form);
 
499
                       (unsigned char*) sort_form);
492
500
  sort_form->column_bitmaps_set(&sort_form->tmp_set, &sort_form->tmp_set);
493
501
 
494
502
  for (;;)
506
514
    {
507
515
      if (indexfile)
508
516
      {
509
 
        if (my_b_read(indexfile,(uchar*) ref_pos,ref_length)) /* purecov: deadcode */
 
517
        if (my_b_read(indexfile,(unsigned char*) ref_pos,ref_length)) /* purecov: deadcode */
510
518
        {
511
519
          error= my_errno ? my_errno : -1;              /* Abort */
512
520
          break;
516
524
      else
517
525
      {
518
526
        error=file->rnd_next(sort_form->record[0]);
 
527
 
519
528
        if (!flag)
520
529
        {
521
530
          my_store_ptr(ref_pos,ref_length,record); // Position to row
553
562
    else
554
563
      file->unlock_row();
555
564
    /* It does not make sense to read more keys in case of a fatal error */
556
 
    if (thd->is_error())
 
565
    if (session->is_error())
557
566
      break;
558
567
  }
559
568
  if (quick_select)
571
580
      file->ha_rnd_end();
572
581
  }
573
582
 
574
 
  if (thd->is_error())
 
583
  if (session->is_error())
575
584
    return(HA_POS_ERROR);
576
 
  
 
585
 
577
586
  /* Signal we should use orignal column read and write maps */
578
587
  sort_form->column_bitmaps_set(save_read_set, save_write_set);
579
588
 
614
623
*/
615
624
 
616
625
static int
617
 
write_keys(SORTPARAM *param, register uchar **sort_keys, uint count,
 
626
write_keys(SORTPARAM *param, register unsigned char **sort_keys, uint32_t count,
618
627
           IO_CACHE *buffpek_pointers, IO_CACHE *tempfile)
619
628
{
620
629
  size_t sort_length, rec_length;
621
 
  uchar **end;
 
630
  unsigned char **end;
622
631
  BUFFPEK buffpek;
623
632
 
624
633
  sort_length= param->sort_length;
625
634
  rec_length= param->rec_length;
626
 
  my_string_ptr_sort((uchar*) sort_keys, (uint) count, sort_length);
 
635
  my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, sort_length);
627
636
  if (!my_b_inited(tempfile) &&
628
 
      open_cached_file(tempfile, mysql_tmpdir, TEMP_PREFIX, DISK_BUFFER_SIZE,
 
637
      open_cached_file(tempfile, drizzle_tmpdir, TEMP_PREFIX, DISK_BUFFER_SIZE,
629
638
                       MYF(MY_WME)))
630
639
    goto err;                                   /* purecov: inspected */
631
640
  /* check we won't have more buffpeks than we can possibly keep in memory */
633
642
    goto err;
634
643
  buffpek.file_pos= my_b_tell(tempfile);
635
644
  if ((ha_rows) count > param->max_rows)
636
 
    count=(uint) param->max_rows;               /* purecov: inspected */
 
645
    count=(uint32_t) param->max_rows;               /* purecov: inspected */
637
646
  buffpek.count=(ha_rows) count;
638
647
  for (end=sort_keys+count ; sort_keys != end ; sort_keys++)
639
 
    if (my_b_write(tempfile, (uchar*) *sort_keys, (uint) rec_length))
 
648
    if (my_b_write(tempfile, (unsigned char*) *sort_keys, (uint32_t) rec_length))
640
649
      goto err;
641
 
  if (my_b_write(buffpek_pointers, (uchar*) &buffpek, sizeof(buffpek)))
 
650
  if (my_b_write(buffpek_pointers, (unsigned char*) &buffpek, sizeof(buffpek)))
642
651
    goto err;
643
652
  return(0);
644
653
 
651
660
  Store length as suffix in high-byte-first order.
652
661
*/
653
662
 
654
 
static inline void store_length(uchar *to, uint length, uint pack_length)
 
663
static inline void store_length(unsigned char *to, uint32_t length, uint32_t pack_length)
655
664
{
656
665
  switch (pack_length) {
657
666
  case 1:
658
 
    *to= (uchar) length;
 
667
    *to= (unsigned char) length;
659
668
    break;
660
669
  case 2:
661
670
    mi_int2store(to, length);
673
682
/** Make a sort-key from record. */
674
683
 
675
684
static void make_sortkey(register SORTPARAM *param,
676
 
                         register uchar *to, uchar *ref_pos)
 
685
                         register unsigned char *to, unsigned char *ref_pos)
677
686
{
678
687
  register Field *field;
679
688
  register SORT_FIELD *sort_field;
680
 
  register uint length;
 
689
  size_t length;
681
690
 
682
691
  for (sort_field=param->local_sortorder ;
683
692
       sort_field != param->end ;
712
721
        const CHARSET_INFO * const cs=item->collation.collation;
713
722
        char fill_char= ((cs->state & MY_CS_BINSORT) ? (char) 0 : ' ');
714
723
        int diff;
715
 
        uint sort_field_length;
 
724
        uint32_t sort_field_length;
716
725
 
717
726
        if (maybe_null)
718
727
          *to++=1;
754
763
        if (sort_field->need_strxnfrm)
755
764
        {
756
765
          char *from=(char*) res->ptr();
757
 
          uint tmp_length;
758
 
          if ((uchar*) from == to)
 
766
          uint32_t tmp_length;
 
767
          if ((unsigned char*) from == to)
759
768
          {
760
769
            set_if_smaller(length,sort_field->length);
761
770
            memcpy(param->tmp_buffer,from,length);
762
771
            from=param->tmp_buffer;
763
772
          }
764
773
          tmp_length= my_strnxfrm(cs,to,sort_field->length,
765
 
                                  (uchar*) from, length);
 
774
                                  (unsigned char*) from, length);
766
775
          assert(tmp_length == sort_field->length);
767
776
        }
768
777
        else
769
778
        {
770
 
          my_strnxfrm(cs,(uchar*)to,length,(const uchar*)res->ptr(),length);
 
779
          my_strnxfrm(cs,(unsigned char*)to,length,(const unsigned char*)res->ptr(),length);
771
780
          cs->cset->fill(cs, (char *)to+length,diff,fill_char);
772
781
        }
773
782
        break;
789
798
              break;
790
799
            }
791
800
          }
792
 
#if SIZEOF_LONG_LONG > 4
793
 
          to[7]= (uchar) value;
794
 
          to[6]= (uchar) (value >> 8);
795
 
          to[5]= (uchar) (value >> 16);
796
 
          to[4]= (uchar) (value >> 24);
797
 
          to[3]= (uchar) (value >> 32);
798
 
          to[2]= (uchar) (value >> 40);
799
 
          to[1]= (uchar) (value >> 48);
800
 
          if (item->unsigned_flag)                    /* Fix sign */
801
 
            to[0]= (uchar) (value >> 56);
802
 
          else
803
 
            to[0]= (uchar) (value >> 56) ^ 128; /* Reverse signbit */
804
 
#else
805
 
          to[3]= (uchar) value;
806
 
          to[2]= (uchar) (value >> 8);
807
 
          to[1]= (uchar) (value >> 16);
808
 
          if (item->unsigned_flag)                    /* Fix sign */
809
 
            to[0]= (uchar) (value >> 24);
810
 
          else
811
 
            to[0]= (uchar) (value >> 24) ^ 128; /* Reverse signbit */
812
 
#endif
 
801
          to[7]= (unsigned char) value;
 
802
          to[6]= (unsigned char) (value >> 8);
 
803
          to[5]= (unsigned char) (value >> 16);
 
804
          to[4]= (unsigned char) (value >> 24);
 
805
          to[3]= (unsigned char) (value >> 32);
 
806
          to[2]= (unsigned char) (value >> 40);
 
807
          to[1]= (unsigned char) (value >> 48);
 
808
          if (item->unsigned_flag)                    /* Fix sign */
 
809
            to[0]= (unsigned char) (value >> 56);
 
810
          else
 
811
            to[0]= (unsigned char) (value >> 56) ^ 128; /* Reverse signbit */
813
812
          break;
814
813
        }
815
814
      case DECIMAL_RESULT:
818
817
          if (maybe_null)
819
818
          {
820
819
            if (item->null_value)
821
 
            { 
 
820
            {
822
821
              memset(to, 0, sort_field->length+1);
823
822
              to++;
824
823
              break;
843
842
            }
844
843
            *to++=1;
845
844
          }
846
 
          change_double_for_sort(value,(uchar*) to);
 
845
          change_double_for_sort(value,(unsigned char*) to);
847
846
          break;
848
847
        }
849
848
      case ROW_RESULT:
850
 
      default: 
 
849
      default:
851
850
        // This case should never be choosen
852
851
        assert(0);
853
852
        break;
860
859
      length=sort_field->length;
861
860
      while (length--)
862
861
      {
863
 
        *to = (uchar) (~ *to);
 
862
        *to = (unsigned char) (~ *to);
864
863
        to++;
865
864
      }
866
865
    }
870
869
 
871
870
  if (param->addon_field)
872
871
  {
873
 
    /* 
 
872
    /*
874
873
      Save field values appended to sorted fields.
875
874
      First null bit indicators are appended then field values follow.
876
875
      In this implementation we use fixed layout for field values -
877
876
      the same for all records.
878
877
    */
879
878
    SORT_ADDON_FIELD *addonf= param->addon_field;
880
 
    uchar *nulls= to;
 
879
    unsigned char *nulls= to;
881
880
    assert(addonf != 0);
882
881
    memset(nulls, 0, addonf->offset);
883
882
    to+= addonf->offset;
893
892
      else
894
893
      {
895
894
#ifdef HAVE_purify
896
 
        uchar *end= field->pack(to, field->ptr);
897
 
        uint length= (uint) ((to + addonf->length) - end);
 
895
        unsigned char *end= field->pack(to, field->ptr);
 
896
        uint32_t length= (uint32_t) ((to + addonf->length) - end);
898
897
        assert((int) length >= 0);
899
898
        if (length)
900
899
          memset(end, 0, length);
921
920
static void register_used_fields(SORTPARAM *param)
922
921
{
923
922
  register SORT_FIELD *sort_field;
924
 
  TABLE *table=param->sort_form;
925
 
  MY_BITMAP *bitmap= table->read_set;
 
923
  Table *table=param->sort_form;
926
924
 
927
925
  for (sort_field= param->local_sortorder ;
928
926
       sort_field != param->end ;
932
930
    if ((field= sort_field->field))
933
931
    {
934
932
      if (field->table == table)
935
 
      bitmap_set_bit(bitmap, field->field_index);
 
933
        table->setReadSet(field->field_index);
936
934
    }
937
935
    else
938
936
    {                                           // Item
939
937
      sort_field->item->walk(&Item::register_field_in_read_map, 1,
940
 
                             (uchar *) table);
 
938
                             (unsigned char *) table);
941
939
    }
942
940
  }
943
941
 
946
944
    SORT_ADDON_FIELD *addonf= param->addon_field;
947
945
    Field *field;
948
946
    for ( ; (field= addonf->field) ; addonf++)
949
 
      bitmap_set_bit(bitmap, field->field_index);
 
947
      table->setReadSet(field->field_index);
950
948
  }
951
949
  else
952
950
  {
956
954
}
957
955
 
958
956
 
959
 
static bool save_index(SORTPARAM *param, uchar **sort_keys, uint count, 
960
 
                       FILESORT_INFO *table_sort)
 
957
static bool save_index(SORTPARAM *param, unsigned char **sort_keys, uint32_t count,
 
958
                       filesort_info_st *table_sort)
961
959
{
962
 
  uint offset,res_length;
963
 
  uchar *to;
 
960
  uint32_t offset,res_length;
 
961
  unsigned char *to;
964
962
 
965
 
  my_string_ptr_sort((uchar*) sort_keys, (uint) count, param->sort_length);
 
963
  my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, param->sort_length);
966
964
  res_length= param->res_length;
967
965
  offset= param->rec_length-res_length;
968
966
  if ((ha_rows) count > param->max_rows)
969
 
    count=(uint) param->max_rows;
970
 
  if (!(to= table_sort->record_pointers= 
971
 
        (uchar*) my_malloc(res_length*count, MYF(MY_WME))))
 
967
    count=(uint32_t) param->max_rows;
 
968
  if (!(to= table_sort->record_pointers=
 
969
        (unsigned char*) malloc(res_length*count)))
972
970
    return(1);                 /* purecov: inspected */
973
 
  for (uchar **end= sort_keys+count ; sort_keys != end ; sort_keys++)
 
971
  for (unsigned char **end= sort_keys+count ; sort_keys != end ; sort_keys++)
974
972
  {
975
973
    memcpy(to, *sort_keys+offset, res_length);
976
974
    to+= res_length;
981
979
 
982
980
/** Merge buffers to make < MERGEBUFF2 buffers. */
983
981
 
984
 
int merge_many_buff(SORTPARAM *param, uchar *sort_buffer,
985
 
                    BUFFPEK *buffpek, uint *maxbuffer, IO_CACHE *t_file)
 
982
int merge_many_buff(SORTPARAM *param, unsigned char *sort_buffer,
 
983
                    BUFFPEK *buffpek, uint32_t *maxbuffer, IO_CACHE *t_file)
986
984
{
987
 
  register uint i;
 
985
  register uint32_t i;
988
986
  IO_CACHE t_file2,*from_file,*to_file,*temp;
989
987
  BUFFPEK *lastbuff;
990
988
 
991
989
  if (*maxbuffer < MERGEBUFF2)
992
990
    return(0);                          /* purecov: inspected */
993
991
  if (flush_io_cache(t_file) ||
994
 
      open_cached_file(&t_file2,mysql_tmpdir,TEMP_PREFIX,DISK_BUFFER_SIZE,
 
992
      open_cached_file(&t_file2,drizzle_tmpdir,TEMP_PREFIX,DISK_BUFFER_SIZE,
995
993
                        MYF(MY_WME)))
996
994
    return(1);                          /* purecov: inspected */
997
995
 
1017
1015
    temp=from_file; from_file=to_file; to_file=temp;
1018
1016
    setup_io_cache(from_file);
1019
1017
    setup_io_cache(to_file);
1020
 
    *maxbuffer= (uint) (lastbuff-buffpek)-1;
 
1018
    *maxbuffer= (uint32_t) (lastbuff-buffpek)-1;
1021
1019
  }
1022
1020
cleanup:
1023
1021
  close_cached_file(to_file);                   // This holds old result
1035
1033
  Read data to buffer.
1036
1034
 
1037
1035
  @retval
1038
 
    (uint)-1 if something goes wrong
 
1036
    (uint32_t)-1 if something goes wrong
1039
1037
*/
1040
1038
 
1041
 
uint read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek,
1042
 
                    uint rec_length)
 
1039
uint32_t read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek,
 
1040
                        uint32_t rec_length)
1043
1041
{
1044
 
  register uint count;
1045
 
  uint length;
 
1042
  register uint32_t count;
 
1043
  uint32_t length;
1046
1044
 
1047
 
  if ((count=(uint) min((ha_rows) buffpek->max_keys,buffpek->count)))
 
1045
  if ((count= (uint32_t) min((ha_rows) buffpek->max_keys,buffpek->count)))
1048
1046
  {
1049
 
    if (pread(fromfile->file,(uchar*) buffpek->base, (length= rec_length*count),buffpek->file_pos) == 0)
1050
 
      return((uint) -1);                        /* purecov: inspected */
1051
 
    buffpek->key=buffpek->base;
 
1047
    if (pread(fromfile->file,(unsigned char*) buffpek->base, (length= rec_length*count),buffpek->file_pos) == 0)
 
1048
      return((uint32_t) -1);                    /* purecov: inspected */
 
1049
 
 
1050
    buffpek->key= buffpek->base;
1052
1051
    buffpek->file_pos+= length;                 /* New filepos */
1053
 
    buffpek->count-=    count;
 
1052
    buffpek->count-= count;
1054
1053
    buffpek->mem_count= count;
1055
1054
  }
1056
1055
  return (count*rec_length);
1057
1056
} /* read_to_buffer */
1058
1057
 
1059
1058
 
1060
 
/**
1061
 
  Put all room used by freed buffer to use in adjacent buffer.
1062
 
 
1063
 
  Note, that we can't simply distribute memory evenly between all buffers,
1064
 
  because new areas must not overlap with old ones.
1065
 
 
1066
 
  @param[in] queue      list of non-empty buffers, without freed buffer
1067
 
  @param[in] reuse      empty buffer
1068
 
  @param[in] key_length key length
1069
 
*/
1070
 
 
1071
 
void reuse_freed_buff(QUEUE *queue, BUFFPEK *reuse, uint key_length)
 
1059
class compare_functor
1072
1060
{
1073
 
  uchar *reuse_end= reuse->base + reuse->max_keys * key_length;
1074
 
  for (uint i= 0; i < queue->elements; ++i)
 
1061
  qsort2_cmp key_compare;
 
1062
  void *key_compare_arg;
 
1063
  public:
 
1064
  compare_functor(qsort2_cmp in_key_compare, void *in_compare_arg)
 
1065
    : key_compare(in_key_compare), key_compare_arg(in_compare_arg) { }
 
1066
  inline bool operator()(const BUFFPEK *i, const BUFFPEK *j) const
1075
1067
  {
1076
 
    BUFFPEK *bp= (BUFFPEK *) queue_element(queue, i);
1077
 
    if (bp->base + bp->max_keys * key_length == reuse->base)
1078
 
    {
1079
 
      bp->max_keys+= reuse->max_keys;
1080
 
      return;
1081
 
    }
1082
 
    else if (bp->base == reuse_end)
1083
 
    {
1084
 
      bp->base= reuse->base;
1085
 
      bp->max_keys+= reuse->max_keys;
1086
 
      return;
1087
 
    }
 
1068
    int val= key_compare(key_compare_arg,
 
1069
                      &i->key, &j->key);
 
1070
    return (val >= 0);
1088
1071
  }
1089
 
  assert(0);
1090
 
}
 
1072
};
1091
1073
 
1092
1074
 
1093
1075
/**
1109
1091
*/
1110
1092
 
1111
1093
int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
1112
 
                  IO_CACHE *to_file, uchar *sort_buffer,
 
1094
                  IO_CACHE *to_file, unsigned char *sort_buffer,
1113
1095
                  BUFFPEK *lastbuff, BUFFPEK *Fb, BUFFPEK *Tb,
1114
1096
                  int flag)
1115
1097
{
1116
1098
  int error;
1117
 
  uint rec_length,res_length,offset;
 
1099
  uint32_t rec_length,res_length,offset;
1118
1100
  size_t sort_length;
1119
1101
  uint32_t maxcount;
1120
1102
  ha_rows max_rows,org_max_rows;
1121
1103
  my_off_t to_start_filepos;
1122
 
  uchar *strpos;
 
1104
  unsigned char *strpos;
1123
1105
  BUFFPEK *buffpek;
1124
 
  QUEUE queue;
1125
1106
  qsort2_cmp cmp;
1126
1107
  void *first_cmp_arg;
1127
 
  volatile THD::killed_state *killed= &current_thd->killed;
1128
 
  THD::killed_state not_killable;
 
1108
  volatile Session::killed_state *killed= &current_session->killed;
 
1109
  Session::killed_state not_killable;
1129
1110
 
1130
 
  status_var_increment(current_thd->status_var.filesort_merge_passes);
 
1111
  status_var_increment(current_session->status_var.filesort_merge_passes);
1131
1112
  if (param->not_killable)
1132
1113
  {
1133
1114
    killed= &not_killable;
1134
 
    not_killable= THD::NOT_KILLED;
 
1115
    not_killable= Session::NOT_KILLED;
1135
1116
  }
1136
1117
 
1137
1118
  error=0;
1139
1120
  res_length= param->res_length;
1140
1121
  sort_length= param->sort_length;
1141
1122
  offset= rec_length-res_length;
1142
 
  maxcount= (uint32_t) (param->keys/((uint) (Tb-Fb) +1));
 
1123
  maxcount= (uint32_t) (param->keys/((uint32_t) (Tb-Fb) +1));
1143
1124
  to_start_filepos= my_b_tell(to_file);
1144
 
  strpos= (uchar*) sort_buffer;
 
1125
  strpos= (unsigned char*) sort_buffer;
1145
1126
  org_max_rows=max_rows= param->max_rows;
1146
1127
 
1147
1128
  /* The following will fire if there is not enough space in sort_buffer */
1148
1129
  assert(maxcount!=0);
1149
 
  
 
1130
 
1150
1131
  if (param->unique_buff)
1151
1132
  {
1152
1133
    cmp= param->compare;
1157
1138
    cmp= get_ptr_compare(sort_length);
1158
1139
    first_cmp_arg= (void*) &sort_length;
1159
1140
  }
1160
 
  if (init_queue(&queue, (uint) (Tb-Fb)+1, offsetof(BUFFPEK,key), 0,
1161
 
                 (queue_compare) cmp, first_cmp_arg))
1162
 
    return(1);                                /* purecov: inspected */
 
1141
  priority_queue<BUFFPEK *, vector<BUFFPEK *>, compare_functor > 
 
1142
    queue(compare_functor(cmp, first_cmp_arg));
1163
1143
  for (buffpek= Fb ; buffpek <= Tb ; buffpek++)
1164
1144
  {
1165
1145
    buffpek->base= strpos;
1166
1146
    buffpek->max_keys= maxcount;
1167
 
    strpos+= (uint) (error= (int) read_to_buffer(from_file, buffpek,
 
1147
    strpos+= (uint32_t) (error= (int) read_to_buffer(from_file, buffpek,
1168
1148
                                                                         rec_length));
1169
1149
    if (error == -1)
1170
1150
      goto err;                                 /* purecov: inspected */
1171
1151
    buffpek->max_keys= buffpek->mem_count;      // If less data in buffers than expected
1172
 
    queue_insert(&queue, (uchar*) buffpek);
 
1152
    queue.push(buffpek);
1173
1153
  }
1174
1154
 
1175
1155
  if (param->unique_buff)
1176
1156
  {
1177
 
    /* 
 
1157
    /*
1178
1158
       Called by Unique::get()
1179
1159
       Copy the first argument to param->unique_buff for unique removal.
1180
1160
       Store it also in 'to_file'.
1182
1162
       This is safe as we know that there is always more than one element
1183
1163
       in each block to merge (This is guaranteed by the Unique:: algorithm
1184
1164
    */
1185
 
    buffpek= (BUFFPEK*) queue_top(&queue);
 
1165
    buffpek= queue.top();
1186
1166
    memcpy(param->unique_buff, buffpek->key, rec_length);
1187
 
    if (my_b_write(to_file, (uchar*) buffpek->key, rec_length))
 
1167
    if (my_b_write(to_file, (unsigned char*) buffpek->key, rec_length))
1188
1168
    {
1189
1169
      error=1; goto err;                        /* purecov: inspected */
1190
1170
    }
1195
1175
      error= 0;                                       /* purecov: inspected */
1196
1176
      goto end;                                       /* purecov: inspected */
1197
1177
    }
1198
 
    queue_replaced(&queue);                        // Top element has been used
 
1178
    /* Top element has been used */
 
1179
    queue.pop();
 
1180
    queue.push(buffpek);
1199
1181
  }
1200
1182
  else
1201
1183
    cmp= 0;                                        // Not unique
1202
1184
 
1203
 
  while (queue.elements > 1)
 
1185
  while (queue.size() > 1)
1204
1186
  {
1205
1187
    if (*killed)
1206
1188
    {
1208
1190
    }
1209
1191
    for (;;)
1210
1192
    {
1211
 
      buffpek= (BUFFPEK*) queue_top(&queue);
 
1193
      buffpek= queue.top();
1212
1194
      if (cmp)                                        // Remove duplicates
1213
1195
      {
1214
1196
        if (!(*cmp)(first_cmp_arg, &(param->unique_buff),
1215
 
                    (uchar**) &buffpek->key))
 
1197
                    (unsigned char**) &buffpek->key))
1216
1198
              goto skip_duplicate;
1217
1199
            memcpy(param->unique_buff, buffpek->key, rec_length);
1218
1200
      }
1219
1201
      if (flag == 0)
1220
1202
      {
1221
 
        if (my_b_write(to_file,(uchar*) buffpek->key, rec_length))
 
1203
        if (my_b_write(to_file,(unsigned char*) buffpek->key, rec_length))
1222
1204
        {
1223
1205
          error=1; goto err;                        /* purecov: inspected */
1224
1206
        }
1225
1207
      }
1226
1208
      else
1227
1209
      {
1228
 
        if (my_b_write(to_file, (uchar*) buffpek->key+offset, res_length))
 
1210
        if (my_b_write(to_file, (unsigned char*) buffpek->key+offset, res_length))
1229
1211
        {
1230
1212
          error=1; goto err;                        /* purecov: inspected */
1231
1213
        }
1243
1225
        if (!(error= (int) read_to_buffer(from_file,buffpek,
1244
1226
                                          rec_length)))
1245
1227
        {
1246
 
          VOID(queue_remove(&queue,0));
1247
 
          reuse_freed_buff(&queue, buffpek, rec_length);
 
1228
          queue.pop();
1248
1229
          break;                        /* One buffer have been removed */
1249
1230
        }
1250
1231
        else if (error == -1)
1251
1232
          goto err;                        /* purecov: inspected */
1252
1233
      }
1253
 
      queue_replaced(&queue);              /* Top element has been replaced */
 
1234
      /* Top element has been replaced */
 
1235
      queue.pop();
 
1236
      queue.push(buffpek);
1254
1237
    }
1255
1238
  }
1256
 
  buffpek= (BUFFPEK*) queue_top(&queue);
 
1239
  buffpek= queue.top();
1257
1240
  buffpek->base= sort_buffer;
1258
1241
  buffpek->max_keys= param->keys;
1259
1242
 
1263
1246
  */
1264
1247
  if (cmp)
1265
1248
  {
1266
 
    if (!(*cmp)(first_cmp_arg, &(param->unique_buff), (uchar**) &buffpek->key))
 
1249
    if (!(*cmp)(first_cmp_arg, &(param->unique_buff), (unsigned char**) &buffpek->key))
1267
1250
    {
1268
1251
      buffpek->key+= rec_length;         // Remove duplicate
1269
1252
      --buffpek->mem_count;
1274
1257
  {
1275
1258
    if ((ha_rows) buffpek->mem_count > max_rows)
1276
1259
    {                                        /* Don't write too many records */
1277
 
      buffpek->mem_count= (uint) max_rows;
 
1260
      buffpek->mem_count= (uint32_t) max_rows;
1278
1261
      buffpek->count= 0;                        /* Don't read more */
1279
1262
    }
1280
1263
    max_rows-= buffpek->mem_count;
1281
1264
    if (flag == 0)
1282
1265
    {
1283
 
      if (my_b_write(to_file,(uchar*) buffpek->key,
 
1266
      if (my_b_write(to_file,(unsigned char*) buffpek->key,
1284
1267
                     (rec_length*buffpek->mem_count)))
1285
1268
      {
1286
1269
        error= 1; goto err;                        /* purecov: inspected */
1288
1271
    }
1289
1272
    else
1290
1273
    {
1291
 
      register uchar *end;
 
1274
      register unsigned char *end;
1292
1275
      strpos= buffpek->key+offset;
1293
1276
      for (end= strpos+buffpek->mem_count*rec_length ;
1294
1277
           strpos != end ;
1295
1278
           strpos+= rec_length)
1296
 
      {     
1297
 
        if (my_b_write(to_file, (uchar *) strpos, res_length))
 
1279
      {
 
1280
        if (my_b_write(to_file, (unsigned char *) strpos, res_length))
1298
1281
        {
1299
 
          error=1; goto err;                        
 
1282
          error=1; goto err;
1300
1283
        }
1301
1284
      }
1302
1285
    }
1308
1291
  lastbuff->count= min(org_max_rows-max_rows, param->max_rows);
1309
1292
  lastbuff->file_pos= to_start_filepos;
1310
1293
err:
1311
 
  delete_queue(&queue);
1312
1294
  return(error);
1313
1295
} /* merge_buffers */
1314
1296
 
1315
1297
 
1316
1298
        /* Do a merge to output-file (save only positions) */
1317
1299
 
1318
 
static int merge_index(SORTPARAM *param, uchar *sort_buffer,
1319
 
                       BUFFPEK *buffpek, uint maxbuffer,
 
1300
static int merge_index(SORTPARAM *param, unsigned char *sort_buffer,
 
1301
                       BUFFPEK *buffpek, uint32_t maxbuffer,
1320
1302
                       IO_CACHE *tempfile, IO_CACHE *outfile)
1321
1303
{
1322
1304
  if (merge_buffers(param,tempfile,outfile,sort_buffer,buffpek,buffpek,
1326
1308
} /* merge_index */
1327
1309
 
1328
1310
 
1329
 
static uint suffix_length(uint32_t string_length)
 
1311
static uint32_t suffix_length(uint32_t string_length)
1330
1312
{
1331
1313
  if (string_length < 256)
1332
1314
    return 1;
1342
1324
/**
1343
1325
  Calculate length of sort key.
1344
1326
 
1345
 
  @param thd                      Thread handler
 
1327
  @param session                          Thread handler
1346
1328
  @param sortorder                Order of items to sort
1347
1329
  @param s_length                 Number of items to sort
1348
1330
  @param[out] multi_byte_charset Set to 1 if we are using multi-byte charset
1357
1339
    Total length of sort buffer in bytes
1358
1340
*/
1359
1341
 
1360
 
static uint
1361
 
sortlength(THD *thd, SORT_FIELD *sortorder, uint s_length,
 
1342
static uint32_t
 
1343
sortlength(Session *session, SORT_FIELD *sortorder, uint32_t s_length,
1362
1344
           bool *multi_byte_charset)
1363
1345
{
1364
 
  register uint length;
 
1346
  register uint32_t length;
1365
1347
  const CHARSET_INFO *cs;
1366
1348
  *multi_byte_charset= 0;
1367
1349
 
1392
1374
      switch (sortorder->result_type) {
1393
1375
      case STRING_RESULT:
1394
1376
        sortorder->length=sortorder->item->max_length;
1395
 
        set_if_smaller(sortorder->length, thd->variables.max_sort_length);
 
1377
        set_if_smaller(sortorder->length,
 
1378
                       session->variables.max_sort_length);
1396
1379
        if (use_strnxfrm((cs=sortorder->item->collation.collation)))
1397
 
        { 
 
1380
        {
1398
1381
          sortorder->length= cs->coll->strnxfrmlen(cs, sortorder->length);
1399
1382
          sortorder->need_strxnfrm= 1;
1400
1383
          *multi_byte_charset= 1;
1407
1390
        }
1408
1391
        break;
1409
1392
      case INT_RESULT:
1410
 
#if SIZEOF_LONG_LONG > 4
1411
1393
        sortorder->length=8;                    // Size of intern int64_t
1412
 
#else
1413
 
        sortorder->length=4;
1414
 
#endif
1415
1394
        break;
1416
1395
      case DECIMAL_RESULT:
1417
1396
        sortorder->length=
1418
 
          my_decimal_get_binary_size(sortorder->item->max_length - 
 
1397
          my_decimal_get_binary_size(sortorder->item->max_length -
1419
1398
                                     (sortorder->item->decimals ? 1 : 0),
1420
1399
                                     sortorder->item->decimals);
1421
1400
        break;
1423
1402
        sortorder->length=sizeof(double);
1424
1403
        break;
1425
1404
      case ROW_RESULT:
1426
 
      default: 
 
1405
      default:
1427
1406
        // This case should never be choosen
1428
1407
        assert(0);
1429
1408
        break;
1431
1410
      if (sortorder->item->maybe_null)
1432
1411
        length++;                               // Place for NULL marker
1433
1412
    }
1434
 
    set_if_smaller(sortorder->length, thd->variables.max_sort_length);
 
1413
    set_if_smaller(sortorder->length,
 
1414
                   (size_t)session->variables.max_sort_length);
1435
1415
    length+=sortorder->length;
1436
1416
  }
1437
1417
  sortorder->field= (Field*) 0;                 // end marker
1445
1425
 
1446
1426
  The function first finds out what fields are used in the result set.
1447
1427
  Then it calculates the length of the buffer to store the values of
1448
 
  these fields together with the value of sort values. 
 
1428
  these fields together with the value of sort values.
1449
1429
  If the calculated length is not greater than max_length_for_sort_data
1450
1430
  the function allocates memory for an array of descriptors containing
1451
1431
  layouts for the values of the non-sorted fields in the buffer and
1452
1432
  fills them.
1453
1433
 
1454
 
  @param thd                 Current thread
 
1434
  @param session                 Current thread
1455
1435
  @param ptabfield           Array of references to the table fields
1456
1436
  @param sortlength          Total length of sorted fields
1457
1437
  @param[out] plength        Total length of appended fields
1467
1447
*/
1468
1448
 
1469
1449
static SORT_ADDON_FIELD *
1470
 
get_addon_fields(THD *thd, Field **ptabfield, uint sortlength, uint *plength)
 
1450
get_addon_fields(Session *session, Field **ptabfield, uint32_t sortlength, uint32_t *plength)
1471
1451
{
1472
1452
  Field **pfield;
1473
1453
  Field *field;
1474
1454
  SORT_ADDON_FIELD *addonf;
1475
 
  uint length= 0;
1476
 
  uint fields= 0;
1477
 
  uint null_fields= 0;
1478
 
  MY_BITMAP *read_set= (*ptabfield)->table->read_set;
 
1455
  uint32_t length= 0;
 
1456
  uint32_t fields= 0;
 
1457
  uint32_t null_fields= 0;
1479
1458
 
1480
1459
  /*
1481
1460
    If there is a reference to a field in the query add it
1483
1462
    Note for future refinement:
1484
1463
    This this a too strong condition.
1485
1464
    Actually we need only the fields referred in the
1486
 
    result set. And for some of them it makes sense to use 
 
1465
    result set. And for some of them it makes sense to use
1487
1466
    the values directly from sorted fields.
1488
1467
  */
1489
1468
  *plength= 0;
1490
1469
 
1491
1470
  for (pfield= ptabfield; (field= *pfield) ; pfield++)
1492
1471
  {
1493
 
    if (!bitmap_is_set(read_set, field->field_index))
 
1472
    if (!(field->isReadSet()))
1494
1473
      continue;
1495
1474
    if (field->flags & BLOB_FLAG)
1496
1475
      return 0;
1498
1477
    if (field->maybe_null())
1499
1478
      null_fields++;
1500
1479
    fields++;
1501
 
  } 
 
1480
  }
1502
1481
  if (!fields)
1503
1482
    return 0;
1504
1483
  length+= (null_fields+7)/8;
1505
1484
 
1506
 
  if (length+sortlength > thd->variables.max_length_for_sort_data ||
1507
 
      !(addonf= (SORT_ADDON_FIELD *) my_malloc(sizeof(SORT_ADDON_FIELD)*
1508
 
                                               (fields+1), MYF(MY_WME))))
 
1485
  if (length+sortlength > session->variables.max_length_for_sort_data ||
 
1486
      !(addonf= (SORT_ADDON_FIELD *) malloc(sizeof(SORT_ADDON_FIELD)*
 
1487
                                            (fields+1))))
1509
1488
    return 0;
1510
1489
 
1511
1490
  *plength= length;
1513
1492
  null_fields= 0;
1514
1493
  for (pfield= ptabfield; (field= *pfield) ; pfield++)
1515
1494
  {
1516
 
    if (!bitmap_is_set(read_set, field->field_index))
 
1495
    if (!(field->isReadSet()))
1517
1496
      continue;
1518
1497
    addonf->field= field;
1519
1498
    addonf->offset= length;
1533
1512
    addonf++;
1534
1513
  }
1535
1514
  addonf->field= 0;     // Put end marker
1536
 
  
 
1515
 
1537
1516
  return (addonf-fields);
1538
1517
}
1539
1518
 
1553
1532
    void.
1554
1533
*/
1555
1534
 
1556
 
static void 
1557
 
unpack_addon_fields(struct st_sort_addon_field *addon_field, uchar *buff)
 
1535
static void
 
1536
unpack_addon_fields(struct st_sort_addon_field *addon_field, unsigned char *buff)
1558
1537
{
1559
1538
  Field *field;
1560
1539
  SORT_ADDON_FIELD *addonf= addon_field;
1578
1557
 
1579
1558
#define DBL_EXP_DIG (sizeof(double)*8-DBL_MANT_DIG)
1580
1559
 
1581
 
void change_double_for_sort(double nr,uchar *to)
 
1560
void change_double_for_sort(double nr,unsigned char *to)
1582
1561
{
1583
 
  uchar *tmp=(uchar*) to;
 
1562
  unsigned char *tmp=(unsigned char*) to;
1584
1563
  if (nr == 0.0)
1585
1564
  {                                             /* Change to zero string */
1586
 
    tmp[0]=(uchar) 128;
 
1565
    tmp[0]=(unsigned char) 128;
1587
1566
    memset(tmp+1, 0, sizeof(nr)-1);
1588
1567
  }
1589
1568
  else
1592
1571
    memcpy(tmp,&nr,sizeof(nr));
1593
1572
#else
1594
1573
    {
1595
 
      uchar *ptr= (uchar*) &nr;
 
1574
      unsigned char *ptr= (unsigned char*) &nr;
1596
1575
#if defined(__FLOAT_WORD_ORDER) && (__FLOAT_WORD_ORDER == __BIG_ENDIAN)
1597
1576
      tmp[0]= ptr[3]; tmp[1]=ptr[2]; tmp[2]= ptr[1]; tmp[3]=ptr[0];
1598
1577
      tmp[4]= ptr[7]; tmp[5]=ptr[6]; tmp[6]= ptr[5]; tmp[7]=ptr[4];
1604
1583
#endif
1605
1584
    if (tmp[0] & 128)                           /* Negative */
1606
1585
    {                                           /* make complement */
1607
 
      uint i;
 
1586
      uint32_t i;
1608
1587
      for (i=0 ; i < sizeof(nr); i++)
1609
 
        tmp[i]=tmp[i] ^ (uchar) 255;
 
1588
        tmp[i]=tmp[i] ^ (unsigned char) 255;
1610
1589
    }
1611
1590
    else
1612
1591
    {                                   /* Set high and move exponent one up */
1613
 
      ushort exp_part=(((ushort) tmp[0] << 8) | (ushort) tmp[1] |
1614
 
                       (ushort) 32768);
1615
 
      exp_part+= (ushort) 1 << (16-1-DBL_EXP_DIG);
1616
 
      tmp[0]= (uchar) (exp_part >> 8);
1617
 
      tmp[1]= (uchar) exp_part;
 
1592
      uint16_t exp_part=(((uint16_t) tmp[0] << 8) | (uint16_t) tmp[1] |
 
1593
                       (uint16_t) 32768);
 
1594
      exp_part+= (uint16_t) 1 << (16-1-DBL_EXP_DIG);
 
1595
      tmp[0]= (unsigned char) (exp_part >> 8);
 
1596
      tmp[1]= (unsigned char) exp_part;
1618
1597
    }
1619
1598
  }
1620
1599
}