~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/filesort.cc

  • Committer: Brian Aker
  • Date: 2008-12-16 07:07:50 UTC
  • Revision ID: brian@tangent.org-20081216070750-o5ykltxxqvn2awrx
Fixed errors test.

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