~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/filesort.cc

  • Committer: Brian Aker
  • Date: 2009-04-17 01:45:33 UTC
  • Revision ID: brian@gaz-20090417014533-exdrtriab9zecqs2
Refactor get_variable to session

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 <bitset>
 
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),
 
187
    records=cmin((ha_rows) (select->quick->records*2+EXTRA_RECORDS*2),
185
188
                table->file->stats.records)+EXTRA_RECORDS;
186
189
    selected_records_file=0;
187
190
  }
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= cmax((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) cmin(records+1, 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
219
    old_memavl=memavl;
217
220
    if ((memavl=memavl/4*3) < min_sort_memory && old_memavl > min_sort_memory)
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
 
  MY_BITMAP *save_read_set, *save_write_set;
 
457
  bitset<MAX_FIELDS> *save_read_set, *save_write_set;
450
458
 
451
459
  idx=indexpos=0;
452
460
  error=quick_select=0;
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
 
482
490
  save_read_set=  sort_form->read_set;
483
491
  save_write_set= sort_form->write_set;
484
492
  /* Set up temporary column read map for columns used by sort */
485
 
  bitmap_clear_all(&sort_form->tmp_set);
 
493
  sort_form->tmp_set.reset();
486
494
  /* Temporary set for register_used_fields and register_field_in_read_map */
487
495
  sort_form->read_set= &sort_form->tmp_set;
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
        if (!error)
 
528
          update_virtual_fields_marked_for_write(sort_form);
 
529
 
519
530
        if (!flag)
520
531
        {
521
532
          my_store_ptr(ref_pos,ref_length,record); // Position to row
553
564
    else
554
565
      file->unlock_row();
555
566
    /* It does not make sense to read more keys in case of a fatal error */
556
 
    if (thd->is_error())
 
567
    if (session->is_error())
557
568
      break;
558
569
  }
559
570
  if (quick_select)
571
582
      file->ha_rnd_end();
572
583
  }
573
584
 
574
 
  if (thd->is_error())
 
585
  if (session->is_error())
575
586
    return(HA_POS_ERROR);
576
 
  
 
587
 
577
588
  /* Signal we should use orignal column read and write maps */
578
589
  sort_form->column_bitmaps_set(save_read_set, save_write_set);
579
590
 
614
625
*/
615
626
 
616
627
static int
617
 
write_keys(SORTPARAM *param, register uchar **sort_keys, uint count,
 
628
write_keys(SORTPARAM *param, register unsigned char **sort_keys, uint32_t count,
618
629
           IO_CACHE *buffpek_pointers, IO_CACHE *tempfile)
619
630
{
620
631
  size_t sort_length, rec_length;
621
 
  uchar **end;
 
632
  unsigned char **end;
622
633
  BUFFPEK buffpek;
623
634
 
624
635
  sort_length= param->sort_length;
625
636
  rec_length= param->rec_length;
626
 
  my_string_ptr_sort((uchar*) sort_keys, (uint) count, sort_length);
 
637
  my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, sort_length);
627
638
  if (!my_b_inited(tempfile) &&
628
 
      open_cached_file(tempfile, mysql_tmpdir, TEMP_PREFIX, DISK_BUFFER_SIZE,
 
639
      open_cached_file(tempfile, drizzle_tmpdir, TEMP_PREFIX, DISK_BUFFER_SIZE,
629
640
                       MYF(MY_WME)))
630
641
    goto err;                                   /* purecov: inspected */
631
642
  /* check we won't have more buffpeks than we can possibly keep in memory */
633
644
    goto err;
634
645
  buffpek.file_pos= my_b_tell(tempfile);
635
646
  if ((ha_rows) count > param->max_rows)
636
 
    count=(uint) param->max_rows;               /* purecov: inspected */
 
647
    count=(uint32_t) param->max_rows;               /* purecov: inspected */
637
648
  buffpek.count=(ha_rows) count;
638
649
  for (end=sort_keys+count ; sort_keys != end ; sort_keys++)
639
 
    if (my_b_write(tempfile, (uchar*) *sort_keys, (uint) rec_length))
 
650
    if (my_b_write(tempfile, (unsigned char*) *sort_keys, (uint32_t) rec_length))
640
651
      goto err;
641
 
  if (my_b_write(buffpek_pointers, (uchar*) &buffpek, sizeof(buffpek)))
 
652
  if (my_b_write(buffpek_pointers, (unsigned char*) &buffpek, sizeof(buffpek)))
642
653
    goto err;
643
654
  return(0);
644
655
 
651
662
  Store length as suffix in high-byte-first order.
652
663
*/
653
664
 
654
 
static inline void store_length(uchar *to, uint length, uint pack_length)
 
665
static inline void store_length(unsigned char *to, uint32_t length, uint32_t pack_length)
655
666
{
656
667
  switch (pack_length) {
657
668
  case 1:
658
 
    *to= (uchar) length;
 
669
    *to= (unsigned char) length;
659
670
    break;
660
671
  case 2:
661
672
    mi_int2store(to, length);
673
684
/** Make a sort-key from record. */
674
685
 
675
686
static void make_sortkey(register SORTPARAM *param,
676
 
                         register uchar *to, uchar *ref_pos)
 
687
                         register unsigned char *to, unsigned char *ref_pos)
677
688
{
678
689
  register Field *field;
679
690
  register SORT_FIELD *sort_field;
680
 
  register uint length;
 
691
  size_t length;
681
692
 
682
693
  for (sort_field=param->local_sortorder ;
683
694
       sort_field != param->end ;
712
723
        const CHARSET_INFO * const cs=item->collation.collation;
713
724
        char fill_char= ((cs->state & MY_CS_BINSORT) ? (char) 0 : ' ');
714
725
        int diff;
715
 
        uint sort_field_length;
 
726
        uint32_t sort_field_length;
716
727
 
717
728
        if (maybe_null)
718
729
          *to++=1;
754
765
        if (sort_field->need_strxnfrm)
755
766
        {
756
767
          char *from=(char*) res->ptr();
757
 
          uint tmp_length;
758
 
          if ((uchar*) from == to)
 
768
          uint32_t tmp_length;
 
769
          if ((unsigned char*) from == to)
759
770
          {
760
771
            set_if_smaller(length,sort_field->length);
761
772
            memcpy(param->tmp_buffer,from,length);
762
773
            from=param->tmp_buffer;
763
774
          }
764
775
          tmp_length= my_strnxfrm(cs,to,sort_field->length,
765
 
                                  (uchar*) from, length);
 
776
                                  (unsigned char*) from, length);
766
777
          assert(tmp_length == sort_field->length);
767
778
        }
768
779
        else
769
780
        {
770
 
          my_strnxfrm(cs,(uchar*)to,length,(const uchar*)res->ptr(),length);
 
781
          my_strnxfrm(cs,(unsigned char*)to,length,(const unsigned char*)res->ptr(),length);
771
782
          cs->cset->fill(cs, (char *)to+length,diff,fill_char);
772
783
        }
773
784
        break;
789
800
              break;
790
801
            }
791
802
          }
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
 
803
          to[7]= (unsigned char) value;
 
804
          to[6]= (unsigned char) (value >> 8);
 
805
          to[5]= (unsigned char) (value >> 16);
 
806
          to[4]= (unsigned char) (value >> 24);
 
807
          to[3]= (unsigned char) (value >> 32);
 
808
          to[2]= (unsigned char) (value >> 40);
 
809
          to[1]= (unsigned char) (value >> 48);
 
810
          if (item->unsigned_flag)                    /* Fix sign */
 
811
            to[0]= (unsigned char) (value >> 56);
 
812
          else
 
813
            to[0]= (unsigned char) (value >> 56) ^ 128; /* Reverse signbit */
813
814
          break;
814
815
        }
815
816
      case DECIMAL_RESULT:
818
819
          if (maybe_null)
819
820
          {
820
821
            if (item->null_value)
821
 
            { 
 
822
            {
822
823
              memset(to, 0, sort_field->length+1);
823
824
              to++;
824
825
              break;
843
844
            }
844
845
            *to++=1;
845
846
          }
846
 
          change_double_for_sort(value,(uchar*) to);
 
847
          change_double_for_sort(value,(unsigned char*) to);
847
848
          break;
848
849
        }
849
850
      case ROW_RESULT:
850
 
      default: 
 
851
      default:
851
852
        // This case should never be choosen
852
853
        assert(0);
853
854
        break;
860
861
      length=sort_field->length;
861
862
      while (length--)
862
863
      {
863
 
        *to = (uchar) (~ *to);
 
864
        *to = (unsigned char) (~ *to);
864
865
        to++;
865
866
      }
866
867
    }
870
871
 
871
872
  if (param->addon_field)
872
873
  {
873
 
    /* 
 
874
    /*
874
875
      Save field values appended to sorted fields.
875
876
      First null bit indicators are appended then field values follow.
876
877
      In this implementation we use fixed layout for field values -
877
878
      the same for all records.
878
879
    */
879
880
    SORT_ADDON_FIELD *addonf= param->addon_field;
880
 
    uchar *nulls= to;
 
881
    unsigned char *nulls= to;
881
882
    assert(addonf != 0);
882
883
    memset(nulls, 0, addonf->offset);
883
884
    to+= addonf->offset;
893
894
      else
894
895
      {
895
896
#ifdef HAVE_purify
896
 
        uchar *end= field->pack(to, field->ptr);
897
 
        uint length= (uint) ((to + addonf->length) - end);
 
897
        unsigned char *end= field->pack(to, field->ptr);
 
898
        uint32_t length= (uint32_t) ((to + addonf->length) - end);
898
899
        assert((int) length >= 0);
899
900
        if (length)
900
901
          memset(end, 0, length);
921
922
static void register_used_fields(SORTPARAM *param)
922
923
{
923
924
  register SORT_FIELD *sort_field;
924
 
  TABLE *table=param->sort_form;
925
 
  MY_BITMAP *bitmap= table->read_set;
 
925
  Table *table=param->sort_form;
 
926
  bitset<MAX_FIELDS> *bitmap= table->read_set;
926
927
 
927
928
  for (sort_field= param->local_sortorder ;
928
929
       sort_field != param->end ;
932
933
    if ((field= sort_field->field))
933
934
    {
934
935
      if (field->table == table)
935
 
      bitmap_set_bit(bitmap, field->field_index);
 
936
        bitmap->set(field->field_index);
936
937
    }
937
938
    else
938
939
    {                                           // Item
939
940
      sort_field->item->walk(&Item::register_field_in_read_map, 1,
940
 
                             (uchar *) table);
 
941
                             (unsigned char *) table);
941
942
    }
942
943
  }
943
944
 
946
947
    SORT_ADDON_FIELD *addonf= param->addon_field;
947
948
    Field *field;
948
949
    for ( ; (field= addonf->field) ; addonf++)
949
 
      bitmap_set_bit(bitmap, field->field_index);
 
950
      bitmap->set(field->field_index);
950
951
  }
951
952
  else
952
953
  {
956
957
}
957
958
 
958
959
 
959
 
static bool save_index(SORTPARAM *param, uchar **sort_keys, uint count, 
960
 
                       FILESORT_INFO *table_sort)
 
960
static bool save_index(SORTPARAM *param, unsigned char **sort_keys, uint32_t count,
 
961
                       filesort_info_st *table_sort)
961
962
{
962
 
  uint offset,res_length;
963
 
  uchar *to;
 
963
  uint32_t offset,res_length;
 
964
  unsigned char *to;
964
965
 
965
 
  my_string_ptr_sort((uchar*) sort_keys, (uint) count, param->sort_length);
 
966
  my_string_ptr_sort((unsigned char*) sort_keys, (uint32_t) count, param->sort_length);
966
967
  res_length= param->res_length;
967
968
  offset= param->rec_length-res_length;
968
969
  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))))
 
970
    count=(uint32_t) param->max_rows;
 
971
  if (!(to= table_sort->record_pointers=
 
972
        (unsigned char*) malloc(res_length*count)))
972
973
    return(1);                 /* purecov: inspected */
973
 
  for (uchar **end= sort_keys+count ; sort_keys != end ; sort_keys++)
 
974
  for (unsigned char **end= sort_keys+count ; sort_keys != end ; sort_keys++)
974
975
  {
975
976
    memcpy(to, *sort_keys+offset, res_length);
976
977
    to+= res_length;
981
982
 
982
983
/** Merge buffers to make < MERGEBUFF2 buffers. */
983
984
 
984
 
int merge_many_buff(SORTPARAM *param, uchar *sort_buffer,
985
 
                    BUFFPEK *buffpek, uint *maxbuffer, IO_CACHE *t_file)
 
985
int merge_many_buff(SORTPARAM *param, unsigned char *sort_buffer,
 
986
                    BUFFPEK *buffpek, uint32_t *maxbuffer, IO_CACHE *t_file)
986
987
{
987
 
  register uint i;
 
988
  register uint32_t i;
988
989
  IO_CACHE t_file2,*from_file,*to_file,*temp;
989
990
  BUFFPEK *lastbuff;
990
991
 
991
992
  if (*maxbuffer < MERGEBUFF2)
992
993
    return(0);                          /* purecov: inspected */
993
994
  if (flush_io_cache(t_file) ||
994
 
      open_cached_file(&t_file2,mysql_tmpdir,TEMP_PREFIX,DISK_BUFFER_SIZE,
 
995
      open_cached_file(&t_file2,drizzle_tmpdir,TEMP_PREFIX,DISK_BUFFER_SIZE,
995
996
                        MYF(MY_WME)))
996
997
    return(1);                          /* purecov: inspected */
997
998
 
1017
1018
    temp=from_file; from_file=to_file; to_file=temp;
1018
1019
    setup_io_cache(from_file);
1019
1020
    setup_io_cache(to_file);
1020
 
    *maxbuffer= (uint) (lastbuff-buffpek)-1;
 
1021
    *maxbuffer= (uint32_t) (lastbuff-buffpek)-1;
1021
1022
  }
1022
1023
cleanup:
1023
1024
  close_cached_file(to_file);                   // This holds old result
1035
1036
  Read data to buffer.
1036
1037
 
1037
1038
  @retval
1038
 
    (uint)-1 if something goes wrong
 
1039
    (uint32_t)-1 if something goes wrong
1039
1040
*/
1040
1041
 
1041
 
uint read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek,
1042
 
                    uint rec_length)
 
1042
uint32_t read_to_buffer(IO_CACHE *fromfile, BUFFPEK *buffpek,
 
1043
                    uint32_t rec_length)
1043
1044
{
1044
 
  register uint count;
1045
 
  uint length;
 
1045
  register uint32_t count;
 
1046
  uint32_t length;
1046
1047
 
1047
 
  if ((count=(uint) min((ha_rows) buffpek->max_keys,buffpek->count)))
 
1048
  if ((count=(uint32_t) cmin((ha_rows) buffpek->max_keys,buffpek->count)))
1048
1049
  {
1049
 
    if (pread(fromfile->file,(uchar*) buffpek->base, (length= rec_length*count),buffpek->file_pos) == 0)
1050
 
      return((uint) -1);                        /* purecov: inspected */
 
1050
    if (pread(fromfile->file,(unsigned char*) buffpek->base, (length= rec_length*count),buffpek->file_pos) == 0)
 
1051
      return((uint32_t) -1);                    /* purecov: inspected */
1051
1052
    buffpek->key=buffpek->base;
1052
1053
    buffpek->file_pos+= length;                 /* New filepos */
1053
1054
    buffpek->count-=    count;
1057
1058
} /* read_to_buffer */
1058
1059
 
1059
1060
 
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)
 
1061
class compare_functor
1072
1062
{
1073
 
  uchar *reuse_end= reuse->base + reuse->max_keys * key_length;
1074
 
  for (uint i= 0; i < queue->elements; ++i)
 
1063
  qsort2_cmp key_compare;
 
1064
  void *key_compare_arg;
 
1065
  public:
 
1066
  compare_functor(qsort2_cmp in_key_compare, void *in_compare_arg)
 
1067
    : key_compare(in_key_compare), key_compare_arg(in_compare_arg) { }
 
1068
  inline bool operator()(const BUFFPEK *i, const BUFFPEK *j) const
1075
1069
  {
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
 
    }
 
1070
    int val= key_compare(key_compare_arg,
 
1071
                      &i->key, &j->key);
 
1072
    return (val >= 0);
1088
1073
  }
1089
 
  assert(0);
1090
 
}
 
1074
};
1091
1075
 
1092
1076
 
1093
1077
/**
1109
1093
*/
1110
1094
 
1111
1095
int merge_buffers(SORTPARAM *param, IO_CACHE *from_file,
1112
 
                  IO_CACHE *to_file, uchar *sort_buffer,
 
1096
                  IO_CACHE *to_file, unsigned char *sort_buffer,
1113
1097
                  BUFFPEK *lastbuff, BUFFPEK *Fb, BUFFPEK *Tb,
1114
1098
                  int flag)
1115
1099
{
1116
1100
  int error;
1117
 
  uint rec_length,res_length,offset;
 
1101
  uint32_t rec_length,res_length,offset;
1118
1102
  size_t sort_length;
1119
1103
  uint32_t maxcount;
1120
1104
  ha_rows max_rows,org_max_rows;
1121
1105
  my_off_t to_start_filepos;
1122
 
  uchar *strpos;
 
1106
  unsigned char *strpos;
1123
1107
  BUFFPEK *buffpek;
1124
 
  QUEUE queue;
1125
1108
  qsort2_cmp cmp;
1126
1109
  void *first_cmp_arg;
1127
 
  volatile THD::killed_state *killed= &current_thd->killed;
1128
 
  THD::killed_state not_killable;
 
1110
  volatile Session::killed_state *killed= &current_session->killed;
 
1111
  Session::killed_state not_killable;
1129
1112
 
1130
 
  status_var_increment(current_thd->status_var.filesort_merge_passes);
 
1113
  status_var_increment(current_session->status_var.filesort_merge_passes);
1131
1114
  if (param->not_killable)
1132
1115
  {
1133
1116
    killed= &not_killable;
1134
 
    not_killable= THD::NOT_KILLED;
 
1117
    not_killable= Session::NOT_KILLED;
1135
1118
  }
1136
1119
 
1137
1120
  error=0;
1139
1122
  res_length= param->res_length;
1140
1123
  sort_length= param->sort_length;
1141
1124
  offset= rec_length-res_length;
1142
 
  maxcount= (uint32_t) (param->keys/((uint) (Tb-Fb) +1));
 
1125
  maxcount= (uint32_t) (param->keys/((uint32_t) (Tb-Fb) +1));
1143
1126
  to_start_filepos= my_b_tell(to_file);
1144
 
  strpos= (uchar*) sort_buffer;
 
1127
  strpos= (unsigned char*) sort_buffer;
1145
1128
  org_max_rows=max_rows= param->max_rows;
1146
1129
 
1147
1130
  /* The following will fire if there is not enough space in sort_buffer */
1148
1131
  assert(maxcount!=0);
1149
 
  
 
1132
 
1150
1133
  if (param->unique_buff)
1151
1134
  {
1152
1135
    cmp= param->compare;
1157
1140
    cmp= get_ptr_compare(sort_length);
1158
1141
    first_cmp_arg= (void*) &sort_length;
1159
1142
  }
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 */
 
1143
  priority_queue<BUFFPEK *, vector<BUFFPEK *>, compare_functor > 
 
1144
    queue(compare_functor(cmp, first_cmp_arg));
1163
1145
  for (buffpek= Fb ; buffpek <= Tb ; buffpek++)
1164
1146
  {
1165
1147
    buffpek->base= strpos;
1166
1148
    buffpek->max_keys= maxcount;
1167
 
    strpos+= (uint) (error= (int) read_to_buffer(from_file, buffpek,
 
1149
    strpos+= (uint32_t) (error= (int) read_to_buffer(from_file, buffpek,
1168
1150
                                                                         rec_length));
1169
1151
    if (error == -1)
1170
1152
      goto err;                                 /* purecov: inspected */
1171
1153
    buffpek->max_keys= buffpek->mem_count;      // If less data in buffers than expected
1172
 
    queue_insert(&queue, (uchar*) buffpek);
 
1154
    queue.push(buffpek);
1173
1155
  }
1174
1156
 
1175
1157
  if (param->unique_buff)
1176
1158
  {
1177
 
    /* 
 
1159
    /*
1178
1160
       Called by Unique::get()
1179
1161
       Copy the first argument to param->unique_buff for unique removal.
1180
1162
       Store it also in 'to_file'.
1182
1164
       This is safe as we know that there is always more than one element
1183
1165
       in each block to merge (This is guaranteed by the Unique:: algorithm
1184
1166
    */
1185
 
    buffpek= (BUFFPEK*) queue_top(&queue);
 
1167
    buffpek= queue.top();
1186
1168
    memcpy(param->unique_buff, buffpek->key, rec_length);
1187
 
    if (my_b_write(to_file, (uchar*) buffpek->key, rec_length))
 
1169
    if (my_b_write(to_file, (unsigned char*) buffpek->key, rec_length))
1188
1170
    {
1189
1171
      error=1; goto err;                        /* purecov: inspected */
1190
1172
    }
1195
1177
      error= 0;                                       /* purecov: inspected */
1196
1178
      goto end;                                       /* purecov: inspected */
1197
1179
    }
1198
 
    queue_replaced(&queue);                        // Top element has been used
 
1180
    /* Top element has been used */
 
1181
    queue.pop();
 
1182
    queue.push(buffpek);
1199
1183
  }
1200
1184
  else
1201
1185
    cmp= 0;                                        // Not unique
1202
1186
 
1203
 
  while (queue.elements > 1)
 
1187
  while (queue.size() > 1)
1204
1188
  {
1205
1189
    if (*killed)
1206
1190
    {
1208
1192
    }
1209
1193
    for (;;)
1210
1194
    {
1211
 
      buffpek= (BUFFPEK*) queue_top(&queue);
 
1195
      buffpek= queue.top();
1212
1196
      if (cmp)                                        // Remove duplicates
1213
1197
      {
1214
1198
        if (!(*cmp)(first_cmp_arg, &(param->unique_buff),
1215
 
                    (uchar**) &buffpek->key))
 
1199
                    (unsigned char**) &buffpek->key))
1216
1200
              goto skip_duplicate;
1217
1201
            memcpy(param->unique_buff, buffpek->key, rec_length);
1218
1202
      }
1219
1203
      if (flag == 0)
1220
1204
      {
1221
 
        if (my_b_write(to_file,(uchar*) buffpek->key, rec_length))
 
1205
        if (my_b_write(to_file,(unsigned char*) buffpek->key, rec_length))
1222
1206
        {
1223
1207
          error=1; goto err;                        /* purecov: inspected */
1224
1208
        }
1225
1209
      }
1226
1210
      else
1227
1211
      {
1228
 
        if (my_b_write(to_file, (uchar*) buffpek->key+offset, res_length))
 
1212
        if (my_b_write(to_file, (unsigned char*) buffpek->key+offset, res_length))
1229
1213
        {
1230
1214
          error=1; goto err;                        /* purecov: inspected */
1231
1215
        }
1243
1227
        if (!(error= (int) read_to_buffer(from_file,buffpek,
1244
1228
                                          rec_length)))
1245
1229
        {
1246
 
          VOID(queue_remove(&queue,0));
1247
 
          reuse_freed_buff(&queue, buffpek, rec_length);
 
1230
          queue.pop();
1248
1231
          break;                        /* One buffer have been removed */
1249
1232
        }
1250
1233
        else if (error == -1)
1251
1234
          goto err;                        /* purecov: inspected */
1252
1235
      }
1253
 
      queue_replaced(&queue);              /* Top element has been replaced */
 
1236
      /* Top element has been replaced */
 
1237
      queue.pop();
 
1238
      queue.push(buffpek);
1254
1239
    }
1255
1240
  }
1256
 
  buffpek= (BUFFPEK*) queue_top(&queue);
 
1241
  buffpek= queue.top();
1257
1242
  buffpek->base= sort_buffer;
1258
1243
  buffpek->max_keys= param->keys;
1259
1244
 
1263
1248
  */
1264
1249
  if (cmp)
1265
1250
  {
1266
 
    if (!(*cmp)(first_cmp_arg, &(param->unique_buff), (uchar**) &buffpek->key))
 
1251
    if (!(*cmp)(first_cmp_arg, &(param->unique_buff), (unsigned char**) &buffpek->key))
1267
1252
    {
1268
1253
      buffpek->key+= rec_length;         // Remove duplicate
1269
1254
      --buffpek->mem_count;
1274
1259
  {
1275
1260
    if ((ha_rows) buffpek->mem_count > max_rows)
1276
1261
    {                                        /* Don't write too many records */
1277
 
      buffpek->mem_count= (uint) max_rows;
 
1262
      buffpek->mem_count= (uint32_t) max_rows;
1278
1263
      buffpek->count= 0;                        /* Don't read more */
1279
1264
    }
1280
1265
    max_rows-= buffpek->mem_count;
1281
1266
    if (flag == 0)
1282
1267
    {
1283
 
      if (my_b_write(to_file,(uchar*) buffpek->key,
 
1268
      if (my_b_write(to_file,(unsigned char*) buffpek->key,
1284
1269
                     (rec_length*buffpek->mem_count)))
1285
1270
      {
1286
1271
        error= 1; goto err;                        /* purecov: inspected */
1288
1273
    }
1289
1274
    else
1290
1275
    {
1291
 
      register uchar *end;
 
1276
      register unsigned char *end;
1292
1277
      strpos= buffpek->key+offset;
1293
1278
      for (end= strpos+buffpek->mem_count*rec_length ;
1294
1279
           strpos != end ;
1295
1280
           strpos+= rec_length)
1296
 
      {     
1297
 
        if (my_b_write(to_file, (uchar *) strpos, res_length))
 
1281
      {
 
1282
        if (my_b_write(to_file, (unsigned char *) strpos, res_length))
1298
1283
        {
1299
 
          error=1; goto err;                        
 
1284
          error=1; goto err;
1300
1285
        }
1301
1286
      }
1302
1287
    }
1305
1290
         != -1 && error != 0);
1306
1291
 
1307
1292
end:
1308
 
  lastbuff->count= min(org_max_rows-max_rows, param->max_rows);
 
1293
  lastbuff->count= cmin(org_max_rows-max_rows, param->max_rows);
1309
1294
  lastbuff->file_pos= to_start_filepos;
1310
1295
err:
1311
 
  delete_queue(&queue);
1312
1296
  return(error);
1313
1297
} /* merge_buffers */
1314
1298
 
1315
1299
 
1316
1300
        /* Do a merge to output-file (save only positions) */
1317
1301
 
1318
 
static int merge_index(SORTPARAM *param, uchar *sort_buffer,
1319
 
                       BUFFPEK *buffpek, uint maxbuffer,
 
1302
static int merge_index(SORTPARAM *param, unsigned char *sort_buffer,
 
1303
                       BUFFPEK *buffpek, uint32_t maxbuffer,
1320
1304
                       IO_CACHE *tempfile, IO_CACHE *outfile)
1321
1305
{
1322
1306
  if (merge_buffers(param,tempfile,outfile,sort_buffer,buffpek,buffpek,
1326
1310
} /* merge_index */
1327
1311
 
1328
1312
 
1329
 
static uint suffix_length(uint32_t string_length)
 
1313
static uint32_t suffix_length(uint32_t string_length)
1330
1314
{
1331
1315
  if (string_length < 256)
1332
1316
    return 1;
1342
1326
/**
1343
1327
  Calculate length of sort key.
1344
1328
 
1345
 
  @param thd                      Thread handler
 
1329
  @param session                          Thread handler
1346
1330
  @param sortorder                Order of items to sort
1347
1331
  @param s_length                 Number of items to sort
1348
1332
  @param[out] multi_byte_charset Set to 1 if we are using multi-byte charset
1357
1341
    Total length of sort buffer in bytes
1358
1342
*/
1359
1343
 
1360
 
static uint
1361
 
sortlength(THD *thd, SORT_FIELD *sortorder, uint s_length,
 
1344
static uint32_t
 
1345
sortlength(Session *session, SORT_FIELD *sortorder, uint32_t s_length,
1362
1346
           bool *multi_byte_charset)
1363
1347
{
1364
 
  register uint length;
 
1348
  register uint32_t length;
1365
1349
  const CHARSET_INFO *cs;
1366
1350
  *multi_byte_charset= 0;
1367
1351
 
1392
1376
      switch (sortorder->result_type) {
1393
1377
      case STRING_RESULT:
1394
1378
        sortorder->length=sortorder->item->max_length;
1395
 
        set_if_smaller(sortorder->length, thd->variables.max_sort_length);
 
1379
        set_if_smaller(sortorder->length,
 
1380
                       session->variables.max_sort_length);
1396
1381
        if (use_strnxfrm((cs=sortorder->item->collation.collation)))
1397
 
        { 
 
1382
        {
1398
1383
          sortorder->length= cs->coll->strnxfrmlen(cs, sortorder->length);
1399
1384
          sortorder->need_strxnfrm= 1;
1400
1385
          *multi_byte_charset= 1;
1407
1392
        }
1408
1393
        break;
1409
1394
      case INT_RESULT:
1410
 
#if SIZEOF_LONG_LONG > 4
1411
1395
        sortorder->length=8;                    // Size of intern int64_t
1412
 
#else
1413
 
        sortorder->length=4;
1414
 
#endif
1415
1396
        break;
1416
1397
      case DECIMAL_RESULT:
1417
1398
        sortorder->length=
1418
 
          my_decimal_get_binary_size(sortorder->item->max_length - 
 
1399
          my_decimal_get_binary_size(sortorder->item->max_length -
1419
1400
                                     (sortorder->item->decimals ? 1 : 0),
1420
1401
                                     sortorder->item->decimals);
1421
1402
        break;
1423
1404
        sortorder->length=sizeof(double);
1424
1405
        break;
1425
1406
      case ROW_RESULT:
1426
 
      default: 
 
1407
      default:
1427
1408
        // This case should never be choosen
1428
1409
        assert(0);
1429
1410
        break;
1431
1412
      if (sortorder->item->maybe_null)
1432
1413
        length++;                               // Place for NULL marker
1433
1414
    }
1434
 
    set_if_smaller(sortorder->length, thd->variables.max_sort_length);
 
1415
    set_if_smaller(sortorder->length,
 
1416
                   (size_t)session->variables.max_sort_length);
1435
1417
    length+=sortorder->length;
1436
1418
  }
1437
1419
  sortorder->field= (Field*) 0;                 // end marker
1445
1427
 
1446
1428
  The function first finds out what fields are used in the result set.
1447
1429
  Then it calculates the length of the buffer to store the values of
1448
 
  these fields together with the value of sort values. 
 
1430
  these fields together with the value of sort values.
1449
1431
  If the calculated length is not greater than max_length_for_sort_data
1450
1432
  the function allocates memory for an array of descriptors containing
1451
1433
  layouts for the values of the non-sorted fields in the buffer and
1452
1434
  fills them.
1453
1435
 
1454
 
  @param thd                 Current thread
 
1436
  @param session                 Current thread
1455
1437
  @param ptabfield           Array of references to the table fields
1456
1438
  @param sortlength          Total length of sorted fields
1457
1439
  @param[out] plength        Total length of appended fields
1467
1449
*/
1468
1450
 
1469
1451
static SORT_ADDON_FIELD *
1470
 
get_addon_fields(THD *thd, Field **ptabfield, uint sortlength, uint *plength)
 
1452
get_addon_fields(Session *session, Field **ptabfield, uint32_t sortlength, uint32_t *plength)
1471
1453
{
1472
1454
  Field **pfield;
1473
1455
  Field *field;
1474
1456
  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;
 
1457
  uint32_t length= 0;
 
1458
  uint32_t fields= 0;
 
1459
  uint32_t null_fields= 0;
 
1460
  bitset<MAX_FIELDS> *read_set= (*ptabfield)->table->read_set;
1479
1461
 
1480
1462
  /*
1481
1463
    If there is a reference to a field in the query add it
1483
1465
    Note for future refinement:
1484
1466
    This this a too strong condition.
1485
1467
    Actually we need only the fields referred in the
1486
 
    result set. And for some of them it makes sense to use 
 
1468
    result set. And for some of them it makes sense to use
1487
1469
    the values directly from sorted fields.
1488
1470
  */
1489
1471
  *plength= 0;
1490
1472
 
1491
1473
  for (pfield= ptabfield; (field= *pfield) ; pfield++)
1492
1474
  {
1493
 
    if (!bitmap_is_set(read_set, field->field_index))
 
1475
    if (!read_set->test(field->field_index))
1494
1476
      continue;
1495
1477
    if (field->flags & BLOB_FLAG)
1496
1478
      return 0;
1498
1480
    if (field->maybe_null())
1499
1481
      null_fields++;
1500
1482
    fields++;
1501
 
  } 
 
1483
  }
1502
1484
  if (!fields)
1503
1485
    return 0;
1504
1486
  length+= (null_fields+7)/8;
1505
1487
 
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))))
 
1488
  if (length+sortlength > session->variables.max_length_for_sort_data ||
 
1489
      !(addonf= (SORT_ADDON_FIELD *) malloc(sizeof(SORT_ADDON_FIELD)*
 
1490
                                            (fields+1))))
1509
1491
    return 0;
1510
1492
 
1511
1493
  *plength= length;
1513
1495
  null_fields= 0;
1514
1496
  for (pfield= ptabfield; (field= *pfield) ; pfield++)
1515
1497
  {
1516
 
    if (!bitmap_is_set(read_set, field->field_index))
 
1498
    if (!read_set->test(field->field_index))
1517
1499
      continue;
1518
1500
    addonf->field= field;
1519
1501
    addonf->offset= length;
1533
1515
    addonf++;
1534
1516
  }
1535
1517
  addonf->field= 0;     // Put end marker
1536
 
  
 
1518
 
1537
1519
  return (addonf-fields);
1538
1520
}
1539
1521
 
1553
1535
    void.
1554
1536
*/
1555
1537
 
1556
 
static void 
1557
 
unpack_addon_fields(struct st_sort_addon_field *addon_field, uchar *buff)
 
1538
static void
 
1539
unpack_addon_fields(struct st_sort_addon_field *addon_field, unsigned char *buff)
1558
1540
{
1559
1541
  Field *field;
1560
1542
  SORT_ADDON_FIELD *addonf= addon_field;
1578
1560
 
1579
1561
#define DBL_EXP_DIG (sizeof(double)*8-DBL_MANT_DIG)
1580
1562
 
1581
 
void change_double_for_sort(double nr,uchar *to)
 
1563
void change_double_for_sort(double nr,unsigned char *to)
1582
1564
{
1583
 
  uchar *tmp=(uchar*) to;
 
1565
  unsigned char *tmp=(unsigned char*) to;
1584
1566
  if (nr == 0.0)
1585
1567
  {                                             /* Change to zero string */
1586
 
    tmp[0]=(uchar) 128;
 
1568
    tmp[0]=(unsigned char) 128;
1587
1569
    memset(tmp+1, 0, sizeof(nr)-1);
1588
1570
  }
1589
1571
  else
1592
1574
    memcpy(tmp,&nr,sizeof(nr));
1593
1575
#else
1594
1576
    {
1595
 
      uchar *ptr= (uchar*) &nr;
 
1577
      unsigned char *ptr= (unsigned char*) &nr;
1596
1578
#if defined(__FLOAT_WORD_ORDER) && (__FLOAT_WORD_ORDER == __BIG_ENDIAN)
1597
1579
      tmp[0]= ptr[3]; tmp[1]=ptr[2]; tmp[2]= ptr[1]; tmp[3]=ptr[0];
1598
1580
      tmp[4]= ptr[7]; tmp[5]=ptr[6]; tmp[6]= ptr[5]; tmp[7]=ptr[4];
1604
1586
#endif
1605
1587
    if (tmp[0] & 128)                           /* Negative */
1606
1588
    {                                           /* make complement */
1607
 
      uint i;
 
1589
      uint32_t i;
1608
1590
      for (i=0 ; i < sizeof(nr); i++)
1609
 
        tmp[i]=tmp[i] ^ (uchar) 255;
 
1591
        tmp[i]=tmp[i] ^ (unsigned char) 255;
1610
1592
    }
1611
1593
    else
1612
1594
    {                                   /* 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;
 
1595
      uint16_t exp_part=(((uint16_t) tmp[0] << 8) | (uint16_t) tmp[1] |
 
1596
                       (uint16_t) 32768);
 
1597
      exp_part+= (uint16_t) 1 << (16-1-DBL_EXP_DIG);
 
1598
      tmp[0]= (unsigned char) (exp_part >> 8);
 
1599
      tmp[1]= (unsigned char) exp_part;
1618
1600
    }
1619
1601
  }
1620
1602
}