~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/filesort.cc

  • Committer: Monty Taylor
  • Date: 2008-09-15 00:46:33 UTC
  • mfrom: (383.1.55 client-split)
  • Revision ID: monty@inaugust.com-20080915004633-fmjw27fi41cxs35w
Merged from client-split.

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