~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/filesort.cc

  • Committer: Patrick Galbraith
  • Date: 2009-10-08 22:42:05 UTC
  • mto: (1166.5.3 memcached_functions)
  • mto: This revision was merged to the branch mainline in revision 1189.
  • Revision ID: patg@patrick-galbraiths-macbook-pro.local-20091008224205-gq1pehjsivvx0qo9
Starting over with a fresh tree, moved in memcached functions.

Memcached Functions for Drizzle. 

All tests pass.

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