~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/filesort.cc

  • Committer: Brian Aker
  • Date: 2010-05-27 01:25:56 UTC
  • mfrom: (1567.1.4 new-staging)
  • Revision ID: brian@gaz-20100527012556-5zgkirkl7swbigd6
Merge of Brian, Paul. PBXT compile issue, and test framework cleanup. 

Show diffs side-by-side

added added

removed removed

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