~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/filesort.cc

  • Committer: Monty Taylor
  • Date: 2009-10-06 19:40:45 UTC
  • mto: This revision was merged to the branch mainline in revision 1184.
  • Revision ID: mordred@inaugust.com-20091006194045-ojptaq2sx6ck6q63
No more server_includes.h in headers.

Show diffs side-by-side

added added

removed removed

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